xlru_cache/lib.rs
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A cache that holds a limited number of key-value pairs. When the
12//! capacity of the cache is exceeded, the least-recently-used
13//! (where "used" means a look-up or putting the pair into the cache)
14//! pair is automatically removed.
15//!
16//! # Examples
17//!
18//! ```
19//! use lru_cache::LruCache;
20//!
21//! let mut cache = LruCache::new(2);
22//!
23//! cache.insert(1, 10);
24//! cache.insert(2, 20);
25//! cache.insert(3, 30);
26//! assert!(cache.get_mut(&1).is_none());
27//! assert_eq!(*cache.get_mut(&2).unwrap(), 20);
28//! assert_eq!(*cache.get_mut(&3).unwrap(), 30);
29//!
30//! cache.insert(2, 22);
31//! assert_eq!(*cache.get_mut(&2).unwrap(), 22);
32//!
33//! cache.insert(6, 60);
34//! assert!(cache.get_mut(&3).is_none());
35//!
36//! cache.set_capacity(1);
37//! assert!(cache.get_mut(&2).is_none());
38//! ```
39
40extern crate linked_hash_map;
41
42use std::borrow::Borrow;
43use std::collections::hash_map::RandomState;
44use std::fmt;
45use std::hash::{Hash, BuildHasher};
46
47use linked_hash_map::LinkedHashMap;
48
49#[cfg(feature = "heapsize_impl")]
50mod heapsize;
51
52// FIXME(conventions): implement indexing?
53
54/// An LRU cache.
55#[derive(Clone)]
56pub struct LruCache<K: Eq + Hash, V, S: BuildHasher = RandomState> {
57 map: LinkedHashMap<K, V, S>,
58 max_size: usize,
59}
60
61impl<K: Eq + Hash, V> LruCache<K, V> {
62 /// Creates an empty cache that can hold at most `capacity` items.
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// use lru_cache::LruCache;
68 /// let mut cache: LruCache<i32, &str> = LruCache::new(10);
69 /// ```
70 pub fn new(capacity: usize) -> Self {
71 LruCache {
72 map: LinkedHashMap::new(),
73 max_size: capacity,
74 }
75 }
76}
77
78impl<K: Eq + Hash, V, S: BuildHasher> LruCache<K, V, S> {
79 /// Creates an empty cache that can hold at most `capacity` items with the given hash builder.
80 pub fn with_hasher(capacity: usize, hash_builder: S) -> Self {
81 LruCache { map: LinkedHashMap::with_hasher(hash_builder), max_size: capacity }
82 }
83
84 /// Checks if the map contains the given key.
85 ///
86 /// # Examples
87 ///
88 /// ```
89 /// use lru_cache::LruCache;
90 ///
91 /// let mut cache = LruCache::new(1);
92 ///
93 /// cache.insert(1, "a");
94 /// assert_eq!(cache.contains_key(&1), true);
95 /// ```
96 pub fn contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool
97 where K: Borrow<Q>,
98 Q: Hash + Eq
99 {
100 self.get_mut(key).is_some()
101 }
102
103 /// Inserts a key-value pair into the cache. If the key already existed, the old value is
104 /// returned.
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use lru_cache::LruCache;
110 ///
111 /// let mut cache = LruCache::new(2);
112 ///
113 /// cache.insert(1, "a");
114 /// cache.insert(2, "b");
115 /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
116 /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
117 /// ```
118 pub fn insert(&mut self, k: K, v: V) -> Option<V> {
119 let old_val = self.map.insert(k, v);
120 if self.len() > self.capacity() {
121 self.remove_lru();
122 }
123 old_val
124 }
125
126 /// Returns a mutable reference to the value corresponding to the given key in the cache, if
127 /// any.
128 ///
129 /// # Examples
130 ///
131 /// ```
132 /// use lru_cache::LruCache;
133 ///
134 /// let mut cache = LruCache::new(2);
135 ///
136 /// cache.insert(1, "a");
137 /// cache.insert(2, "b");
138 /// cache.insert(2, "c");
139 /// cache.insert(3, "d");
140 ///
141 /// assert_eq!(cache.get_mut(&1), None);
142 /// assert_eq!(cache.get_mut(&2), Some(&mut "c"));
143 /// ```
144 pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
145 where K: Borrow<Q>,
146 Q: Hash + Eq
147 {
148 self.map.get_refresh(k)
149 }
150
151 pub fn peek_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
152 where K: Borrow<Q>,
153 Q: Hash + Eq
154 {
155 self.map.get_mut(k)
156 }
157
158 /// Removes the given key from the cache and returns its corresponding value.
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use lru_cache::LruCache;
164 ///
165 /// let mut cache = LruCache::new(2);
166 ///
167 /// cache.insert(2, "a");
168 ///
169 /// assert_eq!(cache.remove(&1), None);
170 /// assert_eq!(cache.remove(&2), Some("a"));
171 /// assert_eq!(cache.remove(&2), None);
172 /// assert_eq!(cache.len(), 0);
173 /// ```
174 pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
175 where K: Borrow<Q>,
176 Q: Hash + Eq
177 {
178 self.map.remove(k)
179 }
180
181 /// Returns the maximum number of key-value pairs the cache can hold.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// use lru_cache::LruCache;
187 /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
188 /// assert_eq!(cache.capacity(), 2);
189 /// ```
190 pub fn capacity(&self) -> usize {
191 self.max_size
192 }
193
194 /// Sets the number of key-value pairs the cache can hold. Removes
195 /// least-recently-used key-value pairs if necessary.
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// use lru_cache::LruCache;
201 ///
202 /// let mut cache = LruCache::new(2);
203 ///
204 /// cache.insert(1, "a");
205 /// cache.insert(2, "b");
206 /// cache.insert(3, "c");
207 ///
208 /// assert_eq!(cache.get_mut(&1), None);
209 /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
210 /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
211 ///
212 /// cache.set_capacity(3);
213 /// cache.insert(1, "a");
214 /// cache.insert(2, "b");
215 ///
216 /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
217 /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
218 /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
219 ///
220 /// cache.set_capacity(1);
221 ///
222 /// assert_eq!(cache.get_mut(&1), None);
223 /// assert_eq!(cache.get_mut(&2), None);
224 /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
225 /// ```
226 pub fn set_capacity(&mut self, capacity: usize) {
227 for _ in capacity..self.len() {
228 self.remove_lru();
229 }
230 self.max_size = capacity;
231 }
232
233 /// Removes and returns the least recently used key-value pair as a tuple.
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// use lru_cache::LruCache;
239 ///
240 /// let mut cache = LruCache::new(2);
241 ///
242 /// cache.insert(1, "a");
243 /// cache.insert(2, "b");
244 ///
245 /// assert_eq!(cache.remove_lru(), Some((1, "a")));
246 /// assert_eq!(cache.len(), 1);
247 /// ```
248 #[inline]
249 pub fn remove_lru(&mut self) -> Option<(K, V)> {
250 self.map.pop_front()
251 }
252
253 /// Returns the number of key-value pairs in the cache.
254 pub fn len(&self) -> usize { self.map.len() }
255
256 /// Returns `true` if the cache contains no key-value pairs.
257 pub fn is_empty(&self) -> bool { self.map.is_empty() }
258
259 /// Removes all key-value pairs from the cache.
260 pub fn clear(&mut self) { self.map.clear(); }
261
262 /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order.
263 ///
264 /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
265 ///
266 /// # Examples
267 ///
268 /// ```
269 /// use lru_cache::LruCache;
270 ///
271 /// let mut cache = LruCache::new(2);
272 ///
273 /// cache.insert(1, 10);
274 /// cache.insert(2, 20);
275 /// cache.insert(3, 30);
276 ///
277 /// let kvs: Vec<_> = cache.iter().collect();
278 /// assert_eq!(kvs, [(&2, &20), (&3, &30)]);
279 /// ```
280 pub fn iter(&self) -> Iter<K, V> { Iter(self.map.iter()) }
281
282 /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order,
283 /// with mutable references to the values.
284 ///
285 /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use lru_cache::LruCache;
291 ///
292 /// let mut cache = LruCache::new(2);
293 ///
294 /// cache.insert(1, 10);
295 /// cache.insert(2, 20);
296 /// cache.insert(3, 30);
297 ///
298 /// let mut n = 2;
299 ///
300 /// for (k, v) in cache.iter_mut() {
301 /// assert_eq!(*k, n);
302 /// assert_eq!(*v, n * 10);
303 /// *v *= 10;
304 /// n += 1;
305 /// }
306 ///
307 /// assert_eq!(n, 4);
308 /// assert_eq!(cache.get_mut(&2), Some(&mut 200));
309 /// assert_eq!(cache.get_mut(&3), Some(&mut 300));
310 /// ```
311 pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) }
312}
313
314impl<K: Eq + Hash, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> {
315 fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I) {
316 for (k, v) in iter {
317 self.insert(k, v);
318 }
319 }
320}
321
322impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for LruCache<K, V, S> {
323 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
324 f.debug_map().entries(self.iter().rev()).finish()
325 }
326}
327
328impl<K: Eq + Hash, V, S: BuildHasher> IntoIterator for LruCache<K, V, S> {
329 type Item = (K, V);
330 type IntoIter = IntoIter<K, V>;
331
332 fn into_iter(self) -> IntoIter<K, V> {
333 IntoIter(self.map.into_iter())
334 }
335}
336
337impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a LruCache<K, V, S> {
338 type Item = (&'a K, &'a V);
339 type IntoIter = Iter<'a, K, V>;
340 fn into_iter(self) -> Iter<'a, K, V> { self.iter() }
341}
342
343impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a mut LruCache<K, V, S> {
344 type Item = (&'a K, &'a mut V);
345 type IntoIter = IterMut<'a, K, V>;
346 fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() }
347}
348
349/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
350///
351/// # Examples
352///
353/// ```
354/// use lru_cache::LruCache;
355///
356/// let mut cache = LruCache::new(2);
357///
358/// cache.insert(1, 10);
359/// cache.insert(2, 20);
360/// cache.insert(3, 30);
361///
362/// let mut n = 2;
363///
364/// for (k, v) in cache {
365/// assert_eq!(k, n);
366/// assert_eq!(v, n * 10);
367/// n += 1;
368/// }
369///
370/// assert_eq!(n, 4);
371/// ```
372#[derive(Clone)]
373pub struct IntoIter<K, V>(linked_hash_map::IntoIter<K, V>);
374
375impl<K, V> Iterator for IntoIter<K, V> {
376 type Item = (K, V);
377
378 fn next(&mut self) -> Option<(K, V)> {
379 self.0.next()
380 }
381
382 fn size_hint(&self) -> (usize, Option<usize>) {
383 self.0.size_hint()
384 }
385}
386
387impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
388 fn next_back(&mut self) -> Option<(K, V)> {
389 self.0.next_back()
390 }
391}
392
393impl<K, V> ExactSizeIterator for IntoIter<K, V> {
394 fn len(&self) -> usize {
395 self.0.len()
396 }
397}
398
399/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
400///
401/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
402pub struct Iter<'a, K: 'a, V: 'a>(linked_hash_map::Iter<'a, K, V>);
403
404impl<'a, K, V> Clone for Iter<'a, K, V> {
405 fn clone(&self) -> Iter<'a, K, V> { Iter(self.0.clone()) }
406}
407
408impl<'a, K, V> Iterator for Iter<'a, K, V> {
409 type Item = (&'a K, &'a V);
410 fn next(&mut self) -> Option<(&'a K, &'a V)> { self.0.next() }
411 fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
412}
413
414impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
415 fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.0.next_back() }
416}
417
418impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
419 fn len(&self) -> usize { self.0.len() }
420}
421
422/// An iterator over a cache's key-value pairs in least- to most-recently-used order with mutable
423/// references to the values.
424///
425/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
426pub struct IterMut<'a, K: 'a, V: 'a>(linked_hash_map::IterMut<'a, K, V>);
427
428impl<'a, K, V> Iterator for IterMut<'a, K, V> {
429 type Item = (&'a K, &'a mut V);
430 fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next() }
431 fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
432}
433
434impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
435 fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next_back() }
436}
437
438impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
439 fn len(&self) -> usize { self.0.len() }
440}
441
442#[cfg(test)]
443mod tests {
444 use super::LruCache;
445
446 #[test]
447 fn test_put_and_get() {
448 let mut cache = LruCache::new(2);
449 cache.insert(1, 10);
450 cache.insert(2, 20);
451 assert_eq!(cache.get_mut(&1), Some(&mut 10));
452 assert_eq!(cache.get_mut(&2), Some(&mut 20));
453 assert_eq!(cache.len(), 2);
454 }
455
456 #[test]
457 fn test_put_update() {
458 let mut cache = LruCache::new(1);
459 cache.insert("1", 10);
460 cache.insert("1", 19);
461 assert_eq!(cache.get_mut("1"), Some(&mut 19));
462 assert_eq!(cache.len(), 1);
463 }
464
465 #[test]
466 fn test_contains_key() {
467 let mut cache = LruCache::new(1);
468 cache.insert("1", 10);
469 assert_eq!(cache.contains_key("1"), true);
470 }
471
472 #[test]
473 fn test_expire_lru() {
474 let mut cache = LruCache::new(2);
475 cache.insert("foo1", "bar1");
476 cache.insert("foo2", "bar2");
477 cache.insert("foo3", "bar3");
478 assert!(cache.get_mut("foo1").is_none());
479 cache.insert("foo2", "bar2update");
480 cache.insert("foo4", "bar4");
481 assert!(cache.get_mut("foo3").is_none());
482 }
483
484 #[test]
485 fn test_pop() {
486 let mut cache = LruCache::new(2);
487 cache.insert(1, 10);
488 cache.insert(2, 20);
489 assert_eq!(cache.len(), 2);
490 let opt1 = cache.remove(&1);
491 assert!(opt1.is_some());
492 assert_eq!(opt1.unwrap(), 10);
493 assert!(cache.get_mut(&1).is_none());
494 assert_eq!(cache.len(), 1);
495 }
496
497 #[test]
498 fn test_change_capacity() {
499 let mut cache = LruCache::new(2);
500 assert_eq!(cache.capacity(), 2);
501 cache.insert(1, 10);
502 cache.insert(2, 20);
503 cache.set_capacity(1);
504 assert!(cache.get_mut(&1).is_none());
505 assert_eq!(cache.capacity(), 1);
506 }
507
508 #[test]
509 fn test_debug() {
510 let mut cache = LruCache::new(3);
511 cache.insert(1, 10);
512 cache.insert(2, 20);
513 cache.insert(3, 30);
514 assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
515 cache.insert(2, 22);
516 assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
517 cache.insert(6, 60);
518 assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
519 cache.get_mut(&3);
520 assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
521 cache.set_capacity(2);
522 assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
523 }
524
525 #[test]
526 fn test_remove() {
527 let mut cache = LruCache::new(3);
528 cache.insert(1, 10);
529 cache.insert(2, 20);
530 cache.insert(3, 30);
531 cache.insert(4, 40);
532 cache.insert(5, 50);
533 cache.remove(&3);
534 cache.remove(&4);
535 assert!(cache.get_mut(&3).is_none());
536 assert!(cache.get_mut(&4).is_none());
537 cache.insert(6, 60);
538 cache.insert(7, 70);
539 cache.insert(8, 80);
540 assert!(cache.get_mut(&5).is_none());
541 assert_eq!(cache.get_mut(&6), Some(&mut 60));
542 assert_eq!(cache.get_mut(&7), Some(&mut 70));
543 assert_eq!(cache.get_mut(&8), Some(&mut 80));
544 }
545
546 #[test]
547 fn test_clear() {
548 let mut cache = LruCache::new(2);
549 cache.insert(1, 10);
550 cache.insert(2, 20);
551 cache.clear();
552 assert!(cache.get_mut(&1).is_none());
553 assert!(cache.get_mut(&2).is_none());
554 assert_eq!(format!("{:?}", cache), "{}");
555 }
556
557 #[test]
558 fn test_iter() {
559 let mut cache = LruCache::new(3);
560 cache.insert(1, 10);
561 cache.insert(2, 20);
562 cache.insert(3, 30);
563 cache.insert(4, 40);
564 cache.insert(5, 50);
565 assert_eq!(cache.iter().collect::<Vec<_>>(),
566 [(&3, &30), (&4, &40), (&5, &50)]);
567 assert_eq!(cache.iter_mut().collect::<Vec<_>>(),
568 [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]);
569 assert_eq!(cache.iter().rev().collect::<Vec<_>>(),
570 [(&5, &50), (&4, &40), (&3, &30)]);
571 assert_eq!(cache.iter_mut().rev().collect::<Vec<_>>(),
572 [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]);
573 }
574}