intuicio_frontend_simpleton/library/
map.rs

1use 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}