intuicio_frontend_simpleton/library/
map.rs1use crate::{library::closure::Closure, Array, Function, Integer, Map, Reference, Text};
2use intuicio_core::{context::Context, define_native_struct, registry::Registry, IntuicioStruct};
3use intuicio_derive::{intuicio_function, intuicio_method, intuicio_methods, IntuicioStruct};
4
5#[intuicio_function(module_name = "map", use_registry)]
6pub fn new(registry: &Registry, capacity: Reference) -> Reference {
7 Reference::new_map(
8 Map::with_capacity(capacity.read::<Integer>().map(|v| *v as _).unwrap_or(0)),
9 registry,
10 )
11}
12
13#[intuicio_function(module_name = "map")]
14pub fn reserve(mut map: Reference, additional: Reference) -> Reference {
15 map.write::<Map>()
16 .unwrap()
17 .reserve(*additional.read::<Integer>().unwrap() as usize);
18 Reference::null()
19}
20
21#[intuicio_function(module_name = "map", use_registry)]
22pub fn size(registry: &Registry, map: Reference) -> Reference {
23 Reference::new_integer(map.read::<Map>().unwrap().len() as Integer, registry)
24}
25
26#[intuicio_function(module_name = "map", use_registry)]
27pub fn capacity(registry: &Registry, map: Reference) -> Reference {
28 Reference::new_integer(map.read::<Map>().unwrap().capacity() as Integer, registry)
29}
30
31#[intuicio_function(module_name = "map")]
32pub fn clear(mut map: Reference) -> Reference {
33 map.write::<Map>().unwrap().clear();
34 Reference::null()
35}
36
37#[intuicio_function(module_name = "map", use_registry)]
38pub fn contains_key(registry: &Registry, map: Reference, key: Reference) -> Reference {
39 let result = map
40 .read::<Map>()
41 .unwrap()
42 .contains_key(key.read::<Text>().unwrap().as_str());
43 Reference::new_boolean(result, registry)
44}
45
46#[intuicio_function(module_name = "map", use_registry)]
47pub fn contains_value(registry: &Registry, map: Reference, value: Reference) -> Reference {
48 let result = map
49 .read::<Map>()
50 .unwrap()
51 .values()
52 .any(|item| value.does_share_reference(item, true));
53 Reference::new_boolean(result, registry)
54}
55
56#[intuicio_function(module_name = "map", use_registry)]
57pub fn find_key(registry: &Registry, map: Reference, value: Reference) -> Reference {
58 map.read::<Map>()
59 .unwrap()
60 .iter()
61 .find(|(_, item)| value.does_share_reference(item, true))
62 .map(|(key, _)| Reference::new_text(key.to_owned(), registry))
63 .unwrap_or_default()
64}
65
66#[intuicio_function(module_name = "map")]
67pub fn remove(mut map: Reference, key: Reference) -> Reference {
68 map.write::<Map>()
69 .unwrap()
70 .remove(key.read::<Text>().unwrap().as_str())
71 .unwrap_or_default()
72}
73
74#[intuicio_function(module_name = "map")]
75pub fn set(mut map: Reference, key: Reference, value: Reference) -> Reference {
76 map.write::<Map>()
77 .unwrap()
78 .insert(key.read::<Text>().unwrap().to_owned(), value)
79 .unwrap_or_default()
80}
81
82#[intuicio_function(module_name = "map")]
83pub fn get(map: Reference, key: Reference) -> Reference {
84 map.read::<Map>()
85 .unwrap()
86 .get(key.read::<Text>().unwrap().as_str())
87 .cloned()
88 .unwrap_or_default()
89}
90
91#[intuicio_function(module_name = "map", use_registry)]
92pub fn join(registry: &Registry, a: Reference, b: Reference) -> Reference {
93 Reference::new_map(
94 a.read::<Map>()
95 .unwrap()
96 .iter()
97 .chain(b.read::<Map>().unwrap().iter())
98 .map(|(k, v)| (k.to_owned(), v.clone()))
99 .collect::<Map>(),
100 registry,
101 )
102}
103
104#[intuicio_function(module_name = "map", use_registry)]
105pub fn zip(registry: &Registry, keys: Reference, values: Reference) -> Reference {
106 Reference::new_map(
107 keys.read::<Array>()
108 .unwrap()
109 .iter()
110 .map(|key| key.read::<Text>().unwrap().to_owned())
111 .zip(values.read::<Array>().unwrap().iter().cloned())
112 .collect::<Map>(),
113 registry,
114 )
115}
116
117#[intuicio_function(module_name = "map", use_registry)]
118pub fn keys(registry: &Registry, map: Reference) -> Reference {
119 Reference::new_array(
120 map.read::<Map>()
121 .unwrap()
122 .keys()
123 .map(|key| Reference::new_text(key.to_owned(), registry))
124 .collect::<Array>(),
125 registry,
126 )
127}
128
129#[intuicio_function(module_name = "map", use_registry)]
130pub fn values(registry: &Registry, map: Reference) -> Reference {
131 Reference::new_array(
132 map.read::<Map>()
133 .unwrap()
134 .values()
135 .cloned()
136 .collect::<Array>(),
137 registry,
138 )
139}
140
141#[intuicio_function(module_name = "map", use_registry)]
142pub fn iter(registry: &Registry, map: Reference) -> Reference {
143 let keys = map.read::<Map>().unwrap().keys().cloned().collect();
144 Reference::new(
145 MapIter {
146 map,
147 index: 0,
148 keys,
149 next: Reference::new(
150 Closure {
151 function: Function::by_name("next", "map_iter", registry).unwrap(),
152 captured: vec![],
153 },
154 registry,
155 ),
156 },
157 registry,
158 )
159}
160
161#[intuicio_function(module_name = "map", use_context, use_registry)]
162pub fn collect(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
163 let mut result = Map::new();
164 loop {
165 let value = crate::library::iter::next(context, registry, iterator.clone());
166 if value.is_null() {
167 break;
168 }
169 if let Some(pair) = value.read::<Array>() {
170 let key = pair.first().unwrap().read::<Text>().unwrap().to_owned();
171 let value = pair.get(1).unwrap().clone();
172 result.insert(key, value);
173 } else if let Some(pair) = value.read::<Map>() {
174 let key = pair.get("key").unwrap().read::<Text>().unwrap().to_owned();
175 let value = pair.get("value").unwrap().clone();
176 result.insert(key, value);
177 } else if let Some(pair) = value.read_object() {
178 let key = pair
179 .read_field::<Reference>("key")
180 .unwrap()
181 .read::<Text>()
182 .unwrap()
183 .to_owned();
184 let value = pair.read_field::<Reference>("value").unwrap().clone();
185 result.insert(key, value);
186 };
187 }
188 Reference::new_map(result, registry)
189}
190
191#[derive(IntuicioStruct, Default)]
192#[intuicio(name = "Pair", module_name = "map", override_send = true)]
193pub struct Pair {
194 pub key: Reference,
195 pub value: Reference,
196}
197
198#[derive(IntuicioStruct, Default)]
199#[intuicio(name = "MapIter", module_name = "map_iter")]
200pub struct MapIter {
201 #[intuicio(ignore)]
202 pub map: Reference,
203 #[intuicio(ignore)]
204 pub index: usize,
205 #[intuicio(ignore)]
206 pub keys: Vec<String>,
207 pub next: Reference,
208}
209
210#[intuicio_methods(module_name = "map_iter")]
211impl MapIter {
212 #[intuicio_method(use_registry)]
213 pub fn next(registry: &Registry, mut iterator: Reference) -> Reference {
214 let mut iterator = iterator.write::<MapIter>().unwrap();
215 let map = iterator.map.clone();
216 let map = map.read::<Map>().unwrap();
217 if iterator.index >= map.len() {
218 return Reference::null();
219 }
220 let index = iterator.index;
221 iterator.index += 1;
222 let key = iterator.keys.get(index).unwrap();
223 map.get(key)
224 .map(|value| {
225 Reference::new(
226 Pair {
227 key: Reference::new_text(key.to_owned(), registry),
228 value: value.clone(),
229 },
230 registry,
231 )
232 })
233 .unwrap_or_default()
234 }
235}
236
237pub fn install(registry: &mut Registry) {
238 registry.add_type(define_native_struct! {
239 registry => mod map struct Map (Map) {}
240 [override_send = true]
241 });
242 registry.add_function(new::define_function(registry));
243 registry.add_function(reserve::define_function(registry));
244 registry.add_function(size::define_function(registry));
245 registry.add_function(capacity::define_function(registry));
246 registry.add_function(clear::define_function(registry));
247 registry.add_function(contains_key::define_function(registry));
248 registry.add_function(contains_value::define_function(registry));
249 registry.add_function(find_key::define_function(registry));
250 registry.add_function(remove::define_function(registry));
251 registry.add_function(set::define_function(registry));
252 registry.add_function(get::define_function(registry));
253 registry.add_function(join::define_function(registry));
254 registry.add_function(zip::define_function(registry));
255 registry.add_function(keys::define_function(registry));
256 registry.add_function(values::define_function(registry));
257 registry.add_function(iter::define_function(registry));
258 registry.add_function(collect::define_function(registry));
259 registry.add_type(Pair::define_struct(registry));
260 registry.add_type(MapIter::define_struct(registry));
261 registry.add_function(MapIter::next__define_function(registry));
262}
263
264#[macro_export]
265macro_rules! map {
266 ($( $key:ident : $value:expr ),* $(,)?) => {{
267 let mut result = $crate::Map::new();
268 $(
269 result.insert(stringify!($key).to_string(), $value);
270 )*
271 result
272 }};
273}