rune/modules/
object.rs

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