diffus/diffable_impls/
collection.rs1use crate::{
2 edit::{self, collection},
3 Diffable, Same,
4};
5
6macro_rules! collection_impl {
7 ($($typ:ident),*) => {
8 $(
9 impl<'a, T: Same + Diffable<'a> + 'a> Diffable<'a> for $typ<T> {
10 type Diff = Vec<collection::Edit<'a, T, T::Diff>>;
11
12 fn diff(&'a self, other: &'a Self) -> edit::Edit<Self> {
13
14 let s = crate::lcs::lcs_post_change(
15 crate::lcs::lcs(
16 || self.iter(),
17 || other.iter(),
18 self.len(),
19 other.len(),
20 )
21 )
22 .collect::<Vec<_>>();
23
24 if s.iter().all(collection::Edit::is_copy) {
25 edit::Edit::Copy(self)
26 } else {
27 edit::Edit::Change(s)
28 }
29 }
30 }
31 )*
32 }
33}
34
35use std::collections::{BinaryHeap, LinkedList, VecDeque};
36collection_impl! {
37 BinaryHeap, LinkedList, Vec, VecDeque
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn diff() {
46 use super::Diffable;
47
48 let left = b"XMJYAUZ".to_vec();
49 let right = b"MZJAWXU".to_vec();
50
51 let diff = left.diff(&right);
52 if let edit::Edit::Change(diff) = diff {
53 use collection::Edit::*;
54
55 assert_eq!(
56 diff.into_iter().collect::<Vec<_>>(),
57 vec![
58 Remove(&b'X'),
59 Copy(&b'M'),
60 Insert(&b'Z'),
61 Copy(&b'J'),
62 Remove(&b'Y'),
63 Copy(&b'A'),
64 Insert(&b'W'),
65 Insert(&b'X'),
66 Copy(&b'U'),
67 Remove(&b'Z')
68 ]
69 );
70 } else {
71 unreachable!()
72 }
73 }
74}