diffus/diffable_impls/
collection.rsuse crate::{
edit::{self, collection},
Diffable, Same,
};
macro_rules! collection_impl {
($($typ:ident),*) => {
$(
impl<'a, T: Same + Diffable<'a> + 'a> Diffable<'a> for $typ<T> {
type Diff = Vec<collection::Edit<'a, T, T::Diff>>;
fn diff(&'a self, other: &'a Self) -> edit::Edit<Self> {
let s = crate::lcs::lcs_post_change(
crate::lcs::lcs(
|| self.iter(),
|| other.iter(),
self.len(),
other.len(),
)
)
.collect::<Vec<_>>();
if s.iter().all(collection::Edit::is_copy) {
edit::Edit::Copy(self)
} else {
edit::Edit::Change(s)
}
}
}
)*
}
}
use std::collections::{BinaryHeap, LinkedList, VecDeque};
collection_impl! {
BinaryHeap, LinkedList, Vec, VecDeque
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn diff() {
use super::Diffable;
let left = b"XMJYAUZ".to_vec();
let right = b"MZJAWXU".to_vec();
let diff = left.diff(&right);
if let edit::Edit::Change(diff) = diff {
use collection::Edit::*;
assert_eq!(
diff.into_iter().collect::<Vec<_>>(),
vec![
Remove(&b'X'),
Copy(&b'M'),
Insert(&b'Z'),
Copy(&b'J'),
Remove(&b'Y'),
Copy(&b'A'),
Insert(&b'W'),
Insert(&b'X'),
Copy(&b'U'),
Remove(&b'Z')
]
);
} else {
unreachable!()
}
}
}