diff options
Diffstat (limited to 'src/util/crdt')
-rw-r--r-- | src/util/crdt/lww.rs | 5 | ||||
-rw-r--r-- | src/util/crdt/lww_map.rs | 9 | ||||
-rw-r--r-- | src/util/crdt/map.rs | 25 |
3 files changed, 31 insertions, 8 deletions
diff --git a/src/util/crdt/lww.rs b/src/util/crdt/lww.rs index 99bd8e7c..adb07711 100644 --- a/src/util/crdt/lww.rs +++ b/src/util/crdt/lww.rs @@ -57,10 +57,7 @@ where } } - /// Build a new CRDT from a previous non-compatible one - /// - /// Compared to new, the CRDT's timestamp is not set to now - /// but must be set to the previous, non-compatible, CRDT's timestamp. + /// Build a new LWW CRDT from its raw pieces: a timestamp and the value pub fn raw(ts: u64, value: T) -> Self { Self { ts, v: value } } diff --git a/src/util/crdt/lww_map.rs b/src/util/crdt/lww_map.rs index 1746c3cc..c155c3a8 100644 --- a/src/util/crdt/lww_map.rs +++ b/src/util/crdt/lww_map.rs @@ -38,10 +38,11 @@ where Self { vals: vec![] } } - /// Used to migrate from a map defined in an incompatible format. This produces - /// a map that contains a single item with the specified timestamp (copied from - /// the incompatible format). Do this as many times as you have items to migrate, - /// and put them all together using the CRDT merge operator. + /// This produces a map that contains a single item with the specified timestamp. + /// + /// Used to migrate from a map defined in an incompatible format. Do this as many + /// times as you have items to migrate, and put them all together using the + /// CRDT merge operator. pub fn raw_item(k: K, ts: u64, v: V) -> Self { Self { vals: vec![(k, ts, v)], diff --git a/src/util/crdt/map.rs b/src/util/crdt/map.rs index ad9a6e55..f9ed19b6 100644 --- a/src/util/crdt/map.rs +++ b/src/util/crdt/map.rs @@ -1,3 +1,5 @@ +use std::iter::{FromIterator, IntoIterator}; + use serde::{Deserialize, Serialize}; use crate::crdt::crdt::*; @@ -98,3 +100,26 @@ where Self::new() } } + +/// A crdt map can be created from an iterator of key-value pairs. +/// Note that all keys in the iterator must be distinct: +/// this function will throw a panic if it is not the case. +impl<K, V> FromIterator<(K, V)> for Map<K, V> +where + K: Clone + Ord, + V: Clone + Crdt, +{ + fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { + let mut vals: Vec<(K, V)> = iter.into_iter().collect(); + vals.sort_by_cached_key(|tup| tup.0.clone()); + + // sanity check + for i in 1..vals.len() { + if vals[i - 1].0 == vals[i].0 { + panic!("Duplicate key in crdt::Map resulting from .from_iter() or .collect()"); + } + } + + Self { vals } + } +} |