safemesh_crdt/crdt/
rga.rs1use crate::{Crdt, MergeError, Mergeable, RecordId, WireError};
6use alloc::{collections::BTreeSet, vec::Vec};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
10pub enum RgaDelta<P, V> {
11 Insert { position: P, value: V },
12 Delete { position: P },
13}
14
15#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct Rga<P: Ord, V: Ord> {
22 pub(super) placed: BTreeSet<(P, V)>,
23 pub(super) tombstones: BTreeSet<P>,
24}
25
26impl<P: Ord, V: Ord> Rga<P, V> {
27 pub fn new() -> Self {
28 Rga {
29 placed: BTreeSet::new(),
30 tombstones: BTreeSet::new(),
31 }
32 }
33
34 pub fn insert(&mut self, position: P, value: V) {
35 self.placed.insert((position, value));
36 }
37
38 pub fn delete(&mut self, position: P) {
39 self.tombstones.insert(position);
40 }
41
42 pub fn merge(&mut self, other: &Self)
43 where
44 P: Clone,
45 V: Clone,
46 {
47 self.placed.extend(other.placed.iter().cloned());
48 self.tombstones.extend(other.tombstones.iter().cloned());
49 }
50
51 pub fn placed(&self) -> &BTreeSet<(P, V)> {
52 &self.placed
53 }
54
55 pub fn tombstones(&self) -> &BTreeSet<P> {
56 &self.tombstones
57 }
58}
59
60impl<P: Ord + Clone, V: Ord + Clone> Rga<P, V> {
61 pub fn live_entries(&self) -> Vec<(P, V)> {
63 self.placed
64 .iter()
65 .filter_map(|(position, value)| {
66 if self.tombstones.contains(position) {
67 None
68 } else {
69 Some((position.clone(), value.clone()))
70 }
71 })
72 .collect()
73 }
74
75 pub fn read_positions(&self) -> Vec<P> {
78 let mut positions: Vec<P> = self
79 .live_entries()
80 .into_iter()
81 .map(|(position, _)| position)
82 .collect();
83 positions.dedup();
85 positions
86 }
87}
88
89impl<P: Ord, V: Ord> Default for Rga<P, V> {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95impl<P: Ord + Clone, V: Ord + Clone> Mergeable for Rga<P, V> {
96 fn merge(&mut self, other: &Self) -> Result<(), MergeError> {
97 Rga::merge(self, other);
98 Ok(())
99 }
100}
101
102impl<P: Ord + Clone, V: Ord + Clone> Crdt for Rga<P, V> {
103 type Delta = RgaDelta<P, V>;
104
105 fn validate_record(&self, id: RecordId, _delta: &Self::Delta) -> Result<(), WireError> {
110 id.require_positive_sequence("RGA")
111 }
112
113 fn apply_delta(&mut self, delta: Self::Delta) {
114 match delta {
115 RgaDelta::Insert { position, value } => self.insert(position, value),
116 RgaDelta::Delete { position } => self.delete(position),
117 }
118 }
119}