Function diff_changes

Source
pub fn diff_changes<'a, T: HasChanges>(
    old: &'a T,
    new: &'a T,
) -> Vec<T::Change<'a>>
Expand description

Convenience helper.

Examples found in repository?
examples/vec-changes.rs (line 35)
27fn main() {
28    // 1. Tail-removal of a duplicate
29    let old = Bag {
30        items: vec!['A', 'A', 'A', 'A'],
31    };
32    let new = Bag {
33        items: vec!['A', 'A', 'A'],
34    };
35    dump("[A, A, A, A] -> [A, A, A]", &diff_changes(&old, &new));
36
37    // 2. Remove first element ⇒ everything shifts left
38    let old = Bag {
39        items: vec!['A', 'B', 'C'],
40    };
41    let new = Bag {
42        items: vec!['B', 'C'],
43    };
44    dump("[A, B, C] -> [B, C]", &diff_changes(&old, &new));
45
46    // 3. Mixed removal + moves with duplicates
47    let old = Bag {
48        items: vec!['A', 'B', 'A', 'A'],
49    };
50    let new = Bag {
51        items: vec!['B', 'A', 'A'],
52    };
53    dump("[A, B, A, A] -> [B, A, A]", &diff_changes(&old, &new));
54
55    // 4. Pure insertions (one value appears for the first time, then again)
56    let old = Bag {
57        items: vec!['X', 'Y'],
58    };
59    let new = Bag {
60        items: vec!['X', 'A', 'Y', 'A'],
61    };
62    dump("[X,Y] -> [X,A, Y,A]", &diff_changes(&old, &new));
63}
More examples
Hide additional examples
examples/changes.rs (line 37)
21fn main() {
22    let old = User {
23        age: 30,
24        address: Address {
25            street: "1 Main".into(),
26            city: "Paris".into(),
27            residents: vec!["Alice".into(), "Bob".into()],
28        },
29    };
30
31    let mut new = old.clone();
32    new.age = 31; // scalar
33    new.address.city = "Berlin".into(); // nested scalar
34    new.address.residents.retain(|n| n != "Bob"); // remove one
35    new.address.residents.push("Carol".into()); // add one
36
37    let changes = diff_changes(&old, &new);
38
39    for ch in &changes {
40        #[allow(clippy::deprecated_cfg_attr)]
41        #[cfg_attr(rustfmt, rustfmt_skip)]
42        match ch {
43            UserChange::age(age) => println!("age -> {age}"),
44            UserChange::address(AddressChange::self_(address)) => println!("address -> {address:?}"),
45            UserChange::address(AddressChange::city(val)) => println!("city -> {val}"),
46            UserChange::address(AddressChange::residents(Changed::Added(name))) => println!("resident + -> {name}"),
47            UserChange::address(AddressChange::residents(Changed::Removed(name))) => println!("resident - -> {name}"),
48            _ => {}
49        }
50    }
51
52    for ch in &changes {
53        changed!(ch;
54            User.age(age)                      => { println!("age -> {age}"); };
55            User.address@(snapshot)            => { println!("address -> {snapshot:?}"); };
56            User.address.city(v)               => { println!("city -> {v}"); };
57            User.address.residents(Added(v))   => { println!("+res -> {v}"); };
58            User.address.residents(Removed(v)) => { println!("-res -> {v}"); };
59        );
60    }
61
62    println!("\nCHANGES: {changes:?}");
63}
examples/complex.rs (line 149)
93fn main() -> Result<(), Box<dyn std::error::Error>> {
94    /* baseline */
95    let old = Company {
96        name: "Acme Inc.".into(),
97        staff: vec![
98            Account {
99                id: 1,
100                username: "alice".into(),
101                password: "secret".into(),
102                roles: HashSet::from(["admin".into()]),
103                preferences: HashMap::from([("theme".into(), "dark".into())]),
104                address: Address {
105                    street: "1 Main".into(),
106                    city: "Paris".into(),
107                },
108            },
109            Account {
110                id: 2,
111                username: "bob".into(),
112                password: "hunter2".into(),
113                roles: HashSet::from(["user".into()]),
114                preferences: HashMap::new(),
115                address: Address {
116                    street: "99 Broadway".into(),
117                    city: "London".into(),
118                },
119            },
120        ],
121    };
122
123    /* edited version  */
124    let mut new = old.clone();
125    new.name = "Acme Corp.".into();
126    new.staff[0].address.city = "Berlin".into();
127    new.staff[0].roles.insert("devops".into());
128    new.staff[1].roles.remove("user");
129    new.staff[0]
130        .preferences
131        .insert("notifications".into(), "email".into());
132
133    /* insert + move */
134    let charlie = Account {
135        id: 3,
136        username: "charlie".into(),
137        password: "pwd".into(),
138        roles: HashSet::from(["user".into()]),
139        preferences: HashMap::new(),
140        address: Address {
141            street: "5 High".into(),
142            city: "Madrid".into(),
143        },
144    };
145    new.staff.insert(0, charlie); // AddedAt
146    new.staff.swap(1, 2); // Moved
147
148    println!("Company diff");
149    let diff = diff_changes(&old, &new);
150    dump_company(&diff);
151
152    println!("\n Alice diff");
153    let old_alice = old.staff.iter().find(|a| a.id == 1).unwrap();
154    let new_alice = new.staff.iter().find(|a| a.id == 1).unwrap();
155    let alice_diff = diff_changes(old_alice, new_alice);
156    dump_account(&alice_diff);
157
158    Ok(())
159}