y_octo/doc/codec/
delete_set.rs

1use std::{
2    collections::{hash_map::Entry, HashMap},
3    ops::{Deref, DerefMut, Range},
4};
5
6use super::*;
7use crate::doc::OrderRange;
8
9impl<R: CrdtReader> CrdtRead<R> for Range<u64> {
10    fn read(decoder: &mut R) -> JwstCodecResult<Self> {
11        let clock = decoder.read_var_u64()?;
12        let len = decoder.read_var_u64()?;
13        Ok(clock..clock + len)
14    }
15}
16
17impl<W: CrdtWriter> CrdtWrite<W> for Range<u64> {
18    fn write(&self, encoder: &mut W) -> JwstCodecResult {
19        encoder.write_var_u64(self.start)?;
20        encoder.write_var_u64(self.end - self.start)?;
21        Ok(())
22    }
23}
24
25impl<R: CrdtReader> CrdtRead<R> for OrderRange {
26    fn read(decoder: &mut R) -> JwstCodecResult<Self> {
27        let num_of_deletes = decoder.read_var_u64()? as usize;
28        if num_of_deletes == 1 {
29            Ok(OrderRange::Range(Range::<u64>::read(decoder)?))
30        } else {
31            let mut deletes = Vec::with_capacity(num_of_deletes);
32
33            for _ in 0..num_of_deletes {
34                deletes.push(Range::<u64>::read(decoder)?);
35            }
36
37            Ok(OrderRange::Fragment(deletes))
38        }
39    }
40}
41
42impl<W: CrdtWriter> CrdtWrite<W> for OrderRange {
43    fn write(&self, encoder: &mut W) -> JwstCodecResult {
44        match self {
45            OrderRange::Range(range) => {
46                encoder.write_var_u64(1)?;
47                range.write(encoder)?;
48            }
49            OrderRange::Fragment(ranges) => {
50                encoder.write_var_u64(ranges.len() as u64)?;
51                for range in ranges {
52                    range.write(encoder)?;
53                }
54            }
55        }
56
57        Ok(())
58    }
59}
60
61#[derive(Debug, Default, Clone, PartialEq)]
62pub struct DeleteSet(pub HashMap<Client, OrderRange>);
63
64impl Deref for DeleteSet {
65    type Target = HashMap<Client, OrderRange>;
66
67    fn deref(&self) -> &Self::Target {
68        &self.0
69    }
70}
71
72impl<const N: usize> From<[(Client, Vec<Range<u64>>); N]> for DeleteSet {
73    fn from(value: [(Client, Vec<Range<u64>>); N]) -> Self {
74        let mut map = HashMap::with_capacity(N);
75        for (client, ranges) in value {
76            map.insert(client, ranges.into());
77        }
78        Self(map)
79    }
80}
81
82impl DerefMut for DeleteSet {
83    fn deref_mut(&mut self) -> &mut Self::Target {
84        &mut self.0
85    }
86}
87
88impl DeleteSet {
89    pub fn add(&mut self, client: Client, from: Clock, len: Clock) {
90        self.add_range(client, from..from + len);
91    }
92
93    pub fn add_range(&mut self, client: Client, range: Range<u64>) {
94        match self.0.entry(client) {
95            Entry::Occupied(e) => {
96                let r = e.into_mut();
97                if r.is_empty() {
98                    *r = range.into();
99                } else {
100                    r.push(range);
101                }
102            }
103            Entry::Vacant(e) => {
104                e.insert(range.into());
105            }
106        }
107    }
108
109    #[allow(dead_code)]
110    pub fn batch_push(&mut self, client: Client, ranges: Vec<Range<u64>>) {
111        match self.0.entry(client) {
112            Entry::Occupied(e) => {
113                e.into_mut().extends(ranges);
114            }
115            Entry::Vacant(e) => {
116                e.insert(ranges.into());
117            }
118        }
119    }
120
121    pub fn merge(&mut self, other: &Self) {
122        for (client, range) in &other.0 {
123            match self.0.entry(*client) {
124                Entry::Occupied(e) => {
125                    e.into_mut().merge(range.clone());
126                }
127                Entry::Vacant(e) => {
128                    e.insert(range.clone());
129                }
130            }
131        }
132    }
133}
134
135impl<R: CrdtReader> CrdtRead<R> for DeleteSet {
136    fn read(decoder: &mut R) -> JwstCodecResult<Self> {
137        let num_of_clients = decoder.read_var_u64()? as usize;
138        let mut map = HashMap::with_capacity(num_of_clients);
139
140        for _ in 0..num_of_clients {
141            let client = decoder.read_var_u64()?;
142            let deletes = OrderRange::read(decoder)?;
143            map.insert(client, deletes);
144        }
145
146        Ok(DeleteSet(map))
147    }
148}
149
150impl<W: CrdtWriter> CrdtWrite<W> for DeleteSet {
151    fn write(&self, encoder: &mut W) -> JwstCodecResult {
152        encoder.write_var_u64(self.len() as u64)?;
153        let mut clients = self.keys().copied().collect::<Vec<_>>();
154
155        // Descending
156        clients.sort_by(|a, b| b.cmp(a));
157
158        for client in clients {
159            encoder.write_var_u64(client)?;
160            self.get(&client).unwrap().write(encoder)?;
161        }
162
163        Ok(())
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_delete_set_add() {
173        let delete_set = DeleteSet::from([
174            (1, vec![0..10, 20..30]),
175            (2, vec![0..5, 10..20]),
176            (3, vec![15..20, 30..35]),
177            (4, vec![0..10]),
178        ]);
179
180        {
181            let mut delete_set = delete_set.clone();
182            delete_set.add(1, 5, 25);
183            assert_eq!(delete_set.get(&1), Some(&OrderRange::Range(0..30)));
184        }
185
186        {
187            let mut delete_set = delete_set;
188            delete_set.add(1, 5, 10);
189            assert_eq!(delete_set.get(&1), Some(&OrderRange::Fragment(vec![0..15, 20..30])));
190        }
191    }
192
193    #[test]
194    fn test_delete_set_batch_push() {
195        let delete_set = DeleteSet::from([
196            (1, vec![0..10, 20..30]),
197            (2, vec![0..5, 10..20]),
198            (3, vec![15..20, 30..35]),
199            (4, vec![0..10]),
200        ]);
201
202        {
203            let mut delete_set = delete_set.clone();
204            delete_set.batch_push(1, vec![0..5, 10..20]);
205            assert_eq!(delete_set.get(&1), Some(&OrderRange::Range(0..30)));
206        }
207
208        {
209            let mut delete_set = delete_set;
210            delete_set.batch_push(1, vec![40..50, 10..20]);
211            assert_eq!(delete_set.get(&1), Some(&OrderRange::Fragment(vec![0..30, 40..50])));
212        }
213    }
214
215    #[test]
216    fn test_encode_decode() {
217        let delete_set = DeleteSet::from([(1, vec![0..10, 20..30]), (2, vec![0..5, 10..20])]);
218        let mut encoder = RawEncoder::default();
219        delete_set.write(&mut encoder).unwrap();
220        let mut decoder = RawDecoder::new(encoder.into_inner());
221        let decoded = DeleteSet::read(&mut decoder).unwrap();
222        assert_eq!(delete_set, decoded);
223    }
224}