1use super::difference::Difference;
4
5pub use pgevolve_core_macros::Diff as DiffMacro;
10
11pub trait Diff {
18 fn diff(&self, other: &Self) -> Vec<Difference>;
20
21 fn canonical_eq(&self, other: &Self) -> bool {
23 self.diff(other).is_empty()
24 }
25}
26
27pub fn diff_field<T: PartialEq + std::fmt::Display>(
29 path: &str,
30 from: &T,
31 to: &T,
32) -> Vec<Difference> {
33 if from == to {
34 Vec::new()
35 } else {
36 vec![Difference::new(path, from, to)]
37 }
38}
39
40#[must_use]
42pub fn prefix_diffs(prefix: &str, diffs: Vec<Difference>) -> Vec<Difference> {
43 diffs.into_iter().map(|d| d.prefix_path(prefix)).collect()
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn diff_field_matches() {
52 let r = diff_field("name", &1, &1);
53 assert!(r.is_empty());
54 }
55
56 #[test]
57 fn diff_field_reports() {
58 let r = diff_field("name", &1, &2);
59 assert_eq!(r.len(), 1);
60 assert_eq!(r[0].path, "name");
61 }
62
63 #[test]
64 fn prefix_diffs_simple() {
65 let d = vec![Difference::new("len", "5", "10")];
66 let p = prefix_diffs("ty", d);
67 assert_eq!(p[0].path, "ty.len");
68 }
69
70 #[test]
71 fn prefix_diffs_empty_path() {
72 let d = vec![Difference::new("", "a", "b")];
73 let p = prefix_diffs("ty", d);
74 assert_eq!(p[0].path, "ty");
75 }
76}