use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::RwLock;
pub static DEFAULT_CACHE_CAPACITY: usize = 10_000;
#[derive(Debug)]
pub(crate) struct Cache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
map: RwLock<HashMap<K, V>>,
pub capacity: usize,
}
impl<K, V> PartialEq for Cache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
fn eq(&self, _other: &Cache<K, V>) -> bool {
true
}
}
impl<K, V> Default for Cache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
fn default() -> Self {
Self::new(DEFAULT_CACHE_CAPACITY)
}
}
impl<K, V> Cache<K, V>
where
K: Eq + Hash + Clone,
V: Clone,
{
pub(crate) fn new(capacity: usize) -> Self {
let map = RwLock::new(HashMap::with_capacity(capacity));
Cache { map, capacity }
}
pub(crate) fn fresh(&self) -> Self {
Self::new(self.capacity)
}
pub(crate) fn clear(&self) {
self.map.write().unwrap().clear();
}
#[allow(dead_code)]
pub(crate) fn get_values<'a, I, Q>(&self, keys_iter: I) -> Option<Vec<Option<V>>>
where
I: Iterator<Item = &'a Q>,
K: Borrow<Q>,
Q: Hash + Eq + ?Sized + 'a,
{
if let Ok(ref mut cache) = self.map.try_read() {
Some(keys_iter.map(|k| cache.get(k).cloned()).collect())
} else {
None
}
}
pub(crate) fn get<Q>(&self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
if let Ok(ref mut cache) = self.map.try_read() {
cache.get(key).cloned()
} else {
None
}
}
pub(crate) fn set_values<I>(&self, entries: I)
where
I: IntoIterator<Item = (K, V)>,
{
if let Ok(cache) = self.map.try_read() {
if cache.len() >= self.capacity {
return;
}
} else {
return;
}
if let Ok(mut cache) = self.map.try_write() {
let free = self.capacity - cache.len();
cache.extend(entries.into_iter().take(free));
}
}
pub(crate) fn set(&self, key: K, value: V) {
self.set_values(std::iter::once((key, value)))
}
}