use std::hash::Hash;
use std::time::Duration;
use crate::hasher::hash_value;
#[cfg(feature = "critical")]
pub trait CriticalKey: Hash + Clone + Send + 'static {
fn channel() -> &'static str;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CacheStrategy {
Lru,
Mru,
Lfu,
Mfu,
Fifo,
}
pub trait ImcCacheable: Clone + Send + Sync + 'static {
type Id: Hash + Eq + Clone + Send + 'static;
type Key: Hash + Clone + Send + 'static;
fn cache_id(&self) -> Self::Id;
fn cache_strategy() -> CacheStrategy { CacheStrategy::Lru }
fn cache_ttl() -> Option<Duration> { None }
fn cache_max_size() -> usize { 10_000 }
fn cache_value_size(&self) -> Option<usize> { None }
fn cache_max_value_size() -> usize { 1_048_576 }
fn cache_invalidation_channel() -> Option<&'static str> { None }
}
impl<T: ImcCacheable> ImcCacheable for Vec<T> {
type Id = String;
type Key = String;
fn cache_id(&self) -> String {
let ids: Vec<T::Id> = self.iter().map(|e| e.cache_id()).collect();
hash_value(&ids).to_string()
}
fn cache_strategy() -> CacheStrategy { T::cache_strategy() }
fn cache_ttl() -> Option<Duration> { T::cache_ttl() }
fn cache_max_size() -> usize { T::cache_max_size() }
fn cache_invalidation_channel() -> Option<&'static str> { None }
fn cache_value_size(&self) -> Option<usize> {
let elem: Option<usize> = self.iter().try_fold(0usize, |acc, e| {
e.cache_value_size().map(|s| acc + s)
});
elem.map(|s| s + self.capacity() * std::mem::size_of::<T>())
}
fn cache_max_value_size() -> usize { T::cache_max_value_size() }
}