text_diff/
merge.rs

1use Difference;
2
3// merges the changes from two strings, given a common substring
4pub fn merge (orig: &str, edit: &str, common: &str, split: &str) -> Vec<Difference> {
5    let mut ret = Vec::new();
6
7    let mut a = orig.split(split);
8    let mut b = edit.split(split);
9
10    let mut same = String::new();
11    for c in common.split(split) {
12        let mut add = String::new();
13        let mut rem = String::new();
14
15        let mut x = a.next();
16        while x != None && Some(c) != x {
17            if rem.len() > 0 {
18                rem.push_str(split);
19            }
20            rem.push_str(x.unwrap());
21            x = a.next();
22        }
23
24        let mut y = b.next();
25        while y != None && Some(c) != y {
26            if add.len() > 0 {
27                add.push_str(split);
28            }
29            add.push_str(y.unwrap());
30            y = b.next();
31        }
32
33        if add.len() > 0 || rem.len() > 0 {
34            ret.push(Difference::Same(same.clone()));
35            same.clear();
36        }
37
38        if rem.len() > 0 {
39            ret.push(Difference::Rem(rem.clone()));
40        }
41
42        if add.len() > 0 {
43            ret.push(Difference::Add(add.clone()));
44        }
45
46        if same.len() > 0 {
47            same.push_str(split);
48        }
49        same.push_str(c);
50    }
51    if same.len() > 0 {
52        ret.push(Difference::Same(same.clone()));
53    }
54
55    // TODO avoid duplication
56
57    let mut rem = String::new();
58
59    for x in a {
60        if rem.len() > 0 {
61            rem.push_str(split);
62        }
63        rem.push_str(x);
64    }
65    if rem.len() > 0 {
66        ret.push(Difference::Rem(rem.clone()));
67    }
68
69    let mut add = String::new();
70    for y in b {
71        if add.len() > 0 {
72            add.push_str(split);
73        }
74        add.push_str(y);
75    }
76    if add.len() > 0 {
77        ret.push(Difference::Add(add.clone()));
78    }
79
80    ret
81}
82
83
84#[test]
85fn test_merge() {
86    assert_eq!(merge("testa", "tost", "tst", ""), vec![
87               Difference::Same("t".to_string()),
88               Difference::Rem("e".to_string()),
89               Difference::Add("o".to_string()),
90               Difference::Same("st".to_string()),
91               Difference::Rem("a".to_string()),
92    ]);
93}