Skip to main content

priority_lfu/
traits.rs

1use std::hash::Hash;
2
3use priority_lfu_derive::DeepSizeOf;
4
5use crate::deepsize::DeepSizeOf;
6
7pub(crate) const NUM_POLICY_BUCKETS: usize = 3;
8
9/// Cache eviction policy determining retention priority.
10///
11/// Lower discriminant values = higher priority = evicted last.
12#[repr(u8)]
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, DeepSizeOf)]
14pub enum CachePolicy {
15	/// Critical metadata that should persist (catalog, schemas, indexes).
16	/// Last to be evicted, highest retention.
17	Critical = 0,
18
19	/// Standard cacheable data (recent queries, lookup results).
20	/// Normal eviction behavior.
21	#[default]
22	Standard = 1,
23
24	/// Temporary or easily recomputed data (intermediate results, aggregations).
25	/// First to be evicted.
26	Volatile = 2,
27}
28
29/// Marker trait for cache keys. Associates a key type with its value type.
30///
31/// # Example
32///
33/// ```
34/// use priority_lfu::{DeepSizeOf, CacheKey, CachePolicy};
35///
36/// #[derive(Hash, Eq, PartialEq, Clone)]
37/// struct UserId(u64);
38///
39/// #[derive(Clone, Debug, PartialEq, DeepSizeOf)]
40/// struct UserData {
41///     name: String,
42/// }
43///
44/// impl CacheKey for UserId {
45///     type Value = UserData;
46///
47///     fn policy(&self) -> CachePolicy {
48///         CachePolicy::Standard
49///     }
50/// }
51/// ```
52pub trait CacheKey: Hash + Eq + Clone + Send + Sync + 'static {
53	/// The value type associated with this key.
54	type Value: DeepSizeOf + Send + Sync;
55
56	/// Eviction policy determining retention priority.
57	///
58	/// This method is called on the key, allowing different keys to have
59	/// different policies for the same value type.
60	fn policy(&self) -> CachePolicy {
61		CachePolicy::Standard
62	}
63}
64
65/// Trait for borrowed keys that can look up entries of type `K`.
66///
67/// This trait enables zero-allocation cache lookups using borrowed key types.
68/// For example, you can use `(&str, &str)` to look up entries stored with
69/// `(String, String)` keys, avoiding the allocation of owned strings.
70///
71/// # Hash Consistency Requirement
72///
73/// **CRITICAL**: The `Hash` implementation MUST produce the same hash as `K`
74/// for equivalent keys. If the hashes differ, lookups will fail.
75///
76/// # Example
77///
78/// ```
79/// use std::hash::{Hash, Hasher};
80/// use priority_lfu::{CacheKey, CacheKeyLookup, CachePolicy, DeepSizeOf};
81///
82/// // Owned key type
83/// #[derive(Hash, Eq, PartialEq, Clone)]
84/// struct DbCacheKey(String, String);
85///
86/// impl CacheKey for DbCacheKey {
87///     type Value = String;
88/// }
89///
90/// // Borrowed lookup type
91/// struct DbCacheKeyRef<'a>(&'a str, &'a str);
92///
93/// impl Hash for DbCacheKeyRef<'_> {
94///     fn hash<H: Hasher>(&self, state: &mut H) {
95///         // MUST match DbCacheKey's hash implementation
96///         self.0.hash(state);
97///         self.1.hash(state);
98///     }
99/// }
100///
101/// impl CacheKeyLookup<DbCacheKey> for DbCacheKeyRef<'_> {
102///     fn eq_key(&self, key: &DbCacheKey) -> bool {
103///         self.0 == key.0 && self.1 == key.1
104///     }
105///
106///     fn to_owned_key(self) -> DbCacheKey {
107///         DbCacheKey(self.0.to_owned(), self.1.to_owned())
108///     }
109/// }
110/// ```
111pub trait CacheKeyLookup<K: CacheKey>: Hash {
112	/// Check equality against an owned key.
113	///
114	/// Returns `true` if this borrowed key is equivalent to the given owned key.
115	fn eq_key(&self, key: &K) -> bool;
116
117	/// Convert this borrowed key to an owned key.
118	fn to_owned_key(self) -> K;
119}
120
121/// Blanket implementation: every `CacheKey` can look up itself.
122///
123/// This allows existing code using `cache.get(&key)` to continue working unchanged.
124impl<K: CacheKey> CacheKeyLookup<K> for K {
125	fn eq_key(&self, key: &K) -> bool {
126		self == key
127	}
128
129	fn to_owned_key(self) -> K {
130		self
131	}
132}