use ahash::RandomState;
use dashmap::DashMap;
use elysees::Arc;
use std::borrow::Borrow;
use std::hash::{BuildHasher, Hash};
pub mod arr;
pub trait Caches<T: ?Sized>: Hash + Eq + Clone {
fn can_collect(&self) -> bool;
}
impl<T: Hash + Eq> Caches<T> for Arc<T> {
#[inline]
fn can_collect(&self) -> bool {
self.is_unique()
}
}
#[derive(Debug)]
pub struct Cache<T: ?Sized, C: Caches<T> = Arc<T>, S: BuildHasher + Clone = RandomState> {
cache: DashMap<C, (), S>,
cached: std::marker::PhantomData<T>,
}
impl<T: Hash + Eq> Cache<T> {
pub fn new() -> Cache<T> {
Cache {
cache: DashMap::new(),
cached: std::marker::PhantomData,
}
}
}
impl<T: ?Sized, C: Caches<T>, S: BuildHasher + Clone + Default> Default for Cache<T, C, S> {
fn default() -> Cache<T, C, S> {
Cache {
cache: DashMap::default(),
cached: std::marker::PhantomData,
}
}
}
impl<T: Eq + Hash + ?Sized, C: Caches<T>, S: BuildHasher + Clone> Cache<T, C, S> {
pub fn cache<Q>(&self, value: Q) -> C
where
C: Borrow<Q>,
Q: Into<C> + Hash + Eq,
{
if let Some(cached) = self.cache.get(&value) {
return cached.key().clone();
}
self.cache.entry(value.into()).or_default().key().clone()
}
pub fn gc(&self) -> usize {
let mut collected = 0;
self.cache.retain(|arc, _| {
if arc.can_collect() {
collected += 1;
false
} else {
true
}
});
collected
}
pub fn len(&self) -> usize {
self.cache.len()
}
pub fn is_empty(&self) -> bool {
self.cache.is_empty()
}
}