use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
#[derive(Clone, Debug, PartialEq)]
pub enum ParamValue {
Bool(bool),
UInt(u64),
Double(f64),
Str(String),
}
#[derive(Clone, Debug, Default)]
pub struct Params {
entries: BTreeMap<String, ParamValue>,
}
fn norm(key: &str) -> String {
key.strip_prefix(':').unwrap_or(key).to_string()
}
impl Params {
pub fn new() -> Self {
Self::default()
}
pub fn set(&mut self, key: &str, value: ParamValue) {
self.entries.insert(norm(key), value);
}
pub fn get(&self, key: &str) -> Option<&ParamValue> {
self.entries.get(&norm(key))
}
pub fn get_bool(&self, key: &str, default: bool) -> bool {
match self.get(key) {
Some(ParamValue::Bool(b)) => *b,
_ => default,
}
}
pub fn get_uint(&self, key: &str, default: u64) -> u64 {
match self.get(key) {
Some(ParamValue::UInt(u)) => *u,
_ => default,
}
}
pub fn contains(&self, key: &str) -> bool {
self.entries.contains_key(&norm(key))
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::{ParamValue, Params};
#[test]
fn set_get_roundtrip_and_colon_normalisation() {
let mut p = Params::new();
p.set(":produce-models", ParamValue::Bool(true));
p.set("timeout", ParamValue::UInt(5000));
assert!(p.get_bool("produce-models", false));
assert!(p.get_bool(":produce-models", false));
assert_eq!(p.get_uint("timeout", 0), 5000);
assert!(p.contains(":timeout"));
assert_eq!(p.len(), 2);
}
#[test]
fn defaults_on_missing_or_wrong_type() {
let mut p = Params::new();
p.set("random-seed", ParamValue::UInt(7));
assert!(p.get_bool("random-seed", true)); assert_eq!(p.get_uint("nonexistent", 42), 42); assert!(p.get("nonexistent").is_none());
}
}