use crate::{value::UserValue, value_log::ValueLogId, ValueHandle};
use quick_cache::{sync::Cache, Equivalent, Weighter};
type Item = UserValue;
#[derive(Eq, std::hash::Hash, PartialEq)]
pub struct CacheKey(ValueLogId, ValueHandle);
impl Equivalent<CacheKey> for (ValueLogId, &ValueHandle) {
fn equivalent(&self, key: &CacheKey) -> bool {
self.0 == key.0 && self.1 == &key.1
}
}
impl From<(ValueLogId, ValueHandle)> for CacheKey {
fn from((vid, vhandle): (ValueLogId, ValueHandle)) -> Self {
Self(vid, vhandle)
}
}
#[derive(Clone)]
struct BlobWeighter;
impl Weighter<CacheKey, Item> for BlobWeighter {
#[allow(clippy::cast_possible_truncation)]
fn weight(&self, _: &CacheKey, blob: &Item) -> u64 {
blob.len() as u64
}
}
pub struct BlobCache {
data: Cache<CacheKey, Item, BlobWeighter, rustc_hash::FxBuildHasher>,
capacity: u64,
}
impl std::fmt::Debug for BlobCache {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "BlobCache<cap: {} bytes>", self.capacity)
}
}
impl BlobCache {
#[must_use]
pub fn with_capacity_bytes(bytes: u64) -> Self {
use quick_cache::sync::DefaultLifecycle;
#[allow(clippy::default_trait_access)]
let quick_cache = Cache::with(
10_000,
bytes,
BlobWeighter,
Default::default(),
DefaultLifecycle::default(),
);
Self {
data: quick_cache,
capacity: bytes,
}
}
pub(crate) fn insert(&self, key: CacheKey, value: UserValue) {
self.data.insert(key, value);
}
pub(crate) fn get(&self, vlog_id: ValueLogId, vhandle: &ValueHandle) -> Option<Item> {
self.data.get(&(vlog_id, vhandle))
}
#[must_use]
pub fn capacity(&self) -> u64 {
self.capacity
}
#[must_use]
pub fn size(&self) -> u64 {
self.data.weight()
}
#[must_use]
pub fn len(&self) -> usize {
self.data.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}