1use lru::LruCache;
2use std::borrow::Borrow;
3use std::cell::RefCell;
4use std::convert::Infallible;
5use std::hash::Hash;
6
7pub struct CellLruCache<K, V> {
9 inner: RefCell<LruCache<K, V>>,
10}
11
12impl<K, V> CellLruCache<K, V>
13where
14 K: Hash + Eq,
15 V: Clone,
16{
17 pub fn new(cap: usize) -> Self {
19 Self { inner: RefCell::new(LruCache::<K, V>::new(cap)) }
20 }
21
22 pub fn len(&self) -> usize {
24 self.inner.borrow().len()
25 }
26
27 pub fn is_empty(&self) -> bool {
29 self.inner.borrow().is_empty()
30 }
31
32 pub fn get_or_put<F>(&self, key: K, f: F) -> V
36 where
37 V: Clone,
38 F: FnOnce(&K) -> V,
39 {
40 Result::<_, Infallible>::unwrap(self.get_or_try_put(key, |k| Ok(f(k))))
41 }
42
43 pub fn get_or_try_put<F, E>(&self, key: K, f: F) -> Result<V, E>
52 where
53 V: Clone,
54 F: FnOnce(&K) -> Result<V, E>,
55 {
56 if let Some(result) = self.get(&key) {
57 return Ok(result);
58 }
59 let val = f(&key)?;
60 let val_clone = val.clone();
61 self.inner.borrow_mut().put(key, val_clone);
62 Ok(val)
63 }
64
65 pub fn put(&self, key: K, value: V) {
68 self.inner.borrow_mut().put(key, value);
69 }
70
71 pub fn pop<Q>(&self, key: &Q) -> Option<V>
72 where
73 lru::KeyRef<K>: Borrow<Q>,
74 Q: Hash + Eq + ?Sized,
75 {
76 self.inner.borrow_mut().pop(key)
77 }
78
79 pub fn get<Q>(&self, key: &Q) -> Option<V>
82 where
83 lru::KeyRef<K>: Borrow<Q>,
84 Q: Hash + Eq + ?Sized,
85 {
86 self.inner.borrow_mut().get(key).cloned()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_cache() {
96 let cache = CellLruCache::<u64, Vec<u64>>::new(100);
97
98 assert_eq!(cache.get(&0u64), None);
99 assert_eq!(cache.get_or_put(123u64, |key| vec![*key, 123]), vec![123u64, 123]);
100 assert_eq!(cache.get(&123u64), Some(vec![123u64, 123]));
101 assert_eq!(cache.get(&0u64), None);
102 }
103}