use std::collections::BTreeMap;
use super::VmValue;
pub trait VmDictExt {
fn put(&mut self, key: &str, value: VmValue);
fn put_str(&mut self, key: &str, value: impl AsRef<str>);
fn put_opt_str(&mut self, key: &str, value: Option<impl AsRef<str>>);
fn put_opt(&mut self, key: &str, value: Option<VmValue>);
fn put_bool(&mut self, key: &str, value: bool);
fn put_int(&mut self, key: &str, value: i64);
}
impl VmDictExt for BTreeMap<String, VmValue> {
fn put(&mut self, key: &str, value: VmValue) {
self.insert(key.to_string(), value);
}
fn put_str(&mut self, key: &str, value: impl AsRef<str>) {
self.insert(key.to_string(), VmValue::string(value));
}
fn put_opt_str(&mut self, key: &str, value: Option<impl AsRef<str>>) {
if let Some(value) = value {
self.insert(key.to_string(), VmValue::string(value));
}
}
fn put_opt(&mut self, key: &str, value: Option<VmValue>) {
if let Some(value) = value {
self.insert(key.to_string(), value);
}
}
fn put_bool(&mut self, key: &str, value: bool) {
self.insert(key.to_string(), VmValue::Bool(value));
}
fn put_int(&mut self, key: &str, value: i64) {
self.insert(key.to_string(), VmValue::Int(value));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn put_str_matches_manual_construction() {
let mut dict = BTreeMap::new();
dict.put_str("k", "v");
match dict.get("k") {
Some(VmValue::String(s)) => assert_eq!(s.as_ref(), "v"),
other => panic!("expected string value, got {other:?}"),
}
}
#[test]
fn put_opt_str_skips_none_and_inserts_some() {
let mut dict = BTreeMap::new();
dict.put_opt_str("present", Some("v"));
dict.put_opt_str("absent", None::<&str>);
assert!(dict.contains_key("present"));
assert!(!dict.contains_key("absent"));
}
#[test]
fn put_handles_scalars() {
let mut dict = BTreeMap::new();
dict.put_bool("b", true);
dict.put_int("n", 7);
dict.put("nil", VmValue::Nil);
assert!(matches!(dict.get("b"), Some(VmValue::Bool(true))));
assert!(matches!(dict.get("n"), Some(VmValue::Int(7))));
assert!(matches!(dict.get("nil"), Some(VmValue::Nil)));
}
}