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