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 40 extern crate linked_hash_map; 41 42 use std::borrow::Borrow; 43 use std::collections::hash_map::RandomState; 44 use std::fmt; 45 use std::hash::{Hash, BuildHasher}; 46 47 use linked_hash_map::LinkedHashMap; 48 49 #[cfg(feature = "heapsize_impl")] 50 mod heapsize; 51 52 // FIXME(conventions): implement indexing? 53 54 /// An LRU cache. 55 #[derive(Clone)] 56 pub struct LruCache<K: Eq + Hash, V, S: BuildHasher = RandomState> { 57 map: LinkedHashMap<K, V, S>, 58 max_size: usize, 59 } 60 61 impl<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 /// ``` new(capacity: usize) -> Self70 pub fn new(capacity: usize) -> Self { 71 LruCache { 72 map: LinkedHashMap::new(), 73 max_size: capacity, 74 } 75 } 76 } 77 78 impl<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. with_hasher(capacity: usize, hash_builder: S) -> Self80 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 /// ``` contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq96 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 /// ``` insert(&mut self, k: K, v: V) -> Option<V>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 /// ``` get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Hash + Eq144 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 /// ``` remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Hash + Eq167 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 /// ``` capacity(&self) -> usize183 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 /// ``` set_capacity(&mut self, capacity: usize)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] remove_lru(&mut self) -> Option<(K, V)>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. len(&self) -> usize247 pub fn len(&self) -> usize { self.map.len() } 248 249 /// Returns `true` if the cache contains no key-value pairs. is_empty(&self) -> bool250 pub fn is_empty(&self) -> bool { self.map.is_empty() } 251 252 /// Removes all key-value pairs from the cache. clear(&mut self)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 /// ``` iter(&self) -> Iter<K, V>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 /// ``` iter_mut(&mut self) -> IterMut<K, V>304 pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut(self.map.iter_mut()) } 305 } 306 307 impl<K: Eq + Hash, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> { extend<I: IntoIterator<Item=(K, V)>>(&mut self, iter: I)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 315 impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for LruCache<K, V, S> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 317 f.debug_map().entries(self.iter().rev()).finish() 318 } 319 } 320 321 impl<K: Eq + Hash, V, S: BuildHasher> IntoIterator for LruCache<K, V, S> { 322 type Item = (K, V); 323 type IntoIter = IntoIter<K, V>; 324 into_iter(self) -> IntoIter<K, V>325 fn into_iter(self) -> IntoIter<K, V> { 326 IntoIter(self.map.into_iter()) 327 } 328 } 329 330 impl<'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>; into_iter(self) -> Iter<'a, K, V>333 fn into_iter(self) -> Iter<'a, K, V> { self.iter() } 334 } 335 336 impl<'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>; into_iter(self) -> 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)] 366 pub struct IntoIter<K, V>(linked_hash_map::IntoIter<K, V>); 367 368 impl<K, V> Iterator for IntoIter<K, V> { 369 type Item = (K, V); 370 next(&mut self) -> Option<(K, V)>371 fn next(&mut self) -> Option<(K, V)> { 372 self.0.next() 373 } 374 size_hint(&self) -> (usize, Option<usize>)375 fn size_hint(&self) -> (usize, Option<usize>) { 376 self.0.size_hint() 377 } 378 } 379 380 impl<K, V> DoubleEndedIterator for IntoIter<K, V> { next_back(&mut self) -> Option<(K, V)>381 fn next_back(&mut self) -> Option<(K, V)> { 382 self.0.next_back() 383 } 384 } 385 386 impl<K, V> ExactSizeIterator for IntoIter<K, V> { len(&self) -> usize387 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. 395 pub struct Iter<'a, K: 'a, V: 'a>(linked_hash_map::Iter<'a, K, V>); 396 397 impl<'a, K, V> Clone for Iter<'a, K, V> { clone(&self) -> Iter<'a, K, V>398 fn clone(&self) -> Iter<'a, K, V> { Iter(self.0.clone()) } 399 } 400 401 impl<'a, K, V> Iterator for Iter<'a, K, V> { 402 type Item = (&'a K, &'a V); next(&mut self) -> Option<(&'a K, &'a V)>403 fn next(&mut self) -> Option<(&'a K, &'a V)> { self.0.next() } size_hint(&self) -> (usize, Option<usize>)404 fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } 405 } 406 407 impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { next_back(&mut self) -> Option<(&'a K, &'a V)>408 fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.0.next_back() } 409 } 410 411 impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { len(&self) -> usize412 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. 419 pub struct IterMut<'a, K: 'a, V: 'a>(linked_hash_map::IterMut<'a, K, V>); 420 421 impl<'a, K, V> Iterator for IterMut<'a, K, V> { 422 type Item = (&'a K, &'a mut V); next(&mut self) -> Option<(&'a K, &'a mut V)>423 fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next() } size_hint(&self) -> (usize, Option<usize>)424 fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() } 425 } 426 427 impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { next_back(&mut self) -> Option<(&'a K, &'a mut V)>428 fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.0.next_back() } 429 } 430 431 impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { len(&self) -> usize432 fn len(&self) -> usize { self.0.len() } 433 } 434 435 #[cfg(test)] 436 mod tests { 437 use super::LruCache; 438 439 #[test] test_put_and_get()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] test_put_update()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] test_contains_key()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] test_expire_lru()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] test_pop()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] test_change_capacity()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] test_debug()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] test_remove()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] test_clear()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] test_iter()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 } 568