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