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,
{
fn from(map: std::collections::BTreeMap<K::Default, V::Default>) -> Self {
ComObject::new(StockMap {
map: std::sync::RwLock::new(map),
})
.into_interface()
}
}