1use std::fmt::Debug;
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[derive(PartialEq, Debug)]
5pub enum Changed<T> {
6 Unchanged,
7 Changed(T),
8}
9
10impl<T> Changed<T> {
11 #[inline]
12 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Changed<U> {
13 match self {
14 Changed::Unchanged => Changed::Unchanged,
15 Changed::Changed(x) => Changed::Changed(f(x)),
16 }
17 }
18
19 pub fn take(&mut self) -> Option<T> {
20 match std::mem::take(self) {
21 Changed::Unchanged => None,
22 Changed::Changed(x) => Some(x),
23 }
24 }
25
26 pub fn to_changes(&mut self) -> Vec<T> {
27 match std::mem::take(self) {
28 Changed::Unchanged => vec![],
29 Changed::Changed(x) => vec![x],
30 }
31 }
32
33 pub fn is_unchanged(&self) -> bool {
34 match self {
35 Changed::Unchanged => true,
36 Changed::Changed(_) => false,
37 }
38 }
39}
40
41impl<T: Default> Changed<T> {
42 #[inline]
43 pub fn unwrap_or_default(self) -> T {
44 match self {
45 Changed::Changed(x) => x,
46 Changed::Unchanged => Default::default(),
47 }
48 }
49}
50
51impl<T> Default for Changed<T> {
52 #[inline]
53 fn default() -> Self {
54 Changed::Unchanged
55 }
56}
57
58impl<T> From<Option<T>> for Changed<T> {
59 #[inline]
60 fn from(opt: Option<T>) -> Self {
61 match opt {
62 None => Changed::Unchanged,
63 Some(x) => Changed::Changed(x),
64 }
65 }
66}
67
68impl<T> Iterator for Changed<T> {
69 type Item = T;
70 fn next(&mut self) -> Option<T> {
71 self.take()
72 }
73}
74
75pub trait Comparable {
76 type Desc: PartialEq + Debug;
81
82 fn describe(&self) -> Self::Desc;
84
85 type Change: PartialEq + Debug;
90
91 fn comparison(&self, other: &Self) -> Changed<Self::Change>;
96}
97
98impl<T: Comparable> Comparable for &T {
99 type Desc = T::Desc;
100
101 fn describe(&self) -> Self::Desc {
102 (*self).describe()
103 }
104
105 type Change = T::Change;
106
107 fn comparison(&self, other: &Self) -> Changed<Self::Change> {
108 (*self).comparison(other)
109 }
110}