Skip to main content

windows_collections/
map.rs

1use super::*;
2use windows_core::*;
3
4struct StockMap<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}
13
14implement_decl! {
15    impl<K, V> StockMap as StockMap_Impl: [
16        IMap<K, V>,
17        IIterable<IKeyValuePair<K, V>>,
18    ]
19    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
20}
21
22impl<K, V> IIterable_Impl<IKeyValuePair<K, V>> for StockMap_Impl<K, V>
23where
24    K: RuntimeType,
25    V: RuntimeType,
26    K::Default: Clone + Ord,
27    V::Default: Clone,
28{
29    fn First(&self) -> Result<IIterator<IKeyValuePair<K, V>>> {
30        let snapshot: Vec<(K::Default, V::Default)> = self
31            .map
32            .read()
33            .unwrap()
34            .iter()
35            .map(|(k, v)| (k.clone(), v.clone()))
36            .collect();
37        Ok(ComObject::new(StockMapIterator::<K, V> {
38            snapshot,
39            current: 0.into(),
40        })
41        .into_interface())
42    }
43}
44
45impl<K, V> IMap_Impl<K, V> for StockMap_Impl<K, V>
46where
47    K: RuntimeType,
48    V: RuntimeType,
49    K::Default: Clone + Ord,
50    V::Default: Clone,
51{
52    fn Lookup(&self, key: Ref<K>) -> Result<V> {
53        let map = self.map.read().unwrap();
54        let value = map
55            .get(ref_as_default::<K>(&key))
56            .ok_or_else(|| Error::from(E_BOUNDS))?;
57        V::from_default(value)
58    }
59
60    fn Size(&self) -> Result<u32> {
61        Ok(self.map.read().unwrap().len().try_into()?)
62    }
63
64    fn HasKey(&self, key: Ref<K>) -> Result<bool> {
65        Ok(self
66            .map
67            .read()
68            .unwrap()
69            .contains_key(ref_as_default::<K>(&key)))
70    }
71
72    fn GetView(&self) -> Result<IMapView<K, V>> {
73        let snapshot = self.map.read().unwrap().clone();
74        Ok(IMapView::<K, V>::from(snapshot))
75    }
76
77    fn Insert(&self, key: Ref<K>, value: Ref<V>) -> Result<bool> {
78        let mut map = self.map.write().unwrap();
79        let replaced = map.contains_key(ref_as_default::<K>(&key));
80        map.insert(
81            ref_as_default::<K>(&key).clone(),
82            ref_as_default::<V>(&value).clone(),
83        );
84        Ok(replaced)
85    }
86
87    fn Remove(&self, key: Ref<K>) -> Result<()> {
88        let mut map = self.map.write().unwrap();
89        if map.remove(ref_as_default::<K>(&key)).is_none() {
90            return Err(Error::from(E_BOUNDS));
91        }
92        Ok(())
93    }
94
95    fn Clear(&self) -> Result<()> {
96        self.map.write().unwrap().clear();
97        Ok(())
98    }
99}
100
101struct StockMapIterator<K, V>
102where
103    K: RuntimeType + 'static,
104    V: RuntimeType + 'static,
105    K::Default: Clone + Ord,
106    V::Default: Clone,
107{
108    snapshot: Vec<(K::Default, V::Default)>,
109    current: std::sync::atomic::AtomicUsize,
110}
111
112implement_decl! {
113    impl<K, V> StockMapIterator as StockMapIterator_Impl: [
114        IIterator<IKeyValuePair<K, V>>,
115    ]
116    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
117}
118
119impl<K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockMapIterator_Impl<K, V>
120where
121    K: RuntimeType,
122    V: RuntimeType,
123    K::Default: Clone + Ord,
124    V::Default: Clone,
125{
126    fn Current(&self) -> Result<IKeyValuePair<K, V>> {
127        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
128        if let Some((key, value)) = self.snapshot.get(current) {
129            Ok(ComObject::new(key_value_pair::StockKeyValuePair {
130                key: key.clone(),
131                value: value.clone(),
132            })
133            .into_interface())
134        } else {
135            Err(Error::from(E_BOUNDS))
136        }
137    }
138
139    fn HasCurrent(&self) -> Result<bool> {
140        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
141        Ok(self.snapshot.len() > current)
142    }
143
144    fn MoveNext(&self) -> Result<bool> {
145        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
146        let len = self.snapshot.len();
147        if current < len {
148            self.current
149                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
150        }
151        Ok(len > current + 1)
152    }
153
154    fn GetMany(&self, items: &mut [Option<IKeyValuePair<K, V>>]) -> Result<u32> {
155        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
156        if current >= self.snapshot.len() {
157            return Ok(0);
158        }
159
160        let actual = std::cmp::min(self.snapshot.len() - current, items.len());
161        let (items, _) = items.split_at_mut(actual);
162
163        for (item, (key, value)) in items.iter_mut().zip(self.snapshot[current..].iter()) {
164            *item = Some(
165                ComObject::new(key_value_pair::StockKeyValuePair {
166                    key: key.clone(),
167                    value: value.clone(),
168                })
169                .into_interface(),
170            );
171        }
172
173        self.current
174            .fetch_add(actual, std::sync::atomic::Ordering::Relaxed);
175
176        Ok(actual as u32)
177    }
178}
179
180impl<K, V> From<std::collections::BTreeMap<K::Default, V::Default>> for IMap<K, V>
181where
182    K: RuntimeType,
183    V: RuntimeType,
184    K::Default: Clone + Ord,
185    V::Default: Clone,
186{
187    /// Creates a mutable `IMap<K, V>` from the given key/value pairs.
188    fn from(map: std::collections::BTreeMap<K::Default, V::Default>) -> Self {
189        ComObject::new(StockMap {
190            map: std::sync::RwLock::new(map),
191        })
192        .into_interface()
193    }
194}