1#![deny(unsafe_code)]
15
16use std::{
17 cmp::Ordering,
18 collections::{BTreeSet, HashMap},
19 fmt::Debug,
20 ops::{Bound, Range, RangeBounds},
21 sync::Arc,
22};
23
24use serde::{Deserialize, Serialize};
25use string_cache::DefaultAtom;
26
27pub mod legacy;
28pub mod rich_text;
29pub use rich_text::{vv::VersionVector, RichText};
30mod small_set;
31#[cfg(feature = "test")]
32mod test_utils;
33pub(crate) type InternalString = DefaultAtom;
34type Lamport = u32;
35type ClientID = u64;
36type Counter = u32;
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
39pub struct OpID {
40 client: ClientID,
41 counter: Counter,
42}
43
44impl OpID {
45 pub fn inc(&self, inc: Counter) -> Self {
46 Self {
47 client: self.client,
48 counter: self.counter + inc as Counter,
49 }
50 }
51
52 pub fn inc_i32(&self, inc: i32) -> Self {
53 if inc > 0 {
54 Self {
55 client: self.client,
56 counter: self.counter + inc as Counter,
57 }
58 } else {
59 let (mut counter, overflow) = self.counter.overflowing_sub((-inc) as Counter);
60 if overflow {
61 counter = Counter::MAX;
62 }
63
64 Self {
65 client: self.client,
66 counter,
67 }
68 }
69 }
70}
71
72pub(crate) struct IdSpan {
73 id: OpID,
74 len: Counter,
75}
76
77impl IdSpan {
78 pub fn new(id: OpID, len: usize) -> Self {
79 Self {
80 id,
81 len: len as Counter,
82 }
83 }
84
85 pub fn contains(&self, id: OpID) -> bool {
86 self.id.client == id.client
87 && self.id.counter <= id.counter
88 && id.counter < self.id.counter + self.len
89 }
90}
91
92#[derive(Debug, Clone)]
93pub enum RangeOp {
94 Patch(Patch),
95 Annotate(Annotation),
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
99pub enum AnchorType {
100 Before,
101 After,
102}
103
104#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
105pub enum Behavior {
106 Inclusive = 2,
110 Merge = 0,
114 Delete = 1,
117}
118
119#[derive(Clone, Copy, Debug)]
121pub struct Patch {
122 pub id: OpID,
123 pub target_range_id: OpID,
124 pub move_start_to: Option<OpID>,
125 pub move_end_to: Option<OpID>,
126 pub lamport: Lamport,
127}
128
129#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
130pub struct Annotation {
131 pub id: OpID,
132 pub range_lamport: (Lamport, OpID),
134 pub range: AnchorRange,
135 pub behavior: Behavior,
136 pub type_: InternalString,
138 pub meta: Option<Vec<u8>>,
139}
140
141#[derive(Debug, Clone, PartialEq, Eq)]
142pub struct Style {
143 pub start_type: AnchorType,
144 pub end_type: AnchorType,
145 pub behavior: Behavior,
146 pub type_: InternalString,
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
151pub struct AnchorRange {
152 pub start: Anchor,
153 pub end: Anchor,
154}
155
156#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
157pub struct Anchor {
158 pub id: Option<OpID>,
160 pub type_: AnchorType,
161}
162
163impl RangeOp {
164 fn id(&self) -> OpID {
165 match self {
166 RangeOp::Patch(x) => x.id,
167 RangeOp::Annotate(x) => x.id,
168 }
169 }
170
171 #[allow(unused)]
172 fn set_id(&mut self, id: OpID) {
173 match self {
174 RangeOp::Patch(x) => x.id = id,
175 RangeOp::Annotate(x) => x.id = id,
176 }
177 }
178
179 #[allow(unused)]
180 fn lamport(&self) -> Lamport {
181 match self {
182 RangeOp::Patch(x) => x.lamport,
183 RangeOp::Annotate(x) => x.range_lamport.0,
184 }
185 }
186}
187
188impl Anchor {
189 pub fn before(id: OpID) -> Self {
190 Self {
191 id: Some(id),
192 type_: AnchorType::Before,
193 }
194 }
195
196 pub fn after(id: OpID) -> Self {
197 Self {
198 id: Some(id),
199 type_: AnchorType::After,
200 }
201 }
202
203 pub fn before_none() -> Self {
204 Self {
205 id: None,
206 type_: AnchorType::Before,
207 }
208 }
209
210 pub fn after_none() -> Self {
211 Self {
212 id: None,
213 type_: AnchorType::After,
214 }
215 }
216}
217
218impl<T: RangeBounds<OpID>> From<T> for AnchorRange {
219 fn from(range: T) -> Self {
220 let start = match range.start_bound() {
221 Bound::Included(x) => Anchor {
222 id: Some(*x),
223 type_: AnchorType::Before,
224 },
225 Bound::Excluded(x) => Anchor {
226 id: Some(*x),
227 type_: AnchorType::After,
228 },
229 Bound::Unbounded => Anchor {
230 id: None,
231 type_: AnchorType::After,
232 },
233 };
234 let end = match range.end_bound() {
235 Bound::Included(x) => Anchor {
236 id: Some(*x),
237 type_: AnchorType::After,
238 },
239 Bound::Excluded(x) => Anchor {
240 id: Some(*x),
241 type_: AnchorType::Before,
242 },
243 Bound::Unbounded => Anchor {
244 id: None,
245 type_: AnchorType::Before,
246 },
247 };
248 Self { start, end }
249 }
250}
251
252impl OpID {
253 pub fn new(client: u64, counter: Counter) -> Self {
254 Self { client, counter }
255 }
256}