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 pub fn new(timeout: Option<Duration>) -> SimpleCache<K, V> {
35 SimpleCache {
36 hashmap: HashMap::new(),
37 timeout,
38 }
39 }
40
41 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 pub fn keys(&self) -> Vec<K> {
74 self.hashmap.keys().map(|k| k.clone()).collect::<Vec<K>>()
75 }
76
77 pub fn values(&self) -> Vec<V> {
86 self.hashmap
87 .values()
88 .map(|v| v.value.clone())
89 .collect::<Vec<V>>()
90 }
91
92 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 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 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 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}