Skip to main content

script_bindings/
like.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Implementation of `setlike<...>` and `maplike<..., ...>` WebIDL declarations.
6
7use std::hash::Hash;
8
9use indexmap::{IndexMap, IndexSet};
10use js::conversions::ToJSValConvertible;
11
12use crate::cell::DomRefCell;
13use crate::iterable::Iterable;
14
15/// Every Setlike dom_struct must implement this to provide access to underlying storage
16/// so codegen can automatically generate all setlike methods
17///
18/// In case you use a type that implements Setlike as underlying storage it's recommended to use `setlike` macro.
19// In webidl: `setlike<Key>`
20pub trait Setlike {
21    /// The type of the key of the set.
22    type Key: ToJSValConvertible + Clone; // clone is for impl<T: Setlike> Maplike for T
23
24    fn get_index(&self, index: u32) -> Option<Self::Key>;
25
26    fn size(&self) -> u32;
27    fn add(&self, key: Self::Key);
28    fn has(&self, key: Self::Key) -> bool;
29    fn clear(&self);
30    fn delete(&self, key: Self::Key) -> bool;
31}
32
33// we can only have one iterable for T
34// so we have impl<T: Maplike> Iterable for T
35// and minimal:
36impl<T: Setlike> Maplike for T {
37    type Key = <T as Setlike>::Key;
38
39    type Value = <T as Setlike>::Key;
40
41    #[inline]
42    fn get_index(&self, index: u32) -> Option<(Self::Key, Self::Value)> {
43        self.get_index(index).map(|k| (k.clone(), k))
44    }
45
46    fn get(&self, _key: Self::Key) -> Option<Self::Value> {
47        unimplemented!()
48    }
49
50    #[inline]
51    fn size(&self) -> u32 {
52        self.size()
53    }
54
55    fn set(&self, _key: Self::Key, _value: Self::Value) {
56        unimplemented!()
57    }
58
59    fn has(&self, _key: Self::Key) -> bool {
60        unimplemented!()
61    }
62
63    fn clear(&self) {
64        unimplemented!()
65    }
66
67    fn delete(&self, _key: Self::Key) -> bool {
68        unimplemented!()
69    }
70}
71
72/// Every Maplike dom_struct must implement this
73/// to provide access to underlying storage
74/// so codegen can automatically generate all maplike methods
75///
76/// In case you use a type that implements Maplike as underlying storage it's recommended to use `maplike` macro.
77// In webidl: `maplike<Key, Value>`
78pub trait Maplike {
79    /// The type of the key of the map.
80    type Key: ToJSValConvertible;
81    /// The type of the value of the map.
82    type Value: ToJSValConvertible;
83
84    fn get_index(&self, index: u32) -> Option<(Self::Key, Self::Value)>;
85
86    fn get(&self, key: Self::Key) -> Option<Self::Value>;
87    fn size(&self) -> u32;
88    fn set(&self, key: Self::Key, value: Self::Value);
89    fn has(&self, key: Self::Key) -> bool;
90    fn clear(&self);
91    fn delete(&self, key: Self::Key) -> bool;
92}
93
94impl<T: Maplike> Iterable for T {
95    type Key = T::Key;
96
97    type Value = T::Value;
98
99    #[inline]
100    fn get_iterable_length(&self) -> u32 {
101        self.size()
102    }
103
104    #[inline]
105    fn get_value_at_index(&self, index: u32) -> <T as Maplike>::Value {
106        // SAFETY: we are checking bounds manually
107        self.get_index(index).unwrap().1
108    }
109
110    #[inline]
111    fn get_key_at_index(&self, index: u32) -> <T as Maplike>::Key {
112        // SAFETY: we are checking bounds manually
113        self.get_index(index).unwrap().0
114    }
115}
116
117impl<K, V> Maplike for DomRefCell<IndexMap<K, V>>
118where
119    K: ToJSValConvertible + Eq + PartialEq + Hash + Clone,
120    V: ToJSValConvertible + Clone,
121{
122    type Key = K;
123    type Value = V;
124
125    #[inline(always)]
126    fn get_index(&self, index: u32) -> Option<(Self::Key, Self::Value)> {
127        self.borrow()
128            .get_index(index as usize)
129            .map(|(k, v)| (k.to_owned(), v.to_owned()))
130    }
131
132    #[inline(always)]
133    fn get(&self, key: Self::Key) -> Option<Self::Value> {
134        self.borrow().get(&key).cloned()
135    }
136
137    #[inline(always)]
138    fn size(&self) -> u32 {
139        self.borrow().len() as u32
140    }
141
142    #[inline(always)]
143    fn set(&self, key: Self::Key, value: Self::Value) {
144        self.borrow_mut().insert(key, value);
145    }
146
147    #[inline(always)]
148    fn has(&self, key: Self::Key) -> bool {
149        self.borrow().contains_key(&key)
150    }
151
152    #[inline(always)]
153    fn clear(&self) {
154        self.borrow_mut().clear()
155    }
156
157    #[inline(always)]
158    fn delete(&self, key: Self::Key) -> bool {
159        self.borrow_mut().shift_remove(&key).is_some()
160    }
161}
162
163impl<K> Setlike for DomRefCell<IndexSet<K>>
164where
165    K: ToJSValConvertible + Eq + PartialEq + Hash + Clone,
166{
167    type Key = K;
168
169    #[inline(always)]
170    fn get_index(&self, index: u32) -> Option<Self::Key> {
171        self.borrow().get_index(index as usize).cloned()
172    }
173
174    #[inline(always)]
175    fn size(&self) -> u32 {
176        self.borrow().len() as u32
177    }
178
179    #[inline(always)]
180    fn add(&self, key: Self::Key) {
181        self.borrow_mut().insert(key);
182    }
183
184    #[inline(always)]
185    fn has(&self, key: Self::Key) -> bool {
186        self.borrow().contains(&key)
187    }
188
189    #[inline(always)]
190    fn clear(&self) {
191        self.borrow_mut().clear()
192    }
193
194    #[inline(always)]
195    fn delete(&self, key: Self::Key) -> bool {
196        self.borrow_mut().shift_remove(&key)
197    }
198}