loro_delta/
lib.rs

1use delta_rope::rle_tree::DeltaTreeTrait;
2use delta_trait::{DeltaAttr, DeltaValue};
3use enum_as_inner::EnumAsInner;
4use generic_btree::{
5    rle::{HasLength, Mergeable, Sliceable},
6    BTree,
7};
8use std::fmt::Debug;
9
10pub mod array_vec;
11mod delta_item;
12mod delta_rope;
13pub mod delta_trait;
14pub mod iter;
15pub mod text_delta;
16pub mod utf16;
17
18/// A [DeltaRope] is a rope-like data structure that can be used to represent
19/// a sequence of [DeltaItem]. It has efficient operations for composing other
20/// [DeltaRope]s. It can also be used as a rope, where it only contains insertions.
21#[derive(Clone)]
22pub struct DeltaRope<V: DeltaValue, Attr: DeltaAttr> {
23    tree: BTree<DeltaTreeTrait<V, Attr>>,
24}
25
26pub struct DeltaRopeBuilder<V: DeltaValue, Attr: DeltaAttr> {
27    items: Vec<DeltaItem<V, Attr>>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, EnumAsInner)]
31pub enum DeltaItem<V, Attr> {
32    Retain {
33        len: usize,
34        attr: Attr,
35    },
36    /// This is the combined of a delete and an insert.
37    ///
38    /// They are two separate operations in the original Quill Delta format.
39    /// But the order of two neighboring delete and insert operations can be
40    /// swapped without changing the result. So Quill requires that the insert
41    /// always comes before the delete. So it creates room for invalid deltas
42    /// by the type system. Using Replace is a way to avoid this.
43    Replace {
44        value: V,
45        attr: Attr,
46        delete: usize,
47    },
48}
49
50impl<V: DeltaValue, Attr: DeltaAttr> DeltaItem<V, Attr> {
51    fn is_insert(&self) -> bool {
52        match self {
53            DeltaItem::Retain { .. } => false,
54            DeltaItem::Replace { value, .. } => value.rle_len() > 0,
55        }
56    }
57
58    fn is_delete(&self) -> bool {
59        match self {
60            DeltaItem::Retain { .. } => false,
61            DeltaItem::Replace { value, delete, .. } => value.rle_len() == 0 && *delete > 0,
62        }
63    }
64
65    fn is_replace(&self) -> bool {
66        match self {
67            DeltaItem::Retain { .. } => false,
68            DeltaItem::Replace { .. } => true,
69        }
70    }
71
72    fn is_retain(&self) -> bool {
73        match self {
74            DeltaItem::Retain { .. } => true,
75            DeltaItem::Replace { .. } => false,
76        }
77    }
78}