compose_library/foundations/
map.rs

1use crate::repr::Repr;
2use crate::{ArrayIter, Heap, Trace};
3use compose_library::{HeapRef, IntoValue, IterValue, UntypedRef, Value, Vm};
4use compose_macros::func;
5use compose_macros::{scope, ty};
6use ecow::{EcoString, EcoVec};
7use std::collections::HashMap;
8use std::ops::{Deref, DerefMut};
9use compose_library::diag::StrResult;
10use compose_library::ops::Comparison;
11
12#[ty(scope, cast, name = "Map")]
13#[derive(Debug, Clone, PartialEq)]
14pub struct MapValue(HeapRef<Map>);
15
16impl Trace for MapValue {
17    fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
18        f(self.0.key())
19    }
20}
21
22impl MapValue {
23    pub fn new(heap: &mut Heap) -> Self {
24        Self(heap.alloc(Map::new()))
25    }
26
27    pub fn from(heap: &mut Heap, values: HashMap<EcoString, Value>) -> Self {
28        Self(heap.alloc(values.into()))
29    }
30
31    pub fn shallow_clone(&self, vm: &mut dyn Vm) -> Self {
32        let clone = self.0.get_unwrap(vm.heap()).clone();
33
34        Self(vm.heap_mut().alloc(clone))
35    }
36
37    pub fn heap_ref(&self) -> HeapRef<Map> {
38        self.0
39    }
40}
41
42#[scope]
43impl MapValue {
44    #[func]
45    pub fn get(&self, vm: &dyn Vm, key: EcoString) -> Option<Value> {
46        self.0.get_unwrap(vm.heap()).get(&key).cloned()
47    }
48
49    #[func]
50    pub fn insert(&mut self, vm: &mut dyn Vm, key: EcoString, value: Value) {
51        self.0.get_mut_unwrap(vm.heap_mut()).insert(key, value);
52    }
53
54    #[func]
55    pub fn len(&self, vm: &dyn Vm) -> usize {
56        self.0.get_unwrap(vm.heap()).len()
57    }
58
59    #[func]
60    pub fn contains_key(&self, vm: &dyn Vm, key: EcoString) -> bool {
61        self.0.get_unwrap(vm.heap()).contains_key(&key)
62    }
63
64    #[func]
65    pub fn values(&self, vm: &mut dyn Vm) -> IterValue {
66        let values: EcoVec<_> = self.0.get_unwrap(vm.heap()).values().cloned().collect();
67
68        IterValue::new(ArrayIter::from(values).into(), vm)
69    }
70
71    #[func]
72    pub fn keys(&self, vm: &mut dyn Vm) -> IterValue {
73        let keys: EcoVec<_> = self
74            .0
75            .get_unwrap(vm.heap())
76            .keys()
77            .map(|s| s.as_str().into_value())
78            .collect();
79
80        IterValue::new(ArrayIter::from(keys).into(), vm)
81    }
82}
83
84impl Repr for MapValue {
85    fn repr(&self, vm: &dyn Vm) -> EcoString {
86        let inner = self.0.get_unwrap(vm.heap());
87        let mut repr = EcoString::new();
88        repr.push_str("{\n");
89        for (key, value) in inner.iter() {
90            repr.push_str(&format!("\t{}: {},\n", key, value.repr(vm)));
91        }
92        repr.push('}');
93        repr
94    }
95}
96
97#[derive(Debug, Clone, PartialEq)]
98pub struct Map {
99    values: HashMap<EcoString, Value>,
100}
101
102impl Map {
103    pub fn new() -> Self {
104        Self {
105            values: HashMap::new(),
106        }
107    }
108}
109
110impl Comparison for Map {
111    fn equals(&self, other: &Self, _heap: &Heap) -> StrResult<bool> {
112        Ok(self.values == other.values)
113    }
114}
115
116impl Trace for Map {
117    fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
118        for (_, value) in self.values.iter() {
119            value.visit_refs(f);
120        }
121    }
122}
123
124impl Deref for Map {
125    type Target = HashMap<EcoString, Value>;
126
127    fn deref(&self) -> &Self::Target {
128        &self.values
129    }
130}
131
132impl DerefMut for Map {
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        &mut self.values
135    }
136}
137
138impl From<HashMap<EcoString, Value>> for Map {
139    fn from(values: HashMap<EcoString, Value>) -> Self {
140        Self { values }
141    }
142}