1 use core::{ 2 borrow::Borrow, 3 fmt, 4 hash::{BuildHasher, Hash}, 5 }; 6 7 use crate::linked_hash_map::{self, LinkedHashMap}; 8 use crate::DefaultHashBuilder; 9 10 pub use crate::linked_hash_map::{ 11 Drain, Entry, IntoIter, Iter, IterMut, OccupiedEntry, RawEntryBuilder, RawEntryBuilderMut, 12 RawOccupiedEntryMut, RawVacantEntryMut, VacantEntry, 13 }; 14 15 pub struct LruCache<K, V, S = DefaultHashBuilder> { 16 map: LinkedHashMap<K, V, S>, 17 max_size: usize, 18 } 19 20 impl<K: Eq + Hash, V> LruCache<K, V> { 21 #[inline] new(capacity: usize) -> Self22 pub fn new(capacity: usize) -> Self { 23 LruCache { 24 map: LinkedHashMap::new(), 25 max_size: capacity, 26 } 27 } 28 29 /// Create a new unbounded `LruCache` that does not automatically evict entries. 30 /// 31 /// A simple convenience method that is equivalent to `LruCache::new(usize::MAX)` 32 #[inline] new_unbounded() -> Self33 pub fn new_unbounded() -> Self { 34 LruCache::new(usize::MAX) 35 } 36 } 37 38 impl<K, V, S> LruCache<K, V, S> { 39 #[inline] with_hasher(capacity: usize, hash_builder: S) -> Self40 pub fn with_hasher(capacity: usize, hash_builder: S) -> Self { 41 LruCache { 42 map: LinkedHashMap::with_hasher(hash_builder), 43 max_size: capacity, 44 } 45 } 46 47 #[inline] capacity(&self) -> usize48 pub fn capacity(&self) -> usize { 49 self.max_size 50 } 51 52 #[inline] len(&self) -> usize53 pub fn len(&self) -> usize { 54 self.map.len() 55 } 56 57 #[inline] is_empty(&self) -> bool58 pub fn is_empty(&self) -> bool { 59 self.map.is_empty() 60 } 61 62 #[inline] clear(&mut self)63 pub fn clear(&mut self) { 64 self.map.clear(); 65 } 66 67 #[inline] iter(&self) -> Iter<K, V>68 pub fn iter(&self) -> Iter<K, V> { 69 self.map.iter() 70 } 71 72 #[inline] iter_mut(&mut self) -> IterMut<K, V>73 pub fn iter_mut(&mut self) -> IterMut<K, V> { 74 self.map.iter_mut() 75 } 76 77 #[inline] drain(&mut self) -> Drain<K, V>78 pub fn drain(&mut self) -> Drain<K, V> { 79 self.map.drain() 80 } 81 } 82 83 impl<K: Eq + Hash, V, S> LruCache<K, V, S> 84 where 85 S: BuildHasher, 86 { 87 #[inline] contains_key<Q>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq + ?Sized,88 pub fn contains_key<Q>(&self, key: &Q) -> bool 89 where 90 K: Borrow<Q>, 91 Q: Hash + Eq + ?Sized, 92 { 93 self.map.contains_key(key) 94 } 95 96 /// Insert a new value into the `LruCache`. 97 /// 98 /// If necessary, will remove the value at the front of the LRU list to make room. 99 #[inline] insert(&mut self, k: K, v: V) -> Option<V>100 pub fn insert(&mut self, k: K, v: V) -> Option<V> { 101 let old_val = self.map.insert(k, v); 102 if self.len() > self.capacity() { 103 self.remove_lru(); 104 } 105 old_val 106 } 107 108 /// Get the value for the given key, *without* marking the value as recently used and moving it 109 /// to the back of the LRU list. 110 #[inline] peek<Q>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,111 pub fn peek<Q>(&self, k: &Q) -> Option<&V> 112 where 113 K: Borrow<Q>, 114 Q: Hash + Eq + ?Sized, 115 { 116 self.map.get(k) 117 } 118 119 /// Get the value for the given key mutably, *without* marking the value as recently used and 120 /// moving it to the back of the LRU list. 121 #[inline] peek_mut<Q>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,122 pub fn peek_mut<Q>(&mut self, k: &Q) -> Option<&mut V> 123 where 124 K: Borrow<Q>, 125 Q: Hash + Eq + ?Sized, 126 { 127 self.map.get_mut(k) 128 } 129 130 /// Retrieve the given key, marking it as recently used and moving it to the back of the LRU 131 /// list. 132 #[inline] get<Q>(&mut self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,133 pub fn get<Q>(&mut self, k: &Q) -> Option<&V> 134 where 135 K: Borrow<Q>, 136 Q: Hash + Eq + ?Sized, 137 { 138 self.get_mut(k).map(|v| &*v) 139 } 140 141 /// Retrieve the given key, marking it as recently used and moving it to the back of the LRU 142 /// list. 143 #[inline] get_mut<Q>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,144 pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V> 145 where 146 K: Borrow<Q>, 147 Q: Hash + Eq + ?Sized, 148 { 149 match self.map.raw_entry_mut().from_key(k) { 150 linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 151 occupied.to_back(); 152 Some(occupied.into_mut()) 153 } 154 linked_hash_map::RawEntryMut::Vacant(_) => None, 155 } 156 } 157 158 /// If the returned entry is vacant, it will always have room to insert a single value. By 159 /// using the entry API, you can exceed the configured capacity by 1. 160 /// 161 /// The returned entry is not automatically moved to the back of the LRU list. By calling 162 /// `Entry::to_back` / `Entry::to_front` you can manually control the position of this entry in 163 /// the LRU list. 164 #[inline] entry(&mut self, key: K) -> Entry<'_, K, V, S>165 pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { 166 if self.len() > self.capacity() { 167 self.remove_lru(); 168 } 169 self.map.entry(key) 170 } 171 172 /// The constructed raw entry is never automatically moved to the back of the LRU list. By 173 /// calling `Entry::to_back` / `Entry::to_front` you can manually control the position of this 174 /// entry in the LRU list. 175 #[inline] raw_entry(&self) -> RawEntryBuilder<'_, K, V, S>176 pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { 177 self.map.raw_entry() 178 } 179 180 /// If the constructed raw entry is vacant, it will always have room to insert a single value. 181 /// By using the raw entry API, you can exceed the configured capacity by 1. 182 /// 183 /// The constructed raw entry is never automatically moved to the back of the LRU list. By 184 /// calling `Entry::to_back` / `Entry::to_front` you can manually control the position of this 185 /// entry in the LRU list. 186 #[inline] raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S>187 pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { 188 if self.len() > self.capacity() { 189 self.remove_lru(); 190 } 191 self.map.raw_entry_mut() 192 } 193 194 #[inline] remove<Q>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,195 pub fn remove<Q>(&mut self, k: &Q) -> Option<V> 196 where 197 K: Borrow<Q>, 198 Q: Hash + Eq + ?Sized, 199 { 200 self.map.remove(k) 201 } 202 203 #[inline] remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,204 pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)> 205 where 206 K: Borrow<Q>, 207 Q: Hash + Eq + ?Sized, 208 { 209 self.map.remove_entry(k) 210 } 211 212 /// Set the new cache capacity for the `LruCache`. 213 /// 214 /// If there are more entries in the `LruCache` than the new capacity will allow, they are 215 /// removed. 216 #[inline] set_capacity(&mut self, capacity: usize)217 pub fn set_capacity(&mut self, capacity: usize) { 218 for _ in capacity..self.len() { 219 self.remove_lru(); 220 } 221 self.max_size = capacity; 222 } 223 224 /// Remove the least recently used entry and return it. 225 /// 226 /// If the `LruCache` is empty this will return None. 227 #[inline] remove_lru(&mut self) -> Option<(K, V)>228 pub fn remove_lru(&mut self) -> Option<(K, V)> { 229 self.map.pop_front() 230 } 231 } 232 233 impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher + Clone> Clone for LruCache<K, V, S> { 234 #[inline] clone(&self) -> Self235 fn clone(&self) -> Self { 236 LruCache { 237 map: self.map.clone(), 238 max_size: self.max_size, 239 } 240 } 241 } 242 243 impl<K: Eq + Hash, V, S: BuildHasher> Extend<(K, V)> for LruCache<K, V, S> { 244 #[inline] extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I)245 fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) { 246 for (k, v) in iter { 247 self.insert(k, v); 248 } 249 } 250 } 251 252 impl<K, V, S> IntoIterator for LruCache<K, V, S> { 253 type Item = (K, V); 254 type IntoIter = IntoIter<K, V>; 255 256 #[inline] into_iter(self) -> IntoIter<K, V>257 fn into_iter(self) -> IntoIter<K, V> { 258 self.map.into_iter() 259 } 260 } 261 262 impl<'a, K, V, S> IntoIterator for &'a LruCache<K, V, S> { 263 type Item = (&'a K, &'a V); 264 type IntoIter = Iter<'a, K, V>; 265 266 #[inline] into_iter(self) -> Iter<'a, K, V>267 fn into_iter(self) -> Iter<'a, K, V> { 268 self.iter() 269 } 270 } 271 272 impl<'a, K, V, S> IntoIterator for &'a mut LruCache<K, V, S> { 273 type Item = (&'a K, &'a mut V); 274 type IntoIter = IterMut<'a, K, V>; 275 276 #[inline] into_iter(self) -> IterMut<'a, K, V>277 fn into_iter(self) -> IterMut<'a, K, V> { 278 self.iter_mut() 279 } 280 } 281 282 impl<K, V, S> fmt::Debug for LruCache<K, V, S> 283 where 284 K: fmt::Debug, 285 V: fmt::Debug, 286 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result287 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 288 f.debug_map().entries(self.iter().rev()).finish() 289 } 290 } 291