windows-collections 0.100.0

Windows collection types
Documentation
use super::*;
use windows_core::*;

struct StockMap<K, V>
where
    K: RuntimeType + 'static,
    V: RuntimeType + 'static,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    map: std::sync::RwLock<std::collections::BTreeMap<K::Default, V::Default>>,
}

implement_decl! {
    impl<K, V> StockMap as StockMap_Impl: [
        IMap<K, V>,
        IIterable<IKeyValuePair<K, V>>,
    ]
    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
}

impl<K, V> IIterable_Impl<IKeyValuePair<K, V>> for StockMap_Impl<K, V>
where
    K: RuntimeType,
    V: RuntimeType,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    fn First(&self) -> Result<IIterator<IKeyValuePair<K, V>>> {
        let snapshot: Vec<(K::Default, V::Default)> = self
            .map
            .read()
            .unwrap()
            .iter()
            .map(|(k, v)| (k.clone(), v.clone()))
            .collect();
        Ok(ComObject::new(StockMapIterator::<K, V> {
            snapshot,
            current: 0.into(),
        })
        .into_interface())
    }
}

impl<K, V> IMap_Impl<K, V> for StockMap_Impl<K, V>
where
    K: RuntimeType,
    V: RuntimeType,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    fn Lookup(&self, key: Ref<K>) -> Result<V> {
        let map = self.map.read().unwrap();
        let value = map
            .get(ref_as_default::<K>(&key))
            .ok_or_else(|| Error::from(E_BOUNDS))?;
        V::from_default(value)
    }

    fn Size(&self) -> Result<u32> {
        Ok(self.map.read().unwrap().len().try_into()?)
    }

    fn HasKey(&self, key: Ref<K>) -> Result<bool> {
        Ok(self
            .map
            .read()
            .unwrap()
            .contains_key(ref_as_default::<K>(&key)))
    }

    fn GetView(&self) -> Result<IMapView<K, V>> {
        let snapshot = self.map.read().unwrap().clone();
        Ok(IMapView::<K, V>::from(snapshot))
    }

    fn Insert(&self, key: Ref<K>, value: Ref<V>) -> Result<bool> {
        let mut map = self.map.write().unwrap();
        let replaced = map.contains_key(ref_as_default::<K>(&key));
        map.insert(
            ref_as_default::<K>(&key).clone(),
            ref_as_default::<V>(&value).clone(),
        );
        Ok(replaced)
    }

    fn Remove(&self, key: Ref<K>) -> Result<()> {
        let mut map = self.map.write().unwrap();
        if map.remove(ref_as_default::<K>(&key)).is_none() {
            return Err(Error::from(E_BOUNDS));
        }
        Ok(())
    }

    fn Clear(&self) -> Result<()> {
        self.map.write().unwrap().clear();
        Ok(())
    }
}

struct StockMapIterator<K, V>
where
    K: RuntimeType + 'static,
    V: RuntimeType + 'static,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    snapshot: Vec<(K::Default, V::Default)>,
    current: std::sync::atomic::AtomicUsize,
}

implement_decl! {
    impl<K, V> StockMapIterator as StockMapIterator_Impl: [
        IIterator<IKeyValuePair<K, V>>,
    ]
    where K: RuntimeType + 'static, V: RuntimeType + 'static, K::Default: Clone + Ord, V::Default: Clone
}

impl<K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockMapIterator_Impl<K, V>
where
    K: RuntimeType,
    V: RuntimeType,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    fn Current(&self) -> Result<IKeyValuePair<K, V>> {
        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
        if let Some((key, value)) = self.snapshot.get(current) {
            Ok(ComObject::new(key_value_pair::StockKeyValuePair {
                key: key.clone(),
                value: value.clone(),
            })
            .into_interface())
        } else {
            Err(Error::from(E_BOUNDS))
        }
    }

    fn HasCurrent(&self) -> Result<bool> {
        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
        Ok(self.snapshot.len() > current)
    }

    fn MoveNext(&self) -> Result<bool> {
        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
        let len = self.snapshot.len();
        if current < len {
            self.current
                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
        }
        Ok(len > current + 1)
    }

    fn GetMany(&self, items: &mut [Option<IKeyValuePair<K, V>>]) -> Result<u32> {
        let current = self.current.load(std::sync::atomic::Ordering::Relaxed);
        if current >= self.snapshot.len() {
            return Ok(0);
        }

        let actual = std::cmp::min(self.snapshot.len() - current, items.len());
        let (items, _) = items.split_at_mut(actual);

        for (item, (key, value)) in items.iter_mut().zip(self.snapshot[current..].iter()) {
            *item = Some(
                ComObject::new(key_value_pair::StockKeyValuePair {
                    key: key.clone(),
                    value: value.clone(),
                })
                .into_interface(),
            );
        }

        self.current
            .fetch_add(actual, std::sync::atomic::Ordering::Relaxed);

        Ok(actual as u32)
    }
}

impl<K, V> From<std::collections::BTreeMap<K::Default, V::Default>> for IMap<K, V>
where
    K: RuntimeType,
    V: RuntimeType,
    K::Default: Clone + Ord,
    V::Default: Clone,
{
    /// Creates a mutable `IMap<K, V>` from the given key/value pairs.
    fn from(map: std::collections::BTreeMap<K::Default, V::Default>) -> Self {
        ComObject::new(StockMap {
            map: std::sync::RwLock::new(map),
        })
        .into_interface()
    }
}