aboutsummaryrefslogtreecommitdiff
path: root/src/util/crdt/deletable.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crdt/deletable.rs')
-rw-r--r--src/util/crdt/deletable.rs72
1 files changed, 72 insertions, 0 deletions
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<T> {
+ Present(T),
+ Deleted,
+}
+
+impl<T: Crdt> Deletable<T> {
+ /// 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<T> {
+ match self {
+ Self::Present(v) => Some(v),
+ Self::Deleted => None,
+ }
+ }
+ /// Is object deleted?
+ pub fn is_deleted(&self) -> bool {
+ matches!(self, Self::Deleted)
+ }
+}
+
+impl<T> From<Option<T>> for Deletable<T> {
+ fn from(v: Option<T>) -> Self {
+ v.map(Self::Present).unwrap_or(Self::Deleted)
+ }
+}
+
+impl<T> From<Deletable<T>> for Option<T> {
+ fn from(v: Deletable<T>) -> Option<T> {
+ match v {
+ Deletable::Present(v) => Some(v),
+ Deletable::Deleted => None,
+ }
+ }
+}
+
+impl<T: Crdt> Crdt for Deletable<T> {
+ 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),
+ }
+ }
+ }
+}