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}