simple_cache_rs/
lib.rs

1use std::collections::HashMap;
2use std::fmt::Debug;
3use std::hash::Hash;
4use std::time::{Duration, Instant};
5
6#[derive(Debug, Clone)]
7struct Entry<V> {
8    value: V,
9    insert_time: Instant,
10}
11
12#[derive(Debug, Clone)]
13pub struct SimpleCache<K, V> {
14    hashmap: HashMap<K, Entry<V>>,
15    timeout: Option<Duration>,
16}
17
18impl<K: Eq + Hash + Clone + Debug, V: Clone + Debug> SimpleCache<K, V> {
19    /// Returns a new instance of SimpleCache
20    ///
21    /// ```
22    /// use simple_cache_rs::SimpleCache;
23    ///
24    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
25    /// ```
26    /// OR
27    /// ```
28    /// use simple_cache_rs::SimpleCache;
29    /// use std::time::Duration;
30    ///
31    /// let timeout = Duration::new(5, 0);
32    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(Some(timeout));
33    /// ```
34    pub fn new(timeout: Option<Duration>) -> SimpleCache<K, V> {
35        SimpleCache {
36            hashmap: HashMap::new(),
37            timeout,
38        }
39    }
40
41    /// Get a value optionally from the cache, if the value is expired this method will return None
42    /// and delete the value lazily from the cache.
43    /// ```
44    /// use simple_cache_rs::SimpleCache;
45    ///
46    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
47    ///
48    /// cache.get(&1);
49    /// ```
50    pub fn get(&mut self, key: &K) -> Option<V> {
51        let entry = self.hashmap.get(key)?;
52
53        if let Some(timeout) = self.timeout {
54            if entry.insert_time.elapsed() >= timeout {
55                self.delete(key);
56                return None;
57            }
58        }
59
60
61
62        Some(entry.value.clone())
63    }
64
65    /// Get all keys that are in the cache
66    /// ```
67    /// use simple_cache_rs::SimpleCache;
68    ///
69    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
70    ///
71    /// cache.keys();
72    /// ```
73    pub fn keys(&self) -> Vec<K> {
74        self.hashmap.keys().map(|k| k.clone()).collect::<Vec<K>>()
75    }
76
77    /// Get all values that are in the cache
78    /// ```
79    /// use simple_cache_rs::SimpleCache;
80    ///
81    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
82    ///
83    /// cache.values();
84    /// ```
85    pub fn values(&self) -> Vec<V> {
86        self.hashmap
87            .values()
88            .map(|v| v.value.clone())
89            .collect::<Vec<V>>()
90    }
91
92    /// Get all tuples of keys and values that are in the cache
93    /// ```
94    /// use simple_cache_rs::SimpleCache;
95    ///
96    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
97    ///
98    /// cache.tuples();
99    /// ```
100    pub fn tuples(&self) -> Vec<(K, V)> {
101      self.hashmap.iter()
102          .map(|(k, v)| (k.clone(), v.value.clone()))
103          .collect::<Vec<(K, V)>>()
104    }
105
106    /// Insert a batch of items into the cache
107    /// ```
108    /// use simple_cache_rs::SimpleCache;
109    ///
110    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
111    ///
112    /// let items = vec!((1, String::from("a")), (2, String::from("b")));
113    /// cache.insert_batch(items);
114    /// ```
115    pub fn insert_batch(&mut self, items: Vec<(K, V)>) {
116        let i_now = Instant::now();
117
118        for item in items {
119            self.hashmap.insert(
120                item.0,
121                Entry {
122                    value: item.1,
123                    insert_time: i_now,
124                },
125            );
126        }
127    }
128
129    /// Insert an item into the cache
130    /// ```
131    /// use simple_cache_rs::SimpleCache;
132    ///
133    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
134    ///
135    /// cache.insert(1, String::from("a"));
136    /// ```
137    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
138        self.hashmap
139            .insert(
140                key,
141                Entry {
142                    value,
143                    insert_time: Instant::now(),
144                },
145            )
146            .map(|entry| entry.value)
147    }
148
149    /// Remove an entry from the cache
150    /// ```
151    /// use simple_cache_rs::SimpleCache;
152    ///
153    /// let mut cache: SimpleCache<i32, String> = SimpleCache::new(None);
154    ///
155    /// cache.insert(1, String::from("a"));
156    /// cache.delete(&1);
157    /// ```
158    pub fn delete(&mut self, key: &K) -> Option<V> {
159        self.hashmap.remove(key).map(|entry| entry.value)
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::SimpleCache;
166    use std::{thread, time::Duration};
167
168    #[test]
169    fn insert_and_get_item() {
170        let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
171        scache.insert(1, String::from("hello"));
172
173        let v = scache.get(&1);
174        assert_eq!(Some(String::from("hello")), v)
175    }
176
177    #[test]
178    fn insert_and_get_item_and_remove() {
179        let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
180        scache.insert(1, String::from("hello"));
181
182        let v = scache.get(&1);
183        assert_eq!(Some(String::from("hello")), v);
184
185        scache.delete(&1);
186
187        let no_value = scache.get(&1);
188        assert_eq!(None, no_value)
189    }
190
191    #[test]
192    fn insert_batch_test() {
193        let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
194
195        scache.insert_batch(vec![(1, String::from("hello")), (2, String::from("world"))]);
196
197        let values = scache.values();
198
199        assert!(values.contains(&&String::from("hello")));
200        assert!(values.contains(&&String::from("world")))
201    }
202
203    #[test]
204    fn get_keys_test() {
205        let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
206        scache.insert(1, String::from("hello"));
207
208        let keys = scache.keys();
209        assert_eq!(keys, vec!(1))
210    }
211
212    #[test]
213    fn get_values_test() {
214        let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
215        scache.insert(1, String::from("hello"));
216
217        let values = scache.values();
218        assert_eq!(values, vec!("hello"))
219    }
220
221    #[test]
222    fn insert_with_timeout() {
223        let timeout = Duration::new(1, 0);
224        let mut scache: SimpleCache<i32, String> = SimpleCache::new(Some(timeout));
225
226        scache.insert(1, String::from("hello"));
227        thread::sleep(Duration::new(1, 1));
228
229        let v = scache.get(&1);
230        assert_eq!(None, v)
231    }
232
233    #[test]
234    fn get_tuples_test() {
235      let mut scache: SimpleCache<i32, String> = SimpleCache::new(None);
236      scache.insert(1, String::from("hello"));
237
238      let values: Vec<(i32, String)> = scache.tuples();
239      assert_eq!(values, vec!((1, String::from("hello"))))
240    }
241}