const_lru/iters/
iter_mut.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 mutable values of the `ConstLru` from most-recently-used to least-recently-used
8///
9/// Does not change the LRU order of the elements.
10pub struct IterMut<'a, K, V, const CAP: usize, I: PrimInt + Unsigned> {
11    cursors: DoubleEndedIterCursors<I, CAP>,
12    const_lru: &'a mut ConstLru<K, V, CAP, I>,
13}
14
15impl<'a, K, V, const CAP: usize, I: PrimInt + Unsigned> IterMut<'a, K, V, CAP, I> {
16    pub fn new(const_lru: &'a mut 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(&mut self, i: usize) -> (&'a K, &'a mut V) {
22        // TODO: double check unsafes
23        let key_ptr = unsafe { self.const_lru.keys[i].assume_init_ref() } as *const _;
24        let key: &'a K = unsafe { &*key_ptr };
25        let val_ptr = unsafe { self.const_lru.values[i].assume_init_mut() } as *mut _;
26        let val: &'a mut V = unsafe { &mut *val_ptr };
27        (key, val)
28    }
29}
30
31impl<'a, K, V, const CAP: usize, I: PrimInt + Unsigned> Iterator for IterMut<'a, K, V, CAP, I> {
32    type Item = (&'a K, &'a mut V);
33
34    fn next(&mut self) -> Option<Self::Item> {
35        if self.cursors.has_ended() {
36            return None;
37        }
38        // consume then increment
39        let i = self.cursors.get_from_head_idx();
40        self.cursors.advance_from_head(self.const_lru);
41        Some(self.get_entry_mut(i))
42    }
43
44    // TODO: look into https://doc.rust-lang.org/std/iter/trait.TrustedLen.html
45    // and consider adding a `seen` field to implement it
46    // when it lands in stable
47    fn size_hint(&self) -> (usize, Option<usize>) {
48        (0, Some(CAP))
49    }
50}
51
52impl<'a, K, V, const CAP: usize, I: PrimInt + Unsigned> DoubleEndedIterator
53    for IterMut<'a, K, V, CAP, I>
54{
55    fn next_back(&mut self) -> Option<Self::Item> {
56        if self.cursors.has_ended() {
57            return None;
58        }
59        // decrement then consume
60        self.cursors.retreat_from_tail(self.const_lru);
61        let i = self.cursors.get_from_tail_idx();
62        Some(self.get_entry_mut(i))
63    }
64}