Skip to main content

windows_collections/
iterable.rs

1use super::*;
2use windows_core::*;
3
4struct StockIterable<T>
5where
6    T: RuntimeType + 'static,
7    T::Default: Clone,
8{
9    values: Vec<T::Default>,
10}
11
12implement_decl! {
13    impl<T> StockIterable as StockIterable_Impl: [
14        IIterable<T>,
15    ]
16    where T: RuntimeType + 'static, T::Default: Clone
17}
18
19impl<T> IIterable_Impl<T> for StockIterable_Impl<T>
20where
21    T: RuntimeType,
22    T::Default: Clone,
23{
24    fn First(&self) -> Result<IIterator<T>> {
25        Ok(ComObject::new(StockIterator {
26            owner: self.to_object(),
27            current: 0.into(),
28        })
29        .into_interface())
30    }
31}
32
33struct StockIterator<T>
34where
35    T: RuntimeType + 'static,
36    T::Default: Clone,
37{
38    owner: ComObject<StockIterable<T>>,
39    current: std::sync::atomic::AtomicUsize,
40}
41
42implement_decl! {
43    impl<T> StockIterator as StockIterator_Impl: [
44        IIterator<T>,
45    ]
46    where T: RuntimeType + 'static, T::Default: Clone
47}
48
49impl<T> IIterator_Impl<T> for StockIterator_Impl<T>
50where
51    T: RuntimeType,
52    T::Default: Clone,
53{
54    fn Current(&self) -> Result<T> {
55        let owner: &StockIterable<T> = &self.owner;
56        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
57
58        if self.owner.values.len() > current {
59            T::from_default(&owner.values[current])
60        } else {
61            Err(Error::from(E_BOUNDS))
62        }
63    }
64
65    fn HasCurrent(&self) -> Result<bool> {
66        let owner: &StockIterable<T> = &self.owner;
67        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
68
69        Ok(owner.values.len() > current)
70    }
71
72    fn MoveNext(&self) -> Result<bool> {
73        let owner: &StockIterable<T> = &self.owner;
74        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
75
76        if current < owner.values.len() {
77            self.current
78                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
79        }
80
81        Ok(owner.values.len() > current + 1)
82    }
83
84    fn GetMany(&self, values: &mut [T::Default]) -> Result<u32> {
85        let owner: &StockIterable<T> = &self.owner;
86        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
87
88        if current >= owner.values.len() {
89            return Ok(0);
90        }
91
92        let actual = std::cmp::min(owner.values.len() - current, values.len());
93        let (values, _) = values.split_at_mut(actual);
94        values.clone_from_slice(&owner.values[current..current + actual]);
95
96        self.current
97            .fetch_add(actual, std::sync::atomic::Ordering::Relaxed);
98
99        Ok(actual as u32)
100    }
101}
102
103impl<T> From<Vec<T::Default>> for IIterable<T>
104where
105    T: RuntimeType,
106    T::Default: Clone,
107{
108    /// Creates an `IIterable<T>` that yields the given values.
109    fn from(values: Vec<T::Default>) -> Self {
110        ComObject::new(StockIterable { values }).into_interface()
111    }
112}