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