1use super::difference::Difference;
4
5pub trait Equiv {
13 fn differences(&self, other: &Self) -> Vec<Difference>;
15
16 fn canonical_eq(&self, other: &Self) -> bool {
18 self.differences(other).is_empty()
19 }
20}
21
22pub fn field_difference<T: PartialEq + std::fmt::Display>(
24 path: &str,
25 from: &T,
26 to: &T,
27) -> Vec<Difference> {
28 if from == to {
29 Vec::new()
30 } else {
31 vec![Difference::new(path, from, to)]
32 }
33}
34
35#[must_use]
37pub fn prefix_differences(prefix: &str, diffs: Vec<Difference>) -> Vec<Difference> {
38 diffs.into_iter().map(|d| d.prefix_path(prefix)).collect()
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn field_difference_matches() {
47 let r = field_difference("name", &1, &1);
48 assert!(r.is_empty());
49 }
50
51 #[test]
52 fn field_difference_reports() {
53 let r = field_difference("name", &1, &2);
54 assert_eq!(r.len(), 1);
55 assert_eq!(r[0].path, "name");
56 }
57
58 #[test]
59 fn prefix_differences_simple() {
60 let d = vec![Difference::new("len", "5", "10")];
61 let p = prefix_differences("ty", d);
62 assert_eq!(p[0].path, "ty.len");
63 }
64
65 #[test]
66 fn prefix_differences_empty_path() {
67 let d = vec![Difference::new("", "a", "b")];
68 let p = prefix_differences("ty", d);
69 assert_eq!(p[0].path, "ty");
70 }
71}