diff --git a/README.md b/README.md index f699923..1ff7f48 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,9 @@ Below is a simple example of how to instantiate and use a LRU cache. extern crate lru; use lru::LruCache; -use std::num::NonZeroUsize; fn main() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", 3); cache.put("banana", 2); diff --git a/src/lib.rs b/src/lib.rs index cd57a96..6050c7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,10 +30,9 @@ //! extern crate lru; //! //! use lru::LruCache; -//! use std::num::NonZeroUsize; //! //! fn main() { -//! let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); +//! let mut cache = LruCache::new(2); //! cache.put("apple", 3); //! cache.put("banana", 2); //! @@ -72,7 +71,6 @@ use core::hash::{BuildHasher, Hash, Hasher}; use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem; -use core::num::NonZeroUsize; use core::ptr::{self, NonNull}; use core::usize; @@ -179,7 +177,7 @@ pub type DefaultHasher = std::collections::hash_map::RandomState; /// An LRU Cache pub struct LruCache { map: HashMap, NonNull>, S>, - cap: NonZeroUsize, + cap: usize, // head and tail are sigil nodes to facilitate inserting entries head: *mut LruEntry, @@ -193,11 +191,10 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache: LruCache = LruCache::new(NonZeroUsize::new(10).unwrap()); + /// let mut cache: LruCache = LruCache::new(10); /// ``` - pub fn new(cap: NonZeroUsize) -> LruCache { - LruCache::construct(cap, HashMap::with_capacity(cap.get())) + pub fn new(cap: usize) -> LruCache { + LruCache::construct(cap, HashMap::with_capacity(cap)) } /// Creates a new LRU Cache that never automatically evicts items. @@ -206,11 +203,10 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; /// let mut cache: LruCache = LruCache::unbounded(); /// ``` pub fn unbounded() -> LruCache { - LruCache::construct(NonZeroUsize::new(usize::MAX).unwrap(), HashMap::default()) + LruCache::construct(usize::MAX, HashMap::default()) } } @@ -222,16 +218,12 @@ impl LruCache { /// /// ``` /// use lru::{LruCache, DefaultHasher}; - /// use std::num::NonZeroUsize; /// /// let s = DefaultHasher::default(); - /// let mut cache: LruCache = LruCache::with_hasher(NonZeroUsize::new(10).unwrap(), s); + /// let mut cache: LruCache = LruCache::with_hasher(10, s); /// ``` - pub fn with_hasher(cap: NonZeroUsize, hash_builder: S) -> LruCache { - LruCache::construct( - cap, - HashMap::with_capacity_and_hasher(cap.into(), hash_builder), - ) + pub fn with_hasher(cap: usize, hash_builder: S) -> LruCache { + LruCache::construct(cap, HashMap::with_capacity_and_hasher(cap, hash_builder)) } /// Creates a new LRU Cache that never automatically evicts items and @@ -246,15 +238,12 @@ impl LruCache { /// let mut cache: LruCache = LruCache::unbounded_with_hasher(s); /// ``` pub fn unbounded_with_hasher(hash_builder: S) -> LruCache { - LruCache::construct( - NonZeroUsize::new(usize::MAX).unwrap(), - HashMap::with_hasher(hash_builder), - ) + LruCache::construct(usize::MAX, HashMap::with_hasher(hash_builder)) } /// Creates a new LRU Cache with the given capacity. fn construct( - cap: NonZeroUsize, + cap: usize, map: HashMap, NonNull>, S>, ) -> LruCache { // NB: The compiler warns that cache does not need to be marked as mutable if we @@ -281,8 +270,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// assert_eq!(None, cache.put(1, "a")); /// assert_eq!(None, cache.put(2, "b")); @@ -303,8 +291,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// assert_eq!(None, cache.push(1, "a")); /// assert_eq!(None, cache.push(2, "b")); @@ -345,6 +332,10 @@ impl LruCache { Some((k, v)) } None => { + // if the capacity is zero, do nothing + if self.cap() == 0 { + return None; + } let (replaced, node) = self.replace_or_create_node(k, v); let node_ptr: *mut LruEntry = node.as_ptr(); @@ -362,7 +353,8 @@ impl LruCache { // is available. Shared between `put`, `push`, `get_or_insert`, and `get_or_insert_mut`. #[allow(clippy::type_complexity)] fn replace_or_create_node(&mut self, k: K, v: V) -> (Option<(K, V)>, NonNull>) { - if self.len() == self.cap().get() { + debug_assert_ne!(self.cap(), 0); + if self.len() == self.cap() { // if the cache is full, remove the last entry so we can use it for the new key let old_key = KeyRef { k: unsafe { &(*(*(*self.tail).prev).key.as_ptr()) }, @@ -397,8 +389,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -433,8 +424,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put("apple", 8); /// cache.put("banana", 4); @@ -467,24 +457,26 @@ impl LruCache { /// If the key does not exist the provided `FnOnce` is used to populate /// the list and a reference is returned. /// + /// This method will only return `None` when the capacity of the cache is 0 and no entries + /// can be populated. + /// /// # Example /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); /// cache.put(2, "c"); /// cache.put(3, "d"); /// - /// assert_eq!(cache.get_or_insert(2, ||"a"), &"c"); - /// assert_eq!(cache.get_or_insert(3, ||"a"), &"d"); - /// assert_eq!(cache.get_or_insert(1, ||"a"), &"a"); - /// assert_eq!(cache.get_or_insert(1, ||"b"), &"a"); + /// assert_eq!(cache.get_or_insert(2, ||"a"), Some(&"c")); + /// assert_eq!(cache.get_or_insert(3, ||"a"), Some(&"d")); + /// assert_eq!(cache.get_or_insert(1, ||"a"), Some(&"a")); + /// assert_eq!(cache.get_or_insert(1, ||"b"), Some(&"a")); /// ``` - pub fn get_or_insert<'a, F>(&'a mut self, k: K, f: F) -> &'a V + pub fn get_or_insert<'a, F>(&'a mut self, k: K, f: F) -> Option<&'a V> where F: FnOnce() -> V, { @@ -494,8 +486,13 @@ impl LruCache { self.detach(node_ptr); self.attach(node_ptr); - unsafe { &*(*node_ptr).val.as_ptr() } + Some(unsafe { &*(*node_ptr).val.as_ptr() }) } else { + // If the capacity is 0 we do nothing, + // this is the only circumstance that should return None + if self.cap() == 0 { + return None; + } let v = f(); let (_, node) = self.replace_or_create_node(k, v); let node_ptr: *mut LruEntry = node.as_ptr(); @@ -504,7 +501,7 @@ impl LruCache { let keyref = unsafe { (*node_ptr).key.as_ptr() }; self.map.insert(KeyRef { k: keyref }, node); - unsafe { &*(*node_ptr).val.as_ptr() } + Some(unsafe { &*(*node_ptr).val.as_ptr() }) } } @@ -518,8 +515,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -529,13 +525,13 @@ impl LruCache { /// let f = ||->Result<&str, String> {Err("failed".to_owned())}; /// let a = ||->Result<&str, String> {Ok("a")}; /// let b = ||->Result<&str, String> {Ok("b")}; - /// assert_eq!(cache.try_get_or_insert(2, a), Ok(&"c")); - /// assert_eq!(cache.try_get_or_insert(3, a), Ok(&"d")); + /// assert_eq!(cache.try_get_or_insert(2, a), Ok(Some(&"c"))); + /// assert_eq!(cache.try_get_or_insert(3, a), Ok(Some(&"d"))); /// assert_eq!(cache.try_get_or_insert(1, f), Err("failed".to_owned())); - /// assert_eq!(cache.try_get_or_insert(1, b), Ok(&"b")); - /// assert_eq!(cache.try_get_or_insert(1, a), Ok(&"b")); + /// assert_eq!(cache.try_get_or_insert(1, b), Ok(Some(&"b"))); + /// assert_eq!(cache.try_get_or_insert(1, a), Ok(Some(&"b"))); /// ``` - pub fn try_get_or_insert(&mut self, k: K, f: F) -> Result<&V, E> + pub fn try_get_or_insert(&mut self, k: K, f: F) -> Result, E> where F: FnOnce() -> Result, { @@ -545,11 +541,14 @@ impl LruCache { self.detach(node_ptr); self.attach(node_ptr); - unsafe { Ok(&*(*node_ptr).val.as_ptr()) } + Ok(Some(unsafe { &*(*node_ptr).val.as_ptr() })) } else { match f() { Err(e) => Err(e), Ok(v) => { + if self.cap() == 0 { + return Ok(None); + } let (_, node) = self.replace_or_create_node(k, v); let node_ptr: *mut LruEntry = node.as_ptr(); @@ -557,7 +556,7 @@ impl LruCache { let keyref = unsafe { (*node_ptr).key.as_ptr() }; self.map.insert(KeyRef { k: keyref }, node); - Ok(unsafe { &*(*node_ptr).val.as_ptr() }) + Ok(Some(unsafe { &*(*node_ptr).val.as_ptr() })) } } } @@ -572,20 +571,19 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); /// /// let v = cache.get_or_insert_mut(2, ||"c"); - /// assert_eq!(v, &"b"); - /// *v = "d"; - /// assert_eq!(cache.get_or_insert_mut(2, ||"e"), &mut "d"); - /// assert_eq!(cache.get_or_insert_mut(3, ||"f"), &mut "f"); - /// assert_eq!(cache.get_or_insert_mut(3, ||"e"), &mut "f"); + /// assert_eq!(v, Some(&mut "b")); + /// *v.unwrap() = "d"; + /// assert_eq!(cache.get_or_insert_mut(2, ||"e"), Some(&mut "d")); + /// assert_eq!(cache.get_or_insert_mut(3, ||"f"), Some(&mut "f")); + /// assert_eq!(cache.get_or_insert_mut(3, ||"e"), Some(&mut "f")); /// ``` - pub fn get_or_insert_mut<'a, F>(&'a mut self, k: K, f: F) -> &'a mut V + pub fn get_or_insert_mut<'a, F>(&'a mut self, k: K, f: F) -> Option<&'a mut V> where F: FnOnce() -> V, { @@ -595,9 +593,12 @@ impl LruCache { self.detach(node_ptr); self.attach(node_ptr); - unsafe { &mut *(*node_ptr).val.as_mut_ptr() } + Some(unsafe { &mut *(*node_ptr).val.as_mut_ptr() }) } else { let v = f(); + if self.cap() == 0 { + return None; + } let (_, node) = self.replace_or_create_node(k, v); let node_ptr: *mut LruEntry = node.as_ptr(); @@ -605,7 +606,7 @@ impl LruCache { let keyref = unsafe { (*node_ptr).key.as_ptr() }; self.map.insert(KeyRef { k: keyref }, node); - unsafe { &mut *(*node_ptr).val.as_mut_ptr() } + Some(unsafe { &mut *(*node_ptr).val.as_mut_ptr() }) } } @@ -617,8 +618,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -644,8 +644,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -672,8 +671,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -702,8 +700,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -728,8 +725,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(2, "a"); /// @@ -768,8 +764,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "a"); @@ -805,8 +800,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// /// cache.put(2, "a"); /// cache.put(3, "b"); @@ -832,8 +826,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + /// let mut cache = LruCache::new(3); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -866,8 +859,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + /// let mut cache = LruCache::new(3); /// /// cache.put(1, "a"); /// cache.put(2, "b"); @@ -902,8 +894,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// assert_eq!(cache.len(), 0); /// /// cache.put(1, "a"); @@ -925,8 +916,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache = LruCache::new(2); /// assert!(cache.is_empty()); /// /// cache.put(1, "a"); @@ -942,11 +932,10 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache: LruCache = LruCache::new(NonZeroUsize::new(2).unwrap()); - /// assert_eq!(cache.cap().get(), 2); + /// let mut cache: LruCache = LruCache::new(2); + /// assert_eq!(cache.cap(), 2); /// ``` - pub fn cap(&self) -> NonZeroUsize { + pub fn cap(&self) -> usize { self.cap } @@ -957,12 +946,11 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache: LruCache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache: LruCache = LruCache::new(2); /// /// cache.put(1, "a"); /// cache.put(2, "b"); - /// cache.resize(NonZeroUsize::new(4).unwrap()); + /// cache.resize(4); /// cache.put(3, "c"); /// cache.put(4, "d"); /// @@ -972,13 +960,13 @@ impl LruCache { /// assert_eq!(cache.get(&3), Some(&"c")); /// assert_eq!(cache.get(&4), Some(&"d")); /// ``` - pub fn resize(&mut self, cap: NonZeroUsize) { + pub fn resize(&mut self, cap: usize) { // return early if capacity doesn't change if cap == self.cap { return; } - while self.map.len() > cap.get() { + while self.map.len() > cap { self.pop_lru(); } self.map.shrink_to_fit(); @@ -992,8 +980,7 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; - /// let mut cache: LruCache = LruCache::new(NonZeroUsize::new(2).unwrap()); + /// let mut cache: LruCache = LruCache::new(2); /// assert_eq!(cache.len(), 0); /// /// cache.put(1, "a"); @@ -1016,9 +1003,8 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; /// - /// let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + /// let mut cache = LruCache::new(3); /// cache.put("a", 1); /// cache.put("b", 2); /// cache.put("c", 3); @@ -1043,14 +1029,13 @@ impl LruCache { /// /// ``` /// use lru::LruCache; - /// use std::num::NonZeroUsize; /// /// struct HddBlock { /// dirty: bool, /// data: [u8; 512] /// } /// - /// let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + /// let mut cache = LruCache::new(3); /// cache.put(0, HddBlock { dirty: false, data: [0x00; 512]}); /// cache.put(1, HddBlock { dirty: true, data: [0x55; 512]}); /// cache.put(2, HddBlock { dirty: true, data: [0x77; 512]}); @@ -1356,7 +1341,7 @@ impl IntoIterator for LruCache { #[cfg(test)] mod tests { use super::LruCache; - use core::{fmt::Debug, num::NonZeroUsize}; + use core::fmt::Debug; use scoped_threadpool::Pool; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -1402,12 +1387,10 @@ mod tests { #[test] #[cfg(feature = "hashbrown")] fn test_with_hasher() { - use core::num::NonZeroUsize; - use hashbrown::hash_map::DefaultHashBuilder; let s = DefaultHashBuilder::default(); - let mut cache = LruCache::with_hasher(NonZeroUsize::new(16).unwrap(), s); + let mut cache = LruCache::with_hasher(16, s); for i in 0..13370 { cache.put(i, ()); @@ -1417,13 +1400,13 @@ mod tests { #[test] fn test_put_and_get() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert!(cache.is_empty()); assert_eq!(cache.put("apple", "red"), None); assert_eq!(cache.put("banana", "yellow"), None); - assert_eq!(cache.cap().get(), 2); + assert_eq!(cache.cap(), 2); assert_eq!(cache.len(), 2); assert!(!cache.is_empty()); assert_opt_eq(cache.get(&"apple"), "red"); @@ -1432,36 +1415,36 @@ mod tests { #[test] fn test_put_and_get_or_insert() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert!(cache.is_empty()); assert_eq!(cache.put("apple", "red"), None); assert_eq!(cache.put("banana", "yellow"), None); - assert_eq!(cache.cap().get(), 2); + assert_eq!(cache.cap(), 2); assert_eq!(cache.len(), 2); assert!(!cache.is_empty()); - assert_eq!(cache.get_or_insert("apple", || "orange"), &"red"); - assert_eq!(cache.get_or_insert("banana", || "orange"), &"yellow"); - assert_eq!(cache.get_or_insert("lemon", || "orange"), &"orange"); - assert_eq!(cache.get_or_insert("lemon", || "red"), &"orange"); + assert_opt_eq(cache.get_or_insert("apple", || "orange"), &"red"); + assert_opt_eq(cache.get_or_insert("banana", || "orange"), &"yellow"); + assert_opt_eq(cache.get_or_insert("lemon", || "orange"), &"orange"); + assert_opt_eq(cache.get_or_insert("lemon", || "red"), &"orange"); } #[test] fn test_try_get_or_insert() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert_eq!( cache.try_get_or_insert::<_, &str>("apple", || Ok("red")), - Ok(&"red") + Ok(Some(&"red")) ); assert_eq!( cache.try_get_or_insert::<_, &str>("apple", || Err("failed")), - Ok(&"red") + Ok(Some(&"red")) ); assert_eq!( cache.try_get_or_insert::<_, &str>("banana", || Ok("orange")), - Ok(&"orange") + Ok(Some(&"orange")) ); assert_eq!( cache.try_get_or_insert::<_, &str>("lemon", || Err("failed")), @@ -1469,39 +1452,51 @@ mod tests { ); assert_eq!( cache.try_get_or_insert::<_, &str>("banana", || Err("failed")), - Ok(&"orange") + Ok(Some(&"orange")) ); } #[test] fn test_put_and_get_or_insert_mut() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert!(cache.is_empty()); assert_eq!(cache.put("apple", "red"), None); assert_eq!(cache.put("banana", "yellow"), None); - assert_eq!(cache.cap().get(), 2); + assert_eq!(cache.cap(), 2); assert_eq!(cache.len(), 2); let v = cache.get_or_insert_mut("apple", || "orange"); - assert_eq!(v, &"red"); - *v = "blue"; + assert_eq!(v, Some(&mut "red")); + *v.unwrap() = "blue"; - assert_eq!(cache.get_or_insert_mut("apple", || "orange"), &"blue"); - assert_eq!(cache.get_or_insert_mut("banana", || "orange"), &"yellow"); - assert_eq!(cache.get_or_insert_mut("lemon", || "orange"), &"orange"); - assert_eq!(cache.get_or_insert_mut("lemon", || "red"), &"orange"); + assert_eq!( + cache.get_or_insert_mut("apple", || "orange"), + Some(&mut "blue") + ); + assert_eq!( + cache.get_or_insert_mut("banana", || "orange"), + Some(&mut "yellow") + ); + assert_eq!( + cache.get_or_insert_mut("lemon", || "orange"), + Some(&mut "orange") + ); + assert_eq!( + cache.get_or_insert_mut("lemon", || "red"), + Some(&mut "orange") + ); } #[test] fn test_put_and_get_mut() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); - assert_eq!(cache.cap().get(), 2); + assert_eq!(cache.cap(), 2); assert_eq!(cache.len(), 2); assert_opt_eq_mut(cache.get_mut(&"apple"), "red"); assert_opt_eq_mut(cache.get_mut(&"banana"), "yellow"); @@ -1509,7 +1504,7 @@ mod tests { #[test] fn test_get_mut_and_update() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", 1); cache.put("banana", 3); @@ -1519,7 +1514,7 @@ mod tests { *v = 4; } - assert_eq!(cache.cap().get(), 2); + assert_eq!(cache.cap(), 2); assert_eq!(cache.len(), 2); assert_opt_eq_mut(cache.get_mut(&"apple"), 4); assert_opt_eq_mut(cache.get_mut(&"banana"), 3); @@ -1527,7 +1522,7 @@ mod tests { #[test] fn test_put_update() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(1); assert_eq!(cache.put("apple", "red"), None); assert_eq!(cache.put("apple", "green"), Some("red")); @@ -1538,7 +1533,7 @@ mod tests { #[test] fn test_put_removes_oldest() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert_eq!(cache.put("apple", "red"), None); assert_eq!(cache.put("banana", "yellow"), None); @@ -1560,7 +1555,7 @@ mod tests { #[test] fn test_peek() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1577,7 +1572,7 @@ mod tests { #[test] fn test_peek_mut() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1602,7 +1597,7 @@ mod tests { #[test] fn test_peek_lru() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); assert!(cache.peek_lru().is_none()); @@ -1619,7 +1614,7 @@ mod tests { #[test] fn test_contains() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1632,7 +1627,7 @@ mod tests { #[test] fn test_pop() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1651,7 +1646,7 @@ mod tests { #[test] fn test_pop_entry() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1669,7 +1664,7 @@ mod tests { #[test] fn test_pop_lru() { - let mut cache = LruCache::new(NonZeroUsize::new(200).unwrap()); + let mut cache = LruCache::new(200); for i in 0..75 { cache.put(i, "A"); @@ -1704,7 +1699,7 @@ mod tests { #[test] fn test_clear() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put("apple", "red"); cache.put("banana", "yellow"); @@ -1719,11 +1714,11 @@ mod tests { #[test] fn test_resize_larger() { - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); cache.put(1, "a"); cache.put(2, "b"); - cache.resize(NonZeroUsize::new(4).unwrap()); + cache.resize(4); cache.put(3, "c"); cache.put(4, "d"); @@ -1736,14 +1731,14 @@ mod tests { #[test] fn test_resize_smaller() { - let mut cache = LruCache::new(NonZeroUsize::new(4).unwrap()); + let mut cache = LruCache::new(4); cache.put(1, "a"); cache.put(2, "b"); cache.put(3, "c"); cache.put(4, "d"); - cache.resize(NonZeroUsize::new(2).unwrap()); + cache.resize(2); assert_eq!(cache.len(), 2); assert!(cache.get(&1).is_none()); @@ -1756,7 +1751,7 @@ mod tests { fn test_send() { use std::thread; - let mut cache = LruCache::new(NonZeroUsize::new(4).unwrap()); + let mut cache = LruCache::new(4); cache.put(1, "a"); let handle = thread::spawn(move || { @@ -1769,7 +1764,7 @@ mod tests { #[test] fn test_multiple_threads() { let mut pool = Pool::new(1); - let mut cache = LruCache::new(NonZeroUsize::new(4).unwrap()); + let mut cache = LruCache::new(4); cache.put(1, "a"); let cache_ref = &cache; @@ -1784,7 +1779,7 @@ mod tests { #[test] fn test_iter_forwards() { - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); cache.put("c", 3); @@ -1823,7 +1818,7 @@ mod tests { #[test] fn test_iter_backwards() { - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); cache.put("c", 3); @@ -1863,7 +1858,7 @@ mod tests { #[test] fn test_iter_forwards_and_backwards() { - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); cache.put("c", 3); @@ -1903,7 +1898,7 @@ mod tests { #[test] fn test_iter_multiple_threads() { let mut pool = Pool::new(1); - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); cache.put("c", 3); @@ -1931,7 +1926,7 @@ mod tests { #[test] fn test_iter_clone() { - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); @@ -1956,7 +1951,7 @@ mod tests { #[test] fn test_into_iter() { - let mut cache = LruCache::new(NonZeroUsize::new(3).unwrap()); + let mut cache = LruCache::new(3); cache.put("a", 1); cache.put("b", 2); cache.put("c", 3); @@ -1977,7 +1972,7 @@ mod tests { #[test] fn test_that_pop_actually_detaches_node() { - let mut cache = LruCache::new(NonZeroUsize::new(5).unwrap()); + let mut cache = LruCache::new(5); cache.put("a", 1); cache.put("b", 2); @@ -2002,7 +1997,7 @@ mod tests { fn test_get_with_borrow() { use alloc::string::String; - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); let key = String::from("apple"); cache.put(key, "red"); @@ -2014,7 +2009,7 @@ mod tests { fn test_get_mut_with_borrow() { use alloc::string::String; - let mut cache = LruCache::new(NonZeroUsize::new(2).unwrap()); + let mut cache = LruCache::new(2); let key = String::from("apple"); cache.put(key, "red"); @@ -2036,7 +2031,7 @@ mod tests { let n = 100; for _ in 0..n { - let mut cache = LruCache::new(NonZeroUsize::new(1).unwrap()); + let mut cache = LruCache::new(1); for i in 0..n { cache.put(i, DropCounter {}); } @@ -2058,7 +2053,7 @@ mod tests { let n = 100; for _ in 0..n { - let mut cache = LruCache::new(NonZeroUsize::new(1).unwrap()); + let mut cache = LruCache::new(1); for i in 0..n { cache.put(i, DropCounter {}); } @@ -2081,11 +2076,11 @@ mod tests { let n = 100; for _ in 0..n { - let mut cache = LruCache::new(NonZeroUsize::new(1).unwrap()); + let mut cache = LruCache::new(1); for i in 0..n { cache.put(i, DropCounter {}); } - cache.clear(); + cache.resize(0); } assert_eq!(DROP_COUNT.load(Ordering::SeqCst), n * n); } @@ -2111,7 +2106,7 @@ mod tests { let n = 100; for _ in 0..n { - let mut cache = LruCache::new(NonZeroUsize::new(1).unwrap()); + let mut cache = LruCache::new(1); for i in 0..100 { cache.put(KeyDropCounter(i), i); @@ -2124,7 +2119,7 @@ mod tests { #[test] fn test_promote_and_demote() { - let mut cache = LruCache::new(NonZeroUsize::new(5).unwrap()); + let mut cache = LruCache::new(5); for i in 0..5 { cache.push(i, i); } @@ -2139,6 +2134,12 @@ mod tests { assert_eq!(cache.pop_lru(), Some((0, 0))); assert_eq!(cache.pop_lru(), None); } + + #[test] + fn test_zero_cap_no_crash() { + let mut cache = LruCache::new(0); + cache.put("reizeiin", "tohka"); + } } /// Doctests for what should *not* compile