Skip to main content

linked_hash_table/
iter.rs

1//! Iterator types produced by [`LinkedHashMap`].
2//!
3//! All iterator structs are returned by methods on [`LinkedHashMap`]; you
4//! rarely need to name them explicitly.
5//!
6//! | Type | Created by | Yields |
7//! |------|-----------|--------|
8//! | [`Iter`] | [`iter`] | `(&K, &V)` |
9//! | [`IterMut`] | [`iter_mut`] | `(&K, &mut V)` |
10//! | [`Keys`] | [`keys`] | `&K` |
11//! | [`Values`] | [`values`] | `&V` |
12//! | [`ValuesMut`] | [`values_mut`] | `&mut V` |
13//! | [`Drain`] | [`drain`] | `(K, V)`: empties the map |
14//! | [`IntoIter`] | [`into_iter`] | `(K, V)`: consumes the map |
15//!
16//! [`LinkedHashMap`]: crate::LinkedHashMap
17//! [`iter`]: crate::LinkedHashMap::iter
18//! [`iter_mut`]: crate::LinkedHashMap::iter_mut
19//! [`keys`]: crate::LinkedHashMap::keys
20//! [`values`]: crate::LinkedHashMap::values
21//! [`values_mut`]: crate::LinkedHashMap::values_mut
22//! [`drain`]: crate::LinkedHashMap::drain
23//! [`into_iter`]: crate::LinkedHashMap::into_iter
24
25use std::marker::PhantomData;
26use std::ptr::NonNull;
27
28use crate::node::Node;
29
30/// Iterator over `(&K, &V)` pairs in insertion order.
31///
32/// Created by [`LinkedHashMap::iter`](crate::LinkedHashMap::iter).
33pub struct Iter<'a, K, V> {
34    pub(crate) front: *const Node<K, V>,
35    pub(crate) back: *const Node<K, V>,
36    pub(crate) len: usize,
37    // The `PhantomData` ensures that the output references are properly
38    // constrained by the lifetime of the `&LinkedHashMap` that created this iterator.
39    pub(crate) _marker: PhantomData<(&'a K, &'a V)>,
40}
41
42// SAFETY: `Iter` only holds raw traversal pointers plus PhantomData tying
43// yielded references to `'a`. Sending/sharing the iterator is safe when
44// both referenced types are `Sync` (required for `&K`/`&V` across threads).
45unsafe impl<K: Sync, V: Sync> Send for Iter<'_, K, V> {}
46unsafe impl<K: Sync, V: Sync> Sync for Iter<'_, K, V> {}
47
48impl<'a, K, V> Iterator for Iter<'a, K, V> {
49    type Item = (&'a K, &'a V);
50
51    fn next(&mut self) -> Option<Self::Item> {
52        if self.len == 0 {
53            return None;
54        }
55        // SAFETY: `len > 0` guarantees that `front` is a live, fully-initialised
56        // real node (not the tail sentinel).  The `PhantomData` lifetime ties the
57        // output references to `'a`, which is the lifetime of the `&LinkedHashMap`.
58        unsafe {
59            let node = self.front;
60            self.front = (*node).next;
61            self.len -= 1;
62            Some((Node::key_ref(node), Node::value_ref(node)))
63        }
64    }
65
66    #[inline]
67    fn size_hint(&self) -> (usize, Option<usize>) {
68        (self.len, Some(self.len))
69    }
70}
71
72impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
73    fn next_back(&mut self) -> Option<Self::Item> {
74        if self.len == 0 {
75            return None;
76        }
77        // SAFETY: `len > 0` guarantees that `back` is a live real node (not the
78        // head sentinel).
79        unsafe {
80            let node = self.back;
81            self.back = (*node).prev;
82            self.len -= 1;
83            Some((Node::key_ref(node), Node::value_ref(node)))
84        }
85    }
86}
87
88impl<K, V> ExactSizeIterator for Iter<'_, K, V> {}
89
90/// Iterator over `(&K, &mut V)` pairs in insertion order.
91///
92/// Created by [`LinkedHashMap::iter_mut`](crate::LinkedHashMap::iter_mut).
93pub struct IterMut<'a, K, V> {
94    pub(crate) front: *mut Node<K, V>,
95    pub(crate) back: *mut Node<K, V>,
96    pub(crate) len: usize,
97    pub(crate) _marker: PhantomData<(&'a K, &'a mut V)>,
98}
99
100// SAFETY: `IterMut` is created from `&mut LinkedHashMap`, so it has exclusive
101// iteration state. Moving it to another thread is safe when `K: Sync` (for
102// yielded `&K`) and `V: Send` (for yielded `&mut V`).
103unsafe impl<K: Sync, V: Send> Send for IterMut<'_, K, V> {}
104
105impl<'a, K, V> Iterator for IterMut<'a, K, V> {
106    type Item = (&'a K, &'a mut V);
107
108    fn next(&mut self) -> Option<Self::Item> {
109        if self.len == 0 {
110            return None;
111        }
112        // SAFETY: The `&mut LinkedHashMap` borrow that created this iterator
113        // guarantees exclusive access.  Each node is yielded exactly once, so
114        // no two outstanding `&mut V` references can alias.
115        unsafe {
116            let node = self.front;
117            self.front = (*node).next;
118            self.len -= 1;
119            Some((Node::key_ref(node), Node::value_mut(node)))
120        }
121    }
122
123    #[inline]
124    fn size_hint(&self) -> (usize, Option<usize>) {
125        (self.len, Some(self.len))
126    }
127}
128
129impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
130    fn next_back(&mut self) -> Option<Self::Item> {
131        if self.len == 0 {
132            return None;
133        }
134        // SAFETY: Same as next(), but traversing from the back.
135        unsafe {
136            let node = self.back;
137            self.back = (*node).prev;
138            self.len -= 1;
139            Some((Node::key_ref(node), Node::value_mut(node)))
140        }
141    }
142}
143
144impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {}
145
146/// Iterator over keys in insertion order.
147///
148/// Created by [`LinkedHashMap::keys`](crate::LinkedHashMap::keys).
149pub struct Keys<'a, K, V> {
150    pub(crate) inner: Iter<'a, K, V>,
151}
152
153impl<'a, K, V> Iterator for Keys<'a, K, V> {
154    type Item = &'a K;
155
156    #[inline]
157    fn next(&mut self) -> Option<&'a K> {
158        self.inner.next().map(|(k, _)| k)
159    }
160
161    #[inline]
162    fn size_hint(&self) -> (usize, Option<usize>) {
163        self.inner.size_hint()
164    }
165}
166
167impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> {
168    #[inline]
169    fn next_back(&mut self) -> Option<&'a K> {
170        self.inner.next_back().map(|(k, _)| k)
171    }
172}
173
174impl<K, V> ExactSizeIterator for Keys<'_, K, V> {}
175
176/// Iterator over values in insertion order.
177///
178/// Created by [`LinkedHashMap::values`](crate::LinkedHashMap::values).
179pub struct Values<'a, K, V> {
180    pub(crate) inner: Iter<'a, K, V>,
181}
182
183impl<'a, K, V> Iterator for Values<'a, K, V> {
184    type Item = &'a V;
185
186    #[inline]
187    fn next(&mut self) -> Option<&'a V> {
188        self.inner.next().map(|(_, v)| v)
189    }
190
191    #[inline]
192    fn size_hint(&self) -> (usize, Option<usize>) {
193        self.inner.size_hint()
194    }
195}
196
197impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
198    #[inline]
199    fn next_back(&mut self) -> Option<&'a V> {
200        self.inner.next_back().map(|(_, v)| v)
201    }
202}
203
204impl<K, V> ExactSizeIterator for Values<'_, K, V> {}
205
206/// Mutable iterator over values in insertion order.
207///
208/// Created by [`LinkedHashMap::values_mut`](crate::LinkedHashMap::values_mut).
209pub struct ValuesMut<'a, K, V> {
210    pub(crate) inner: IterMut<'a, K, V>,
211}
212
213impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
214    type Item = &'a mut V;
215
216    #[inline]
217    fn next(&mut self) -> Option<&'a mut V> {
218        self.inner.next().map(|(_, v)| v)
219    }
220
221    #[inline]
222    fn size_hint(&self) -> (usize, Option<usize>) {
223        self.inner.size_hint()
224    }
225}
226
227impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {}
228
229/// Draining iterator: removes and yields every `(K, V)` pair in insertion
230/// order, leaving the map empty.
231///
232/// Created by [`LinkedHashMap::drain`](crate::LinkedHashMap::drain).
233/// If the iterator is dropped before it is fully consumed, the remaining
234/// elements are freed and the map's sentinel linkage is restored so the map
235/// can be used again immediately.
236pub struct Drain<'a, K, V> {
237    pub(crate) front: *mut Node<K, V>,
238    pub(crate) tail_ptr: *mut Node<K, V>,
239    pub(crate) head_ptr: *mut Node<K, V>,
240    pub(crate) len: usize,
241    pub(crate) _marker: PhantomData<&'a mut (K, V)>,
242}
243
244// SAFETY: `Drain` has unique ownership of all remaining nodes after
245// `LinkedHashMap::drain` clears the table index. Moving it across threads is
246// safe when moved-out elements are `Send`.
247unsafe impl<K: Send, V: Send> Send for Drain<'_, K, V> {}
248
249impl<K, V> Iterator for Drain<'_, K, V> {
250    type Item = (K, V);
251
252    fn next(&mut self) -> Option<(K, V)> {
253        if self.len == 0 {
254            return None;
255        }
256        // SAFETY: `len > 0` means `front` points to a live real node.  We move
257        // the key/value out with `assume_init_read` (the MaybeUninit slots are
258        // now logically uninitialised) and then free the bare Node allocation.
259        unsafe {
260            let node = self.front;
261            self.front = (*node).next;
262            self.len -= 1;
263            let k = Node::key_read(node);
264            let v = Node::value_read(node);
265            let _ = Box::from_raw(node); // free allocation; fields already moved
266            Some((k, v))
267        }
268    }
269
270    #[inline]
271    fn size_hint(&self) -> (usize, Option<usize>) {
272        (self.len, Some(self.len))
273    }
274}
275
276impl<K, V> Drop for Drain<'_, K, V> {
277    fn drop(&mut self) {
278        // Eagerly drop any nodes that the caller did not consume.
279        // SAFETY: Remaining nodes are live and fully initialised.  The owning
280        // map's HashMap index was cleared before Drain was created, so these
281        // nodes are exclusively owned by this iterator.
282        unsafe {
283            let mut cur = self.front;
284            while cur != self.tail_ptr {
285                let next = (*cur).next;
286                Node::drop_real(cur);
287                cur = next;
288            }
289            // Restore the sentinel linkage so the map is in a valid empty state
290            // the moment Drain is dropped.
291            (*self.head_ptr).next = self.tail_ptr;
292            (*self.tail_ptr).prev = self.head_ptr;
293        }
294    }
295}
296
297impl<K, V> ExactSizeIterator for Drain<'_, K, V> {}
298
299/// Consuming iterator: yields every `(K, V)` pair in insertion order,
300/// consuming the map.
301///
302/// Created by calling `.into_iter()` on a [`LinkedHashMap`](crate::LinkedHashMap).
303pub struct IntoIter<K, V> {
304    pub(crate) front: *mut Node<K, V>,
305    pub(crate) tail: NonNull<Node<K, V>>,
306    pub(crate) head: NonNull<Node<K, V>>,
307    pub(crate) len: usize,
308}
309
310// SAFETY: IntoIter exclusively owns all the nodes it points to (it takes
311// ownership from the map via mem::forget + ptr::read).  No aliasing is
312// possible.
313unsafe impl<K: Send, V: Send> Send for IntoIter<K, V> {}
314unsafe impl<K: Sync, V: Sync> Sync for IntoIter<K, V> {}
315
316impl<K, V> Iterator for IntoIter<K, V> {
317    type Item = (K, V);
318
319    fn next(&mut self) -> Option<(K, V)> {
320        if self.len == 0 {
321            return None;
322        }
323        // SAFETY: `len > 0` guarantees `front` is a live real node.
324        unsafe {
325            let node = self.front;
326            self.front = (*node).next;
327            self.len -= 1;
328            let k = Node::key_read(node);
329            let v = Node::value_read(node);
330            let _ = Box::from_raw(node);
331            Some((k, v))
332        }
333    }
334
335    #[inline]
336    fn size_hint(&self) -> (usize, Option<usize>) {
337        (self.len, Some(self.len))
338    }
339}
340
341impl<K, V> Drop for IntoIter<K, V> {
342    fn drop(&mut self) {
343        // Free un-consumed real nodes.
344        // SAFETY: Remaining nodes are live, real, and exclusively owned by
345        // this iterator.
346        unsafe {
347            let mut cur = self.front;
348            while cur != self.tail.as_ptr() {
349                let next = (*cur).next;
350                Node::drop_real(cur);
351                cur = next;
352            }
353            // Free the two sentinel nodes whose key/value are uninitialised.
354            Node::drop_sentinel(self.head.as_ptr());
355            Node::drop_sentinel(self.tail.as_ptr());
356        }
357    }
358}
359
360impl<K, V> ExactSizeIterator for IntoIter<K, V> {}
361
362// Variance assertions
363//
364// These compile-time checks verify that each iterator type is *covariant*
365// in its lifetime and type parameters: a longer lifetime / more-derived type
366// can be shortened / widened to match a shorter lifetime / less-derived type.
367//
368// The pattern is: write a function that accepts the "longer" type and returns
369// the "shorter" type with only implicit subtyping — if the compiler accepts it,
370// the type is covariant in those parameters.
371
372#[cfg(not(coverage))]
373const _: () = {
374    /// `Iter<'long, K, V>` is covariant in `'a`, `K`, and `V`.
375    fn _check_iter<'long: 'short, 'short, K, V>(x: Iter<'long, K, V>) -> Iter<'short, K, V> {
376        x
377    }
378
379    /// `IterMut<'long, K, V>` is covariant in `'a` and `K`, but NOT in `V`
380    /// (it yields `&'a mut V`).  We only assert covariance in `'a` and `K`.
381    fn _check_iter_mut_lifetime<'long: 'short, 'short, K, V>(
382        x: IterMut<'long, K, V>,
383    ) -> IterMut<'short, K, V> {
384        x
385    }
386
387    /// `Keys<'long, K, V>` is covariant in `'a` and `K`.
388    fn _check_keys<'long: 'short, 'short, K, V>(x: Keys<'long, K, V>) -> Keys<'short, K, V> {
389        x
390    }
391
392    /// `Values<'long, K, V>` is covariant in `'a` and `V`.
393    fn _check_values<'long: 'short, 'short, K, V>(x: Values<'long, K, V>) -> Values<'short, K, V> {
394        x
395    }
396
397    /// `IntoIter<K, V>` is covariant in `K` and `V`.
398    ///
399    /// Since `IntoIter` has no lifetime, we verify this by confirming that the
400    /// struct compiles and the PhantomData annotation is sound.  The owned
401    /// `(K, V)` pairs it yields make covariance safe.
402    fn _check_into_iter<K, V>(_: IntoIter<K, V>) {}
403};