peace_diff/
tracked.rs

1use std::hash::{Hash, Hasher};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{Equality, MaybeEq};
6
7/// Tracks the known state of a value.
8#[derive(Clone, Debug, Deserialize, Serialize, Eq)]
9pub enum Tracked<T> {
10    /// Value does not exist.
11    None,
12    /// Value exists, but its content is not known.
13    Unknown,
14    /// Value exists.
15    Known(T),
16}
17
18impl<T> PartialEq for Tracked<T>
19where
20    T: PartialEq,
21{
22    fn eq(&self, other: &Self) -> bool {
23        match (self, other) {
24            // Both non-existent values.
25            (Self::None, Self::None) => true,
26
27            // Both known values with info.
28            (Self::Known(t_self), Self::Known(t_other)) => t_self.eq(t_other),
29
30            // One known value and one non-existent, or
31            // Any unknown value.
32            (Self::Known(_), Self::None)
33            | (Self::None, Self::Known(_))
34            | (_, Self::Unknown)
35            | (Self::Unknown, _) => false,
36        }
37    }
38}
39
40impl<T> Hash for Tracked<T>
41where
42    T: Hash,
43{
44    fn hash<H: Hasher>(&self, state: &mut H) {
45        match self {
46            Self::None => 0.hash(state),
47            Self::Known(t) => t.hash(state),
48            Self::Unknown => 2.hash(state),
49        }
50    }
51}
52
53impl<T> MaybeEq for Tracked<T>
54where
55    T: MaybeEq,
56{
57    fn maybe_eq(&self, other: &Self) -> Equality {
58        match (self, other) {
59            // Both non-existent values.
60            (Self::None, Self::None) => Equality::Equal,
61
62            // Both known values with info.
63            (Self::Known(t_self), Self::Known(t_other)) => t_self.maybe_eq(t_other),
64
65            // One known value and one non-existent.
66            (Self::Known(_), Self::None) | (Self::None, Self::Known(_)) => Equality::NotEqual,
67
68            // Any unknown value.
69            (_, Self::Unknown) | (Self::Unknown, _) => Equality::Unknown,
70        }
71    }
72}