wot_network/
trust_depth.rs

1use std::{cmp::Ordering, fmt};
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#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
8pub enum TrustDepth {
9    /// Encoded as 0 on the wire
10    None,
11    /// Can only be 1..=254
12    Limited(u8),
13    /// encoded as 255 on the wire
14    Unlimited,
15}
16
17impl TrustDepth {
18    /// Subtract `n` from this TrustDepth
19    ///
20    /// - `TrustDepth::Unlimited` always stays `TrustDepth::Unlimited`
21    /// - `TrustDepth::None` always stays `TrustDepth::None`.
22    /// - `TrustDepth::Limited(value)` will be set to `value - 1`.
23    ///   If the result would be 0 or negative, `TrustDepth::None` is returned.
24    pub fn minus(&self, n: u8) -> TrustDepth {
25        match self {
26            TrustDepth::Unlimited => TrustDepth::Unlimited,
27            TrustDepth::Limited(val) => {
28                if *val >= n {
29                    TrustDepth::from(val - n)
30                } else {
31                    TrustDepth::None
32                }
33            }
34            TrustDepth::None => TrustDepth::None,
35        }
36    }
37}
38
39impl From<u8> for TrustDepth {
40    fn from(value: u8) -> Self {
41        match value {
42            0 => Self::None,
43            u8::MAX => Self::Unlimited,
44            i => Self::Limited(i),
45        }
46    }
47}
48
49impl PartialEq<u8> for TrustDepth {
50    fn eq(&self, other: &u8) -> bool {
51        match self {
52            TrustDepth::None => *other == 0,
53            TrustDepth::Limited(val) => val == other,
54            TrustDepth::Unlimited => *other == u8::MAX,
55        }
56    }
57}
58
59impl PartialOrd<u8> for TrustDepth {
60    fn partial_cmp(&self, other: &u8) -> Option<Ordering> {
61        match self {
62            TrustDepth::None => 0u8.partial_cmp(other),
63            TrustDepth::Limited(val) => val.partial_cmp(other),
64            TrustDepth::Unlimited => u8::MAX.partial_cmp(other),
65        }
66    }
67}
68
69impl TrustDepth {
70    /// Check if the length of a path is acceptable relative to this TrustDepth.
71    ///
72    /// For limited trust depth, `path_len` must be below the depth limit.
73    /// However, for [`TrustDepth::Unlimited`] any path length is acceptable.
74    pub fn acceptable_path_len(&self, path_len: usize) -> bool {
75        match self {
76            Self::None => false,
77            Self::Limited(limit) => (*limit as usize) > path_len,
78            Self::Unlimited => true,
79        }
80    }
81}
82
83impl PartialOrd<Self> for TrustDepth {
84    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
85        Some(self.cmp(other))
86    }
87}
88
89impl Ord for TrustDepth {
90    fn cmp(&self, other: &TrustDepth) -> Ordering {
91        match (*self, other) {
92            (Self::Unlimited, Self::Unlimited) => Ordering::Equal,
93            (Self::Unlimited, Self::Limited(_) | Self::None) => Ordering::Greater,
94            (Self::Limited(_) | Self::None, Self::Unlimited) => Ordering::Less,
95            (Self::None, Self::None) => Ordering::Equal,
96            (Self::None, Self::Limited(_)) => Ordering::Less,
97            (Self::Limited(_), Self::None) => Ordering::Greater,
98            (Self::Limited(value), Self::Limited(other)) => value.cmp(other),
99        }
100    }
101}
102
103impl From<TrustDepth> for u8 {
104    fn from(value: TrustDepth) -> Self {
105        match value {
106            TrustDepth::None => 0,
107            TrustDepth::Limited(i) => i,
108            TrustDepth::Unlimited => u8::MAX,
109        }
110    }
111}
112
113impl fmt::Display for TrustDepth {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        match self {
116            TrustDepth::None => write!(f, "None"),
117            TrustDepth::Unlimited => write!(f, "Unlimited"),
118            TrustDepth::Limited(val) => write!(f, "{}", val),
119        }
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use crate::TrustDepth;
126
127    #[test]
128    fn trust_depth() {
129        let depth1 = TrustDepth::Limited(0);
130        let depth2 = TrustDepth::Limited(1);
131        let depth3 = TrustDepth::Unlimited;
132
133        assert!(depth1 < depth2);
134        assert!(depth1 < depth3);
135        assert!(depth2 < depth3);
136
137        assert_eq!(depth1, depth1);
138        assert_eq!(depth2, depth2);
139        assert_eq!(depth3, depth3);
140    }
141
142    #[test]
143    fn acceptable_path_len() {
144        assert!(TrustDepth::Limited(10).acceptable_path_len(0));
145        assert!(TrustDepth::Limited(10).acceptable_path_len(9));
146
147        assert!(!TrustDepth::Limited(10).acceptable_path_len(10));
148        assert!(!TrustDepth::Limited(10).acceptable_path_len(11));
149
150        assert!(TrustDepth::Unlimited.acceptable_path_len(0));
151        assert!(TrustDepth::Unlimited.acceptable_path_len(10));
152        assert!(TrustDepth::Unlimited.acceptable_path_len(300));
153    }
154}