1use std::hash::Hash;
8
9use atomic_refcell::AtomicRefCell;
10use indexmap::{IndexMap, IndexSet};
11use js::context::JSContext;
12use js::conversions::ToJSValConvertible;
13
14use crate::cell::DomRefCell;
15use crate::iterable::Iterable;
16
17pub trait Setlike {
23 type Key: ToJSValConvertible + Clone; fn get_index(&self, cx: &mut JSContext, index: u32) -> Option<Self::Key>;
27
28 fn size(&self, cx: &mut JSContext) -> u32;
29 fn add(&self, cx: &mut JSContext, key: Self::Key);
30 fn has(&self, cx: &mut JSContext, key: Self::Key) -> bool;
31 fn clear(&self, cx: &mut JSContext);
32 fn delete(&self, cx: &mut JSContext, key: Self::Key) -> bool;
33}
34
35impl<T: Setlike> Maplike for T {
39 type Key = <T as Setlike>::Key;
40
41 type Value = <T as Setlike>::Key;
42
43 #[inline]
44 fn get_index(&self, cx: &mut JSContext, index: u32) -> Option<(Self::Key, Self::Value)> {
45 self.get_index(cx, index).map(|k| (k.clone(), k))
46 }
47
48 fn get(&self, _cx: &mut JSContext, _key: Self::Key) -> Option<Self::Value> {
49 unimplemented!()
50 }
51
52 #[inline]
53 fn size(&self, cx: &mut JSContext) -> u32 {
54 self.size(cx)
55 }
56
57 fn set(&self, _cx: &mut JSContext, _key: Self::Key, _value: Self::Value) {
58 unimplemented!()
59 }
60
61 fn has(&self, _cx: &mut JSContext, _key: Self::Key) -> bool {
62 unimplemented!()
63 }
64
65 fn clear(&self, _cx: &mut JSContext) {
66 unimplemented!()
67 }
68
69 fn delete(&self, _cx: &mut JSContext, _key: Self::Key) -> bool {
70 unimplemented!()
71 }
72}
73
74pub trait Maplike {
81 type Key: ToJSValConvertible;
83 type Value: ToJSValConvertible;
85
86 fn get_index(&self, cx: &mut JSContext, index: u32) -> Option<(Self::Key, Self::Value)>;
87
88 fn get(&self, cx: &mut JSContext, key: Self::Key) -> Option<Self::Value>;
89 fn size(&self, cx: &mut JSContext) -> u32;
90 fn set(&self, cx: &mut JSContext, key: Self::Key, value: Self::Value);
91 fn has(&self, cx: &mut JSContext, key: Self::Key) -> bool;
92 fn clear(&self, cx: &mut JSContext);
93 fn delete(&self, cx: &mut JSContext, key: Self::Key) -> bool;
94}
95
96impl<T: Maplike> Iterable for T {
97 type Key = T::Key;
98
99 type Value = T::Value;
100
101 #[inline]
102 fn get_iterable_length(&self, cx: &mut JSContext) -> u32 {
103 self.size(cx)
104 }
105
106 #[inline]
107 fn get_value_at_index(&self, cx: &mut JSContext, index: u32) -> <T as Maplike>::Value {
108 self.get_index(cx, index).unwrap().1
110 }
111
112 #[inline]
113 fn get_key_at_index(&self, cx: &mut JSContext, index: u32) -> <T as Maplike>::Key {
114 self.get_index(cx, index).unwrap().0
116 }
117}
118
119impl<K, V> Maplike for DomRefCell<IndexMap<K, V>>
120where
121 K: ToJSValConvertible + Eq + PartialEq + Hash + Clone,
122 V: ToJSValConvertible + Clone,
123{
124 type Key = K;
125 type Value = V;
126
127 #[inline(always)]
128 fn get_index(&self, _cx: &mut JSContext, index: u32) -> Option<(Self::Key, Self::Value)> {
129 self.borrow()
130 .get_index(index as usize)
131 .map(|(k, v)| (k.to_owned(), v.to_owned()))
132 }
133
134 #[inline(always)]
135 fn get(&self, _cx: &mut JSContext, key: Self::Key) -> Option<Self::Value> {
136 self.borrow().get(&key).cloned()
137 }
138
139 #[inline(always)]
140 fn size(&self, _cx: &mut JSContext) -> u32 {
141 self.borrow().len() as u32
142 }
143
144 #[inline(always)]
145 fn set(&self, _cx: &mut JSContext, key: Self::Key, value: Self::Value) {
146 self.borrow_mut().insert(key, value);
147 }
148
149 #[inline(always)]
150 fn has(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
151 self.borrow().contains_key(&key)
152 }
153
154 #[inline(always)]
155 fn clear(&self, _cx: &mut JSContext) {
156 self.borrow_mut().clear()
157 }
158
159 #[inline(always)]
160 fn delete(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
161 self.borrow_mut().shift_remove(&key).is_some()
162 }
163}
164
165impl<K> Setlike for DomRefCell<IndexSet<K>>
166where
167 K: ToJSValConvertible + Eq + PartialEq + Hash + Clone,
168{
169 type Key = K;
170
171 #[inline(always)]
172 fn get_index(&self, _cx: &mut JSContext, index: u32) -> Option<Self::Key> {
173 self.borrow().get_index(index as usize).cloned()
174 }
175
176 #[inline(always)]
177 fn size(&self, _cx: &mut JSContext) -> u32 {
178 self.borrow().len() as u32
179 }
180
181 #[inline(always)]
182 fn add(&self, _cx: &mut JSContext, key: Self::Key) {
183 self.borrow_mut().insert(key);
184 }
185
186 #[inline(always)]
187 fn has(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
188 self.borrow().contains(&key)
189 }
190
191 #[inline(always)]
192 fn clear(&self, _cx: &mut JSContext) {
193 self.borrow_mut().clear()
194 }
195
196 #[inline(always)]
197 fn delete(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
198 self.borrow_mut().shift_remove(&key)
199 }
200}
201
202impl<K> Setlike for AtomicRefCell<IndexSet<K>>
203where
204 K: ToJSValConvertible + Eq + PartialEq + Hash + Clone,
205{
206 type Key = K;
207
208 #[inline(always)]
209 fn get_index(&self, _cx: &mut JSContext, index: u32) -> Option<Self::Key> {
210 self.borrow().get_index(index as usize).cloned()
211 }
212
213 #[inline(always)]
214 fn size(&self, _cx: &mut JSContext) -> u32 {
215 self.borrow().len() as u32
216 }
217
218 #[inline(always)]
219 fn add(&self, _cx: &mut JSContext, key: Self::Key) {
220 self.borrow_mut().insert(key);
221 }
222
223 #[inline(always)]
224 fn has(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
225 self.borrow().contains(&key)
226 }
227
228 #[inline(always)]
229 fn clear(&self, _cx: &mut JSContext) {
230 self.borrow_mut().clear()
231 }
232
233 #[inline(always)]
234 fn delete(&self, _cx: &mut JSContext, key: Self::Key) -> bool {
235 self.borrow_mut().shift_remove(&key)
236 }
237}