Skip to main content

rune/runtime/
object.rs

1use core::borrow;
2use core::cmp;
3use core::fmt;
4use core::hash;
5use core::iter;
6
7use rune_alloc::hashbrown::raw::RawIter;
8
9use crate as rune;
10use crate::alloc::hash_map;
11use crate::alloc::prelude::*;
12use crate::alloc::{self, String};
13use crate::runtime::{
14    Dismantle, FieldMap, FromValue, Handover, ProtocolCaller, RawAnyGuard, Ref, ToValue, Value,
15    VmError, Worklist,
16};
17use crate::Any;
18
19/// An owning iterator over the entries of a `Object`.
20///
21/// This `struct` is created by the [`into_iter`] method on [`Object`]
22/// (provided by the `IntoIterator` trait). See its documentation for more.
23///
24/// [`into_iter`]: struct.Object.html#method.into_iter
25/// [`Object`]: struct.Object.html
26pub type IntoIter = hash_map::IntoIter<String, Value>;
27
28/// A mutable iterator over the entries of a `Object`.
29///
30/// This `struct` is created by the [`iter_mut`] method on [`Object`]. See its
31/// documentation for more.
32///
33/// [`iter_mut`]: struct.Object.html#method.iter_mut
34/// [`Object`]: struct.Object.html
35pub type IterMut<'a> = hash_map::IterMut<'a, String, Value>;
36
37/// An iterator over the entries of a `Object`.
38///
39/// This `struct` is created by the [`iter`] method on [`Object`]. See its
40/// documentation for more.
41///
42/// [`iter`]: struct.Object.html#method.iter
43/// [`Object`]: struct.Object.html
44pub type Iter<'a> = hash_map::Iter<'a, String, Value>;
45
46/// An iterator over the keys of a `HashMap`.
47///
48/// This `struct` is created by the [`keys`] method on [`Object`]. See its
49/// documentation for more.
50///
51/// [`keys`]: struct.Object.html#method.keys
52/// [`Object`]: struct.Object.html
53pub type Keys<'a> = hash_map::Keys<'a, String, Value>;
54
55/// An iterator over the values of a `HashMap`.
56///
57/// This `struct` is created by the [`values`] method on [`Object`]. See its
58/// documentation for more.
59///
60/// [`values`]: struct.Object.html#method.values
61/// [`Object`]: struct.Object.html
62pub type Values<'a> = hash_map::Values<'a, String, Value>;
63
64/// Struct representing a dynamic anonymous object.
65///
66/// # Rust Examples
67///
68/// ```rust
69/// use rune::alloc::String;
70///
71/// let mut object = rune::runtime::Object::new();
72/// assert!(object.is_empty());
73///
74/// object.insert_value(String::try_from("foo")?, 42)?;
75/// object.insert_value(String::try_from("bar")?, true)?;
76/// assert_eq!(2, object.len());
77///
78/// assert_eq!(Some(42), object.get_value("foo")?);
79/// assert_eq!(Some(true), object.get_value("bar")?);
80/// assert_eq!(None::<bool>, object.get_value("baz")?);
81/// # Ok::<_, rune::support::Error>(())
82/// ```
83#[derive(Any, Default)]
84#[repr(transparent)]
85#[rune(item = ::std::object, dismantle)]
86pub struct Object {
87    inner: FieldMap<String, Value>,
88}
89
90/// An object is made of the values put into it, and a script can nest one
91/// inside another without any bound, so it hands over what it is made of rather
92/// than being dropped in place.
93impl Dismantle for Object {
94    fn dismantle(&mut self, out: &mut Handover<'_>) {
95        // The map is emptied rather than walked in place, so that what it holds
96        // is handed over in one pass over it.
97        for (_, value) in core::mem::take(&mut self.inner) {
98            out.push(value);
99        }
100    }
101}
102
103impl Object {
104    /// Construct a new object.
105    ///
106    /// # Examples
107    ///
108    /// ```rune
109    /// let object = Object::new();
110    /// object.insert("Hello", "World");
111    /// ```
112    #[inline]
113    #[rune::function(keep, path = Self::new)]
114    pub fn new() -> Self {
115        Self {
116            inner: crate::runtime::new_field_map(),
117        }
118    }
119
120    /// Construct a new object with the given capacity.
121    ///
122    /// # Examples
123    ///
124    /// ```rune
125    /// let object = Object::with_capacity(16);
126    /// object.insert("Hello", "World");
127    /// ```
128    #[inline]
129    #[rune::function(keep, path = Self::with_capacity)]
130    pub fn with_capacity(capacity: usize) -> alloc::Result<Self> {
131        Ok(Self {
132            inner: crate::runtime::new_field_hash_map_with_capacity(capacity)?,
133        })
134    }
135
136    /// Returns the number of elements in the object.
137    ///
138    /// # Examples
139    ///
140    /// ```rune
141    /// let object = Object::with_capacity(16);
142    /// object.insert("Hello", "World");
143    /// assert_eq!(object.len(), 1);
144    /// ```
145    #[inline]
146    #[rune::function(keep)]
147    pub fn len(&self) -> usize {
148        self.inner.len()
149    }
150
151    /// Returns `true` if the object is empty.
152    ///
153    /// # Examples
154    ///
155    /// ```rune
156    /// let object = Object::with_capacity(16);
157    /// assert!(object.is_empty());
158    /// object.insert("Hello", "World");
159    /// assert!(!object.is_empty());
160    /// ```
161    #[inline]
162    #[rune::function(keep)]
163    pub fn is_empty(&self) -> bool {
164        self.inner.is_empty()
165    }
166
167    /// Returns a reference to the value corresponding to the key.
168    #[inline]
169    pub fn get<Q>(&self, k: &Q) -> Option<&Value>
170    where
171        String: borrow::Borrow<Q>,
172        Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
173    {
174        self.inner.get(k)
175    }
176
177    /// Get the given value at the given index.
178    pub fn get_value<Q, T>(&self, k: &Q) -> Result<Option<T>, VmError>
179    where
180        String: borrow::Borrow<Q>,
181        Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
182        T: FromValue,
183    {
184        let value = match self.inner.get(k) {
185            Some(value) => value.clone(),
186            None => return Ok(None),
187        };
188
189        Ok(Some(T::from_value(value)?))
190    }
191
192    /// Returns a mutable reference to the value corresponding to the key.
193    #[inline]
194    pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut Value>
195    where
196        String: borrow::Borrow<Q>,
197        Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
198    {
199        self.inner.get_mut(k)
200    }
201
202    /// Returns `true` if the map contains a value for the specified key.
203    #[inline]
204    pub fn contains_key<Q>(&self, k: &Q) -> bool
205    where
206        String: borrow::Borrow<Q>,
207        Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
208    {
209        self.inner.contains_key(k)
210    }
211
212    /// Removes a key from the map, returning the value at the key if the key
213    /// was previously in the map.
214    #[inline]
215    pub fn remove<Q>(&mut self, k: &Q) -> Option<Value>
216    where
217        String: borrow::Borrow<Q>,
218        Q: ?Sized + hash::Hash + cmp::Eq + cmp::Ord,
219    {
220        self.inner.remove(k)
221    }
222
223    /// Inserts a key-value pair into the dynamic object, converting it as
224    /// necessary through the [`ToValue`] trait.
225    #[inline]
226    pub fn insert_value<T>(&mut self, k: String, v: T) -> Result<(), VmError>
227    where
228        T: ToValue,
229    {
230        // Any value which was already there is taken apart rather than dropped
231        // in place. A native function has no worklist of its own to do that
232        // over, so it gets one which is empty - which costs nothing until it is
233        // handed a value made of other values.
234        if let Some(old) = self.inner.try_insert(k, v.to_value()?)? {
235            Worklist::new().dismantle(old);
236        }
237
238        Ok(())
239    }
240
241    /// Inserts a key-value pair into the map.
242    ///
243    /// If the map did not have this key present, `None` is returned.
244    ///
245    /// # Examples
246    ///
247    /// ```rune
248    /// let map = #{};
249    /// assert_eq!(map.insert("a", 1), None);
250    /// assert_eq!(map.is_empty(), false);
251    ///
252    /// map.insert("b", 2);
253    /// assert_eq!(map.insert("b", 3), Some(2));
254    /// assert_eq!(map["b"], 3);
255    /// ```
256    #[inline]
257    #[rune::function(keep, path = Self::insert)]
258    pub fn insert(&mut self, k: String, v: Value) -> alloc::Result<Option<Value>> {
259        self.inner.try_insert(k, v)
260    }
261
262    /// Take every value in the object apart rather than dropping them where
263    /// they are - see [`Worklist::dismantle`].
264    pub(crate) fn dismantle(&mut self, work: &mut Worklist) {
265        work.dismantle_all(self.inner.iter_mut().map(|(_, value)| value));
266        self.inner.clear();
267    }
268
269    /// Clears the object, removing all key-value pairs. Keeps the allocated
270    /// memory for reuse.
271    #[inline]
272    pub fn clear(&mut self) {
273        self.inner.clear();
274    }
275
276    /// Clears the object, removing all key-value pairs. Keeps the allocated
277    /// memory for reuse.
278    ///
279    /// The values are taken apart rather than dropped where they are - see
280    /// [`Object::dismantle`].
281    #[inline]
282    #[rune::function(keep, path = Self::clear)]
283    pub(crate) fn rune_clear(&mut self) {
284        self.dismantle(&mut Worklist::new());
285    }
286
287    /// An iterator visiting all key-value pairs in arbitrary order.
288    /// The iterator element type is `(&'a String, &'a Value)`.
289    pub fn iter(&self) -> Iter<'_> {
290        self.inner.iter()
291    }
292
293    /// An iterator visiting all keys in arbitrary order.
294    /// The iterator element type is `&'a String`.
295    pub fn keys(&self) -> Keys<'_> {
296        self.inner.keys()
297    }
298
299    /// An iterator visiting all values in arbitrary order.
300    /// The iterator element type is `&'a Value`.
301    pub fn values(&self) -> Values<'_> {
302        self.inner.values()
303    }
304
305    /// An iterator visiting all key-value pairs in arbitrary order,
306    /// with mutable references to the values.
307    ///
308    /// The iterator element type is `(&'a String, &'a mut Value)`.
309    pub fn iter_mut(&mut self) -> IterMut<'_> {
310        self.inner.iter_mut()
311    }
312
313    /// An iterator visiting all keys and values in arbitrary order.
314    ///
315    /// # Examples
316    ///
317    /// ```rune
318    /// let object = #{a: 1, b: 2, c: 3};
319    /// let vec = [];
320    ///
321    /// for key in object.iter() {
322    ///     vec.push(key);
323    /// }
324    ///
325    /// vec.sort_by(|a, b| a.0.cmp(b.0));
326    /// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]);
327    /// ```
328    #[rune::function(keep, path = Self::iter)]
329    pub fn rune_iter(this: Ref<Self>) -> RuneIter {
330        // SAFETY: we're holding onto the related reference guard, and making
331        // sure that it's dropped after the iterator.
332        let iter = unsafe { this.inner.raw_table().iter() };
333        let (_, guard) = Ref::into_raw(this);
334        RuneIter { iter, guard }
335    }
336
337    /// An iterator visiting all keys in arbitrary order.
338    ///
339    /// # Examples
340    ///
341    /// ```rune
342    /// let object = #{a: 1, b: 2, c: 3};
343    /// let vec = [];
344    ///
345    /// for key in object.keys() {
346    ///     vec.push(key);
347    /// }
348    ///
349    /// vec.sort_by(|a, b| a.cmp(b));
350    /// assert_eq!(vec, ["a", "b", "c"]);
351    /// ```
352    #[rune::function(keep, path = Self::keys)]
353    pub fn rune_keys(this: Ref<Self>) -> RuneIterKeys {
354        // SAFETY: we're holding onto the related reference guard, and making
355        // sure that it's dropped after the iterator.
356        let iter = unsafe { this.inner.raw_table().iter() };
357        let (_, guard) = Ref::into_raw(this);
358        RuneIterKeys { iter, guard }
359    }
360
361    /// An iterator visiting all values in arbitrary order.
362    ///
363    /// # Examples
364    ///
365    /// ```rune
366    /// let object = #{a: 1, b: 2, c: 3};
367    /// let vec = [];
368    ///
369    /// for key in object.values() {
370    ///     vec.push(key);
371    /// }
372    ///
373    /// vec.sort_by(|a, b| a.cmp(b));
374    /// assert_eq!(vec, [1, 2, 3]);
375    /// ```
376    #[rune::function(keep, path = Self::values)]
377    pub fn rune_values(this: Ref<Self>) -> RuneValues {
378        // SAFETY: we're holding onto the related reference guard, and making
379        // sure that it's dropped after the iterator.
380        let iter = unsafe { this.inner.raw_table().iter() };
381        let (_, guard) = Ref::into_raw(this);
382        RuneValues { iter, guard }
383    }
384
385    pub(crate) fn partial_eq_with(
386        a: &Self,
387        b: &Self,
388        caller: &mut dyn ProtocolCaller,
389    ) -> Result<bool, VmError> {
390        if a.len() != b.len() {
391            return Ok(false);
392        }
393
394        for (k1, v1) in a.iter() {
395            let Some(v2) = b.get(k1) else {
396                return Ok(false);
397            };
398
399            if !Value::partial_eq_with(v1, v2, caller)? {
400                return Ok(false);
401            }
402        }
403
404        Ok(true)
405    }
406
407    pub(crate) fn eq_with(
408        a: &Self,
409        b: &Self,
410        eq: fn(&Value, &Value, &mut dyn ProtocolCaller) -> Result<bool, VmError>,
411        caller: &mut dyn ProtocolCaller,
412    ) -> Result<bool, VmError> {
413        if a.inner.len() != b.inner.len() {
414            return Ok(false);
415        }
416
417        for (key, a) in a.inner.iter() {
418            let Some(b) = b.inner.get(key) else {
419                return Ok(false);
420            };
421
422            if !eq(a, b, caller)? {
423                return Ok(false);
424            }
425        }
426
427        Ok(true)
428    }
429}
430
431impl TryClone for Object {
432    fn try_clone(&self) -> alloc::Result<Self> {
433        Ok(Self {
434            inner: self.inner.try_clone()?,
435        })
436    }
437}
438
439impl<'a> IntoIterator for &'a Object {
440    type Item = (&'a String, &'a Value);
441    type IntoIter = Iter<'a>;
442
443    fn into_iter(self) -> Self::IntoIter {
444        self.iter()
445    }
446}
447
448impl<'a> IntoIterator for &'a mut Object {
449    type Item = (&'a String, &'a mut Value);
450    type IntoIter = IterMut<'a>;
451
452    fn into_iter(self) -> Self::IntoIter {
453        self.iter_mut()
454    }
455}
456
457impl IntoIterator for Object {
458    type Item = (String, Value);
459    type IntoIter = IntoIter;
460
461    /// Creates a consuming iterator, that is, one that moves each key-value
462    /// pair out of the object in arbitrary order. The object cannot be used
463    /// after calling this.
464    fn into_iter(self) -> Self::IntoIter {
465        self.inner.into_iter()
466    }
467}
468
469impl fmt::Debug for Object {
470    #[inline]
471    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472        f.debug_map().entries(self.inner.iter()).finish()
473    }
474}
475
476#[derive(Any)]
477#[rune(item = ::std::object, name = Iter, dismantle)]
478pub struct RuneIter {
479    iter: RawIter<(String, Value)>,
480    guard: RawAnyGuard,
481}
482
483/// The object is kept alive through a guard rather than through a slot, so
484/// taking the iterator apart releases the guard and hands the object over.
485impl Dismantle for RuneIter {
486    fn dismantle(&mut self, out: &mut Handover<'_>) {
487        out.consume_ref(&mut self.guard);
488    }
489}
490
491impl RuneIter {
492    #[rune::function(instance, keep, protocol = NEXT)]
493    pub fn next(&mut self) -> Result<Option<(String, Value)>, VmError> {
494        unsafe {
495            let Some(bucket) = self.iter.next() else {
496                return Ok(None);
497            };
498
499            let (key, value) = bucket.as_ref();
500            let key = key.try_clone()?;
501            Ok(Some((key, value.clone())))
502        }
503    }
504
505    #[rune::function(instance, keep, protocol = SIZE_HINT)]
506    pub fn size_hint(&self) -> (usize, Option<usize>) {
507        self.iter.size_hint()
508    }
509
510    #[rune::function(instance, keep, protocol = LEN)]
511    pub fn len(&self) -> usize {
512        self.iter.len()
513    }
514}
515
516impl iter::Iterator for RuneIter {
517    type Item = Result<(String, Value), VmError>;
518
519    #[inline]
520    fn next(&mut self) -> Option<Self::Item> {
521        match RuneIter::next(self) {
522            Ok(Some(value)) => Some(Ok(value)),
523            Ok(None) => None,
524            Err(err) => Some(Err(err)),
525        }
526    }
527}
528
529#[derive(Any)]
530#[rune(item = ::std::object, name = Keys, dismantle)]
531pub struct RuneIterKeys {
532    iter: RawIter<(String, Value)>,
533    guard: RawAnyGuard,
534}
535
536/// The object is kept alive through a guard rather than through a slot, so
537/// taking the iterator apart releases the guard and hands the object over.
538impl Dismantle for RuneIterKeys {
539    fn dismantle(&mut self, out: &mut Handover<'_>) {
540        out.consume_ref(&mut self.guard);
541    }
542}
543
544impl RuneIterKeys {
545    #[rune::function(instance, keep, protocol = NEXT)]
546    pub fn next(&mut self) -> Result<Option<String>, VmError> {
547        unsafe {
548            let Some(bucket) = self.iter.next() else {
549                return Ok(None);
550            };
551
552            let (key, _) = bucket.as_ref();
553            let key = key.try_clone()?;
554            Ok(Some(key))
555        }
556    }
557
558    #[rune::function(instance, keep, protocol = SIZE_HINT)]
559    pub fn size_hint(&self) -> (usize, Option<usize>) {
560        self.iter.size_hint()
561    }
562
563    #[rune::function(instance, keep, protocol = LEN)]
564    pub fn len(&self) -> usize {
565        self.iter.len()
566    }
567}
568
569impl iter::Iterator for RuneIterKeys {
570    type Item = Result<String, VmError>;
571
572    #[inline]
573    fn next(&mut self) -> Option<Self::Item> {
574        match RuneIterKeys::next(self) {
575            Ok(Some(value)) => Some(Ok(value)),
576            Ok(None) => None,
577            Err(err) => Some(Err(err)),
578        }
579    }
580}
581
582#[derive(Any)]
583#[rune(item = ::std::object, name = Values, dismantle)]
584pub struct RuneValues {
585    iter: RawIter<(String, Value)>,
586    guard: RawAnyGuard,
587}
588
589/// The object is kept alive through a guard rather than through a slot, so
590/// taking the iterator apart releases the guard and hands the object over.
591impl Dismantle for RuneValues {
592    fn dismantle(&mut self, out: &mut Handover<'_>) {
593        out.consume_ref(&mut self.guard);
594    }
595}
596
597impl RuneValues {
598    #[rune::function(instance, keep, protocol = NEXT)]
599    pub fn next(&mut self) -> Result<Option<Value>, VmError> {
600        unsafe {
601            let Some(bucket) = self.iter.next() else {
602                return Ok(None);
603            };
604
605            let (_, value) = bucket.as_ref();
606            Ok(Some(value.clone()))
607        }
608    }
609
610    #[rune::function(instance, keep, protocol = SIZE_HINT)]
611    pub fn size_hint(&self) -> (usize, Option<usize>) {
612        self.iter.size_hint()
613    }
614
615    #[rune::function(instance, keep, protocol = LEN)]
616    pub fn len(&self) -> usize {
617        self.iter.len()
618    }
619}
620
621impl iter::Iterator for RuneValues {
622    type Item = Result<Value, VmError>;
623
624    #[inline]
625    fn next(&mut self) -> Option<Self::Item> {
626        match RuneValues::next(self) {
627            Ok(Some(value)) => Some(Ok(value)),
628            Ok(None) => None,
629            Err(err) => Some(Err(err)),
630        }
631    }
632}