Skip to main content

windows_collections/
map_view.rs

1use super::*;
2use windows_core::*;
3
4struct StockMapView<K, V>
5where
6    K: RuntimeType + 'static,
7    V: RuntimeType + 'static,
8    K::Default: Clone + Ord,
9    V::Default: Clone,
10{
11    map: std::collections::BTreeMap<K::Default, V::Default>,
12}
13
14implement_decl! {
15    impl<K, V> StockMapView as StockMapView_Impl: [
16        IMapView<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 StockMapView_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            .iter()
33            .map(|(k, v)| (k.clone(), v.clone()))
34            .collect();
35        Ok(ComObject::new(StockMapViewIterator::<K, V> {
36            snapshot,
37            current: 0.into(),
38        })
39        .into_interface())
40    }
41}
42
43impl<K, V> IMapView_Impl<K, V> for StockMapView_Impl<K, V>
44where
45    K: RuntimeType,
46    V: RuntimeType,
47    K::Default: Clone + Ord,
48    V::Default: Clone,
49{
50    fn Lookup(&self, key: Ref<K>) -> Result<V> {
51        let value = self
52            .map
53            .get(ref_as_default::<K>(&key))
54            .ok_or_else(|| Error::from(E_BOUNDS))?;
55
56        V::from_default(value)
57    }
58
59    fn Size(&self) -> Result<u32> {
60        Ok(self.map.len().try_into()?)
61    }
62
63    fn HasKey(&self, key: Ref<K>) -> Result<bool> {
64        Ok(self.map.contains_key(ref_as_default::<K>(&key)))
65    }
66
67    fn Split(&self, first: OutRef<IMapView<K, V>>, second: OutRef<IMapView<K, V>>) -> Result<()> {
68        _ = first.write(None);
69        _ = second.write(None);
70        Ok(())
71    }
72}
73
74struct StockMapViewIterator<K, V>
75where
76    K: RuntimeType + 'static,
77    V: RuntimeType + 'static,
78    K::Default: Clone + Ord,
79    V::Default: Clone,
80{
81    snapshot: Vec<(K::Default, V::Default)>,
82    current: std::sync::atomic::AtomicUsize,
83}
84
85implement_decl! {
86    impl<K, V> StockMapViewIterator as StockMapViewIterator_Impl: [
87        IIterator<IKeyValuePair<K, V>>,
88    ]
89    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
90}
91
92impl<K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockMapViewIterator_Impl<K, V>
93where
94    K: RuntimeType,
95    V: RuntimeType,
96    K::Default: Clone + Ord,
97    V::Default: Clone,
98{
99    fn Current(&self) -> Result<IKeyValuePair<K, V>> {
100        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
101        if let Some((key, value)) = self.snapshot.get(current) {
102            Ok(ComObject::new(key_value_pair::StockKeyValuePair {
103                key: key.clone(),
104                value: value.clone(),
105            })
106            .into_interface())
107        } else {
108            Err(Error::from(E_BOUNDS))
109        }
110    }
111
112    fn HasCurrent(&self) -> Result<bool> {
113        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
114        Ok(self.snapshot.len() > current)
115    }
116
117    fn MoveNext(&self) -> Result<bool> {
118        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
119        let len = self.snapshot.len();
120
121        if current < len {
122            self.current
123                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
124        }
125
126        Ok(len > current + 1)
127    }
128
129    fn GetMany(&self, pairs: &mut [Option<IKeyValuePair<K, V>>]) -> Result<u32> {
130        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
131
132        if current >= self.snapshot.len() {
133            return Ok(0);
134        }
135
136        let actual = std::cmp::min(self.snapshot.len() - current, pairs.len());
137        let (pairs, _) = pairs.split_at_mut(actual);
138
139        for (pair, (key, value)) in pairs.iter_mut().zip(self.snapshot[current..].iter()) {
140            *pair = Some(
141                ComObject::new(key_value_pair::StockKeyValuePair {
142                    key: key.clone(),
143                    value: value.clone(),
144                })
145                .into_interface(),
146            );
147        }
148
149        self.current
150            .fetch_add(actual, std::sync::atomic::Ordering::Relaxed);
151
152        Ok(actual as u32)
153    }
154}
155
156impl<K, V> From<std::collections::BTreeMap<K::Default, V::Default>> for IMapView<K, V>
157where
158    K: RuntimeType,
159    V: RuntimeType,
160    K::Default: Clone + Ord,
161    V::Default: Clone,
162{
163    /// Creates a read-only `IMapView<K, V>` from the given key/value pairs.
164    fn from(map: std::collections::BTreeMap<K::Default, V::Default>) -> Self {
165        ComObject::new(StockMapView { map }).into_interface()
166    }
167}