diff/lib.rs
1mod impls;
2#[cfg(test)]
3mod tests;
4pub mod utils;
5
6pub use diff_derive::Diff;
7pub use impls::*;
8
9/// A trait to diff and apply diffs between two structs
10/// The derive macro can be used on structs when all fields of the struct implement Diff
11/// Implementations are provided for bools, numeric types, Option types, and HashMaps
12pub trait Diff: Sized {
13 /// The type associated with the structs' difference
14 type Repr;
15
16 /// Produces a diff between two structs
17 fn diff(&self, other: &Self) -> Self::Repr;
18
19 /// Produces a diff between two structs, using an external diffing implementation
20 fn diff_custom<D: Differ<Self>>(&self, other: &Self, visitor: &D) -> D::Repr {
21 visitor.diff(self, other)
22 }
23
24 /// Applies the diff directly to the struct
25 fn apply(&mut self, diff: &Self::Repr);
26
27 /// Applies the diff directly to the struct, using an external diffing implementation
28 fn apply_custom<D: Differ<Self>>(&mut self, diff: &D::Repr, visitor: &D) {
29 visitor.apply(self, diff)
30 }
31
32 /// Applies the diff to the struct and produces a new struct
33 fn apply_new(&self, diff: &Self::Repr) -> Self {
34 let mut new = Self::identity();
35 new.apply(&new.diff(self));
36 new.apply(diff);
37 new
38 }
39
40 /// Applies the diff to the struct and produces a new struct, using an external diffing implementation
41 fn apply_new_custom<D: Differ<Self>>(&self, diff: &D::Repr, visitor: &D) -> Self {
42 let mut new = Self::identity();
43 new.apply_custom(&new.diff_custom(self, visitor), visitor);
44 new.apply_custom(diff, visitor);
45 new
46 }
47
48 /// The identity element of the struct
49 /// ```
50 /// use diff::Diff;
51 /// let s = 42;
52 /// let i = <i32 as Diff>::identity();
53 /// assert_eq!(i.apply_new(&i.diff(&s)), s);
54 /// ```
55 /// or mathematically speaking, `i + (s - i) = s`
56 fn identity() -> Self;
57}
58
59/// A trait allowing a custom struct to handle the diffing implementation for a type
60pub trait Differ<T> {
61 type Repr;
62
63 fn diff(&self, a: &T, b: &T) -> Self::Repr;
64
65 fn apply(&self, a: &mut T, b: &Self::Repr);
66}