stable_map/into_iter.rs
1#[cfg(test)]
2mod tests;
3
4use {
5 crate::{
6 linear_storage::LinearStorage,
7 pos_vec::pos::{InUse, Pos},
8 },
9 core::{
10 fmt::{Debug, Formatter},
11 iter::FusedIterator,
12 },
13 hashbrown::hash_map,
14};
15
16/// An owning iterator over the entries of a `StableMap` in arbitrary order.
17/// The iterator element type is `(K, V)`.
18///
19/// This `struct` is created by the [`into_iter`] method on [`StableMap`]
20/// (provided by the [`IntoIterator`] trait). See its documentation for more.
21/// The map cannot be used after calling that method.
22///
23/// [`into_iter`]: crate::StableMap::into_iter
24/// [`StableMap`]: crate::StableMap
25/// [`IntoIterator`]: https://doc.rust-lang.org/core/iter/trait.IntoIterator.html
26///
27/// # Examples
28///
29/// ```
30/// use stable_map::StableMap;
31///
32/// let map: StableMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into();
33///
34/// let mut iter = map.into_iter();
35/// let mut vec = vec![iter.next(), iter.next(), iter.next()];
36///
37/// // The `IntoIter` iterator produces items in arbitrary order, so the
38/// // items must be sorted to test them against a sorted array.
39/// vec.sort_unstable();
40/// assert_eq!(vec, [Some((1, "a")), Some((2, "b")), Some((3, "c"))]);
41///
42/// // It is fused iterator
43/// assert_eq!(iter.next(), None);
44/// assert_eq!(iter.next(), None);
45/// ```
46pub struct IntoIter<K, V> {
47 pub(crate) iter: hash_map::IntoIter<K, Pos<InUse>>,
48 pub(crate) storage: LinearStorage<V>,
49}
50
51impl<K, V> Iterator for IntoIter<K, V> {
52 type Item = (K, V);
53
54 fn next(&mut self) -> Option<Self::Item> {
55 let (k, pos) = self.iter.next()?;
56 let v = unsafe {
57 // SAFETY:
58 // - By the invariants, pos is valid.
59 self.storage.take_unchecked(pos)
60 };
61 Some((k, v))
62 }
63
64 fn size_hint(&self) -> (usize, Option<usize>) {
65 self.iter.size_hint()
66 }
67}
68
69impl<K, V> Debug for IntoIter<K, V> {
70 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
71 f.debug_struct("IntoIter").finish_non_exhaustive()
72 }
73}
74
75impl<K, V> FusedIterator for IntoIter<K, V> {}
76
77impl<K, V> ExactSizeIterator for IntoIter<K, V> {
78 fn len(&self) -> usize {
79 self.iter.len()
80 }
81}
82
83impl<K, V> Default for IntoIter<K, V> {
84 fn default() -> Self {
85 Self {
86 iter: Default::default(),
87 storage: LinearStorage::with_capacity(0),
88 }
89 }
90}
91
92// SAFETY:
93// - This impl is required because Pos<InUse>, Pos<Stored> allow for conflicting access
94// but this API prevents this.
95unsafe impl<K, V> Send for IntoIter<K, V>
96where
97 K: Send,
98 V: Send,
99{
100}
101
102// SAFETY:
103// - This impl is required because Pos<InUse>, Pos<Stored> allow for conflicting access
104// but this API prevents this.
105unsafe impl<K, V> Sync for IntoIter<K, V>
106where
107 K: Sync,
108 V: Sync,
109{
110}