use alloc::collections::{BTreeMap, VecDeque};
pub type CacheDeleteFunction<K, V> = fn(&K, &V);
#[derive(Debug, Clone, Default)]
pub struct Cache<K, V>
where
K: Ord + Clone,
{
map: BTreeMap<K, V>,
order: VecDeque<K>,
max_size: usize,
on_delete: Option<CacheDeleteFunction<K, V>>,
}
impl<K, V> Cache<K, V>
where
K: Ord + Clone,
{
pub fn new(max_size: usize, on_delete: Option<CacheDeleteFunction<K, V>>) -> Self {
Self { map: BTreeMap::new(), order: VecDeque::new(), max_size, on_delete }
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn set(&mut self, key: K, value: V) {
if self.map.contains_key(&key) {
self.order.retain(|k| k != &key);
}
self.order.push_front(key.clone());
self.map.insert(key, value);
while self.order.len() > self.max_size {
if let Some(oldest) = self.order.pop_back() {
self.delete(&oldest);
}
}
}
pub fn get(&mut self, key: &K) -> Option<&V> {
if self.map.contains_key(key) {
self.order.retain(|k| k != key);
self.order.push_front(key.clone());
}
self.map.get(key)
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
if self.map.contains_key(key) {
self.order.retain(|k| k != key);
self.order.push_front(key.clone());
}
self.map.get_mut(key)
}
pub fn delete(&mut self, key: &K) -> bool {
if let Some(value) = self.map.remove(key) {
self.order.retain(|k| k != key);
if let Some(ref callback) = self.on_delete {
callback(key, &value);
}
return true;
}
false
}
}