use std::collections::btree_map::{Entry, IntoIter, IntoKeys}; use std::collections::BTreeMap; use std::ops::Deref; use crate::Semilattice; /// Grow-only map. /// /// Conflicting elements are merged via the [`Semilattice`] instance. #[derive(Debug, Clone, PartialEq, Eq)] pub struct GMap { inner: BTreeMap, } impl GMap { pub fn singleton(key: K, value: V) -> Self { Self { inner: BTreeMap::from_iter([(key, value)]), } } pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { self.inner.get_mut(key) } pub fn insert(&mut self, key: K, value: V) { match self.inner.entry(key) { Entry::Occupied(mut e) => { e.get_mut().merge(value); } Entry::Vacant(e) => { e.insert(value); } } } } impl GMap { pub fn into_keys(self) -> IntoKeys { self.inner.into_keys() } } impl FromIterator<(K, V)> for GMap { fn from_iter>(iter: I) -> Self { let mut map = GMap::default(); for (k, v) in iter.into_iter() { map.insert(k, v); } map } } impl Extend<(K, V)> for GMap { fn extend>(&mut self, iter: I) { for (k, v) in iter.into_iter() { self.insert(k, v); } } } impl IntoIterator for GMap { type Item = (K, V); type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl Default for GMap { fn default() -> Self { Self { inner: BTreeMap::default(), } } } impl Semilattice for GMap { fn merge(&mut self, other: Self) { for (k, v) in other.into_iter() { self.insert(k, v); } } } impl Deref for GMap { type Target = BTreeMap; fn deref(&self) -> &Self::Target { &self.inner } } #[cfg(test)] mod tests { use qcheck_macros::quickcheck; use super::*; use crate::ord::Max; #[quickcheck] fn prop_semilattice( a: Vec<(u8, Max)>, b: Vec<(u8, Max)>, c: Vec<(u8, Max)>, mix: Vec<(u8, Max)>, ) { let mut a = GMap::from_iter(a); let mut b = GMap::from_iter(b); let c = GMap::from_iter(c); a.extend(mix.clone()); b.extend(mix); crate::test::assert_laws(&a, &b, &c); } }