oxihuman_core/
value_cache.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone)]
12pub struct ValueEntry {
13 pub value: f32,
14 pub version: u32,
15 pub dirty: bool,
16}
17
18#[allow(dead_code)]
20#[derive(Debug, Clone, Default)]
21pub struct ValueCache {
22 entries: HashMap<String, ValueEntry>,
23 global_version: u32,
24}
25
26#[allow(dead_code)]
28pub fn new_value_cache() -> ValueCache {
29 ValueCache::default()
30}
31
32#[allow(dead_code)]
34pub fn vc_store(vc: &mut ValueCache, key: &str, value: f32) {
35 vc.entries.insert(
36 key.to_string(),
37 ValueEntry {
38 value,
39 version: vc.global_version,
40 dirty: false,
41 },
42 );
43}
44
45#[allow(dead_code)]
47pub fn vc_get(vc: &ValueCache, key: &str) -> Option<f32> {
48 vc.entries
49 .get(key)
50 .and_then(|e| if e.dirty { None } else { Some(e.value) })
51}
52
53#[allow(dead_code)]
55pub fn vc_invalidate(vc: &mut ValueCache, key: &str) {
56 if let Some(e) = vc.entries.get_mut(key) {
57 e.dirty = true;
58 }
59}
60
61#[allow(dead_code)]
63pub fn vc_invalidate_all(vc: &mut ValueCache) {
64 vc.global_version += 1;
65 for e in vc.entries.values_mut() {
66 e.dirty = true;
67 }
68}
69
70#[allow(dead_code)]
72pub fn vc_is_valid(vc: &ValueCache, key: &str) -> bool {
73 vc.entries.get(key).is_some_and(|e| !e.dirty)
74}
75
76#[allow(dead_code)]
78pub fn vc_len(vc: &ValueCache) -> usize {
79 vc.entries.len()
80}
81
82#[allow(dead_code)]
84pub fn vc_dirty_count(vc: &ValueCache) -> usize {
85 vc.entries.values().filter(|e| e.dirty).count()
86}
87
88#[allow(dead_code)]
90pub fn vc_remove(vc: &mut ValueCache, key: &str) {
91 vc.entries.remove(key);
92}
93
94#[allow(dead_code)]
96pub fn vc_clear(vc: &mut ValueCache) {
97 vc.entries.clear();
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use std::f32::consts::PI;
104
105 #[test]
106 fn test_store_and_get() {
107 let mut vc = new_value_cache();
108 vc_store(&mut vc, "x", PI);
109 assert!((vc_get(&vc, "x").expect("should succeed") - PI).abs() < 1e-5);
110 }
111
112 #[test]
113 fn test_missing_returns_none() {
114 let vc = new_value_cache();
115 assert!(vc_get(&vc, "y").is_none());
116 }
117
118 #[test]
119 fn test_invalidate() {
120 let mut vc = new_value_cache();
121 vc_store(&mut vc, "a", 1.0);
122 vc_invalidate(&mut vc, "a");
123 assert!(vc_get(&vc, "a").is_none());
124 }
125
126 #[test]
127 fn test_invalidate_all() {
128 let mut vc = new_value_cache();
129 vc_store(&mut vc, "a", 1.0);
130 vc_store(&mut vc, "b", 2.0);
131 vc_invalidate_all(&mut vc);
132 assert_eq!(vc_dirty_count(&vc), 2);
133 }
134
135 #[test]
136 fn test_is_valid() {
137 let mut vc = new_value_cache();
138 vc_store(&mut vc, "v", 5.0);
139 assert!(vc_is_valid(&vc, "v"));
140 vc_invalidate(&mut vc, "v");
141 assert!(!vc_is_valid(&vc, "v"));
142 }
143
144 #[test]
145 fn test_remove() {
146 let mut vc = new_value_cache();
147 vc_store(&mut vc, "k", 7.0);
148 vc_remove(&mut vc, "k");
149 assert!(vc_get(&vc, "k").is_none());
150 }
151
152 #[test]
153 fn test_len() {
154 let mut vc = new_value_cache();
155 vc_store(&mut vc, "a", 1.0);
156 vc_store(&mut vc, "b", 2.0);
157 assert_eq!(vc_len(&vc), 2);
158 }
159
160 #[test]
161 fn test_clear() {
162 let mut vc = new_value_cache();
163 vc_store(&mut vc, "x", 9.0);
164 vc_clear(&mut vc);
165 assert_eq!(vc_len(&vc), 0);
166 }
167
168 #[test]
169 fn test_reclean_after_restore() {
170 let mut vc = new_value_cache();
171 vc_store(&mut vc, "m", 1.0);
172 vc_invalidate(&mut vc, "m");
173 vc_store(&mut vc, "m", 2.0);
174 assert!(vc_is_valid(&vc, "m"));
175 }
176}