From 5b1117e582db16cc5aa50840a685875cbd5501f4 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 14 Dec 2021 13:55:11 +0100 Subject: New model for buckets --- src/util/crdt/deletable.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/crdt/lww.rs | 5 ++++ src/util/crdt/lww_map.rs | 12 +++++--- src/util/crdt/mod.rs | 2 ++ 4 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/util/crdt/deletable.rs (limited to 'src/util/crdt') diff --git a/src/util/crdt/deletable.rs b/src/util/crdt/deletable.rs new file mode 100644 index 00000000..c76f5cbb --- /dev/null +++ b/src/util/crdt/deletable.rs @@ -0,0 +1,72 @@ +use serde::{Deserialize, Serialize}; + +use crate::crdt::crdt::*; + +/// Deletable object (once deleted, cannot go back) +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +pub enum Deletable { + Present(T), + Deleted, +} + +impl Deletable { + /// Create a new deletable object that isn't deleted + pub fn present(v: T) -> Self { + Self::Present(v) + } + /// Create a new deletable object that is deleted + pub fn delete() -> Self { + Self::Deleted + } + /// As option + pub fn as_option(&self) -> Option<&T> { + match self { + Self::Present(v) => Some(v), + Self::Deleted => None, + } + } + /// As option, mutable + pub fn as_option_mut(&mut self) -> Option<&mut T> { + match self { + Self::Present(v) => Some(v), + Self::Deleted => None, + } + } + /// Into option + pub fn into_option(self) -> Option { + match self { + Self::Present(v) => Some(v), + Self::Deleted => None, + } + } + /// Is object deleted? + pub fn is_deleted(&self) -> bool { + matches!(self, Self::Deleted) + } +} + +impl From> for Deletable { + fn from(v: Option) -> Self { + v.map(Self::Present).unwrap_or(Self::Deleted) + } +} + +impl From> for Option { + fn from(v: Deletable) -> Option { + match v { + Deletable::Present(v) => Some(v), + Deletable::Deleted => None, + } + } +} + +impl Crdt for Deletable { + fn merge(&mut self, other: &Self) { + if let Deletable::Present(v) = self { + match other { + Deletable::Deleted => *self = Deletable::Deleted, + Deletable::Present(v2) => v.merge(v2), + } + } + } +} diff --git a/src/util/crdt/lww.rs b/src/util/crdt/lww.rs index 43d13f27..bc686e05 100644 --- a/src/util/crdt/lww.rs +++ b/src/util/crdt/lww.rs @@ -82,6 +82,11 @@ where &self.v } + /// Take the value inside the CRDT (discards the timesamp) + pub fn take(self) -> T { + self.v + } + /// Get a mutable reference to the CRDT's value /// /// This is usefull to mutate the inside value without changing the LWW timestamp. diff --git a/src/util/crdt/lww_map.rs b/src/util/crdt/lww_map.rs index 3e9aba79..21cb6e12 100644 --- a/src/util/crdt/lww_map.rs +++ b/src/util/crdt/lww_map.rs @@ -30,8 +30,8 @@ pub struct LwwMap { impl LwwMap where - K: Ord, - V: Crdt, + K: Clone + Ord, + V: Clone + Crdt, { /// Create a new empty map CRDT pub fn new() -> Self { @@ -73,6 +73,10 @@ where }; Self { vals: new_vals } } + + pub fn update_in_place(&mut self, k: K, new_v: V) { + self.merge(&self.update_mutator(k, new_v)); + } /// Takes all of the values of the map and returns them. The current map is reset to the /// empty map. This is very usefull to produce in-place a new map that contains only a delta /// that modifies a certain value: @@ -158,8 +162,8 @@ where impl Default for LwwMap where - K: Ord, - V: Crdt, + K: Clone + Ord, + V: Clone + Crdt, { fn default() -> Self { Self::new() diff --git a/src/util/crdt/mod.rs b/src/util/crdt/mod.rs index 9663a5a5..6ba575ed 100644 --- a/src/util/crdt/mod.rs +++ b/src/util/crdt/mod.rs @@ -12,12 +12,14 @@ mod bool; #[allow(clippy::module_inception)] mod crdt; +mod deletable; mod lww; mod lww_map; mod map; pub use self::bool::*; pub use crdt::*; +pub use deletable::*; pub use lww::*; pub use lww_map::*; pub use map::*; -- cgit v1.2.3