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}