use crate::Foundation::Collections::{IIterable, IIterable_Impl, IIterator, IIterator_Impl}; #[windows_core::implement(IIterable)] struct StockIterable where T: windows_core::RuntimeType + 'static, T::Default: Clone, { values: Vec, } impl IIterable_Impl for StockIterable_Impl where T: windows_core::RuntimeType, T::Default: Clone, { fn First(&self) -> windows_core::Result> { use windows_core::IUnknownImpl; Ok(windows_core::ComObject::new(StockIterator { owner: self.to_object(), current: 0.into() }).into_interface()) } } #[windows_core::implement(IIterator)] struct StockIterator where T: windows_core::RuntimeType + 'static, T::Default: Clone, { owner: windows_core::ComObject>, current: std::sync::atomic::AtomicUsize, } impl IIterator_Impl for StockIterator_Impl where T: windows_core::RuntimeType, T::Default: Clone, { fn Current(&self) -> windows_core::Result { let owner: &StockIterable = &self.owner; let current = self.current.load(std::sync::atomic::Ordering::Relaxed); if self.owner.values.len() > current { T::from_default(&owner.values[current]) } else { Err(windows_core::Error::from(windows_core::imp::E_BOUNDS)) } } fn HasCurrent(&self) -> windows_core::Result { let owner: &StockIterable = &self.owner; let current = self.current.load(std::sync::atomic::Ordering::Relaxed); Ok(owner.values.len() > current) } fn MoveNext(&self) -> windows_core::Result { let owner: &StockIterable = &self.owner; let current = self.current.load(std::sync::atomic::Ordering::Relaxed); if current < owner.values.len() { self.current.fetch_add(1, std::sync::atomic::Ordering::Relaxed); } Ok(owner.values.len() > current + 1) } fn GetMany(&self, values: &mut [T::Default]) -> windows_core::Result { let owner: &StockIterable = &self.owner; let current = self.current.load(std::sync::atomic::Ordering::Relaxed); let actual = std::cmp::min(owner.values.len() - current, values.len()); let (values, _) = values.split_at_mut(actual); values.clone_from_slice(&owner.values[current..current + actual]); self.current.fetch_add(actual, std::sync::atomic::Ordering::Relaxed); Ok(actual as u32) } } impl TryFrom> for IIterable where T: windows_core::RuntimeType, T::Default: Clone, { type Error = windows_core::Error; fn try_from(values: Vec) -> windows_core::Result { // TODO: should provide a fallible try_into or more explicit allocator Ok(windows_core::ComObject::new(StockIterable { values }).into_interface()) } }