gistools/data_structures/
cache.rs

1use alloc::collections::{BTreeMap, VecDeque};
2
3/// Function to be called when a value is deleted from the cache
4pub type CacheDeleteFunction<K, V> = fn(&K, &V);
5
6/// # Cache System
7///
8/// ## Description
9/// A cache of values with a max size to ensure that too much old data is not stored.
10///
11/// Uses the [`CacheDeleteFunction`] type
12///
13/// ## Usage
14///
15/// ```rust
16/// extern crate alloc;
17/// use gistools::data_structures::Cache;
18/// use alloc::borrow::ToOwned;
19/// use alloc::string::{String, ToString};
20///
21/// fn on_delete(key: &String, value: &String) {
22///     println!("Deleted key {} with value {}", key, value);
23/// }
24///
25/// let mut cache = Cache::new(10, Some(on_delete));
26/// cache.set("key".to_owned(), "value".to_owned());
27/// println!("{:?}", cache.get(&"key".to_string())); // Some("value")
28/// cache.delete(&"key".to_string());
29/// ```
30#[derive(Debug, Clone, Default)]
31pub struct Cache<K, V>
32where
33    K: Ord + Clone,
34{
35    map: BTreeMap<K, V>,
36    order: VecDeque<K>,
37    max_size: usize,
38    on_delete: Option<CacheDeleteFunction<K, V>>,
39}
40
41impl<K, V> Cache<K, V>
42where
43    K: Ord + Clone,
44{
45    /// Creates a new cache with a given max size and an optional deletion callback.
46    pub fn new(max_size: usize, on_delete: Option<CacheDeleteFunction<K, V>>) -> Self {
47        Self { map: BTreeMap::new(), order: VecDeque::new(), max_size, on_delete }
48    }
49
50    /// Returns the number of elements in the cache.
51    pub fn len(&self) -> usize {
52        self.map.len()
53    }
54
55    /// Returns true if the cache is empty.
56    pub fn is_empty(&self) -> bool {
57        self.map.is_empty()
58    }
59
60    /// Inserts a key-value pair into the cache.
61    pub fn set(&mut self, key: K, value: V) {
62        if self.map.contains_key(&key) {
63            self.order.retain(|k| k != &key);
64        }
65        self.order.push_front(key.clone());
66        self.map.insert(key, value);
67
68        while self.order.len() > self.max_size {
69            if let Some(oldest) = self.order.pop_back() {
70                self.delete(&oldest);
71            }
72        }
73    }
74
75    /// Retrieves a value from the cache.
76    pub fn get(&mut self, key: &K) -> Option<&V> {
77        if self.map.contains_key(key) {
78            self.order.retain(|k| k != key);
79            self.order.push_front(key.clone());
80        }
81        self.map.get(key)
82    }
83
84    /// Retrieves a mutable value from the cache.
85    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
86        if self.map.contains_key(key) {
87            self.order.retain(|k| k != key);
88            self.order.push_front(key.clone());
89        }
90        self.map.get_mut(key)
91    }
92
93    /// Removes a key from the cache.
94    pub fn delete(&mut self, key: &K) -> bool {
95        if let Some(value) = self.map.remove(key) {
96            self.order.retain(|k| k != key);
97            if let Some(ref callback) = self.on_delete {
98                callback(key, &value);
99            }
100            return true;
101        }
102        false
103    }
104}