compose_library/foundations/
map.rs1use 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}