Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
crdt: Implement `GSet` type, based on `GMap`
Alexis Sellier committed 3 years ago
commit 5c0505e221eb96028d1a92566832cb59d580507d
parent 0a93fa833ebbf650d7cd284f13b353eee393cc54
3 files changed +106 -1
modified radicle-crdt/src/gmap.rs
@@ -1,4 +1,4 @@
-
use std::collections::btree_map::{Entry, IntoIter};
+
use std::collections::btree_map::{Entry, IntoIter, IntoKeys};
use std::collections::BTreeMap;
use std::ops::Deref;

@@ -35,6 +35,12 @@ impl<K: Ord, V: Semilattice> GMap<K, V> {
    }
}

+
impl<K, V> GMap<K, V> {
+
    pub fn into_keys(self) -> IntoKeys<K, V> {
+
        self.inner.into_keys()
+
    }
+
}
+

impl<K: Ord, V: Semilattice> FromIterator<(K, V)> for GMap<K, V> {
    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
        let mut map = GMap::default();
added radicle-crdt/src/gset.rs
@@ -0,0 +1,97 @@
+
use std::collections::btree_map::{IntoKeys, Keys};
+
use std::ops::Deref;
+

+
use crate::GMap;
+
use crate::Semilattice;
+

+
/// Grow-only set.
+
#[derive(Debug, Clone, PartialEq, Eq)]
+
pub struct GSet<K> {
+
    inner: GMap<K, ()>,
+
}
+

+
impl<K: Ord> GSet<K> {
+
    pub fn singleton(key: K) -> Self {
+
        Self {
+
            inner: GMap::from_iter([(key, ())]),
+
        }
+
    }
+

+
    pub fn insert(&mut self, key: K) {
+
        self.inner.insert(key, ());
+
    }
+

+
    pub fn iter(&self) -> Keys<'_, K, ()> {
+
        self.inner.keys()
+
    }
+
}
+

+
impl<K: Ord> FromIterator<K> for GSet<K> {
+
    fn from_iter<I: IntoIterator<Item = K>>(iter: I) -> Self {
+
        let mut map = GSet::default();
+
        for k in iter.into_iter() {
+
            map.insert(k);
+
        }
+
        map
+
    }
+
}
+

+
impl<K: Ord> Extend<K> for GSet<K> {
+
    fn extend<I: IntoIterator<Item = K>>(&mut self, iter: I) {
+
        for k in iter.into_iter() {
+
            self.insert(k);
+
        }
+
    }
+
}
+

+
impl<K> IntoIterator for GSet<K> {
+
    type Item = K;
+
    type IntoIter = IntoKeys<K, ()>;
+

+
    fn into_iter(self) -> Self::IntoIter {
+
        self.inner.into_keys()
+
    }
+
}
+

+
impl<K> Default for GSet<K> {
+
    fn default() -> Self {
+
        Self {
+
            inner: GMap::default(),
+
        }
+
    }
+
}
+

+
impl<K: Ord> Semilattice for GSet<K> {
+
    fn merge(&mut self, other: Self) {
+
        for k in other.into_iter() {
+
            self.insert(k);
+
        }
+
    }
+
}
+

+
impl<K> Deref for GSet<K> {
+
    type Target = GMap<K, ()>;
+

+
    fn deref(&self) -> &Self::Target {
+
        &self.inner
+
    }
+
}
+

+
#[cfg(test)]
+
mod tests {
+
    use qcheck_macros::quickcheck;
+

+
    use super::*;
+

+
    #[quickcheck]
+
    fn prop_semilattice(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>, mix: Vec<u8>) {
+
        let mut a = GSet::from_iter(a);
+
        let mut b = GSet::from_iter(b);
+
        let c = GSet::from_iter(c);
+

+
        a.extend(mix.clone());
+
        b.extend(mix);
+

+
        crate::test::assert_laws(&a, &b, &c);
+
    }
+
}
modified radicle-crdt/src/lib.rs
@@ -4,6 +4,7 @@
#![allow(clippy::type_complexity)]
pub mod clock;
pub mod gmap;
+
pub mod gset;
pub mod lwwmap;
pub mod lwwreg;
pub mod lwwset;
@@ -17,6 +18,7 @@ pub mod test;

pub use clock::Lamport;
pub use gmap::GMap;
+
pub use gset::GSet;
pub use lwwmap::LWWMap;
pub use lwwreg::LWWReg;
pub use lwwset::LWWSet;