wot_network/
trust_depth.rs

1use std::cmp::Ordering;
2
3/// The "trust depth" of a [Delegation](crate::Delegation).
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(TrustDepth::from(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 TrustDepth {
52    /// Check if the length of a path is acceptable relative to this TrustDepth.
53    ///
54    /// For limited trust depth, `path_len` must be below the depth limit.
55    /// However, for [`TrustDepth::Unlimited`] any path length is acceptable.
56    pub fn acceptable_path_len(&self, path_len: usize) -> bool {
57        match self {
58            Self::None => false,
59            Self::Limited(limit) => (*limit as usize) > path_len,
60            Self::Unlimited => true,
61        }
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
114    #[test]
115    fn acceptable_path_len() {
116        assert!(TrustDepth::Limited(10).acceptable_path_len(0));
117        assert!(TrustDepth::Limited(10).acceptable_path_len(9));
118
119        assert!(!TrustDepth::Limited(10).acceptable_path_len(10));
120        assert!(!TrustDepth::Limited(10).acceptable_path_len(11));
121
122        assert!(TrustDepth::Unlimited.acceptable_path_len(0));
123        assert!(TrustDepth::Unlimited.acceptable_path_len(10));
124        assert!(TrustDepth::Unlimited.acceptable_path_len(300));
125    }
126}