simple_expressions/types/
dict.rs

1use crate::types::error::{Error, Result};
2use crate::types::object::Object;
3use crate::types::primitive::Primitive;
4use crate::types::value::Value;
5use crate::types::{function, list};
6
7use crate::types::function::method0;
8use std::any::Any;
9use std::collections::BTreeMap;
10use std::rc::Rc;
11
12pub fn new(map: BTreeMap<String, Value>) -> Value {
13    Value::Object(Rc::new(DictObject::new(map)))
14}
15pub fn new_string_dict(map: BTreeMap<String, String>) -> DictObject {
16    DictObject {
17        map: map.into_iter().map(|(k, v)| (k, Value::Primitive(Primitive::Str(v)))).collect(),
18    }
19}
20pub struct DictObject {
21    map: BTreeMap<String, Value>,
22}
23
24impl DictObject {
25    pub fn new(map: BTreeMap<String, Value>) -> DictObject {
26        DictObject { map }
27    }
28}
29
30impl Object for DictObject {
31    fn type_name(&self) -> &'static str {
32        "dict"
33    }
34    fn get_member(&self, name: &str) -> Result<Value> {
35        match name {
36            "length" => Ok(Value::from(self.map.len() as i64)),
37            "keys" => {
38                let keys: Vec<Value> = self.map.keys().cloned().map(Value::from).collect();
39                Ok(function::method0(move || Ok(list::new(keys.clone()))))
40            }
41            "values" => {
42                let vals: Vec<Value> = self.map.values().cloned().collect();
43                Ok(method0(move || Ok(list::new(vals.clone()))))
44            }
45            "contains" => {
46                let base = self.map.clone();
47                Ok(function::method1(move |arg: &Value| {
48                    if let Value::Primitive(Primitive::Str(s)) = arg {
49                        Ok(Value::from(base.contains_key(s)))
50                    } else {
51                        Err(Error::TypeMismatch("contains expects a string".into()))
52                    }
53                }))
54            }
55            "get" => {
56                let base = self.map.clone();
57                Ok(function::new(std::rc::Rc::new(move |args: &[Value]| {
58                    if args.len() != 2 {
59                        return Err(Error::EvaluationFailed("expected 2 args".into()));
60                    }
61                    let key = match &args[0] {
62                        Value::Primitive(Primitive::Str(s)) => s.clone(),
63                        _ => return Err(Error::TypeMismatch("get expects string key".into())),
64                    };
65                    if let Some(v) = base.get(&key) { Ok(v.clone()) } else { Ok(args[1].clone()) }
66                })))
67            }
68            _ => Err(Error::UnknownMember {
69                type_name: "dict".into(),
70                member: name.to_string(),
71            }),
72        }
73    }
74
75    fn get_key_value(&self, key: &str) -> Result<Value> {
76        self.map.get(key).cloned().ok_or(Error::NoSuchKey(key.to_string()))
77    }
78
79    fn as_string(&self) -> Option<String> {
80        Some(format!("{{{}}}", self.map.iter().map(|(k, v)| format!("{}: {}", k, v)).collect::<Vec<_>>().join(", ")))
81    }
82
83    fn as_bool(&self) -> Option<bool> {
84        Some(!self.map.is_empty())
85    }
86
87    fn equals(&self, other: &Value) -> bool {
88        if let Value::Object(other_obj) = other
89            && let Some(other_dict) = other_obj.as_any().downcast_ref::<DictObject>()
90        {
91            self.map == other_dict.map
92        } else {
93            false
94        }
95    }
96
97    fn as_any(&self) -> &dyn Any {
98        self
99    }
100
101    fn as_any_mut(&mut self) -> &mut dyn Any {
102        self
103    }
104}