aboutsummaryrefslogtreecommitdiff
path: root/src/util/crdt
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crdt')
-rw-r--r--src/util/crdt/lww.rs5
-rw-r--r--src/util/crdt/lww_map.rs9
-rw-r--r--src/util/crdt/map.rs25
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 }
+ }
+}