aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-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
-rw-r--r--src/util/error.rs10
4 files changed, 36 insertions, 13 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 }
+ }
+}
diff --git a/src/util/error.rs b/src/util/error.rs
index 08cf1302..ef5a76f2 100644
--- a/src/util/error.rs
+++ b/src/util/error.rs
@@ -119,17 +119,17 @@ where
}
}
-/// Trait to map error to the Bad Request error code
+/// Trait to map any error type to Error::Message
pub trait OkOrMessage {
- type S2;
- fn ok_or_message<M: Into<String>>(self, message: M) -> Self::S2;
+ type S;
+ fn ok_or_message<M: Into<String>>(self, message: M) -> Result<Self::S, Error>;
}
impl<T, E> OkOrMessage for Result<T, E>
where
E: std::fmt::Display,
{
- type S2 = Result<T, Error>;
+ type S = T;
fn ok_or_message<M: Into<String>>(self, message: M) -> Result<T, Error> {
match self {
Ok(x) => Ok(x),
@@ -139,7 +139,7 @@ where
}
impl<T> OkOrMessage for Option<T> {
- type S2 = Result<T, Error>;
+ type S = T;
fn ok_or_message<M: Into<String>>(self, message: M) -> Result<T, Error> {
match self {
Some(x) => Ok(x),