use std::{cmp::Ordering, fmt};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum TrustDepth {
None,
Limited(u8),
Unlimited,
}
impl TrustDepth {
pub fn minus(&self, n: u8) -> TrustDepth {
match self {
TrustDepth::Unlimited => TrustDepth::Unlimited,
TrustDepth::Limited(val) => {
if *val >= n {
TrustDepth::from(val - n)
} else {
TrustDepth::None
}
}
TrustDepth::None => TrustDepth::None,
}
}
}
impl From<u8> for TrustDepth {
fn from(value: u8) -> Self {
match value {
0 => Self::None,
u8::MAX => Self::Unlimited,
i => Self::Limited(i),
}
}
}
impl PartialEq<u8> for TrustDepth {
fn eq(&self, other: &u8) -> bool {
match self {
TrustDepth::None => *other == 0,
TrustDepth::Limited(val) => val == other,
TrustDepth::Unlimited => *other == u8::MAX,
}
}
}
impl PartialOrd<u8> for TrustDepth {
fn partial_cmp(&self, other: &u8) -> Option<Ordering> {
match self {
TrustDepth::None => 0u8.partial_cmp(other),
TrustDepth::Limited(val) => val.partial_cmp(other),
TrustDepth::Unlimited => u8::MAX.partial_cmp(other),
}
}
}
impl TrustDepth {
pub fn acceptable_path_len(&self, path_len: usize) -> bool {
match self {
Self::None => false,
Self::Limited(limit) => (*limit as usize) > path_len,
Self::Unlimited => true,
}
}
}
impl PartialOrd<Self> for TrustDepth {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TrustDepth {
fn cmp(&self, other: &TrustDepth) -> Ordering {
match (*self, other) {
(Self::Unlimited, Self::Unlimited) => Ordering::Equal,
(Self::Unlimited, Self::Limited(_) | Self::None) => Ordering::Greater,
(Self::Limited(_) | Self::None, Self::Unlimited) => Ordering::Less,
(Self::None, Self::None) => Ordering::Equal,
(Self::None, Self::Limited(_)) => Ordering::Less,
(Self::Limited(_), Self::None) => Ordering::Greater,
(Self::Limited(value), Self::Limited(other)) => value.cmp(other),
}
}
}
impl From<TrustDepth> for u8 {
fn from(value: TrustDepth) -> Self {
match value {
TrustDepth::None => 0,
TrustDepth::Limited(i) => i,
TrustDepth::Unlimited => u8::MAX,
}
}
}
impl fmt::Display for TrustDepth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TrustDepth::None => write!(f, "None"),
TrustDepth::Unlimited => write!(f, "Unlimited"),
TrustDepth::Limited(val) => write!(f, "{}", val),
}
}
}
#[cfg(test)]
mod tests {
use crate::TrustDepth;
#[test]
fn trust_depth() {
let depth1 = TrustDepth::Limited(0);
let depth2 = TrustDepth::Limited(1);
let depth3 = TrustDepth::Unlimited;
assert!(depth1 < depth2);
assert!(depth1 < depth3);
assert!(depth2 < depth3);
assert_eq!(depth1, depth1);
assert_eq!(depth2, depth2);
assert_eq!(depth3, depth3);
}
#[test]
fn acceptable_path_len() {
assert!(TrustDepth::Limited(10).acceptable_path_len(0));
assert!(TrustDepth::Limited(10).acceptable_path_len(9));
assert!(!TrustDepth::Limited(10).acceptable_path_len(10));
assert!(!TrustDepth::Limited(10).acceptable_path_len(11));
assert!(TrustDepth::Unlimited.acceptable_path_len(0));
assert!(TrustDepth::Unlimited.acceptable_path_len(10));
assert!(TrustDepth::Unlimited.acceptable_path_len(300));
}
}