rune/modules/collections/
hash_map.rs

1use crate as rune;
2use crate::alloc::fmt::TryWrite;
3use crate::alloc::prelude::*;
4use crate::hashbrown::{IterRef, KeysRef, Table, ValuesRef};
5use crate::runtime::{
6    EnvProtocolCaller, Formatter, FromValue, Iterator, ProtocolCaller, Ref, Value, VmErrorKind,
7    VmResult,
8};
9use crate::{Any, ContextError, Module};
10
11/// A dynamic hash map.
12#[rune::module(::std::collections::hash_map)]
13pub fn module() -> Result<Module, ContextError> {
14    let mut m = Module::from_meta(self::module_meta)?;
15
16    m.ty::<HashMap>()?;
17    m.function_meta(HashMap::new__meta)?;
18    m.function_meta(HashMap::with_capacity__meta)?;
19    m.function_meta(HashMap::len__meta)?;
20    m.function_meta(HashMap::capacity__meta)?;
21    m.function_meta(HashMap::insert__meta)?;
22    m.function_meta(HashMap::get__meta)?;
23    m.function_meta(HashMap::contains_key__meta)?;
24    m.function_meta(HashMap::remove__meta)?;
25    m.function_meta(HashMap::clear__meta)?;
26    m.function_meta(HashMap::is_empty__meta)?;
27    m.function_meta(HashMap::iter__meta)?;
28    m.function_meta(HashMap::into_iter__meta)?;
29    m.function_meta(HashMap::from_iter__meta)?;
30    m.function_meta(HashMap::keys__meta)?;
31    m.function_meta(HashMap::values__meta)?;
32    m.function_meta(HashMap::extend__meta)?;
33    m.function_meta(HashMap::index_set__meta)?;
34    m.function_meta(HashMap::index_get__meta)?;
35    m.function_meta(HashMap::debug_fmt__meta)?;
36
37    m.function_meta(HashMap::clone__meta)?;
38    m.implement_trait::<HashMap>(rune::item!(::std::clone::Clone))?;
39
40    m.function_meta(HashMap::partial_eq__meta)?;
41    m.implement_trait::<HashMap>(rune::item!(::std::cmp::PartialEq))?;
42
43    m.function_meta(HashMap::eq__meta)?;
44    m.implement_trait::<HashMap>(rune::item!(::std::cmp::Eq))?;
45
46    m.ty::<Iter>()?;
47    m.function_meta(Iter::next)?;
48    m.function_meta(Iter::size_hint)?;
49    m.implement_trait::<Iter>(rune::item!(::std::iter::Iterator))?;
50
51    m.ty::<Keys>()?;
52    m.function_meta(Keys::next)?;
53    m.function_meta(Keys::size_hint)?;
54    m.implement_trait::<Keys>(rune::item!(::std::iter::Iterator))?;
55
56    m.ty::<Values>()?;
57    m.function_meta(Values::next)?;
58    m.function_meta(Values::size_hint)?;
59    m.implement_trait::<Values>(rune::item!(::std::iter::Iterator))?;
60
61    Ok(m)
62}
63
64/// A [hash map] implemented with quadratic probing and SIMD lookup.
65///
66/// By default, `HashMap` uses a hashing algorithm selected to provide
67/// resistance against HashDoS attacks. The algorithm is randomly seeded, and a
68/// reasonable best-effort is made to generate this seed from a high quality,
69/// secure source of randomness provided by the host without blocking the
70/// program. Because of this, the randomness of the seed depends on the output
71/// quality of the system's random number coroutine when the seed is created. In
72/// particular, seeds generated when the system's entropy pool is abnormally low
73/// such as during system boot may be of a lower quality.
74///
75/// The default hashing algorithm is currently SipHash 1-3, though this is
76/// subject to change at any point in the future. While its performance is very
77/// competitive for medium sized keys, other hashing algorithms will outperform
78/// it for small keys such as integers as well as large keys such as long
79/// strings, though those algorithms will typically *not* protect against
80/// attacks such as HashDoS.
81///
82/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
83/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods.
84/// There are many alternative [hashing algorithms available on crates.io].
85///
86/// It is required that the keys implement the [`EQ`] and [`HASH`] protocols. If
87/// you implement these yourself, it is important that the following property
88/// holds:
89///
90/// ```text
91/// k1 == k2 -> hash(k1) == hash(k2)
92/// ```
93///
94/// In other words, if two keys are equal, their hashes must be equal. Violating
95/// this property is a logic error.
96///
97/// It is also a logic error for a key to be modified in such a way that the
98/// key's hash, as determined by the [`HASH`] protocol, or its equality, as
99/// determined by the [`EQ`] protocol, changes while it is in the map. This is
100/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
101/// unsafe code.
102///
103/// The behavior resulting from either logic error is not specified, but will be
104/// encapsulated to the `HashMap` that observed the logic error and not result
105/// in undefined behavior. This could include panics, incorrect results, aborts,
106/// memory leaks, and non-termination.
107///
108/// The hash table implementation is a Rust port of Google's [SwissTable]. The
109/// original C++ version of SwissTable can be found [here], and this [CppCon
110/// talk] gives an overview of how the algorithm works.
111///
112/// [hash map]: crate::collections#use-a-hashmap-when
113/// [hashing algorithms available on crates.io]: https://crates.io/keywords/hasher
114/// [SwissTable]: https://abseil.io/blog/20180927-swisstables
115/// [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
116/// [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
117///
118/// # Examples
119///
120/// ```rune
121/// use std::collections::HashMap;
122///
123/// enum Tile {
124///     Wall,
125/// }
126///
127/// let m = HashMap::new();
128///
129/// m.insert((0, 1), Tile::Wall);
130/// m[(0, 3)] = 5;
131///
132/// assert_eq!(m.get((0, 1)), Some(Tile::Wall));
133/// assert_eq!(m.get((0, 2)), None);
134/// assert_eq!(m[(0, 3)], 5);
135/// ```
136#[derive(Any)]
137#[rune(item = ::std::collections::hash_map)]
138pub(crate) struct HashMap {
139    table: Table<Value>,
140}
141
142impl HashMap {
143    /// Creates an empty `HashMap`.
144    ///
145    /// The hash map is initially created with a capacity of 0, so it will not
146    /// allocate until it is first inserted into.
147    ///
148    /// # Examples
149    ///
150    /// ```rune
151    /// use std::collections::HashMap;
152    /// let map = HashMap::new();
153    /// ```
154    #[rune::function(keep, path = Self::new)]
155    fn new() -> Self {
156        Self {
157            table: Table::new(),
158        }
159    }
160
161    /// Creates an empty `HashMap` with at least the specified capacity.
162    ///
163    /// The hash map will be able to hold at least `capacity` elements without
164    /// reallocating. This method is allowed to allocate for more elements than
165    /// `capacity`. If `capacity` is 0, the hash map will not allocate.
166    ///
167    /// # Examples
168    ///
169    /// ```rune
170    /// use std::collections::HashMap;
171    /// let map = HashMap::with_capacity(10);
172    /// ```
173    #[rune::function(keep, path = Self::with_capacity)]
174    pub(crate) fn with_capacity(capacity: usize) -> VmResult<Self> {
175        VmResult::Ok(Self {
176            table: vm_try!(Table::try_with_capacity(capacity)),
177        })
178    }
179
180    /// Returns the number of elements in the map.
181    ///
182    /// # Examples
183    ///
184    /// ```rune
185    /// use std::collections::HashMap;
186    ///
187    /// let a = HashMap::new();
188    /// assert_eq!(a.len(), 0);
189    /// a.insert(1, "a");
190    /// assert_eq!(a.len(), 1);
191    /// ```
192    #[rune::function(keep)]
193    fn len(&self) -> usize {
194        self.table.len()
195    }
196
197    /// Returns the number of elements the map can hold without reallocating.
198    ///
199    /// This number is a lower bound; the `HashMap<K, V>` might be able to hold
200    /// more, but is guaranteed to be able to hold at least this many.
201    ///
202    /// # Examples
203    ///
204    /// ```rune
205    /// use std::collections::HashMap;
206    /// let map = HashMap::with_capacity(100);
207    /// assert!(map.capacity() >= 100);
208    /// ```
209    #[rune::function(keep)]
210    fn capacity(&self) -> usize {
211        self.table.capacity()
212    }
213
214    /// Returns `true` if the map contains no elements.
215    ///
216    /// # Examples
217    ///
218    /// ```rune
219    /// use std::collections::HashMap;
220    ///
221    /// let a = HashMap::new();
222    /// assert!(a.is_empty());
223    /// a.insert(1, "a");
224    /// assert!(!a.is_empty());
225    /// ```
226    #[rune::function(keep)]
227    fn is_empty(&self) -> bool {
228        self.table.is_empty()
229    }
230
231    /// Inserts a key-value pair into the map.
232    ///
233    /// If the map did not have this key present, [`None`] is returned.
234    ///
235    /// If the map did have this key present, the value is updated, and the old
236    /// value is returned. The key is not updated, though; this matters for
237    /// types that can be `==` without being identical. See the [module-level
238    /// documentation] for more.
239    ///
240    /// [module-level documentation]: crate::collections#insert-and-complex-keys
241    ///
242    /// # Examples
243    ///
244    /// ```rune
245    /// use std::collections::HashMap;
246    ///
247    /// let map = HashMap::new();
248    /// assert_eq!(map.insert(37, "a"), None);
249    /// assert_eq!(map.is_empty(), false);
250    ///
251    /// map.insert(37, "b");
252    /// assert_eq!(map.insert(37, "c"), Some("b"));
253    /// assert_eq!(map[37], "c");
254    /// ```
255    #[rune::function(keep)]
256    pub(crate) fn insert(&mut self, key: Value, value: Value) -> VmResult<Option<Value>> {
257        let mut caller = EnvProtocolCaller;
258        self.table.insert_with(key, value, &mut caller)
259    }
260
261    /// Returns the value corresponding to the [`Key`].
262    ///
263    /// # Examples
264    ///
265    /// ```rune
266    /// use std::collections::HashMap;
267    ///
268    /// let map = HashMap::new();
269    /// map.insert(1, "a");
270    /// assert_eq!(map.get(1), Some("a"));
271    /// assert_eq!(map.get(2), None);
272    /// ```
273    #[rune::function(keep)]
274    fn get(&self, key: Value) -> VmResult<Option<Value>> {
275        let mut caller = EnvProtocolCaller;
276        VmResult::Ok(vm_try!(self.table.get(&key, &mut caller)).map(|(_, v)| v.clone()))
277    }
278
279    /// Returns `true` if the map contains a value for the specified [`Key`].
280    ///
281    /// # Examples
282    ///
283    /// ```rune
284    /// use std::collections::HashMap;
285    ///
286    /// let map = HashMap::new();
287    /// map.insert(1, "a");
288    /// assert_eq!(map.contains_key(1), true);
289    /// assert_eq!(map.contains_key(2), false);
290    /// ```
291    #[rune::function(keep)]
292    fn contains_key(&self, key: Value) -> VmResult<bool> {
293        let mut caller = EnvProtocolCaller;
294        VmResult::Ok(vm_try!(self.table.get(&key, &mut caller)).is_some())
295    }
296
297    /// Removes a key from the map, returning the value at the [`Key`] if the
298    /// key was previously in the map.
299    ///
300    /// # Examples
301    ///
302    /// ```rune
303    /// use std::collections::HashMap;
304    ///
305    /// let map = HashMap::new();
306    /// map.insert(1, "a");
307    /// assert_eq!(map.remove(1), Some("a"));
308    /// assert_eq!(map.remove(1), None);
309    /// ```
310    #[rune::function(keep)]
311    fn remove(&mut self, key: Value) -> VmResult<Option<Value>> {
312        let mut caller = EnvProtocolCaller;
313        self.table.remove_with(&key, &mut caller)
314    }
315
316    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
317    /// for reuse.
318    ///
319    /// # Examples
320    ///
321    /// ```rune
322    /// use std::collections::HashMap;
323    ///
324    /// let a = HashMap::new();
325    /// a.insert(1, "a");
326    /// a.clear();
327    /// assert!(a.is_empty());
328    /// ```
329    #[rune::function(keep)]
330    fn clear(&mut self) {
331        self.table.clear()
332    }
333
334    /// An iterator visiting all key-value pairs in arbitrary order.
335    ///
336    /// # Examples
337    ///
338    /// ```rune
339    /// use std::collections::HashMap;
340    ///
341    /// let map = HashMap::from_iter([
342    ///     ("a", 1),
343    ///     ("b", 2),
344    ///     ("c", 3),
345    /// ]);
346    ///
347    /// let pairs = map.iter().collect::<Vec>();
348    /// pairs.sort();
349    /// assert_eq!(pairs, [("a", 1), ("b", 2), ("c", 3)]);
350    /// ```
351    ///
352    /// # Performance
353    ///
354    /// In the current implementation, iterating over map takes O(capacity) time
355    /// instead of O(len) because it internally visits empty buckets too.
356    #[rune::function(keep, instance, path = Self::iter)]
357    fn iter(this: Ref<Self>) -> Iter {
358        let iter = Table::iter_ref(Ref::map(this, |this| &this.table));
359        Iter { iter }
360    }
361
362    /// An iterator visiting all keys in arbitrary order.
363    ///
364    /// # Examples
365    ///
366    /// ```rune
367    /// use std::collections::HashMap;
368    ///
369    /// let map = HashMap::from_iter([
370    ///     ("a", 1),
371    ///     ("b", 2),
372    ///     ("c", 3),
373    /// ]);
374    ///
375    /// let keys = map.keys().collect::<Vec>();
376    /// keys.sort();
377    /// assert_eq!(keys, ["a", "b", "c"]);
378    /// ```
379    ///
380    /// # Performance
381    ///
382    /// In the current implementation, iterating over keys takes O(capacity)
383    /// time instead of O(len) because it internally visits empty buckets too.
384    #[rune::function(keep, instance, path = Self::keys)]
385    fn keys(this: Ref<Self>) -> Keys {
386        let iter = Table::keys_ref(Ref::map(this, |this| &this.table));
387
388        Keys { iter }
389    }
390
391    /// An iterator visiting all values in arbitrary order.
392    ///
393    /// # Examples
394    ///
395    /// ```rune
396    /// use std::collections::HashMap;
397    ///
398    /// let map = HashMap::from_iter([
399    ///     ("a", 1),
400    ///     ("b", 2),
401    ///     ("c", 3),
402    /// ]);
403    ///
404    /// let values = map.values().collect::<Vec>();
405    /// values.sort();
406    /// assert_eq!(values, [1, 2, 3]);
407    /// ```
408    ///
409    /// # Performance
410    ///
411    /// In the current implementation, iterating over values takes O(capacity)
412    /// time instead of O(len) because it internally visits empty buckets too.
413    #[rune::function(keep, instance, path = Self::values)]
414    fn values(this: Ref<Self>) -> Values {
415        let iter = Table::values_ref(Ref::map(this, |this| &this.table));
416
417        Values { iter }
418    }
419
420    /// Extend this map from an iterator.
421    ///
422    /// # Examples
423    ///
424    /// ```rune
425    /// use std::collections::HashMap;
426    ///
427    /// let map = HashMap::new();
428    ///
429    /// map.extend([
430    ///     ("a", 1),
431    ///     ("b", 2),
432    ///     ("c", 3),
433    /// ]);
434    /// ```
435    #[rune::function(keep)]
436    fn extend(&mut self, value: Value) -> VmResult<()> {
437        let mut it = vm_try!(value.into_iter());
438
439        while let Some(value) = vm_try!(it.next()) {
440            let (key, value) = vm_try!(<(Value, Value)>::from_value(value));
441            vm_try!(self.insert(key, value));
442        }
443
444        VmResult::Ok(())
445    }
446
447    /// Clone the map.
448    ///
449    /// # Examples
450    ///
451    /// ```rune
452    /// use std::collections::HashMap;
453    ///
454    /// let a = HashMap::from_iter([
455    ///     ("a", 1),
456    ///     ("b", 2),
457    /// ]);
458    ///
459    /// let b = a.clone();
460    ///
461    /// b.insert("c", 3);
462    ///
463    /// assert_eq!(a.len(), 2);
464    /// assert_eq!(b.len(), 3);
465    /// ```
466    #[rune::function(keep, instance, path = Self::clone, protocol = CLONE)]
467    fn clone(this: &HashMap) -> VmResult<HashMap> {
468        VmResult::Ok(Self {
469            table: vm_try!(this.table.try_clone()),
470        })
471    }
472
473    /// Convert a hashmap from a value convert into an iterator.
474    ///
475    /// The hashmap can be converted from anything that implements the
476    /// [`INTO_ITER`] protocol, and each item produces should be a tuple pair.
477    ///
478    /// # Examples
479    ///
480    /// ```rune
481    /// use std::collections::HashMap;
482    ///
483    /// let map = HashMap::from_iter([("a", 1), ("b", 2)]);
484    /// assert_eq!(map.len(), 2);
485    /// assert_eq!(map.get("a"), Some(1));
486    /// assert_eq!(map.get("b"), Some(2));
487    /// ```
488    #[rune::function(keep, path = Self::from_iter)]
489    fn from_iter(it: Iterator) -> VmResult<HashMap> {
490        let mut caller = EnvProtocolCaller;
491        Self::from_iter_with(it, &mut caller)
492    }
493
494    pub(crate) fn from_iter_with(
495        mut it: Iterator,
496        caller: &mut dyn ProtocolCaller,
497    ) -> VmResult<Self> {
498        let mut map = Self::new();
499
500        while let Some(value) = vm_try!(it.next()) {
501            let (key, value) = vm_try!(<(Value, Value)>::from_value(value));
502            vm_try!(map.table.insert_with(key, value, caller));
503        }
504
505        VmResult::Ok(map)
506    }
507
508    /// Inserts a key-value pair into the map.
509    ///
510    /// If the map did have this key present, the value is updated.
511    ///
512    /// [module-level documentation]: crate::collections#insert-and-complex-keys
513    ///
514    /// # Examples
515    ///
516    /// ```rune
517    /// use std::collections::HashMap;
518    ///
519    /// let map = HashMap::new();
520    /// map[37] = "a";
521    /// assert!(!map.is_empty());
522    ///
523    /// map[37] = "c";
524    /// assert_eq!(map[37], "c");
525    /// ```
526    #[rune::function(keep, protocol = INDEX_SET)]
527    fn index_set(&mut self, key: Value, value: Value) -> VmResult<()> {
528        let _ = vm_try!(self.insert(key, value));
529        VmResult::Ok(())
530    }
531
532    /// Returns a the value corresponding to the key.
533    ///
534    /// # Panics
535    ///
536    /// Panics if the given value is not present in the map.
537    ///
538    /// ```rune,should_panic
539    /// use std::collections::HashMap;
540    ///
541    /// let map = HashMap::new();
542    /// let _ = map[1];
543    /// ```
544    ///
545    /// # Examples
546    ///
547    /// ```rune
548    /// use std::collections::HashMap;
549    ///
550    /// let map = HashMap::new();
551    /// map[1] = "a";
552    /// assert_eq!(map[1], "a");
553    /// ```
554    #[rune::function(keep, protocol = INDEX_GET)]
555    fn index_get(&self, key: Value) -> VmResult<Value> {
556        use crate::runtime::TypeOf;
557
558        let mut caller = EnvProtocolCaller;
559
560        let Some((_, value)) = vm_try!(self.table.get(&key, &mut caller)) else {
561            return VmResult::err(VmErrorKind::MissingIndexKey {
562                target: Self::type_info(),
563            });
564        };
565
566        VmResult::Ok(value.clone())
567    }
568
569    /// Debug format the current map.
570    ///
571    /// # Examples
572    ///
573    /// ```rune
574    /// use std::collections::HashMap;
575    ///
576    /// let map = HashMap::new();
577    /// map[1] = "a";
578    ///
579    /// assert_eq!(format!("{:?}", map), "{1: \"a\"}");
580    /// ```
581    #[rune::function(keep, protocol = DEBUG_FMT)]
582    fn debug_fmt(&self, f: &mut Formatter) -> VmResult<()> {
583        self.debug_fmt_with(f, &mut EnvProtocolCaller)
584    }
585
586    pub(crate) fn debug_fmt_with(
587        &self,
588        f: &mut Formatter,
589        caller: &mut dyn ProtocolCaller,
590    ) -> VmResult<()> {
591        vm_try!(vm_write!(f, "{{"));
592
593        let mut it = self.table.iter().peekable();
594
595        while let Some((key, value)) = it.next() {
596            vm_try!(key.debug_fmt_with(f, caller));
597            vm_try!(vm_write!(f, ": "));
598            vm_try!(value.debug_fmt_with(f, caller));
599
600            if it.peek().is_some() {
601                vm_try!(vm_write!(f, ", "));
602            }
603        }
604
605        vm_try!(vm_write!(f, "}}"));
606        VmResult::Ok(())
607    }
608
609    /// Perform a partial equality check over two maps.
610    ///
611    /// # Examples
612    ///
613    /// ```rune
614    /// use std::collections::HashMap;
615    ///
616    /// let map1 = HashMap::from_iter([
617    ///     ("a", 1.0),
618    ///     ("c", 3.0),
619    ///     ("b", 2.0),
620    /// ]);
621    ///
622    /// let map2 = HashMap::from_iter([
623    ///     ("c", 3.0),
624    ///     ("a", 1.0),
625    ///     ("b", 2.0),
626    /// ]);
627    ///
628    /// assert!(map1 == map2);
629    ///
630    /// map1["b"] = f64::NAN;
631    /// map2["b"] = f64::NAN;
632    ///
633    /// assert!(map1 != map2);
634    /// ```
635    #[rune::function(keep, protocol = PARTIAL_EQ)]
636    fn partial_eq(&self, other: &Self) -> VmResult<bool> {
637        self.partial_eq_with(other, &mut EnvProtocolCaller)
638    }
639
640    fn partial_eq_with(&self, other: &Self, caller: &mut dyn ProtocolCaller) -> VmResult<bool> {
641        if self.table.len() != other.table.len() {
642            return VmResult::Ok(false);
643        }
644
645        for (k, v1) in self.table.iter() {
646            let Some((_, v2)) = vm_try!(other.table.get(k, caller)) else {
647                return VmResult::Ok(false);
648            };
649
650            if !vm_try!(Value::partial_eq_with(v1, v2, caller)) {
651                return VmResult::Ok(false);
652            }
653        }
654
655        VmResult::Ok(true)
656    }
657
658    /// Perform a total equality check over two maps.
659    ///
660    /// # Examples
661    ///
662    /// ```rune
663    /// use std::collections::HashMap;
664    /// use std::ops::eq;
665    ///
666    /// let map1 = HashMap::from_iter([
667    ///     ("a", 1),
668    ///     ("c", 3),
669    ///     ("b", 2),
670    /// ]);
671    ///
672    /// let map2 = HashMap::from_iter([
673    ///     ("c", 3),
674    ///     ("a", 1),
675    ///     ("b", 2),
676    /// ]);
677    ///
678    /// assert!(eq(map1, map2));
679    /// ```
680    #[rune::function(keep, protocol = EQ)]
681    fn eq(&self, other: &Self) -> VmResult<bool> {
682        self.eq_with(other, &mut EnvProtocolCaller)
683    }
684
685    fn eq_with(&self, other: &Self, caller: &mut EnvProtocolCaller) -> VmResult<bool> {
686        if self.table.len() != other.table.len() {
687            return VmResult::Ok(false);
688        }
689
690        for (k, v1) in self.table.iter() {
691            let Some((_, v2)) = vm_try!(other.table.get(k, caller)) else {
692                return VmResult::Ok(false);
693            };
694
695            if !vm_try!(Value::eq_with(v1, v2, caller)) {
696                return VmResult::Ok(false);
697            }
698        }
699
700        VmResult::Ok(true)
701    }
702
703    /// An iterator visiting all key-value pairs in arbitrary order.
704    ///
705    /// # Examples
706    ///
707    /// ```rune
708    /// use std::collections::HashMap;
709    ///
710    /// let map = HashMap::from_iter([
711    ///     ("a", 1),
712    ///     ("b", 2),
713    ///     ("c", 3),
714    /// ]);
715    ///
716    /// let pairs = [];
717    ///
718    /// for pair in map {
719    ///     pairs.push(pair);
720    /// }
721    ///
722    /// pairs.sort();
723    /// assert_eq!(pairs, [("a", 1), ("b", 2), ("c", 3)]);
724    /// ```
725    ///
726    /// # Performance
727    ///
728    /// In the current implementation, iterating over map takes O(capacity) time
729    /// instead of O(len) because it internally visits empty buckets too.
730    #[rune::function(keep, instance, protocol = INTO_ITER, path = Self)]
731    fn into_iter(this: Ref<Self>) -> Iter {
732        Self::iter(this)
733    }
734}
735
736/// An iterator over a hash map.
737#[derive(Any)]
738#[rune(item = ::std::collections::hash_map)]
739pub(crate) struct Iter {
740    iter: IterRef<Value>,
741}
742
743impl Iter {
744    #[rune::function(instance, protocol = NEXT)]
745    fn next(&mut self) -> Option<(Value, Value)> {
746        self.iter.next()
747    }
748
749    #[rune::function(instance, protocol = SIZE_HINT)]
750    fn size_hint(&self) -> (usize, Option<usize>) {
751        self.iter.size_hint()
752    }
753}
754
755/// An iterator over a the keys in a hash map.
756#[derive(Any)]
757#[rune(item = ::std::collections::hash_map)]
758pub(crate) struct Keys {
759    iter: KeysRef<Value>,
760}
761
762impl Keys {
763    #[rune::function(instance, protocol = NEXT)]
764    fn next(&mut self) -> Option<Value> {
765        self.iter.next()
766    }
767
768    #[rune::function(instance, protocol = SIZE_HINT)]
769    fn size_hint(&self) -> (usize, Option<usize>) {
770        self.iter.size_hint()
771    }
772}
773
774/// An iterator over a the values in a hash map.
775#[derive(Any)]
776#[rune(item = ::std::collections::hash_map)]
777pub(crate) struct Values {
778    iter: ValuesRef<Value>,
779}
780
781impl Values {
782    #[rune::function(instance, protocol = NEXT)]
783    fn next(&mut self) -> Option<Value> {
784        self.iter.next()
785    }
786
787    #[rune::function(instance, protocol = SIZE_HINT)]
788    fn size_hint(&self) -> (usize, Option<usize>) {
789        self.iter.size_hint()
790    }
791}