1use std::{collections::HashMap, hash::Hash};
5
6pub struct LruCache<K, V> {
7 map: HashMap<K, usize>,
8 entries: Vec<Entry<K, V>>,
9 head: Option<usize>,
10 tail: Option<usize>,
11 capacity: usize,
12}
13
14struct Entry<K, V> {
15 key: K,
16 value: V,
17 prev: Option<usize>,
18 next: Option<usize>,
19}
20
21impl<K: Hash + Eq + Clone, V> LruCache<K, V> {
22 pub fn new(capacity: usize) -> Self {
23 assert!(capacity > 0, "LRU cache capacity must be greater than 0");
24 Self {
25 map: HashMap::with_capacity(capacity),
26 entries: Vec::with_capacity(capacity),
27 head: None,
28 tail: None,
29 capacity,
30 }
31 }
32
33 pub fn get(&mut self, key: &K) -> Option<&V> {
34 if let Some(&idx) = self.map.get(key) {
35 self.move_to_front(idx);
36 Some(&self.entries[idx].value)
37 } else {
38 None
39 }
40 }
41
42 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
43 if let Some(&idx) = self.map.get(key) {
44 self.move_to_front(idx);
45 Some(&mut self.entries[idx].value)
46 } else {
47 None
48 }
49 }
50
51 pub fn put(&mut self, key: K, value: V) -> Option<V> {
52 if let Some(&idx) = self.map.get(&key) {
53 let old_value = std::mem::replace(&mut self.entries[idx].value, value);
54 self.move_to_front(idx);
55 return Some(old_value);
56 }
57
58 let evicted = if self.entries.len() >= self.capacity {
59 self.evict_lru()
60 } else {
61 None
62 };
63
64 let idx = self.entries.len();
65 self.entries.push(Entry {
66 key: key.clone(),
67 value,
68 prev: None,
69 next: self.head,
70 });
71
72 if let Some(old_head) = self.head {
73 self.entries[old_head].prev = Some(idx);
74 }
75
76 self.head = Some(idx);
77
78 if self.tail.is_none() {
79 self.tail = Some(idx);
80 }
81
82 self.map.insert(key, idx);
83 evicted
84 }
85
86 pub fn remove(&mut self, key: &K) -> Option<V> {
87 if let Some(idx) = self.map.remove(key) {
88 self.unlink(idx);
89 let entry = self.entries.swap_remove(idx);
90
91 if idx < self.entries.len() {
92 let moved_key = self.entries[idx].key.clone();
93 self.map.insert(moved_key, idx);
94
95 if let Some(prev) = self.entries[idx].prev {
96 self.entries[prev].next = Some(idx);
97 } else {
98 self.head = Some(idx);
99 }
100
101 if let Some(next) = self.entries[idx].next {
102 self.entries[next].prev = Some(idx);
103 } else {
104 self.tail = Some(idx);
105 }
106 }
107
108 Some(entry.value)
109 } else {
110 None
111 }
112 }
113
114 pub fn contains_key(&self, key: &K) -> bool {
115 self.map.contains_key(key)
116 }
117
118 pub fn clear(&mut self) {
119 self.map.clear();
120 self.entries.clear();
121 self.head = None;
122 self.tail = None;
123 }
124
125 pub fn len(&self) -> usize {
126 self.entries.len()
127 }
128
129 pub fn is_empty(&self) -> bool {
130 self.entries.is_empty()
131 }
132
133 pub fn capacity(&self) -> usize {
134 self.capacity
135 }
136
137 pub fn iter(&self) -> LruIter<'_, K, V> {
138 LruIter {
139 entries: &self.entries,
140 current: self.head,
141 }
142 }
143
144 fn move_to_front(&mut self, idx: usize) {
145 if self.head == Some(idx) {
146 return;
147 }
148
149 self.unlink(idx);
150
151 self.entries[idx].prev = None;
152 self.entries[idx].next = self.head;
153
154 if let Some(old_head) = self.head {
155 self.entries[old_head].prev = Some(idx);
156 }
157
158 self.head = Some(idx);
159
160 if self.tail.is_none() {
161 self.tail = Some(idx);
162 }
163 }
164
165 fn unlink(&mut self, idx: usize) {
166 let entry = &self.entries[idx];
167 let prev = entry.prev;
168 let next = entry.next;
169
170 if let Some(p) = prev {
171 self.entries[p].next = next;
172 } else {
173 self.head = next;
174 }
175
176 if let Some(n) = next {
177 self.entries[n].prev = prev;
178 } else {
179 self.tail = prev;
180 }
181 }
182
183 fn evict_lru(&mut self) -> Option<V> {
184 if let Some(tail_idx) = self.tail {
185 let key = self.entries[tail_idx].key.clone();
186 self.remove(&key)
187 } else {
188 None
189 }
190 }
191}
192
193pub struct LruIter<'a, K, V> {
194 entries: &'a [Entry<K, V>],
195 current: Option<usize>,
196}
197
198impl<'a, K, V> Iterator for LruIter<'a, K, V> {
199 type Item = (&'a K, &'a V);
200
201 fn next(&mut self) -> Option<Self::Item> {
202 if let Some(idx) = self.current {
203 let entry = &self.entries[idx];
204 self.current = entry.next;
205 Some((&entry.key, &entry.value))
206 } else {
207 None
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn test_basic_operations() {
218 let mut cache = LruCache::new(2);
219
220 assert_eq!(cache.put(1, "a"), None);
221 assert_eq!(cache.put(2, "b"), None);
222 assert_eq!(cache.get(&1), Some(&"a"));
223 assert_eq!(cache.get(&2), Some(&"b"));
224 assert_eq!(cache.len(), 2);
225 }
226
227 #[test]
228 fn test_eviction() {
229 let mut cache = LruCache::new(2);
230
231 cache.put(1, "a");
232 cache.put(2, "b");
233 let evicted = cache.put(3, "c");
234
235 assert_eq!(evicted, Some("a"));
236 assert_eq!(cache.get(&1), None);
237 assert_eq!(cache.get(&2), Some(&"b"));
238 assert_eq!(cache.get(&3), Some(&"c"));
239 }
240
241 #[test]
242 fn test_lru_order() {
243 let mut cache = LruCache::new(2);
244
245 cache.put(1, "a");
246 cache.put(2, "b");
247 cache.get(&1);
248 cache.put(3, "c");
249
250 assert_eq!(cache.get(&1), Some(&"a"));
251 assert_eq!(cache.get(&2), None);
252 assert_eq!(cache.get(&3), Some(&"c"));
253 }
254
255 #[test]
256 fn test_update_existing() {
257 let mut cache = LruCache::new(2);
258
259 cache.put(1, "a");
260 let old = cache.put(1, "b");
261
262 assert_eq!(old, Some("a"));
263 assert_eq!(cache.get(&1), Some(&"b"));
264 assert_eq!(cache.len(), 1);
265 }
266
267 #[test]
268 fn test_remove() {
269 let mut cache = LruCache::new(2);
270
271 cache.put(1, "a");
272 cache.put(2, "b");
273 let removed = cache.remove(&1);
274
275 assert_eq!(removed, Some("a"));
276 assert_eq!(cache.get(&1), None);
277 assert_eq!(cache.len(), 1);
278 }
279
280 #[test]
281 fn test_clear() {
282 let mut cache = LruCache::new(2);
283
284 cache.put(1, "a");
285 cache.put(2, "b");
286 cache.clear();
287
288 assert_eq!(cache.len(), 0);
289 assert!(cache.is_empty());
290 }
291
292 #[test]
293 fn test_contains_key() {
294 let mut cache = LruCache::new(2);
295
296 cache.put(1, "a");
297 assert!(cache.contains_key(&1));
298 assert!(!cache.contains_key(&2));
299 }
300
301 #[test]
302 fn test_iter() {
303 let mut cache = LruCache::new(3);
304
305 cache.put(1, "a");
306 cache.put(2, "b");
307 cache.put(3, "c");
308 cache.get(&1);
309
310 let items: Vec<_> = cache.iter().collect();
311 assert_eq!(items[0], (&1, &"a"));
312 assert_eq!(items[1], (&3, &"c"));
313 assert_eq!(items[2], (&2, &"b"));
314 }
315}