1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
use async_std::sync::RwLock; use std::collections::HashMap; use crate::item::Item; use chrono::Duration; use std::hash::Hash; struct Cache<T, V> { items: RwLock<HashMap<T, Item<V>>>, item_duration: Duration, } impl<T, V> Cache<T, V> { pub fn new(item_duration: Duration) -> Self { Cache { items: RwLock::new(HashMap::new()), item_duration, } } pub async fn get(&self, key: T) -> Option<V> where T: Eq + Hash, V: Clone { if let Some(item) = self.items.read().await.get(&key).cloned() { return if item.expired() { None } else { Some(item.object) }; }; None } pub async fn set(&self, key: T, value: V) -> Option<V> where T: Eq + Hash { self.items .write() .await .insert(key, Item::new(value, self.item_duration)) .map(|item| item.object) } } #[cfg(test)] mod tests { use crate::cache::Cache; use async_std::task; const KEY: i8 = 0; const VALUE: &str = "VALUE"; #[test] fn set_and_get_value() { task::block_on(async { let cache = Cache::new(chrono::Duration::minutes(1)); cache.set(KEY, VALUE).await; let value = cache.get(KEY).await; match value { Some(value) => assert_eq!(value, VALUE), None => panic!("value was not found in cache") }; }) } }