loro_internal/delta/
tree.rs1use fractional_index::FractionalIndex;
2use rustc_hash::{FxHashMap, FxHashSet};
3use itertools::Itertools;
4use loro_common::{IdFull, TreeID};
5use std::fmt::Debug;
6use std::ops::{Deref, DerefMut};
7
8use crate::state::TreeParentId;
9
10#[derive(Debug, Clone, Default)]
11pub struct TreeDiff {
12 pub diff: Vec<TreeDiffItem>,
13}
14
15#[derive(Debug, Clone)]
16pub struct TreeDiffItem {
17 pub target: TreeID,
18 pub action: TreeExternalDiff,
19}
20
21#[derive(Debug, Clone, PartialEq)]
22pub enum TreeExternalDiff {
23 Create {
24 parent: TreeParentId,
25 index: usize,
26 position: FractionalIndex,
27 },
28 Move {
29 parent: TreeParentId,
30 index: usize,
31 position: FractionalIndex,
32 old_parent: TreeParentId,
33 old_index: usize,
34 },
35 Delete {
36 old_parent: TreeParentId,
37 old_index: usize,
38 },
39}
40
41impl TreeDiff {
42 pub(crate) fn compose(mut self, other: Self) -> Self {
43 self.diff.extend(other.diff);
44 self
46 }
47
48 pub(crate) fn extend<I: IntoIterator<Item = TreeDiffItem>>(mut self, other: I) -> Self {
49 self.diff.extend(other);
50 self
51 }
52
53 fn to_hash_map_mut(&mut self) -> FxHashMap<TreeID, usize> {
54 let mut ans = FxHashSet::default();
55 for index in (0..self.diff.len()).rev() {
56 let target = self.diff[index].target;
57 if ans.contains(&target) {
58 self.diff.remove(index);
59 continue;
60 }
61 ans.insert(target);
62 }
63 self.iter()
64 .map(|x| x.target)
65 .enumerate()
66 .map(|(i, x)| (x, i))
67 .collect()
68 }
69
70 pub(crate) fn transform(&mut self, b: &TreeDiff, left_prior: bool) {
71 if b.is_empty() || self.is_empty() {
73 return;
74 }
75 if !left_prior {
76 let mut self_update = self.to_hash_map_mut();
77 for i in b
78 .iter()
79 .map(|x| x.target)
80 .filter_map(|x| self_update.remove(&x))
81 .sorted()
82 .rev()
83 {
84 self.remove(i);
85 }
86 }
87 }
88}
89
90#[derive(Clone, Default)]
92pub struct TreeDelta {
93 pub(crate) diff: Vec<TreeDeltaItem>,
94}
95
96impl Debug for TreeDelta {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 f.write_str("TreeDelta{ diff: [\n")?;
99 for item in self.diff.iter() {
100 f.write_fmt(format_args!("\t{:?}, \n", item))?;
101 }
102 f.write_str("]}")
103 }
104}
105
106#[derive(Debug, Clone)]
108pub struct TreeDeltaItem {
109 pub target: TreeID,
110 pub action: TreeInternalDiff,
111 pub last_effective_move_op_id: IdFull,
112}
113
114#[derive(Debug, Clone)]
116pub enum TreeInternalDiff {
117 Create {
119 parent: TreeParentId,
120 position: FractionalIndex,
121 },
122 UnCreate,
124 Move {
126 parent: TreeParentId,
127 position: FractionalIndex,
128 },
129 Delete {
131 parent: TreeParentId,
132 position: Option<FractionalIndex>,
133 },
134 MoveInDelete {
136 parent: TreeParentId,
137 position: Option<FractionalIndex>,
138 },
139}
140
141impl TreeDeltaItem {
142 pub(crate) fn new(
147 target: TreeID,
148 parent: TreeParentId,
149 old_parent: TreeParentId,
150 op_id: IdFull,
151 is_new_parent_deleted: bool,
152 is_old_parent_deleted: bool,
153 position: Option<FractionalIndex>,
154 ) -> Self {
155 let action = if matches!(parent, TreeParentId::Unexist) {
156 TreeInternalDiff::UnCreate
157 } else {
158 match (
159 is_new_parent_deleted,
160 is_old_parent_deleted || old_parent == TreeParentId::Unexist,
161 ) {
162 (true, true) => TreeInternalDiff::MoveInDelete { parent, position },
163 (true, false) => TreeInternalDiff::Delete { parent, position },
164 (false, true) => TreeInternalDiff::Create {
165 parent,
166 position: position.unwrap(),
167 },
168 (false, false) => TreeInternalDiff::Move {
169 parent,
170 position: position.unwrap(),
171 },
172 }
173 };
174
175 TreeDeltaItem {
176 target,
177 action,
178 last_effective_move_op_id: op_id,
179 }
180 }
181}
182
183impl Deref for TreeDelta {
184 type Target = Vec<TreeDeltaItem>;
185 fn deref(&self) -> &Self::Target {
186 &self.diff
187 }
188}
189
190impl TreeDelta {
191 pub(crate) fn compose(mut self, x: TreeDelta) -> TreeDelta {
193 self.diff.extend(x.diff);
194 self
195 }
196}
197
198impl Deref for TreeDiff {
199 type Target = Vec<TreeDiffItem>;
200 fn deref(&self) -> &Self::Target {
201 &self.diff
202 }
203}
204
205impl DerefMut for TreeDiff {
206 fn deref_mut(&mut self) -> &mut Self::Target {
207 &mut self.diff
208 }
209}