oxihuman_core/
var_store.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone)]
12pub struct VarEntry {
13 pub name: String,
14 pub value: f32,
15 pub default: f32,
16 pub changed: bool,
17}
18
19#[allow(dead_code)]
21#[derive(Debug, Clone, Default)]
22pub struct VarStore {
23 vars: HashMap<String, VarEntry>,
24}
25
26#[allow(dead_code)]
28pub fn new_var_store() -> VarStore {
29 VarStore::default()
30}
31
32#[allow(dead_code)]
34pub fn vs_declare(vs: &mut VarStore, name: &str, default: f32) {
35 vs.vars.entry(name.to_string()).or_insert(VarEntry {
36 name: name.to_string(),
37 value: default,
38 default,
39 changed: false,
40 });
41}
42
43#[allow(dead_code)]
45pub fn vs_set(vs: &mut VarStore, name: &str, value: f32) {
46 let entry = vs.vars.entry(name.to_string()).or_insert(VarEntry {
47 name: name.to_string(),
48 value,
49 default: value,
50 changed: false,
51 });
52 entry.changed = (entry.value - value).abs() > f32::EPSILON;
53 entry.value = value;
54}
55
56#[allow(dead_code)]
58pub fn vs_get(vs: &VarStore, name: &str) -> Option<f32> {
59 vs.vars.get(name).map(|e| e.value)
60}
61
62#[allow(dead_code)]
64pub fn vs_is_changed(vs: &VarStore, name: &str) -> bool {
65 vs.vars.get(name).is_some_and(|e| e.changed)
66}
67
68#[allow(dead_code)]
70pub fn vs_reset(vs: &mut VarStore, name: &str) {
71 if let Some(e) = vs.vars.get_mut(name) {
72 e.value = e.default;
73 e.changed = false;
74 }
75}
76
77#[allow(dead_code)]
79pub fn vs_flush(vs: &mut VarStore) {
80 for e in vs.vars.values_mut() {
81 e.changed = false;
82 }
83}
84
85#[allow(dead_code)]
87pub fn vs_len(vs: &VarStore) -> usize {
88 vs.vars.len()
89}
90
91#[allow(dead_code)]
93pub fn vs_changed_names(vs: &VarStore) -> Vec<String> {
94 vs.vars
95 .values()
96 .filter(|e| e.changed)
97 .map(|e| e.name.clone())
98 .collect()
99}
100
101#[allow(dead_code)]
103pub fn vs_remove(vs: &mut VarStore, name: &str) {
104 vs.vars.remove(name);
105}
106
107#[allow(dead_code)]
109pub fn vs_clear(vs: &mut VarStore) {
110 vs.vars.clear();
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_declare_and_get() {
119 let mut vs = new_var_store();
120 vs_declare(&mut vs, "mass", 1.0);
121 assert!((vs_get(&vs, "mass").expect("should succeed") - 1.0).abs() < 1e-6);
122 }
123
124 #[test]
125 fn test_set_and_get() {
126 let mut vs = new_var_store();
127 vs_set(&mut vs, "speed", 5.0);
128 assert!((vs_get(&vs, "speed").expect("should succeed") - 5.0).abs() < 1e-6);
129 }
130
131 #[test]
132 fn test_change_flag() {
133 let mut vs = new_var_store();
134 vs_declare(&mut vs, "x", 0.0);
135 vs_set(&mut vs, "x", 1.0);
136 assert!(vs_is_changed(&vs, "x"));
137 }
138
139 #[test]
140 fn test_flush_clears_change() {
141 let mut vs = new_var_store();
142 vs_set(&mut vs, "y", 3.0);
143 vs_flush(&mut vs);
144 assert!(!vs_is_changed(&vs, "y"));
145 }
146
147 #[test]
148 fn test_reset_to_default() {
149 let mut vs = new_var_store();
150 vs_declare(&mut vs, "z", 10.0);
151 vs_set(&mut vs, "z", 99.0);
152 vs_reset(&mut vs, "z");
153 assert!((vs_get(&vs, "z").expect("should succeed") - 10.0).abs() < 1e-6);
154 }
155
156 #[test]
157 fn test_changed_names() {
158 let mut vs = new_var_store();
159 vs_declare(&mut vs, "a", 0.0);
160 vs_declare(&mut vs, "b", 0.0);
161 vs_set(&mut vs, "a", 1.0);
162 let changed = vs_changed_names(&vs);
163 assert!(changed.contains(&"a".to_string()));
164 assert!(!changed.contains(&"b".to_string()));
165 }
166
167 #[test]
168 fn test_remove() {
169 let mut vs = new_var_store();
170 vs_declare(&mut vs, "k", 5.0);
171 vs_remove(&mut vs, "k");
172 assert!(vs_get(&vs, "k").is_none());
173 }
174
175 #[test]
176 fn test_len() {
177 let mut vs = new_var_store();
178 vs_declare(&mut vs, "a", 1.0);
179 vs_declare(&mut vs, "b", 2.0);
180 assert_eq!(vs_len(&vs), 2);
181 }
182
183 #[test]
184 fn test_clear() {
185 let mut vs = new_var_store();
186 vs_declare(&mut vs, "x", 1.0);
187 vs_clear(&mut vs);
188 assert_eq!(vs_len(&vs), 0);
189 }
190}