euv_core/reactive/cache/struct.rs
1use super::*;
2
3/// A fixed-capacity LRU cache.
4///
5/// The cache holds at most `capacity` entries. When a
6/// `put` would exceed the capacity, the
7/// least-recently-used entry is evicted. `get` updates
8/// the recency so the just-read entry becomes the most-
9/// recently-used.
10///
11/// `peek` and `contains` are O(1). `put`, `get`, and
12/// `remove` are O(n) in the number of cached entries
13/// because promoting or dropping a key scans the
14/// recency deque (`VecDeque::retain`); `iter` is O(n).
15///
16/// # Capacity edge cases
17///
18/// - `capacity = 0` - the cache accepts no entries. Both
19/// `put` and `get` behave as no-ops (well, `get` still
20/// evicts because there's nothing to evict; `put`
21/// silently drops the entry).
22/// - `capacity = 1` - the cache holds exactly one entry.
23/// Every `put` evicts the previous entry.
24///
25/// # Lombok `New` derivation
26///
27/// `#[derive(New)]` generates `LruCache::new(capacity)` —
28/// the `map` and `order` fields are skipped with
29/// `#[new(skip)]` so Lombok falls back to
30/// `<HashMap as Default>::default()` and
31/// `<VecDeque as Default>::default()` (which both call
32/// `new()` internally), preserving the canonical
33/// single-argument call site.
34#[derive(Clone, Data, Debug, New)]
35pub struct LruCache<K, V>
36where
37 K: Clone + Eq + Hash,
38{
39 /// The maximum number of entries before eviction
40 /// kicks in.
41 #[get(pub(crate))]
42 pub(crate) capacity: usize,
43 /// The current entries, keyed by K. Default-initialised
44 /// via `#[new(skip)]` (`HashMap::new()`).
45 #[new(skip)]
46 pub(crate) map: HashMap<K, V>,
47 /// The MRU-first order. Front = most recently used,
48 /// back = least recently used. Default-initialised
49 /// via `#[new(skip)]` (`VecDeque::new()`).
50 #[new(skip)]
51 pub(crate) order: VecDeque<K>,
52}