diff --git a/time-cache/src/lib.rs b/time-cache/src/lib.rs index 14747c8..a325285 100644 --- a/time-cache/src/lib.rs +++ b/time-cache/src/lib.rs @@ -1,9 +1,13 @@ +//! Simple cache structure that stores values for a specified time. The cache itself is backed by +//! a HashMap. + use std::{ collections::HashMap, hash::Hash, time::{Duration, Instant}, }; +/// Time based cache, that stores values for a defined time. pub struct Cache { cache: HashMap>, duration: Duration, @@ -13,6 +17,16 @@ impl Cache where K: Eq + Hash, { + /// Creates a new cache. + /// + /// # Example + /// ``` + /// use std::time::Duration; + /// use time_cache::{Cache, CacheResult}; + /// + /// let cache: Cache = Cache::new(Duration::from_secs(0)); + /// assert_eq!(CacheResult::Empty, cache.get(&0)); + /// ``` pub fn new(duration: Duration) -> Self { Self { cache: HashMap::new(), @@ -20,6 +34,20 @@ where } } + /// Get an item from the cache. The item can be either valid, invalid or non existent. + /// + /// # Example + /// ``` + /// use std::time::Duration; + /// use time_cache::{Cache, CacheResult}; + /// + /// let key = 0; + /// let value = 1; + /// let mut cache: Cache = Cache::new(Duration::from_secs(0)); + /// assert_eq!(CacheResult::Empty, cache.get(&key)); + /// cache.store(key, value); + /// assert_eq!(CacheResult::Invalid, cache.get(&key)); + /// ``` pub fn get(&self, key: &K) -> CacheResult<&V> { if let Some(entry) = self.cache.get(key) { if Self::is_valid(Instant::now(), entry) { @@ -32,16 +60,66 @@ where } } + /// Removes an item from the cache. Returns `true` if the key was present. + /// + /// # Example + /// ``` + /// use std::time::Duration; + /// use time_cache::{Cache, CacheResult}; + /// + /// let key = 0; + /// let value = 1; + /// let mut cache: Cache = Cache::new(Duration::from_secs(0)); + /// assert!(!cache.invalidate(&key)); + /// cache.store(key, value); + /// assert!(cache.invalidate(&key)); + /// ``` pub fn invalidate(&mut self, key: &K) -> bool { self.cache.remove(key).is_some() } + /// Stores an item in the cache. + /// + /// # Example + /// ``` + /// use std::time::Duration; + /// use time_cache::{Cache, CacheResult}; + /// + /// let key = 0; + /// let value = 1; + /// let dur = Duration::from_millis(500); + /// let mut cache: Cache = Cache::new(dur); + /// + /// assert_eq!(CacheResult::Empty, cache.get(&key)); + /// cache.store(key, value); + /// assert_eq!(CacheResult::Cached(&value), cache.get(&key)); + /// std::thread::sleep(dur); + /// assert_eq!(CacheResult::Invalid, cache.get(&key)); + /// ``` pub fn store(&mut self, key: K, value: V) -> Option { self.cache .insert(key, CacheEntry::new(value, self.duration)) .map(|old| old.1) } + /// Removes all invalid items from the cache. + /// + /// # Example + /// ``` + /// use std::time::Duration; + /// use time_cache::{Cache, CacheResult}; + /// + /// let key = 0; + /// let value = 1; + /// let dur = Duration::from_secs(0); + /// let mut cache: Cache = Cache::new(dur); + /// + /// assert_eq!(CacheResult::Empty, cache.get(&key)); + /// cache.store(key, value); + /// assert_eq!(CacheResult::Invalid, cache.get(&key)); + /// cache.clear(); + /// assert_eq!(CacheResult::Empty, cache.get(&key)); + /// ``` pub fn clear(&mut self) { let now = Instant::now(); self.cache.retain(|_, v| Self::is_valid(now, v)) @@ -52,9 +130,14 @@ where } } +/// Result when requesting a cached item. +#[derive(Debug, PartialEq)] pub enum CacheResult { + /// Item is cached and still valid Cached(T), + /// Item is cached but invalid Invalid, + /// Item is not in the cache Empty, }