Skip to main content

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}