1use crate::{value::UserValue, value_log::ValueLogId, ValueHandle};
6use quick_cache::{sync::Cache, Equivalent, Weighter};
7
8type Item = UserValue;
9
10#[derive(Eq, std::hash::Hash, PartialEq)]
11pub struct CacheKey(ValueLogId, ValueHandle);
12
13impl Equivalent<CacheKey> for (ValueLogId, &ValueHandle) {
14 fn equivalent(&self, key: &CacheKey) -> bool {
15 self.0 == key.0 && self.1 == &key.1
16 }
17}
18
19impl From<(ValueLogId, ValueHandle)> for CacheKey {
20 fn from((vid, vhandle): (ValueLogId, ValueHandle)) -> Self {
21 Self(vid, vhandle)
22 }
23}
24
25#[derive(Clone)]
26struct BlobWeighter;
27
28impl Weighter<CacheKey, Item> for BlobWeighter {
29 #[allow(clippy::cast_possible_truncation)]
30 fn weight(&self, _: &CacheKey, blob: &Item) -> u64 {
31 blob.len() as u64
32 }
33}
34
35pub struct BlobCache {
41 data: Cache<CacheKey, Item, BlobWeighter, rustc_hash::FxBuildHasher>,
44
45 capacity: u64,
47}
48
49impl std::fmt::Debug for BlobCache {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "BlobCache<cap: {} bytes>", self.capacity)
52 }
53}
54
55impl BlobCache {
56 #[must_use]
58 pub fn with_capacity_bytes(bytes: u64) -> Self {
59 use quick_cache::sync::DefaultLifecycle;
60
61 #[allow(clippy::default_trait_access)]
62 let quick_cache = Cache::with(
63 10_000,
64 bytes,
65 BlobWeighter,
66 Default::default(),
67 DefaultLifecycle::default(),
68 );
69
70 Self {
71 data: quick_cache,
72 capacity: bytes,
73 }
74 }
75
76 pub(crate) fn insert(&self, key: CacheKey, value: UserValue) {
77 self.data.insert(key, value);
78 }
79
80 pub(crate) fn get(&self, vlog_id: ValueLogId, vhandle: &ValueHandle) -> Option<Item> {
81 self.data.get(&(vlog_id, vhandle))
82 }
83
84 #[must_use]
86 pub fn capacity(&self) -> u64 {
87 self.capacity
88 }
89
90 #[must_use]
92 pub fn size(&self) -> u64 {
93 self.data.weight()
94 }
95
96 #[must_use]
98 pub fn len(&self) -> usize {
99 self.data.len()
100 }
101
102 #[must_use]
104 pub fn is_empty(&self) -> bool {
105 self.len() == 0
106 }
107}