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}