Skip to main content

windows_collections/
observable_map.rs

1use super::*;
2use windows_core::*;
3
4struct StockObservableMap<K, V>
5where
6    K: RuntimeType + 'static,
7    V: RuntimeType + 'static,
8    K::Default: Clone + Ord,
9    V::Default: Clone,
10{
11    map: std::sync::RwLock<std::collections::BTreeMap<K::Default, V::Default>>,
12    handlers: Event<MapChangedEventHandler<K, V>>,
13}
14
15implement_decl! {
16    impl<K, V> StockObservableMap as StockObservableMap_Impl: [
17        IObservableMap<K, V>,
18        IMap<K, V>,
19        IIterable<IKeyValuePair<K, V>>,
20    ]
21    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
22}
23
24impl<K, V> IObservableMap_Impl<K, V> for StockObservableMap_Impl<K, V>
25where
26    K: RuntimeType,
27    V: RuntimeType,
28    K::Default: Clone + Ord,
29    V::Default: Clone,
30{
31    fn MapChanged(&self, vhnd: Ref<MapChangedEventHandler<K, V>>) -> Result<i64> {
32        self.handlers.add(vhnd.ok()?)
33    }
34
35    fn RemoveMapChanged(&self, token: i64) -> Result<()> {
36        self.handlers.remove(token);
37        Ok(())
38    }
39}
40
41impl<K, V> IIterable_Impl<IKeyValuePair<K, V>> for StockObservableMap_Impl<K, V>
42where
43    K: RuntimeType,
44    V: RuntimeType,
45    K::Default: Clone + Ord,
46    V::Default: Clone,
47{
48    fn First(&self) -> Result<IIterator<IKeyValuePair<K, V>>> {
49        let snapshot: Vec<(K::Default, V::Default)> = self
50            .map
51            .read()
52            .unwrap()
53            .iter()
54            .map(|(k, v)| (k.clone(), v.clone()))
55            .collect();
56        Ok(ComObject::new(StockObservableMapIterator::<K, V> {
57            snapshot,
58            current: 0.into(),
59        })
60        .into_interface())
61    }
62}
63
64impl<K, V> IMap_Impl<K, V> for StockObservableMap_Impl<K, V>
65where
66    K: RuntimeType,
67    V: RuntimeType,
68    K::Default: Clone + Ord,
69    V::Default: Clone,
70{
71    fn Lookup(&self, key: Ref<K>) -> Result<V> {
72        let map = self.map.read().unwrap();
73        let value = map
74            .get(ref_as_default::<K>(&key))
75            .ok_or_else(|| Error::from(E_BOUNDS))?;
76        V::from_default(value)
77    }
78
79    fn Size(&self) -> Result<u32> {
80        Ok(self.map.read().unwrap().len().try_into()?)
81    }
82
83    fn HasKey(&self, key: Ref<K>) -> Result<bool> {
84        Ok(self
85            .map
86            .read()
87            .unwrap()
88            .contains_key(ref_as_default::<K>(&key)))
89    }
90
91    fn GetView(&self) -> Result<IMapView<K, V>> {
92        let snapshot = self.map.read().unwrap().clone();
93        Ok(IMapView::<K, V>::from(snapshot))
94    }
95
96    fn Insert(&self, key: Ref<K>, value: Ref<V>) -> Result<bool> {
97        let replaced = {
98            let mut map = self.map.write().unwrap();
99            let replaced = map.contains_key(ref_as_default::<K>(&key));
100            map.insert(
101                ref_as_default::<K>(&key).clone(),
102                ref_as_default::<V>(&value).clone(),
103            );
104            replaced
105        };
106        let change = if replaced {
107            CollectionChange::ItemChanged
108        } else {
109            CollectionChange::ItemInserted
110        };
111        self.fire_changed(change, Some(ref_as_default::<K>(&key).clone()));
112        Ok(replaced)
113    }
114
115    fn Remove(&self, key: Ref<K>) -> Result<()> {
116        let key_clone = ref_as_default::<K>(&key).clone();
117        {
118            let mut map = self.map.write().unwrap();
119            if map.remove(ref_as_default::<K>(&key)).is_none() {
120                return Err(Error::from(E_BOUNDS));
121            }
122        }
123        self.fire_changed(CollectionChange::ItemRemoved, Some(key_clone));
124        Ok(())
125    }
126
127    fn Clear(&self) -> Result<()> {
128        self.map.write().unwrap().clear();
129        self.fire_changed(CollectionChange::Reset, None);
130        Ok(())
131    }
132}
133
134impl<K, V> StockObservableMap_Impl<K, V>
135where
136    K: RuntimeType,
137    V: RuntimeType,
138    K::Default: Clone + Ord,
139    V::Default: Clone,
140{
141    fn fire_changed(&self, change: CollectionChange, key: Option<K::Default>) {
142        let observable: IObservableMap<K, V> = self.to_object().into_interface();
143        let args: IMapChangedEventArgs<K> =
144            ComObject::new(StockMapChangedEventArgs { change, key }).into_interface();
145        self.handlers
146            .call(|handler: &MapChangedEventHandler<K, V>| handler.Invoke(&observable, &args));
147    }
148}
149
150struct StockMapChangedEventArgs<K>
151where
152    K: RuntimeType + 'static,
153    K::Default: Clone,
154{
155    change: CollectionChange,
156    key: Option<K::Default>,
157}
158
159implement_decl! {
160    impl<K> StockMapChangedEventArgs as StockMapChangedEventArgs_Impl: [
161        IMapChangedEventArgs<K>,
162    ]
163    where K: RuntimeType + 'static, K::Default: Clone
164}
165
166impl<K> IMapChangedEventArgs_Impl<K> for StockMapChangedEventArgs_Impl<K>
167where
168    K: RuntimeType,
169    K::Default: Clone,
170{
171    fn CollectionChange(&self) -> Result<CollectionChange> {
172        Ok(self.change)
173    }
174
175    fn Key(&self) -> Result<K> {
176        match &self.key {
177            Some(key) => K::from_default(key),
178            None => Err(Error::from(E_BOUNDS)),
179        }
180    }
181}
182
183struct StockObservableMapIterator<K, V>
184where
185    K: RuntimeType + 'static,
186    V: RuntimeType + 'static,
187    K::Default: Clone + Ord,
188    V::Default: Clone,
189{
190    snapshot: Vec<(K::Default, V::Default)>,
191    current: std::sync::atomic::AtomicUsize,
192}
193
194implement_decl! {
195    impl<K, V> StockObservableMapIterator as StockObservableMapIterator_Impl: [
196        IIterator<IKeyValuePair<K, V>>,
197    ]
198    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
199}
200
201impl<K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockObservableMapIterator_Impl<K, V>
202where
203    K: RuntimeType,
204    V: RuntimeType,
205    K::Default: Clone + Ord,
206    V::Default: Clone,
207{
208    fn Current(&self) -> Result<IKeyValuePair<K, V>> {
209        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
210        if let Some((key, value)) = self.snapshot.get(current) {
211            Ok(ComObject::new(key_value_pair::StockKeyValuePair {
212                key: key.clone(),
213                value: value.clone(),
214            })
215            .into_interface())
216        } else {
217            Err(Error::from(E_BOUNDS))
218        }
219    }
220
221    fn HasCurrent(&self) -> Result<bool> {
222        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
223        Ok(self.snapshot.len() > current)
224    }
225
226    fn MoveNext(&self) -> Result<bool> {
227        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
228        let len = self.snapshot.len();
229
230        if current < len {
231            self.current
232                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
233        }
234
235        Ok(len > current + 1)
236    }
237
238    fn GetMany(&self, items: &mut [Option<IKeyValuePair<K, V>>]) -> Result<u32> {
239        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
240
241        if current >= self.snapshot.len() {
242            return Ok(0);
243        }
244
245        let actual = std::cmp::min(self.snapshot.len() - current, items.len());
246        let (items, _) = items.split_at_mut(actual);
247
248        for (item, (key, value)) in items.iter_mut().zip(self.snapshot[current..].iter()) {
249            *item = Some(
250                ComObject::new(key_value_pair::StockKeyValuePair {
251                    key: key.clone(),
252                    value: value.clone(),
253                })
254                .into_interface(),
255            );
256        }
257
258        self.current
259            .fetch_add(actual, std::sync::atomic::Ordering::Relaxed);
260
261        Ok(actual as u32)
262    }
263}
264
265impl<K, V> From<std::collections::BTreeMap<K::Default, V::Default>> for IObservableMap<K, V>
266where
267    K: RuntimeType,
268    V: RuntimeType,
269    K::Default: Clone + Ord,
270    V::Default: Clone,
271{
272    /// Creates an `IObservableMap<K, V>` from the given key/value pairs.
273    fn from(map: std::collections::BTreeMap<K::Default, V::Default>) -> Self {
274        ComObject::new(StockObservableMap {
275            map: std::sync::RwLock::new(map),
276            handlers: Event::new(),
277        })
278        .into_interface()
279    }
280}