zeph_tools/
trust_level.rs1use std::fmt;
7
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Deserialize, Serialize)]
12#[serde(rename_all = "lowercase")]
13pub enum TrustLevel {
14 Trusted,
16 Verified,
18 #[default]
20 Quarantined,
21 Blocked,
23}
24
25impl TrustLevel {
26 #[must_use]
28 pub fn severity(self) -> u8 {
29 match self {
30 Self::Trusted => 0,
31 Self::Verified => 1,
32 Self::Quarantined => 2,
33 Self::Blocked => 3,
34 }
35 }
36
37 #[must_use]
39 pub fn min_trust(self, other: Self) -> Self {
40 if self.severity() >= other.severity() {
41 self
42 } else {
43 other
44 }
45 }
46
47 #[must_use]
48 pub fn is_active(self) -> bool {
49 !matches!(self, Self::Blocked)
50 }
51}
52
53impl fmt::Display for TrustLevel {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 Self::Trusted => f.write_str("trusted"),
57 Self::Verified => f.write_str("verified"),
58 Self::Quarantined => f.write_str("quarantined"),
59 Self::Blocked => f.write_str("blocked"),
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn severity_ordering() {
70 assert!(TrustLevel::Trusted.severity() < TrustLevel::Verified.severity());
71 assert!(TrustLevel::Verified.severity() < TrustLevel::Quarantined.severity());
72 assert!(TrustLevel::Quarantined.severity() < TrustLevel::Blocked.severity());
73 }
74
75 #[test]
76 fn min_trust_picks_least_trusted() {
77 assert_eq!(
78 TrustLevel::Trusted.min_trust(TrustLevel::Quarantined),
79 TrustLevel::Quarantined
80 );
81 assert_eq!(
82 TrustLevel::Blocked.min_trust(TrustLevel::Trusted),
83 TrustLevel::Blocked
84 );
85 }
86
87 #[test]
88 fn is_active() {
89 assert!(TrustLevel::Trusted.is_active());
90 assert!(TrustLevel::Verified.is_active());
91 assert!(TrustLevel::Quarantined.is_active());
92 assert!(!TrustLevel::Blocked.is_active());
93 }
94
95 #[test]
96 fn default_is_quarantined() {
97 assert_eq!(TrustLevel::default(), TrustLevel::Quarantined);
98 }
99
100 #[test]
101 fn display() {
102 assert_eq!(TrustLevel::Trusted.to_string(), "trusted");
103 assert_eq!(TrustLevel::Blocked.to_string(), "blocked");
104 assert_eq!(TrustLevel::Quarantined.to_string(), "quarantined");
105 assert_eq!(TrustLevel::Verified.to_string(), "verified");
106 }
107
108 #[test]
109 fn serde_roundtrip() {
110 let level = TrustLevel::Quarantined;
111 let json = serde_json::to_string(&level).unwrap();
112 assert_eq!(json, "\"quarantined\"");
113 let back: TrustLevel = serde_json::from_str(&json).unwrap();
114 assert_eq!(back, level);
115 }
116
117 #[test]
118 fn serde_all_variants() {
119 let cases = [
120 (TrustLevel::Trusted, "\"trusted\""),
121 (TrustLevel::Verified, "\"verified\""),
122 (TrustLevel::Quarantined, "\"quarantined\""),
123 (TrustLevel::Blocked, "\"blocked\""),
124 ];
125 for (level, expected_json) in cases {
126 let json = serde_json::to_string(&level).unwrap();
127 assert_eq!(json, expected_json);
128 let back: TrustLevel = serde_json::from_str(&json).unwrap();
129 assert_eq!(back, level);
130 }
131 }
132
133 #[test]
134 fn min_trust_same_level_returns_self() {
135 assert_eq!(
136 TrustLevel::Verified.min_trust(TrustLevel::Verified),
137 TrustLevel::Verified
138 );
139 assert_eq!(
140 TrustLevel::Blocked.min_trust(TrustLevel::Blocked),
141 TrustLevel::Blocked
142 );
143 }
144
145 #[test]
146 fn hash_consistent() {
147 use std::collections::HashSet;
148 let mut set = HashSet::new();
149 set.insert(TrustLevel::Trusted);
150 set.insert(TrustLevel::Verified);
151 set.insert(TrustLevel::Quarantined);
152 set.insert(TrustLevel::Blocked);
153 assert_eq!(set.len(), 4);
154 set.insert(TrustLevel::Trusted);
156 assert_eq!(set.len(), 4);
157 }
158}