diff options
Diffstat (limited to 'src/util')
-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 | ||||
-rw-r--r-- | src/util/error.rs | 10 |
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), |