mcraw_tui/preview/
state.rs1use std::collections::HashMap;
2use std::time::Instant;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct FrameKey {
6 pub timestamp_ns: i64,
7}
8
9#[derive(Debug)]
10pub struct CachedFrame {
11 pub timestamp_ns: i64,
12 pub bayer: Vec<u16>,
13 pub last_access: Instant,
14}
15
16impl CachedFrame {
17 pub fn byte_size(&self) -> usize {
18 self.bayer.len() * 2
19 }
20}
21
22pub struct FrameCache {
23 entries: HashMap<FrameKey, CachedFrame>,
24 max_bytes: usize,
25 current_bytes: usize,
26}
27
28impl FrameCache {
29 pub fn new(max_bytes_mb: usize) -> Self {
30 Self {
31 entries: HashMap::new(),
32 max_bytes: max_bytes_mb * 1024 * 1024,
33 current_bytes: 0,
34 }
35 }
36
37 pub fn get(&mut self, key: &FrameKey) -> Option<&CachedFrame> {
38 if let Some(frame) = self.entries.get_mut(key) {
39 frame.last_access = Instant::now();
40 return Some(frame);
41 }
42 None
43 }
44
45 pub fn insert(&mut self, frame: CachedFrame) {
46 let key = FrameKey { timestamp_ns: frame.timestamp_ns };
47 let frame_bytes = frame.byte_size();
48
49 if let Some(old) = self.entries.remove(&key) {
50 self.current_bytes -= old.byte_size();
51 }
52
53 while self.current_bytes + frame_bytes > self.max_bytes && !self.entries.is_empty() {
54 if let Some(oldest_key) = self.entries
55 .iter()
56 .min_by_key(|(_, v)| v.last_access)
57 .map(|(k, _)| *k)
58 {
59 if let Some(old) = self.entries.remove(&oldest_key) {
60 self.current_bytes -= old.byte_size();
61 }
62 }
63 }
64
65 self.current_bytes += frame_bytes;
66 self.entries.insert(key, frame);
67 }
68
69 pub fn clear(&mut self) {
70 self.entries.clear();
71 self.current_bytes = 0;
72 }
73
74 pub fn current_bytes(&self) -> usize {
75 self.current_bytes
76 }
77
78 pub fn len(&self) -> usize {
79 self.entries.len()
80 }
81
82 pub fn is_empty(&self) -> bool {
83 self.entries.is_empty()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn cache_eviction() {
93 let mut cache = FrameCache::new(1); let small_frame = CachedFrame {
95 timestamp_ns: 0,
96 bayer: vec![0u16; 100], last_access: Instant::now(),
98 };
99 cache.insert(small_frame);
100 assert_eq!(cache.len(), 1);
101
102 let key = FrameKey { timestamp_ns: 0 };
103 assert!(cache.get(&key).is_some());
104 }
105
106 #[test]
107 fn cache_clear() {
108 let mut cache = FrameCache::new(256);
109 let frame = CachedFrame {
110 timestamp_ns: 42,
111 bayer: vec![0u16; 1000],
112 last_access: Instant::now(),
113 };
114 cache.insert(frame);
115 assert!(!cache.is_empty());
116 cache.clear();
117 assert!(cache.is_empty());
118 assert_eq!(cache.current_bytes(), 0);
119 }
120}