rune/modules/
object.rs

1//! The dynamic [`Object`] container.
2
3use crate as rune;
4use crate::alloc;
5use crate::alloc::clone::TryClone;
6use crate::alloc::fmt::TryWrite;
7use crate::runtime::object::{RuneIter, RuneIterKeys, RuneValues};
8use crate::runtime::{EnvProtocolCaller, Formatter, Object, Protocol, Value, VmError};
9use crate::{ContextError, Module};
10
11/// The dynamic [`Object`] container.
12///
13/// This modules contains the [`Object`] type, which is a dynamic type erased
14/// container.
15///
16/// Objects in Rune are declared using the special `#{}` syntax, but can also be
17/// interacted with through the fundamental [`Object`] type.
18///
19/// Fields can be added to objects "on the fly", simply by assigning to them:
20///
21/// ```rune
22/// let object = #{};
23/// object.hello = "World";
24/// assert_eq!(object.hello, "World");
25/// ```
26///
27/// # Examples
28///
29/// ```rune
30/// let object1 = #{hello: "World"};
31///
32/// let object2 = Object::new();
33/// object2.insert("hello", "World");
34///
35/// assert_eq!(object1, object2);
36/// ```
37#[rune::module(::std::object)]
38pub fn module() -> Result<Module, ContextError> {
39    let mut m = Module::from_meta(self::module__meta)?;
40
41    m.ty::<Object>()?;
42
43    m.function_meta(Object::new__meta)?;
44    m.function_meta(Object::with_capacity__meta)?;
45    m.function_meta(Object::len__meta)?;
46    m.function_meta(Object::is_empty__meta)?;
47    m.function_meta(Object::insert__meta)?;
48    m.function_meta(remove__meta)?;
49    m.function_meta(Object::clear__meta)?;
50    m.function_meta(contains_key__meta)?;
51    m.function_meta(get__meta)?;
52
53    m.function_meta(partial_eq__meta)?;
54    m.implement_trait::<Object>(rune::item!(::std::cmp::PartialEq))?;
55
56    m.function_meta(eq__meta)?;
57    m.implement_trait::<Object>(rune::item!(::std::cmp::Eq))?;
58
59    m.function_meta(clone__meta)?;
60    m.implement_trait::<Object>(rune::item!(::std::clone::Clone))?;
61
62    m.function_meta(debug_fmt__meta)?;
63
64    m.function_meta(Object::rune_iter__meta)?;
65    m.function_meta(Object::rune_keys__meta)?;
66    m.function_meta(Object::rune_values__meta)?;
67    m.associated_function(&Protocol::INTO_ITER, Object::rune_iter)?;
68
69    m.ty::<RuneIter>()?;
70    m.function_meta(RuneIter::next__meta)?;
71    m.function_meta(RuneIter::size_hint__meta)?;
72    m.implement_trait::<RuneIter>(rune::item!(::std::iter::Iterator))?;
73    m.function_meta(RuneIter::len__meta)?;
74    m.implement_trait::<RuneIter>(rune::item!(::std::iter::ExactSizeIterator))?;
75
76    m.ty::<RuneIterKeys>()?;
77    m.function_meta(RuneIterKeys::next__meta)?;
78    m.function_meta(RuneIterKeys::size_hint__meta)?;
79    m.implement_trait::<RuneIterKeys>(rune::item!(::std::iter::Iterator))?;
80    m.function_meta(RuneIterKeys::len__meta)?;
81    m.implement_trait::<RuneIterKeys>(rune::item!(::std::iter::ExactSizeIterator))?;
82
83    m.ty::<RuneValues>()?;
84    m.function_meta(RuneValues::next__meta)?;
85    m.function_meta(RuneValues::size_hint__meta)?;
86    m.implement_trait::<RuneValues>(rune::item!(::std::iter::Iterator))?;
87    m.function_meta(RuneValues::len__meta)?;
88    m.implement_trait::<RuneValues>(rune::item!(::std::iter::ExactSizeIterator))?;
89    Ok(m)
90}
91
92/// Returns `true` if the map contains a value for the specified key.
93///
94/// # Examples
95///
96/// ```rune
97/// let object = #{a: 42};
98/// assert!(object.contains_key("a"));
99/// ```
100#[rune::function(keep, instance)]
101#[inline]
102fn contains_key(object: &Object, key: &str) -> bool {
103    object.contains_key(key)
104}
105
106/// Removes a key from the map, returning the value at the key if the key was
107/// previously in the map.
108///
109/// # Examples
110///
111/// ```rune
112/// let object = #{a: 42};
113/// assert_eq!(object.remove("a"), Some(42));
114/// assert_eq!(object.remove("a"), None);
115/// ```
116#[rune::function(keep, instance)]
117#[inline]
118fn remove(object: &mut Object, key: &str) -> Option<Value> {
119    object.remove(key)
120}
121
122/// Returns a reference to the value corresponding to the key.
123///
124/// # Examples
125///
126/// ```rune
127/// let object = #{a: 42};
128/// assert_eq!(object.get("a"), Some(42));
129/// assert_eq!(object.get("b"), None);
130/// ```
131#[rune::function(keep, instance)]
132#[inline]
133fn get(object: &Object, key: &str) -> Option<Value> {
134    object.get(key).cloned()
135}
136
137/// Test two objects for partial equality.
138///
139/// # Examples
140///
141/// ```rune
142/// let a = #{a: 42};
143/// let b = #{a: 43};
144///
145/// assert_eq!(a, a);
146/// assert_ne!(a, b);
147/// assert_ne!(b, a);
148/// ```
149#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
150fn partial_eq(this: &Object, other: &Object) -> Result<bool, VmError> {
151    Object::partial_eq_with(this, other, &mut EnvProtocolCaller)
152}
153
154/// Test two objects for total equality.
155///
156/// # Examples
157///
158/// ```rune
159/// use std::ops::eq;
160///
161/// let a = #{a: 42};
162/// let b = #{a: 43};
163///
164/// assert_eq!(eq(a, a), true);
165/// assert_eq!(eq(a, b), false);
166/// assert_eq!(eq(b, a), false);
167/// ```
168#[rune::function(keep, instance, protocol = EQ)]
169fn eq(this: &Object, other: &Object) -> Result<bool, VmError> {
170    Object::eq_with(this, other, Value::eq_with, &mut EnvProtocolCaller)
171}
172
173/// Clones an object.
174///
175/// # Examples
176///
177/// ```rune
178/// let a = #{a: 42};
179/// let b = a.clone();
180/// assert_eq!(a, b);
181///
182/// b.b = 43;
183/// assert_ne!(a, b);
184/// ```
185#[rune::function(keep, instance, protocol = CLONE)]
186fn clone(this: &Object) -> alloc::Result<Object> {
187    this.try_clone()
188}
189
190/// Write a debug representation of an object.
191///
192/// # Examples
193///
194/// ```rune
195/// let a = #{a: 42, b: 43};
196///
197/// println!("{a:?}");
198/// ```
199#[rune::function(keep, instance, protocol = DEBUG_FMT)]
200#[inline]
201fn debug_fmt(this: &Object, f: &mut Formatter) -> alloc::Result<()> {
202    write!(f, "{this:?}")
203}