diffus/diffable_impls/
string.rs1use crate::{
2 edit::{self, string},
3 lcs, Diffable,
4};
5
6impl<'a> Diffable<'a> for str {
7 type Diff = Vec<string::Edit>;
8
9 fn diff(&'a self, other: &'a Self) -> edit::Edit<Self> {
10 let s = lcs::lcs(
11 || self.chars(),
12 || other.chars(),
13 self.chars().count(),
14 other.chars().count(),
15 )
16 .map(Into::into)
17 .collect::<Vec<_>>();
18
19 if s.iter().all(string::Edit::is_copy) {
20 edit::Edit::Copy(self)
21 } else {
22 edit::Edit::Change(s)
23 }
24 }
25}
26
27impl<'a> Diffable<'a> for String {
28 type Diff = <str as Diffable<'a>>::Diff;
29
30 fn diff(&'a self, other: &'a Self) -> edit::Edit<Self> {
31 match self.as_str().diff(other.as_str()) {
32 edit::Edit::Change(diff) => edit::Edit::Change(diff),
33 edit::Edit::Copy(_) => edit::Edit::Copy(self),
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use crate::edit::{self, string};
41
42 #[test]
43 fn string() {
44 use super::Diffable;
45
46 let left = "XMJYAUZ".to_owned();
47 let right = "MZJAWXU".to_owned();
48
49 let diff = left.diff(&right);
50 if let edit::Edit::Change(diff) = diff {
51 assert_eq!(
52 diff.into_iter().collect::<Vec<_>>(),
53 vec![
54 string::Edit::Remove('X'),
55 string::Edit::Copy('M'),
56 string::Edit::Insert('Z'),
57 string::Edit::Copy('J'),
58 string::Edit::Remove('Y'),
59 string::Edit::Copy('A'),
60 string::Edit::Insert('W'),
61 string::Edit::Insert('X'),
62 string::Edit::Copy('U'),
63 string::Edit::Remove('Z')
64 ]
65 );
66 } else {
67 unreachable!()
68 }
69 }
70
71 #[test]
72 fn str() {
73 use super::Diffable;
74
75 let left = "XMJYAUZ";
76 let right = "MZJAWXU";
77
78 let diff = left.diff(&right);
79 if let edit::Edit::Change(diff) = diff {
80 assert_eq!(
81 diff.into_iter().collect::<Vec<_>>(),
82 vec![
83 string::Edit::Remove('X'),
84 string::Edit::Copy('M'),
85 string::Edit::Insert('Z'),
86 string::Edit::Copy('J'),
87 string::Edit::Remove('Y'),
88 string::Edit::Copy('A'),
89 string::Edit::Insert('W'),
90 string::Edit::Insert('X'),
91 string::Edit::Copy('U'),
92 string::Edit::Remove('Z')
93 ]
94 );
95 } else {
96 unreachable!()
97 }
98 }
99}