wot_network/
trust_depth.rs

1use std::cmp::Ordering;
2
3/// The "trust depth" of a delegating certification.
4///
5/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-trust-signature>
6#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
7pub enum TrustDepth {
8    /// Encoded as 0 on the wire
9    None,
10    /// Can only be 1..=254
11    Limited(u8),
12    /// encoded as 255 on the wire
13    Unlimited,
14}
15
16impl TrustDepth {
17    /// Subtract `n` from this TrustDepth
18    ///
19    /// Returns `None` if the subtraction underflows
20    pub fn minus(&self, n: u8) -> Option<TrustDepth> {
21        match self {
22            TrustDepth::Unlimited => Some(TrustDepth::Unlimited),
23            TrustDepth::Limited(val) => {
24                if *val >= n {
25                    Some(Self::Limited(val - n))
26                } else {
27                    None // underflow
28                }
29            }
30            TrustDepth::None => {
31                if n == 0 {
32                    Some(TrustDepth::None)
33                } else {
34                    None // underflow
35                }
36            }
37        }
38    }
39}
40
41impl From<u8> for TrustDepth {
42    fn from(value: u8) -> Self {
43        match value {
44            0 => Self::None,
45            u8::MAX => Self::Unlimited,
46            i => Self::Limited(i),
47        }
48    }
49}
50
51impl PartialEq<u8> for TrustDepth {
52    fn eq(&self, other: &u8) -> bool {
53        let other = TrustDepth::from(*other);
54        *self == other
55    }
56}
57
58impl PartialOrd<u8> for TrustDepth {
59    fn partial_cmp(&self, other: &u8) -> Option<Ordering> {
60        let other = TrustDepth::from(*other);
61        Some(self.cmp(&other))
62    }
63}
64
65impl PartialOrd<Self> for TrustDepth {
66    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
67        Some(self.cmp(other))
68    }
69}
70
71impl Ord for TrustDepth {
72    fn cmp(&self, other: &TrustDepth) -> Ordering {
73        match (*self, other) {
74            (Self::Unlimited, Self::Unlimited) => Ordering::Equal,
75            (Self::Unlimited, Self::Limited(_) | Self::None) => Ordering::Greater,
76            (Self::Limited(_) | Self::None, Self::Unlimited) => Ordering::Less,
77            (Self::None, Self::None) => Ordering::Equal,
78            (Self::None, Self::Limited(_)) => Ordering::Less,
79            (Self::Limited(_), Self::None) => Ordering::Greater,
80            (Self::Limited(value), Self::Limited(other)) => value.cmp(other),
81        }
82    }
83}
84
85impl From<TrustDepth> for u8 {
86    fn from(value: TrustDepth) -> Self {
87        match value {
88            TrustDepth::None => 0,
89            TrustDepth::Limited(i) => i,
90            TrustDepth::Unlimited => u8::MAX,
91        }
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use crate::TrustDepth;
98
99    #[test]
100    fn trust_depth() {
101        let depth1 = TrustDepth::Limited(0);
102        let depth2 = TrustDepth::Limited(1);
103        let depth3 = TrustDepth::Unlimited;
104
105        assert!(depth1 < depth2);
106        assert!(depth1 < depth3);
107        assert!(depth2 < depth3);
108
109        assert_eq!(depth1, depth1);
110        assert_eq!(depth2, depth2);
111        assert_eq!(depth3, depth3);
112    }
113}