1use crate::node::{Mark, Node};
44use serde::{Deserialize, Serialize};
45use serde_json::{Map, Value};
46use std::fmt;
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
52#[serde(tag = "op", rename_all = "camelCase")]
53pub enum Change {
54 SetAttr {
56 path: Vec<usize>,
58 key: String,
60 value: Value,
62 },
63 RemoveAttr {
65 path: Vec<usize>,
67 key: String,
69 },
70 SetText {
72 path: Vec<usize>,
74 text: Option<String>,
76 },
77 SetMarks {
79 path: Vec<usize>,
81 marks: Option<Vec<Mark>>,
83 },
84 SetExtra {
86 path: Vec<usize>,
88 key: String,
90 value: Value,
92 },
93 RemoveExtra {
95 path: Vec<usize>,
97 key: String,
99 },
100 Insert {
102 path: Vec<usize>,
104 index: usize,
106 node: Node,
108 },
109 Remove {
111 path: Vec<usize>,
113 index: usize,
115 },
116 Replace {
118 path: Vec<usize>,
120 node: Node,
122 },
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
128pub struct ApplyError {
129 pub path: Vec<usize>,
131}
132
133impl fmt::Display for ApplyError {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "apply: no node at path {:?}", self.path)
136 }
137}
138
139impl std::error::Error for ApplyError {}
140
141impl Node {
142 pub fn diff(&self, other: &Node) -> Vec<Change> {
145 let mut out = Vec::new();
146 let mut path = Vec::new();
147 diff_node(self, other, &mut path, &mut out);
148 out
149 }
150
151 pub fn apply(&mut self, changes: &[Change]) -> std::result::Result<(), ApplyError> {
153 apply(self, changes)
154 }
155}
156
157pub fn diff(a: &Node, b: &Node) -> Vec<Change> {
159 a.diff(b)
160}
161
162pub fn apply(root: &mut Node, changes: &[Change]) -> std::result::Result<(), ApplyError> {
168 for change in changes {
169 apply_one(root, change)?;
170 }
171 Ok(())
172}
173
174fn diff_node(a: &Node, b: &Node, path: &mut Vec<usize>, out: &mut Vec<Change>) {
177 if a == b {
178 return; }
180 if a.node_type != b.node_type
181 || empty_shape_mismatch(
182 a.attrs.as_ref().map(Map::is_empty),
183 b.attrs.as_ref().map(Map::is_empty),
184 )
185 || empty_shape_mismatch(
186 a.content.as_ref().map(Vec::is_empty),
187 b.content.as_ref().map(Vec::is_empty),
188 )
189 {
190 out.push(Change::Replace {
193 path: path.clone(),
194 node: b.clone(),
195 });
196 return;
197 }
198 diff_attrs(a.attrs.as_ref(), b.attrs.as_ref(), path, out);
199 if a.text != b.text {
200 out.push(Change::SetText {
201 path: path.clone(),
202 text: b.text.clone(),
203 });
204 }
205 if a.marks != b.marks {
206 out.push(Change::SetMarks {
207 path: path.clone(),
208 marks: b.marks.clone(),
209 });
210 }
211 diff_extra(&a.extra, &b.extra, path, out);
212 diff_children(a.children(), b.children(), path, out);
213}
214
215fn empty_shape_mismatch(a_is_empty: Option<bool>, b_is_empty: Option<bool>) -> bool {
221 match b_is_empty {
222 Some(true) => a_is_empty != Some(true),
223 None => a_is_empty == Some(true),
224 Some(false) => false,
225 }
226}
227
228fn diff_attrs(
229 a: Option<&Map<String, Value>>,
230 b: Option<&Map<String, Value>>,
231 path: &mut [usize],
232 out: &mut Vec<Change>,
233) {
234 let empty = Map::new();
235 let am = a.unwrap_or(&empty);
236 let bm = b.unwrap_or(&empty);
237 for (k, v) in bm {
238 if am.get(k) != Some(v) {
239 out.push(Change::SetAttr {
240 path: path.to_vec(),
241 key: k.clone(),
242 value: v.clone(),
243 });
244 }
245 }
246 for k in am.keys() {
247 if !bm.contains_key(k) {
248 out.push(Change::RemoveAttr {
249 path: path.to_vec(),
250 key: k.clone(),
251 });
252 }
253 }
254}
255
256fn diff_extra(
257 am: &Map<String, Value>,
258 bm: &Map<String, Value>,
259 path: &mut [usize],
260 out: &mut Vec<Change>,
261) {
262 for (k, v) in bm {
263 if am.get(k) != Some(v) {
264 out.push(Change::SetExtra {
265 path: path.to_vec(),
266 key: k.clone(),
267 value: v.clone(),
268 });
269 }
270 }
271 for k in am.keys() {
272 if !bm.contains_key(k) {
273 out.push(Change::RemoveExtra {
274 path: path.to_vec(),
275 key: k.clone(),
276 });
277 }
278 }
279}
280
281enum Step {
283 Match,
284 Del(usize),
285 Ins(usize),
286}
287
288fn diff_children(a: &[Node], b: &[Node], path: &mut Vec<usize>, out: &mut Vec<Change>) {
289 let mut start = 0;
292 while start < a.len() && start < b.len() && a[start] == b[start] {
293 start += 1;
294 }
295 let mut ea = a.len();
296 let mut eb = b.len();
297 while ea > start && eb > start && a[ea - 1] == b[eb - 1] {
298 ea -= 1;
299 eb -= 1;
300 }
301
302 let am = &a[start..ea];
303 let bm = &b[start..eb];
304 if am.is_empty() && bm.is_empty() {
305 return;
306 }
307
308 let steps = lcs_align(am, bm);
309 let mut cursor = start; let mut dels: Vec<usize> = Vec::new();
311 let mut inss: Vec<usize> = Vec::new();
312 for step in steps {
313 match step {
314 Step::Match => {
315 flush_gap(am, bm, &dels, &inss, path, &mut cursor, out);
316 dels.clear();
317 inss.clear();
318 cursor += 1; }
320 Step::Del(i) => dels.push(i),
321 Step::Ins(j) => inss.push(j),
322 }
323 }
324 flush_gap(am, bm, &dels, &inss, path, &mut cursor, out);
325}
326
327fn flush_gap(
331 am: &[Node],
332 bm: &[Node],
333 dels: &[usize],
334 inss: &[usize],
335 path: &mut Vec<usize>,
336 cursor: &mut usize,
337 out: &mut Vec<Change>,
338) {
339 let pairs = dels.len().min(inss.len());
340 for k in 0..pairs {
341 let (ai, bj) = (dels[k], inss[k]);
342 if am[ai].node_type == bm[bj].node_type {
343 path.push(*cursor);
345 diff_node(&am[ai], &bm[bj], path, out);
346 path.pop();
347 } else {
348 let mut child = path.clone();
350 child.push(*cursor);
351 out.push(Change::Replace {
352 path: child,
353 node: bm[bj].clone(),
354 });
355 }
356 *cursor += 1;
357 }
358 for _ in &dels[pairs..] {
359 out.push(Change::Remove {
360 path: path.clone(),
361 index: *cursor,
362 }); }
364 for &bj in &inss[pairs..] {
365 out.push(Change::Insert {
366 path: path.clone(),
367 index: *cursor,
368 node: bm[bj].clone(),
369 });
370 *cursor += 1;
371 }
372}
373
374fn lcs_align(a: &[Node], b: &[Node]) -> Vec<Step> {
376 let (m, n) = (a.len(), b.len());
377 if m == 0 {
378 return (0..n).map(Step::Ins).collect();
379 }
380 if n == 0 {
381 return (0..m).map(Step::Del).collect();
382 }
383 let mut dp = vec![vec![0u32; n + 1]; m + 1];
385 for i in (0..m).rev() {
386 for j in (0..n).rev() {
387 dp[i][j] = if a[i] == b[j] {
388 dp[i + 1][j + 1] + 1
389 } else {
390 dp[i + 1][j].max(dp[i][j + 1])
391 };
392 }
393 }
394 let mut steps = Vec::with_capacity(m.max(n));
395 let (mut i, mut j) = (0usize, 0usize);
396 while i < m && j < n {
397 if a[i] == b[j] {
398 steps.push(Step::Match);
399 i += 1;
400 j += 1;
401 } else if dp[i + 1][j] >= dp[i][j + 1] {
402 steps.push(Step::Del(i));
403 i += 1;
404 } else {
405 steps.push(Step::Ins(j));
406 j += 1;
407 }
408 }
409 while i < m {
410 steps.push(Step::Del(i));
411 i += 1;
412 }
413 while j < n {
414 steps.push(Step::Ins(j));
415 j += 1;
416 }
417 steps
418}
419
420fn node_at_mut<'a>(
423 root: &'a mut Node,
424 path: &[usize],
425) -> std::result::Result<&'a mut Node, ApplyError> {
426 root.node_at_mut(path).ok_or_else(|| ApplyError {
427 path: path.to_vec(),
428 })
429}
430
431fn apply_one(root: &mut Node, change: &Change) -> std::result::Result<(), ApplyError> {
432 match change {
433 Change::SetAttr { path, key, value } => {
434 node_at_mut(root, path)?.set_attr(key.clone(), value.clone());
435 }
436 Change::RemoveAttr { path, key } => {
437 node_at_mut(root, path)?.remove_attr(key);
438 }
439 Change::SetText { path, text } => {
440 node_at_mut(root, path)?.text = text.clone();
441 }
442 Change::SetMarks { path, marks } => {
443 node_at_mut(root, path)?.marks = marks.clone();
444 }
445 Change::SetExtra { path, key, value } => {
446 node_at_mut(root, path)?
447 .extra
448 .insert(key.clone(), value.clone());
449 }
450 Change::RemoveExtra { path, key } => {
451 node_at_mut(root, path)?.extra.remove(key);
452 }
453 Change::Insert { path, index, node } => {
454 let parent = node_at_mut(root, path)?;
455 if *index > parent.child_count() {
456 let mut p = path.clone();
457 p.push(*index);
458 return Err(ApplyError { path: p });
459 }
460 parent.insert_child(*index, node.clone());
461 }
462 Change::Remove { path, index } => {
463 if node_at_mut(root, path)?.remove_child(*index).is_none() {
464 let mut p = path.clone();
465 p.push(*index);
466 return Err(ApplyError { path: p });
467 }
468 }
469 Change::Replace { path, node } => {
470 if path.is_empty() {
471 *root = node.clone();
472 } else {
473 let (parent_path, last) = path.split_at(path.len() - 1);
474 let parent = node_at_mut(root, parent_path)?;
475 if parent.replace_child(last[0], node.clone()).is_none() {
476 return Err(ApplyError { path: path.clone() });
477 }
478 }
479 }
480 }
481 Ok(())
482}