const_lru/iters/
into_iter.rs

1use num_traits::{PrimInt, Unsigned};
2
3use crate::ConstLru;
4
5use super::double_ended_iter_cursors::DoubleEndedIterCursors;
6
7/// Iterates through the keys and values of the `ConstLru` from most-recently-used to least-recently-used, consuming the `ConstLru`
8///
9/// Does not change the LRU order of the elements.
10pub struct IntoIter<K, V, const CAP: usize, I: PrimInt + Unsigned> {
11    cursors: DoubleEndedIterCursors<I, CAP>,
12    const_lru: ConstLru<K, V, CAP, I>,
13}
14
15impl<K, V, const CAP: usize, I: PrimInt + Unsigned> IntoIter<K, V, CAP, I> {
16    pub fn new(const_lru: ConstLru<K, V, CAP, I>) -> Self {
17        let cursors = DoubleEndedIterCursors::new(&const_lru);
18        Self { cursors, const_lru }
19    }
20
21    fn get_entry(&mut self, i: usize) -> (K, V) {
22        let key = unsafe { self.const_lru.keys[i].assume_init_read() };
23        let val = unsafe { self.const_lru.values[i].assume_init_read() };
24        (key, val)
25    }
26}
27
28impl<K, V, const CAP: usize, I: PrimInt + Unsigned> Iterator for IntoIter<K, V, CAP, I> {
29    type Item = (K, V);
30
31    fn next(&mut self) -> Option<Self::Item> {
32        if self.cursors.has_ended() {
33            return None;
34        }
35        // consume then increment
36        let i = self.cursors.get_from_head_idx();
37        self.cursors.advance_from_head(&self.const_lru);
38        // get_entry copies out (k, v),
39        // we need to truncate the const_lru so that they dont get dropped again
40        // when const_lru drops
41        self.const_lru.head = self.cursors.get_from_head();
42        self.const_lru.len = self.const_lru.len - I::one();
43        Some(self.get_entry(i))
44    }
45
46    fn size_hint(&self) -> (usize, Option<usize>) {
47        let l = self.const_lru.len.to_usize().unwrap();
48        (l, Some(l))
49    }
50}
51
52// TODO: look into https://doc.rust-lang.org/std/iter/trait.TrustedLen.html when it lands in stable
53impl<K, V, const CAP: usize, I: PrimInt + Unsigned> ExactSizeIterator for IntoIter<K, V, CAP, I> {}
54
55impl<K, V, const CAP: usize, I: PrimInt + Unsigned> DoubleEndedIterator for IntoIter<K, V, CAP, I> {
56    fn next_back(&mut self) -> Option<Self::Item> {
57        if self.cursors.has_ended() {
58            return None;
59        }
60        // decrement then consume
61        self.cursors.retreat_from_tail(&self.const_lru);
62        let i = self.cursors.get_from_tail_idx();
63        // get_entry copies out (k, v),
64        // we need to truncate the const_lru so that they dont get dropped again
65        // when const_lru drops
66
67        // index safety: from_tail is < CAP so prevs[i] wont panic
68        // but might = CAP, but in that case len = 0 so mustve ended
69        self.const_lru.tail = self.const_lru.prevs[i];
70        self.const_lru.len = self.const_lru.len - I::one();
71        Some(self.get_entry(i))
72    }
73}