lru_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    /// Removes the given key from the cache and returns its corresponding value.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// use lru_cache::LruCache;
157    ///
158    /// let mut cache = LruCache::new(2);
159    ///
160    /// cache.insert(2, "a");
161    ///
162    /// assert_eq!(cache.remove(&1), None);
163    /// assert_eq!(cache.remove(&2), Some("a"));
164    /// assert_eq!(cache.remove(&2), None);
165    /// assert_eq!(cache.len(), 0);
166    /// ```
167    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
168        where K: Borrow<Q>,
169              Q: Hash + Eq
170    {
171        self.map.remove(k)
172    }
173
174    /// Returns the maximum number of key-value pairs the cache can hold.
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// use lru_cache::LruCache;
180    /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
181    /// assert_eq!(cache.capacity(), 2);
182    /// ```
183    pub fn capacity(&self) -> usize {
184        self.max_size
185    }
186
187    /// Sets the number of key-value pairs the cache can hold. Removes
188    /// least-recently-used key-value pairs if necessary.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use lru_cache::LruCache;
194    ///
195    /// let mut cache = LruCache::new(2);
196    ///
197    /// cache.insert(1, "a");
198    /// cache.insert(2, "b");
199    /// cache.insert(3, "c");
200    ///
201    /// assert_eq!(cache.get_mut(&1), None);
202    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
203    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
204    ///
205    /// cache.set_capacity(3);
206    /// cache.insert(1, "a");
207    /// cache.insert(2, "b");
208    ///
209    /// assert_eq!(cache.get_mut(&1), Some(&mut "a"));
210    /// assert_eq!(cache.get_mut(&2), Some(&mut "b"));
211    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
212    ///
213    /// cache.set_capacity(1);
214    ///
215    /// assert_eq!(cache.get_mut(&1), None);
216    /// assert_eq!(cache.get_mut(&2), None);
217    /// assert_eq!(cache.get_mut(&3), Some(&mut "c"));
218    /// ```
219    pub fn set_capacity(&mut self, capacity: usize) {
220        for _ in capacity..self.len() {
221            self.remove_lru();
222        }
223        self.max_size = capacity;
224    }
225
226    /// Removes and returns the least recently used key-value pair as a tuple.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use lru_cache::LruCache;
232    ///
233    /// let mut cache = LruCache::new(2);
234    ///
235    /// cache.insert(1, "a");
236    /// cache.insert(2, "b");
237    ///
238    /// assert_eq!(cache.remove_lru(), Some((1, "a")));
239    /// assert_eq!(cache.len(), 1);
240    /// ```
241    #[inline]
242    pub fn remove_lru(&mut self) -> Option<(K, V)> {
243        self.map.pop_front()
244    }
245
246    /// Returns the number of key-value pairs in the cache.
247    pub fn len(&self) -> usize { self.map.len() }
248
249    /// Returns `true` if the cache contains no key-value pairs.
250    pub fn is_empty(&self) -> bool { self.map.is_empty() }
251
252    /// Removes all key-value pairs from the cache.
253    pub fn clear(&mut self) { self.map.clear(); }
254
255    /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order.
256    ///
257    /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// use lru_cache::LruCache;
263    ///
264    /// let mut cache = LruCache::new(2);
265    ///
266    /// cache.insert(1, 10);
267    /// cache.insert(2, 20);
268    /// cache.insert(3, 30);
269    ///
270    /// let kvs: Vec<_> = cache.iter().collect();
271    /// assert_eq!(kvs, [(&2, &20), (&3, &30)]);
272    /// ```
273    pub fn iter(&self) -> Iter<K, V> { Iter(self.map.iter()) }
274
275    /// Returns an iterator over the cache's key-value pairs in least- to most-recently-used order,
276    /// with mutable references to the values.
277    ///
278    /// Accessing the cache through the iterator does _not_ affect the cache's LRU state.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use lru_cache::LruCache;
284    ///
285    /// let mut cache = LruCache::new(2);
286    ///
287    /// cache.insert(1, 10);
288    /// cache.insert(2, 20);
289    /// cache.insert(3, 30);
290    ///
291    /// let mut n = 2;
292    ///
293    /// for (k, v) in cache.iter_mut() {
294    ///     assert_eq!(*k, n);
295    ///     assert_eq!(*v, n * 10);
296    ///     *v *= 10;
297    ///     n += 1;
298    /// }
299    ///
300    /// assert_eq!(n, 4);
301    /// assert_eq!(cache.get_mut(&2), Some(&mut 200));
302    /// assert_eq!(cache.get_mut(&3), Some(&mut 300));
303    /// ```
304    pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) }
305}
306
307impl<K: Eq + Hash, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> {
308    fn extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I) {
309        for (k, v) in iter {
310            self.insert(k, v);
311        }
312    }
313}
314
315impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for LruCache<K, V, S> {
316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317        f.debug_map().entries(self.iter().rev()).finish()
318    }
319}
320
321impl<K: Eq + Hash, V, S: BuildHasher> IntoIterator for LruCache<K, V, S> {
322    type Item = (K, V);
323    type IntoIter = IntoIter<K, V>;
324
325    fn into_iter(self) -> IntoIter<K, V> {
326        IntoIter(self.map.into_iter())
327    }
328}
329
330impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a LruCache<K, V, S> {
331    type Item = (&'a K, &'a V);
332    type IntoIter = Iter<'a, K, V>;
333    fn into_iter(self) -> Iter<'a, K, V> { self.iter() }
334}
335
336impl<'a, K: Eq + Hash, V, S: BuildHasher> IntoIterator for &'a mut LruCache<K, V, S> {
337    type Item = (&'a K, &'a mut V);
338    type IntoIter = IterMut<'a, K, V>;
339    fn into_iter(self) -> IterMut<'a, K, V> { self.iter_mut() }
340}
341
342/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
343///
344/// # Examples
345///
346/// ```
347/// use lru_cache::LruCache;
348///
349/// let mut cache = LruCache::new(2);
350///
351/// cache.insert(1, 10);
352/// cache.insert(2, 20);
353/// cache.insert(3, 30);
354///
355/// let mut n = 2;
356///
357/// for (k, v) in cache {
358///     assert_eq!(k, n);
359///     assert_eq!(v, n * 10);
360///     n += 1;
361/// }
362///
363/// assert_eq!(n, 4);
364/// ```
365#[derive(Clone)]
366pub struct IntoIter<K, V>(linked_hash_map::IntoIter<K, V>);
367
368impl<K, V> Iterator for IntoIter<K, V> {
369    type Item = (K, V);
370
371    fn next(&mut self) -> Option<(K, V)> {
372        self.0.next()
373    }
374
375    fn size_hint(&self) -> (usize, Option<usize>) {
376        self.0.size_hint()
377    }
378}
379
380impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
381    fn next_back(&mut self) -> Option<(K, V)> {
382        self.0.next_back()
383    }
384}
385
386impl<K, V> ExactSizeIterator for IntoIter<K, V> {
387    fn len(&self) -> usize {
388        self.0.len()
389    }
390}
391
392/// An iterator over a cache's key-value pairs in least- to most-recently-used order.
393///
394/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
395pub struct Iter<'a, K: 'a, V: 'a>(linked_hash_map::Iter<'a, K, V>);
396
397impl<'a, K, V> Clone for Iter<'a, K, V> {
398    fn clone(&self) -> Iter<'a, K, V> { Iter(self.0.clone()) }
399}
400
401impl<'a, K, V> Iterator for Iter<'a, K, V> {
402    type Item = (&'a K, &'a V);
403    fn next(&mut self) -> Option<(&'a K, &'a V)> { self.0.next() }
404    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
405}
406
407impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
408    fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.0.next_back() }
409}
410
411impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
412    fn len(&self) -> usize { self.0.len() }
413}
414
415/// An iterator over a cache's key-value pairs in least- to most-recently-used order with mutable
416/// references to the values.
417///
418/// Accessing a cache through the iterator does _not_ affect the cache's LRU state.
419pub struct IterMut<'a, K: 'a, V: 'a>(linked_hash_map::IterMut<'a, K, V>);
420
421impl<'a, K, V> Iterator for IterMut<'a, K, V> {
422    type Item = (&'a K, &'a mut V);
423    fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next() }
424    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
425}
426
427impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
428    fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next_back() }
429}
430
431impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
432    fn len(&self) -> usize { self.0.len() }
433}
434
435#[cfg(test)]
436mod tests {
437    use super::LruCache;
438
439    #[test]
440    fn test_put_and_get() {
441        let mut cache = LruCache::new(2);
442        cache.insert(1, 10);
443        cache.insert(2, 20);
444        assert_eq!(cache.get_mut(&1), Some(&mut 10));
445        assert_eq!(cache.get_mut(&2), Some(&mut 20));
446        assert_eq!(cache.len(), 2);
447    }
448
449    #[test]
450    fn test_put_update() {
451        let mut cache = LruCache::new(1);
452        cache.insert("1", 10);
453        cache.insert("1", 19);
454        assert_eq!(cache.get_mut("1"), Some(&mut 19));
455        assert_eq!(cache.len(), 1);
456    }
457
458    #[test]
459    fn test_contains_key() {
460        let mut cache = LruCache::new(1);
461        cache.insert("1", 10);
462        assert_eq!(cache.contains_key("1"), true);
463    }
464
465    #[test]
466    fn test_expire_lru() {
467        let mut cache = LruCache::new(2);
468        cache.insert("foo1", "bar1");
469        cache.insert("foo2", "bar2");
470        cache.insert("foo3", "bar3");
471        assert!(cache.get_mut("foo1").is_none());
472        cache.insert("foo2", "bar2update");
473        cache.insert("foo4", "bar4");
474        assert!(cache.get_mut("foo3").is_none());
475    }
476
477    #[test]
478    fn test_pop() {
479        let mut cache = LruCache::new(2);
480        cache.insert(1, 10);
481        cache.insert(2, 20);
482        assert_eq!(cache.len(), 2);
483        let opt1 = cache.remove(&1);
484        assert!(opt1.is_some());
485        assert_eq!(opt1.unwrap(), 10);
486        assert!(cache.get_mut(&1).is_none());
487        assert_eq!(cache.len(), 1);
488    }
489
490    #[test]
491    fn test_change_capacity() {
492        let mut cache = LruCache::new(2);
493        assert_eq!(cache.capacity(), 2);
494        cache.insert(1, 10);
495        cache.insert(2, 20);
496        cache.set_capacity(1);
497        assert!(cache.get_mut(&1).is_none());
498        assert_eq!(cache.capacity(), 1);
499    }
500
501    #[test]
502    fn test_debug() {
503        let mut cache = LruCache::new(3);
504        cache.insert(1, 10);
505        cache.insert(2, 20);
506        cache.insert(3, 30);
507        assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
508        cache.insert(2, 22);
509        assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
510        cache.insert(6, 60);
511        assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
512        cache.get_mut(&3);
513        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
514        cache.set_capacity(2);
515        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
516    }
517
518    #[test]
519    fn test_remove() {
520        let mut cache = LruCache::new(3);
521        cache.insert(1, 10);
522        cache.insert(2, 20);
523        cache.insert(3, 30);
524        cache.insert(4, 40);
525        cache.insert(5, 50);
526        cache.remove(&3);
527        cache.remove(&4);
528        assert!(cache.get_mut(&3).is_none());
529        assert!(cache.get_mut(&4).is_none());
530        cache.insert(6, 60);
531        cache.insert(7, 70);
532        cache.insert(8, 80);
533        assert!(cache.get_mut(&5).is_none());
534        assert_eq!(cache.get_mut(&6), Some(&mut 60));
535        assert_eq!(cache.get_mut(&7), Some(&mut 70));
536        assert_eq!(cache.get_mut(&8), Some(&mut 80));
537    }
538
539    #[test]
540    fn test_clear() {
541        let mut cache = LruCache::new(2);
542        cache.insert(1, 10);
543        cache.insert(2, 20);
544        cache.clear();
545        assert!(cache.get_mut(&1).is_none());
546        assert!(cache.get_mut(&2).is_none());
547        assert_eq!(format!("{:?}", cache), "{}");
548    }
549
550    #[test]
551    fn test_iter() {
552        let mut cache = LruCache::new(3);
553        cache.insert(1, 10);
554        cache.insert(2, 20);
555        cache.insert(3, 30);
556        cache.insert(4, 40);
557        cache.insert(5, 50);
558        assert_eq!(cache.iter().collect::<Vec<_>>(),
559                   [(&3, &30), (&4, &40), (&5, &50)]);
560        assert_eq!(cache.iter_mut().collect::<Vec<_>>(),
561                   [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]);
562        assert_eq!(cache.iter().rev().collect::<Vec<_>>(),
563                   [(&5, &50), (&4, &40), (&3, &30)]);
564        assert_eq!(cache.iter_mut().rev().collect::<Vec<_>>(),
565                   [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]);
566    }
567}