use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
#[derive(Debug, Clone)]
pub struct LruCache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
max: usize,
store: HashMap<K, V>,
order: VecDeque<K>,
}
impl<K, V> LruCache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
pub fn new(max: usize) -> Self {
assert!(max > 0, "LRUCache max must be a positive finite number");
Self {
max,
store: HashMap::new(),
order: VecDeque::new(),
}
}
pub fn size(&self) -> usize {
self.store.len()
}
pub fn has(&self, key: &K) -> bool {
self.store.contains_key(key)
}
pub fn get(&mut self, key: &K) -> Option<V> {
let value = self.store.get(key).cloned()?;
self.touch(key);
Some(value)
}
pub fn set(&mut self, key: K, value: V) {
if self.store.contains_key(&key) {
self.order.retain(|k| k != &key);
} else {
while self.store.len() >= self.max {
if let Some(oldest) = self.order.pop_front() {
self.store.remove(&oldest);
} else {
break;
}
}
}
self.order.push_back(key.clone());
self.store.insert(key, value);
}
pub fn clear(&mut self) {
self.store.clear();
self.order.clear();
}
fn touch(&mut self, key: &K) {
self.order.retain(|k| k != key);
self.order.push_back(key.clone());
}
}