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};
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}