oxihuman_core/
proc_context.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[derive(Debug, Clone)]
11pub enum CtxVal {
12 Int(i64),
13 Float(f64),
14 Bool(bool),
15 Text(String),
16}
17
18#[derive(Debug, Default)]
20pub struct ProcContext {
21 entries: HashMap<String, CtxVal>,
22 stage: u32,
23 errors: Vec<String>,
24 warnings: Vec<String>,
25 done: bool,
26}
27
28#[allow(dead_code)]
29impl ProcContext {
30 pub fn new() -> Self {
31 ProcContext::default()
32 }
33
34 pub fn set_int(&mut self, key: &str, v: i64) {
35 self.entries.insert(key.to_string(), CtxVal::Int(v));
36 }
37
38 pub fn set_float(&mut self, key: &str, v: f64) {
39 self.entries.insert(key.to_string(), CtxVal::Float(v));
40 }
41
42 pub fn set_bool(&mut self, key: &str, v: bool) {
43 self.entries.insert(key.to_string(), CtxVal::Bool(v));
44 }
45
46 pub fn set_text(&mut self, key: &str, v: &str) {
47 self.entries
48 .insert(key.to_string(), CtxVal::Text(v.to_string()));
49 }
50
51 pub fn get_int(&self, key: &str) -> Option<i64> {
52 match self.entries.get(key) {
53 Some(CtxVal::Int(v)) => Some(*v),
54 _ => None,
55 }
56 }
57
58 pub fn get_float(&self, key: &str) -> Option<f64> {
59 match self.entries.get(key) {
60 Some(CtxVal::Float(v)) => Some(*v),
61 _ => None,
62 }
63 }
64
65 pub fn get_bool(&self, key: &str) -> Option<bool> {
66 match self.entries.get(key) {
67 Some(CtxVal::Bool(v)) => Some(*v),
68 _ => None,
69 }
70 }
71
72 pub fn get_text(&self, key: &str) -> Option<&str> {
73 match self.entries.get(key) {
74 Some(CtxVal::Text(v)) => Some(v.as_str()),
75 _ => None,
76 }
77 }
78
79 pub fn has(&self, key: &str) -> bool {
80 self.entries.contains_key(key)
81 }
82
83 pub fn remove(&mut self, key: &str) -> bool {
84 self.entries.remove(key).is_some()
85 }
86
87 pub fn stage(&self) -> u32 {
88 self.stage
89 }
90
91 pub fn advance_stage(&mut self) {
92 self.stage += 1;
93 }
94
95 pub fn add_error(&mut self, msg: &str) {
96 self.errors.push(msg.to_string());
97 }
98
99 pub fn add_warning(&mut self, msg: &str) {
100 self.warnings.push(msg.to_string());
101 }
102
103 pub fn has_errors(&self) -> bool {
104 !self.errors.is_empty()
105 }
106
107 pub fn error_count(&self) -> usize {
108 self.errors.len()
109 }
110
111 pub fn warning_count(&self) -> usize {
112 self.warnings.len()
113 }
114
115 pub fn mark_done(&mut self) {
116 self.done = true;
117 }
118
119 pub fn is_done(&self) -> bool {
120 self.done
121 }
122
123 pub fn reset(&mut self) {
124 self.entries.clear();
125 self.errors.clear();
126 self.warnings.clear();
127 self.stage = 0;
128 self.done = false;
129 }
130
131 pub fn entry_count(&self) -> usize {
132 self.entries.len()
133 }
134}
135
136pub fn new_proc_context() -> ProcContext {
137 ProcContext::new()
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn set_and_get_int() {
146 let mut ctx = new_proc_context();
147 ctx.set_int("count", 42);
148 assert_eq!(ctx.get_int("count"), Some(42));
149 }
150
151 #[test]
152 fn set_and_get_float() {
153 let mut ctx = new_proc_context();
154 ctx.set_float("ratio", std::f64::consts::PI);
155 assert!(ctx.get_float("ratio").expect("should succeed") > std::f64::consts::E);
156 }
157
158 #[test]
159 fn set_and_get_bool() {
160 let mut ctx = new_proc_context();
161 ctx.set_bool("ready", true);
162 assert_eq!(ctx.get_bool("ready"), Some(true));
163 }
164
165 #[test]
166 fn set_and_get_text() {
167 let mut ctx = new_proc_context();
168 ctx.set_text("name", "oxihuman");
169 assert_eq!(ctx.get_text("name"), Some("oxihuman"));
170 }
171
172 #[test]
173 fn has_and_remove() {
174 let mut ctx = new_proc_context();
175 ctx.set_int("x", 1);
176 assert!(ctx.has("x"));
177 assert!(ctx.remove("x"));
178 assert!(!ctx.has("x"));
179 }
180
181 #[test]
182 fn stage_advance() {
183 let mut ctx = new_proc_context();
184 assert_eq!(ctx.stage(), 0);
185 ctx.advance_stage();
186 ctx.advance_stage();
187 assert_eq!(ctx.stage(), 2);
188 }
189
190 #[test]
191 fn errors_and_warnings() {
192 let mut ctx = new_proc_context();
193 ctx.add_error("bad");
194 ctx.add_warning("meh");
195 assert!(ctx.has_errors());
196 assert_eq!(ctx.error_count(), 1);
197 assert_eq!(ctx.warning_count(), 1);
198 }
199
200 #[test]
201 fn done_flag() {
202 let mut ctx = new_proc_context();
203 assert!(!ctx.is_done());
204 ctx.mark_done();
205 assert!(ctx.is_done());
206 }
207
208 #[test]
209 fn reset_clears_all() {
210 let mut ctx = new_proc_context();
211 ctx.set_int("k", 1);
212 ctx.add_error("e");
213 ctx.advance_stage();
214 ctx.mark_done();
215 ctx.reset();
216 assert_eq!(ctx.entry_count(), 0);
217 assert!(!ctx.has_errors());
218 assert_eq!(ctx.stage(), 0);
219 assert!(!ctx.is_done());
220 }
221}