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}