Skip to main content

oxihuman_core/
param_set.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5use std::collections::HashMap;
6
7#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub enum ParamValue {
10    Float(f32),
11    Int(i64),
12    Bool(bool),
13    Text(String),
14}
15
16/// A named parameter set for storing typed key-value parameters.
17#[allow(dead_code)]
18pub struct ParamSet {
19    params: HashMap<String, ParamValue>,
20    dirty: bool,
21}
22
23#[allow(dead_code)]
24impl ParamSet {
25    pub fn new() -> Self {
26        Self {
27            params: HashMap::new(),
28            dirty: false,
29        }
30    }
31    pub fn set_float(&mut self, key: &str, v: f32) {
32        self.params.insert(key.to_string(), ParamValue::Float(v));
33        self.dirty = true;
34    }
35    pub fn set_int(&mut self, key: &str, v: i64) {
36        self.params.insert(key.to_string(), ParamValue::Int(v));
37        self.dirty = true;
38    }
39    pub fn set_bool(&mut self, key: &str, v: bool) {
40        self.params.insert(key.to_string(), ParamValue::Bool(v));
41        self.dirty = true;
42    }
43    pub fn set_text(&mut self, key: &str, v: &str) {
44        self.params
45            .insert(key.to_string(), ParamValue::Text(v.to_string()));
46        self.dirty = true;
47    }
48    pub fn get(&self, key: &str) -> Option<&ParamValue> {
49        self.params.get(key)
50    }
51    pub fn get_float(&self, key: &str) -> Option<f32> {
52        if let Some(ParamValue::Float(v)) = self.params.get(key) {
53            Some(*v)
54        } else {
55            None
56        }
57    }
58    pub fn get_int(&self, key: &str) -> Option<i64> {
59        if let Some(ParamValue::Int(v)) = self.params.get(key) {
60            Some(*v)
61        } else {
62            None
63        }
64    }
65    pub fn get_bool(&self, key: &str) -> Option<bool> {
66        if let Some(ParamValue::Bool(v)) = self.params.get(key) {
67            Some(*v)
68        } else {
69            None
70        }
71    }
72    pub fn get_text(&self, key: &str) -> Option<&str> {
73        if let Some(ParamValue::Text(v)) = self.params.get(key) {
74            Some(v.as_str())
75        } else {
76            None
77        }
78    }
79    pub fn remove(&mut self, key: &str) -> bool {
80        self.params.remove(key).is_some()
81    }
82    pub fn contains(&self, key: &str) -> bool {
83        self.params.contains_key(key)
84    }
85    pub fn len(&self) -> usize {
86        self.params.len()
87    }
88    pub fn is_empty(&self) -> bool {
89        self.params.is_empty()
90    }
91    pub fn is_dirty(&self) -> bool {
92        self.dirty
93    }
94    pub fn mark_clean(&mut self) {
95        self.dirty = false;
96    }
97    pub fn clear(&mut self) {
98        self.params.clear();
99        self.dirty = false;
100    }
101    pub fn keys(&self) -> Vec<&str> {
102        self.params.keys().map(|s| s.as_str()).collect()
103    }
104}
105
106impl Default for ParamSet {
107    fn default() -> Self {
108        Self::new()
109    }
110}
111
112#[allow(dead_code)]
113pub fn new_param_set() -> ParamSet {
114    ParamSet::new()
115}
116#[allow(dead_code)]
117pub fn ps_set_float(p: &mut ParamSet, k: &str, v: f32) {
118    p.set_float(k, v);
119}
120#[allow(dead_code)]
121pub fn ps_set_int(p: &mut ParamSet, k: &str, v: i64) {
122    p.set_int(k, v);
123}
124#[allow(dead_code)]
125pub fn ps_set_bool(p: &mut ParamSet, k: &str, v: bool) {
126    p.set_bool(k, v);
127}
128#[allow(dead_code)]
129pub fn ps_set_text(p: &mut ParamSet, k: &str, v: &str) {
130    p.set_text(k, v);
131}
132#[allow(dead_code)]
133pub fn ps_get_float(p: &ParamSet, k: &str) -> Option<f32> {
134    p.get_float(k)
135}
136#[allow(dead_code)]
137pub fn ps_get_int(p: &ParamSet, k: &str) -> Option<i64> {
138    p.get_int(k)
139}
140#[allow(dead_code)]
141pub fn ps_get_bool(p: &ParamSet, k: &str) -> Option<bool> {
142    p.get_bool(k)
143}
144#[allow(dead_code)]
145pub fn ps_get_text<'a>(p: &'a ParamSet, k: &str) -> Option<&'a str> {
146    p.get_text(k)
147}
148#[allow(dead_code)]
149pub fn ps_remove(p: &mut ParamSet, k: &str) -> bool {
150    p.remove(k)
151}
152#[allow(dead_code)]
153pub fn ps_contains(p: &ParamSet, k: &str) -> bool {
154    p.contains(k)
155}
156#[allow(dead_code)]
157pub fn ps_len(p: &ParamSet) -> usize {
158    p.len()
159}
160#[allow(dead_code)]
161pub fn ps_is_empty(p: &ParamSet) -> bool {
162    p.is_empty()
163}
164#[allow(dead_code)]
165pub fn ps_clear(p: &mut ParamSet) {
166    p.clear();
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172    #[test]
173    fn test_set_get_float() {
174        let mut p = new_param_set();
175        ps_set_float(&mut p, "speed", std::f32::consts::PI);
176        assert!(
177            (ps_get_float(&p, "speed").expect("should succeed") - std::f32::consts::PI).abs()
178                < 1e-6
179        );
180    }
181    #[test]
182    fn test_set_get_int() {
183        let mut p = new_param_set();
184        ps_set_int(&mut p, "count", 42);
185        assert_eq!(ps_get_int(&p, "count"), Some(42));
186    }
187    #[test]
188    fn test_set_get_bool() {
189        let mut p = new_param_set();
190        ps_set_bool(&mut p, "flag", true);
191        assert_eq!(ps_get_bool(&p, "flag"), Some(true));
192    }
193    #[test]
194    fn test_set_get_text() {
195        let mut p = new_param_set();
196        ps_set_text(&mut p, "name", "oxihuman");
197        assert_eq!(ps_get_text(&p, "name"), Some("oxihuman"));
198    }
199    #[test]
200    fn test_remove() {
201        let mut p = new_param_set();
202        ps_set_int(&mut p, "x", 1);
203        assert!(ps_remove(&mut p, "x"));
204        assert!(!ps_contains(&p, "x"));
205    }
206    #[test]
207    fn test_dirty_flag() {
208        let mut p = new_param_set();
209        ps_set_float(&mut p, "v", 1.0);
210        assert!(p.is_dirty());
211        p.mark_clean();
212        assert!(!p.is_dirty());
213    }
214    #[test]
215    fn test_len() {
216        let mut p = new_param_set();
217        assert_eq!(ps_len(&p), 0);
218        ps_set_int(&mut p, "a", 1);
219        assert_eq!(ps_len(&p), 1);
220    }
221    #[test]
222    fn test_clear() {
223        let mut p = new_param_set();
224        ps_set_bool(&mut p, "b", false);
225        ps_clear(&mut p);
226        assert!(ps_is_empty(&p));
227    }
228    #[test]
229    fn test_missing_key_returns_none() {
230        let p = new_param_set();
231        assert!(ps_get_float(&p, "nope").is_none());
232    }
233    #[test]
234    fn test_overwrite() {
235        let mut p = new_param_set();
236        ps_set_int(&mut p, "x", 1);
237        ps_set_int(&mut p, "x", 2);
238        assert_eq!(ps_get_int(&p, "x"), Some(2));
239        assert_eq!(ps_len(&p), 1);
240    }
241}