Skip to main content

euv_core/reactive/cache/
impl.rs

1use super::*;
2
3impl<K, V> LruCache<K, V>
4where
5    K: Clone + Eq + Hash,
6{
7    /// Returns the current number of entries in the
8    /// cache.
9    ///
10    /// # Returns
11    ///
12    /// - `usize` - The number of items in the collection.
13    pub fn len(&self) -> usize {
14        self.map.len()
15    }
16
17    /// Returns `true` if the cache is empty.
18    ///
19    /// # Returns
20    ///
21    /// - `bool` - `true` when the collection is empty.
22    pub fn is_empty(&self) -> bool {
23        self.map.is_empty()
24    }
25
26    /// Returns `true` if the cache is at capacity.
27    ///
28    /// # Returns
29    ///
30    /// - `bool` - A boolean.
31    pub fn is_full(&self) -> bool {
32        self.map.len() >= self.capacity
33    }
34
35    /// Returns `true` if the cache contains a value for
36    /// the given key. Does NOT update the recency (use
37    /// `get` for that).
38    ///
39    /// # Arguments
40    ///
41    /// - `&K` - Shared reference to a `K`.
42    ///
43    /// # Returns
44    ///
45    /// - `bool` - A boolean.
46    pub fn contains(&self, key: &K) -> bool {
47        self.map.contains_key(key)
48    }
49
50    /// Returns the value for the given key, updating the
51    /// recency so the entry becomes the most-recently-
52    /// used.
53    ///
54    /// Returns `None` if the key is not in the cache.
55    ///
56    /// # Arguments
57    ///
58    /// - `&K` - Shared reference to a `K`.
59    ///
60    /// # Returns
61    ///
62    /// - `Option<V>` - The current value (or a snapshot thereof).
63    pub fn get(&mut self, key: &K) -> Option<&V> {
64        if self.map.contains_key(key) {
65            // Promote the key to the front of the
66            // order deque. Remove its existing position
67            // first (if any) to avoid duplicates.
68            self.order.retain(|k: &K| k != key);
69            self.order.push_front(key.clone());
70            self.map.get(key)
71        } else {
72            None
73        }
74    }
75
76    /// Returns the value for the given key without
77    /// updating the recency. Useful for "is this cached?"
78    /// checks that should not affect eviction order.
79    ///
80    /// # Arguments
81    ///
82    /// - `&K` - Shared reference to a `K`.
83    ///
84    /// # Returns
85    ///
86    /// - `Option<V>` - `Some(...)` on success, `None` otherwise.
87    pub fn peek(&self, key: &K) -> Option<&V> {
88        self.map.get(key)
89    }
90
91    /// Inserts a key-value pair into the cache. If the
92    /// key is already present, the existing value is
93    /// replaced (and the entry becomes the most-
94    /// recently-used). If the cache is at capacity and
95    /// the key is new, the least-recently-used entry is
96    /// evicted first.
97    ///
98    /// Returns the evicted entry, if any.
99    ///
100    /// # Arguments
101    ///
102    /// - `K: Clone + Eq + Hash` - A generic type parameter.
103    /// - `V` - A `V` parameter.
104    ///
105    /// # Returns
106    ///
107    /// - `Option<(K, V)>` - `Some(...)` on success, `None` otherwise.
108    pub fn put(&mut self, key: K, value: V) -> Option<(K, V)> {
109        // Capacity of 0 — silently drop.
110        if self.capacity == 0 {
111            return None;
112        }
113        // Updating an existing key.
114        if self.map.contains_key(&key) {
115            self.map.insert(key.clone(), value);
116            // Promote the key to the front of the
117            // order deque. Remove its existing position
118            // first (if any) to avoid duplicates.
119            self.order.retain(|k: &K| k != &key);
120            self.order.push_front(key);
121            return None;
122        }
123        // Inserting a new key. Evict if at capacity.
124        let evicted: Option<(K, V)> = if self.map.len() >= self.capacity {
125            let victim_key: K = self.order.pop_back()?;
126            let victim_value: V = self.map.remove(&victim_key)?;
127            Some((victim_key, victim_value))
128        } else {
129            None
130        };
131        self.map.insert(key.clone(), value);
132        self.order.push_front(key);
133        evicted
134    }
135
136    /// Removes the entry for the given key, returning
137    /// the removed value if any.
138    ///
139    /// # Arguments
140    ///
141    /// - `&K` - Shared reference to a `K`.
142    ///
143    /// # Returns
144    ///
145    /// - `Option<V>` - `Some(...)` on success, `None` otherwise.
146    pub fn remove(&mut self, key: &K) -> Option<V> {
147        self.order.retain(|k: &K| k != key);
148        self.map.remove(key)
149    }
150
151    /// Removes every entry from the cache.
152    pub fn clear(&mut self) {
153        self.map.clear();
154        self.order.clear();
155    }
156
157    /// Returns an iterator over the entries in
158    /// most-recently-used-first order.
159    ///
160    /// # Returns
161    ///
162    /// - `impl Iterator<Item` - A `impl Iterator<Item` value.
163    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
164        // We can't return the VecDeque order directly
165        // because the entries would be in order-deque
166        // order, not MRU-first order. Actually they
167        // ARE in MRU-first order — the VecDeque's
168        // front is MRU. So iterating and mapping through
169        // the map gives us MRU-first order.
170        self.order
171            .iter()
172            .filter_map(|k: &K| self.map.get_key_value(k))
173    }
174
175    /// Returns an iterator over the keys in
176    /// most-recently-used-first order.
177    ///
178    /// # Returns
179    ///
180    /// - `impl Iterator<Item` - A `impl Iterator<Item` value.
181    pub fn keys(&self) -> impl Iterator<Item = &K> {
182        self.order.iter()
183    }
184
185    /// Returns an iterator over the values in
186    /// most-recently-used-first order.
187    ///
188    /// # Returns
189    ///
190    /// - `impl Iterator<Item` - A `impl Iterator<Item` value.
191    pub fn values(&self) -> impl Iterator<Item = &V> {
192        self.order.iter().filter_map(|k: &K| self.map.get(k))
193    }
194
195    /// Resizes the cache to a new capacity.
196    ///
197    /// If the new capacity is smaller than the current
198    /// size, the least-recently-used entries are
199    /// evicted until the cache fits.
200    ///
201    /// # Arguments
202    ///
203    /// - `usize` - A non-negative integer (`usize`).
204    pub fn resize(&mut self, new_capacity: usize) {
205        self.capacity = new_capacity;
206        while self.map.len() > self.capacity {
207            if let Some(victim_key) = self.order.pop_back() {
208                self.map.remove(&victim_key);
209            } else {
210                break;
211            }
212        }
213    }
214}