cola/
crdt_edit.rs

1use crate::*;
2
3/// An insertion in CRDT coordinates.
4///
5/// This struct is created by the [`inserted`](Replica::inserted) method on the
6/// [`Replica`] owned by the peer that performed the insertion, and can be
7/// integrated by another [`Replica`] via the
8/// [`integrate_insertion`](Replica::integrate_insertion) method.
9///
10/// See the documentation of those methods for more information.
11#[derive(Debug, Clone, PartialEq)]
12#[cfg_attr(
13    any(feature = "encode", feature = "serde"),
14    derive(serde::Serialize, serde::Deserialize)
15)]
16pub struct Insertion {
17    /// The anchor point of the insertion.
18    anchor: Anchor,
19
20    /// The run timestamp of the [`EditRun`] containing the anchor.
21    anchor_ts: RunTs,
22
23    /// Contains the replica that made the insertion and the temporal range
24    /// of the text that was inserted.
25    text: Text,
26
27    /// The run timestamp of this insertion.
28    run_ts: RunTs,
29
30    /// The Lamport timestamp of this insertion.
31    lamport_ts: LamportTs,
32}
33
34impl Insertion {
35    #[inline(always)]
36    pub(crate) fn anchor(&self) -> Anchor {
37        self.anchor
38    }
39
40    #[inline(always)]
41    pub(crate) fn anchor_ts(&self) -> RunTs {
42        self.anchor_ts
43    }
44
45    #[inline(always)]
46    pub(crate) fn end(&self) -> Length {
47        self.text.range.end
48    }
49
50    #[inline(always)]
51    pub(crate) fn inserted_by(&self) -> ReplicaId {
52        self.text.inserted_by()
53    }
54
55    #[inline]
56    pub(crate) fn is_no_op(&self) -> bool {
57        self.len() == 0
58    }
59
60    #[inline(always)]
61    pub(crate) fn run_ts(&self) -> RunTs {
62        self.run_ts
63    }
64
65    #[inline(always)]
66    pub(crate) fn lamport_ts(&self) -> LamportTs {
67        self.lamport_ts
68    }
69
70    #[inline]
71    pub(crate) fn len(&self) -> Length {
72        self.text.len()
73    }
74
75    #[inline]
76    pub(crate) fn new(
77        anchor: Anchor,
78        anchor_ts: RunTs,
79        text: Text,
80        lamport_ts: LamportTs,
81        run_ts: RunTs,
82    ) -> Self {
83        Self { anchor, anchor_ts, text, lamport_ts, run_ts }
84    }
85
86    #[inline]
87    pub(crate) fn no_op() -> Self {
88        Self::new(Anchor::zero(), 0, Text::new(0, 0..0), 0, 0)
89    }
90
91    #[inline]
92    pub(crate) fn start(&self) -> Length {
93        self.text.range.start
94    }
95
96    /// The [`Text`] of this insertion.
97    #[inline]
98    pub fn text(&self) -> &Text {
99        &self.text
100    }
101}
102
103/// A deletion in CRDT coordinates.
104///
105/// This struct is created by the [`deleted`](Replica::deleted) method on the
106/// [`Replica`] owned by the peer that performed the deletion, and can be
107/// integrated by another [`Replica`] via the
108/// [`integrate_deletion`](Replica::integrate_deletion) method.
109///
110/// See the documentation of those methods for more information.
111#[derive(Debug, Clone, PartialEq)]
112#[cfg_attr(
113    any(feature = "encode", feature = "serde"),
114    derive(serde::Serialize, serde::Deserialize)
115)]
116pub struct Deletion {
117    /// The anchor point of the start of the deleted range.
118    start: Anchor,
119
120    /// The run timestamp of the [`EditRun`] containing the start `Anchor`.
121    start_ts: RunTs,
122
123    /// The anchor point of the end of the deleted range.
124    end: Anchor,
125
126    /// The run timestamp of the [`EditRun`] containing the end `Anchor`.
127    end_ts: RunTs,
128
129    /// The version map of the replica at the time of the deletion. This is
130    /// used by a `Replica` merging this deletion to determine:
131    ///
132    /// a) if it has all the text that the `Replica` who created the
133    ///   deletion had at the time of the deletion, and
134    ///
135    /// b) if there's some additional text within the deleted range that
136    ///  the `Replica` who created the deletion didn't have at the time
137    ///  of the deletion.
138    version_map: VersionMap,
139
140    /// The deletion timestamp of this insertion.
141    deletion_ts: DeletionTs,
142}
143
144impl Deletion {
145    #[inline(always)]
146    pub(crate) fn deleted_by(&self) -> ReplicaId {
147        self.version_map.this_id()
148    }
149
150    #[inline(always)]
151    pub(crate) fn deletion_ts(&self) -> DeletionTs {
152        self.deletion_ts
153    }
154
155    #[inline(always)]
156    pub(crate) fn end(&self) -> Anchor {
157        self.end
158    }
159
160    #[inline(always)]
161    pub(crate) fn end_ts(&self) -> RunTs {
162        self.end_ts
163    }
164
165    #[inline]
166    pub(crate) fn is_no_op(&self) -> bool {
167        self.end.is_zero()
168    }
169
170    #[inline]
171    pub(crate) fn new(
172        start: Anchor,
173        start_ts: RunTs,
174        end: Anchor,
175        end_ts: RunTs,
176        version_map: VersionMap,
177        deletion_ts: DeletionTs,
178    ) -> Self {
179        Deletion { start, start_ts, end, end_ts, version_map, deletion_ts }
180    }
181
182    #[inline]
183    pub(crate) fn no_op() -> Self {
184        Self::new(
185            Anchor::zero(),
186            0,
187            Anchor::zero(),
188            0,
189            VersionMap::new(0, 0),
190            0,
191        )
192    }
193
194    #[inline(always)]
195    pub(crate) fn start(&self) -> Anchor {
196        self.start
197    }
198
199    #[inline(always)]
200    pub(crate) fn start_ts(&self) -> RunTs {
201        self.start_ts
202    }
203
204    #[inline(always)]
205    pub(crate) fn version_map(&self) -> &VersionMap {
206        &self.version_map
207    }
208}