signinum_core/context.rs
1// SPDX-License-Identifier: Apache-2.0
2
3/// Cache hit/miss counters reported by codec contexts.
4#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
5pub struct CacheStats {
6 /// Number of cache lookups that reused existing state.
7 pub hits: u64,
8 /// Number of cache lookups that had to build new state.
9 pub misses: u64,
10 /// Number of currently occupied cache slots.
11 pub occupied_slots: u64,
12 /// Number of cache entries evicted by later insertions.
13 pub evictions: u64,
14}
15
16impl CacheStats {
17 /// Construct cache statistics from explicit counters.
18 pub const fn new(hits: u64, misses: u64) -> Self {
19 Self {
20 hits,
21 misses,
22 occupied_slots: 0,
23 evictions: 0,
24 }
25 }
26
27 /// Construct cache statistics from full counters.
28 pub const fn with_slots(hits: u64, misses: u64, occupied_slots: u64, evictions: u64) -> Self {
29 Self {
30 hits,
31 misses,
32 occupied_slots,
33 evictions,
34 }
35 }
36}
37
38/// Reusable codec state cached across decode calls.
39pub trait CodecContext: Default + Send {
40 /// Drop cached state while keeping the context reusable.
41 fn clear(&mut self);
42
43 /// Return current cache counters, when the codec tracks them.
44 fn cache_stats(&self) -> CacheStats {
45 CacheStats::default()
46 }
47}
48
49/// Wrapper that owns codec context state for repeated decode calls.
50#[derive(Debug, Default)]
51pub struct DecoderContext<C: CodecContext> {
52 codec: C,
53}
54
55impl<C: CodecContext> DecoderContext<C> {
56 /// Construct an empty decoder context.
57 pub fn new() -> Self {
58 Self {
59 codec: C::default(),
60 }
61 }
62
63 /// Borrow the codec-specific context.
64 pub fn codec(&self) -> &C {
65 &self.codec
66 }
67
68 /// Mutably borrow the codec-specific context.
69 pub fn codec_mut(&mut self) -> &mut C {
70 &mut self.codec
71 }
72
73 /// Clear cached codec state.
74 pub fn clear(&mut self) {
75 self.codec.clear();
76 }
77
78 /// Return cache counters from the codec-specific context.
79 pub fn cache_stats(&self) -> CacheStats {
80 self.codec.cache_stats()
81 }
82
83 /// Consume the wrapper and return the codec-specific context.
84 pub fn into_inner(self) -> C {
85 self.codec
86 }
87}