Skip to main content

link_cli/
changes_simplifier.rs

1//! Simplifies the raw changes of one query to the net change of every link.
2//!
3//! Corresponds to `ChangesSimplifier.cs` in C#.
4
5use crate::link::Link;
6use std::collections::HashMap;
7
8/// Reduces the raw `(before, after)` steps a store reports to one change per
9/// link address: from its state before the query to its state after it.
10///
11/// The store reports every step it takes — a link is emptied to `(i: 0 0)`
12/// before it is deleted and created as `(i: 0 0)` before it is set — and the
13/// null link `(0: 0 0)` stands for "no link", before a creation and after a
14/// deletion. The steps of one address form a chain, so its net change is the
15/// `before` of its first step and the `after` of its last:
16///
17/// - a link created and deleted again within the query is not reported;
18/// - a link that ends where it started is reported unchanged, like a link the
19///   query only matched.
20///
21/// The changes are ordered by their `after` state, so deletions come first;
22/// changes with equal `after` states keep the order of their first step.
23pub fn simplify_changes(changes: Vec<(Link, Link)>) -> Vec<(Link, Link)> {
24    let mut net_changes: Vec<(Link, Link)> = Vec::new();
25    let mut position_of_address: HashMap<u32, usize> = HashMap::new();
26    for (before, after) in changes {
27        let address = if before.index != 0 {
28            before.index
29        } else {
30            after.index
31        };
32        if address == 0 {
33            continue;
34        }
35        match position_of_address.get(&address) {
36            Some(&position) => net_changes[position].1 = after,
37            None => {
38                position_of_address.insert(address, net_changes.len());
39                net_changes.push((before, after));
40            }
41        }
42    }
43    net_changes.retain(|(before, after)| !(before.is_null() && after.is_null()));
44    net_changes.sort_by_key(|(_, after)| (after.index, after.source, after.target));
45    net_changes
46}