oxihuman_core/
struct_map.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone, PartialEq)]
12pub enum FieldVal {
13 Bool(bool),
14 Int(i64),
15 Float(f32),
16 Str(String),
17 Bytes(Vec<u8>),
18}
19
20#[allow(dead_code)]
22pub struct StructMap {
23 fields: HashMap<String, FieldVal>,
24 schema: Vec<String>,
25}
26
27#[allow(dead_code)]
28impl StructMap {
29 pub fn new() -> Self {
30 Self {
31 fields: HashMap::new(),
32 schema: Vec::new(),
33 }
34 }
35
36 pub fn declare(&mut self, name: &str) {
38 if !self.schema.contains(&name.to_string()) {
39 self.schema.push(name.to_string());
40 }
41 }
42
43 pub fn set(&mut self, name: &str, val: FieldVal) {
44 self.fields.insert(name.to_string(), val);
45 }
46
47 pub fn get(&self, name: &str) -> Option<&FieldVal> {
48 self.fields.get(name)
49 }
50
51 pub fn remove(&mut self, name: &str) -> bool {
52 self.fields.remove(name).is_some()
53 }
54
55 pub fn contains(&self, name: &str) -> bool {
56 self.fields.contains_key(name)
57 }
58
59 pub fn field_count(&self) -> usize {
60 self.fields.len()
61 }
62
63 pub fn is_empty(&self) -> bool {
64 self.fields.is_empty()
65 }
66
67 pub fn field_names(&self) -> Vec<String> {
68 let mut names: Vec<String> = self.fields.keys().cloned().collect();
69 names.sort();
70 names
71 }
72
73 pub fn get_bool(&self, name: &str) -> Option<bool> {
74 match self.fields.get(name)? {
75 FieldVal::Bool(b) => Some(*b),
76 _ => None,
77 }
78 }
79
80 pub fn get_int(&self, name: &str) -> Option<i64> {
81 match self.fields.get(name)? {
82 FieldVal::Int(i) => Some(*i),
83 _ => None,
84 }
85 }
86
87 pub fn get_float(&self, name: &str) -> Option<f32> {
88 match self.fields.get(name)? {
89 FieldVal::Float(f) => Some(*f),
90 _ => None,
91 }
92 }
93
94 pub fn get_str(&self, name: &str) -> Option<&str> {
95 match self.fields.get(name)? {
96 FieldVal::Str(s) => Some(s.as_str()),
97 _ => None,
98 }
99 }
100
101 pub fn missing_declared(&self) -> Vec<String> {
102 self.schema
103 .iter()
104 .filter(|n| !self.fields.contains_key(*n))
105 .cloned()
106 .collect()
107 }
108
109 pub fn clear(&mut self) {
110 self.fields.clear();
111 }
112}
113
114impl Default for StructMap {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120pub fn new_struct_map() -> StructMap {
121 StructMap::new()
122}
123
124pub fn stm_set(m: &mut StructMap, name: &str, val: FieldVal) {
125 m.set(name, val);
126}
127
128pub fn stm_get(m: &StructMap, name: &str) -> Option<FieldVal> {
129 m.get(name).cloned()
130}
131
132pub fn stm_contains(m: &StructMap, name: &str) -> bool {
133 m.contains(name)
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn empty_on_creation() {
142 let m = new_struct_map();
143 assert!(m.is_empty());
144 }
145
146 #[test]
147 fn set_and_get_bool() {
148 let mut m = new_struct_map();
149 stm_set(&mut m, "active", FieldVal::Bool(true));
150 assert_eq!(m.get_bool("active"), Some(true));
151 }
152
153 #[test]
154 fn set_and_get_int() {
155 let mut m = new_struct_map();
156 stm_set(&mut m, "age", FieldVal::Int(30));
157 assert_eq!(m.get_int("age"), Some(30));
158 }
159
160 #[test]
161 fn set_and_get_float() {
162 let mut m = new_struct_map();
163 stm_set(&mut m, "x", FieldVal::Float(std::f32::consts::PI));
164 assert!((m.get_float("x").expect("should succeed") - std::f32::consts::PI).abs() < 1e-5);
165 }
166
167 #[test]
168 fn set_and_get_str() {
169 let mut m = new_struct_map();
170 stm_set(&mut m, "name", FieldVal::Str("Alice".to_string()));
171 assert_eq!(m.get_str("name"), Some("Alice"));
172 }
173
174 #[test]
175 fn remove_field() {
176 let mut m = new_struct_map();
177 stm_set(&mut m, "tmp", FieldVal::Bool(false));
178 assert!(m.remove("tmp"));
179 assert!(!stm_contains(&m, "tmp"));
180 }
181
182 #[test]
183 fn field_names_sorted() {
184 let mut m = new_struct_map();
185 stm_set(&mut m, "z", FieldVal::Int(1));
186 stm_set(&mut m, "a", FieldVal::Int(2));
187 assert_eq!(m.field_names(), vec!["a".to_string(), "z".to_string()]);
188 }
189
190 #[test]
191 fn missing_declared_fields() {
192 let mut m = new_struct_map();
193 m.declare("x");
194 m.declare("y");
195 stm_set(&mut m, "x", FieldVal::Int(0));
196 assert_eq!(m.missing_declared(), vec!["y".to_string()]);
197 }
198
199 #[test]
200 fn clear_resets() {
201 let mut m = new_struct_map();
202 stm_set(&mut m, "k", FieldVal::Bool(true));
203 m.clear();
204 assert!(m.is_empty());
205 }
206
207 #[test]
208 fn wrong_type_returns_none() {
209 let mut m = new_struct_map();
210 stm_set(&mut m, "x", FieldVal::Int(5));
211 assert_eq!(m.get_bool("x"), None);
212 }
213}