difference/
merge.rs
1use Difference;
2
3pub fn merge(orig: &str, edit: &str, common: &str, split: &str) -> Vec<Difference> {
5 let mut ret = Vec::new();
6
7 let mut l = orig.split(split).peekable();
8 let mut r = edit.split(split).peekable();
9 let mut c = common.split(split).peekable();
10
11 if orig == "" {
13 l.next();
14 }
15 if edit == "" {
16 r.next();
17 }
18 if common == "" {
19 c.next();
20 }
21
22 while l.peek().is_some() || r.peek().is_some() {
23 let mut same = Vec::new();
24 while l.peek().is_some() && l.peek() == c.peek() && r.peek() == c.peek() {
25 same.push(l.next().unwrap());
26 r.next();
27 c.next();
28 }
29 if !same.is_empty() {
30 let joined = same.join(split);
31 if split != "" || joined != "" {
32 ret.push(Difference::Same(joined));
33 }
34 }
35
36 let mut rem = Vec::new();
37 while l.peek().is_some() && l.peek() != c.peek() {
38 rem.push(l.next().unwrap());
39 }
40 if !rem.is_empty() {
41 ret.push(Difference::Rem(rem.join(split)));
42 }
43
44 let mut add = Vec::new();
45 while r.peek().is_some() && r.peek() != c.peek() {
46 add.push(r.next().unwrap());
47 }
48 if !add.is_empty() {
49 ret.push(Difference::Add(add.join(split)));
50 }
51 }
52
53 ret
54}
55
56
57#[test]
58fn test_merge() {
59 assert_eq!(
60 merge("testa", "tost", "tst", ""),
61 vec![
62 Difference::Same("t".to_string()),
63 Difference::Rem("e".to_string()),
64 Difference::Add("o".to_string()),
65 Difference::Same("st".to_string()),
66 Difference::Rem("a".to_string()),
67 ]
68 );
69
70 assert_eq!(
71 merge("", "a", "", ""),
72 vec![Difference::Add("a".to_string())]
73 );
74
75 assert_eq!(
76 merge("a\nb", "a\n\nb", "a\nb", "\n"),
77 vec![
78 Difference::Same("a".to_string()),
79 Difference::Add("".to_string()),
80 Difference::Same("b".to_string()),
81 ]
82 );
83
84 assert_eq!(
85 merge("a\n", "c\n", "\n", "\n"),
86 vec![
87 Difference::Rem("a".to_string()),
88 Difference::Add("c".to_string()),
89 Difference::Same("".to_string()),
90 ]
91 );
92}