nuit_core/utils/
diff.rs

1use super::{IdPath, IdPathBuf};
2
3/// A type that can be diffed in terms of id paths.
4pub trait Diff: Sized {
5    /// Appends the difference to "construct" this type from the given other one
6    /// to the given difference.
7    fn record_diff<'a>(&'a self, old: &'a Self, id_path: &IdPath, difference: &mut Difference<&'a Self>);
8
9    /// Computes the difference to "construct" this type from the given other one.
10    fn diff<'a>(&'a self, old: &'a Self) -> Difference<&'a Self> {
11        let mut difference = Difference::new();
12        self.record_diff(old, IdPath::root(), &mut difference);
13        return difference;
14    }
15}
16
17/// The difference between two values.
18#[derive(Debug, PartialEq, Eq, Clone)]
19pub struct Difference<T> {
20    pub removed: Vec<(IdPathBuf, T)>,
21    pub changed: Vec<(IdPathBuf, T, T)>,
22    pub added: Vec<(IdPathBuf, T)>,
23}
24
25impl<T> Difference<T> {
26    pub fn new() -> Self {
27        Self {
28            removed: Vec::new(),
29            changed: Vec::new(),
30            added: Vec::new(),
31        }
32    }
33
34    pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Difference<U> {
35        Difference {
36            removed: self.removed.into_iter().map(|(p, x)| (p, f(x))).collect(),
37            changed: self.changed.into_iter().map(|(p, x, y)| (p, f(x), f(y))).collect(),
38            added: self.added.into_iter().map(|(p, x)| (p, f(x))).collect(),
39        }
40    }
41}
42
43impl<T> Default for Difference<T> {
44    fn default() -> Self {
45        Self::new()
46    }
47}