diffus/diffable_impls/
collection.rs

1use 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}