aboutsummaryrefslogtreecommitdiff
path: root/src/util/crdt/deletable.rs
blob: e771acebb40a81066ed7db063995a0a8c72fc137 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use serde::{Deserialize, Serialize};

use crate::crdt::crdt::*;

/// Deletable object (once deleted, cannot go back)
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
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),
			}
		}
	}
}