wanning_core/
revocation.rs1use std::collections::BTreeSet;
11
12#[derive(Clone, Debug, Default, PartialEq, Eq)]
14pub struct RevocationSet {
15 revoked: BTreeSet<String>,
16}
17
18impl RevocationSet {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn revoke(&mut self, delegation_id: &str) -> bool {
25 self.revoked.insert(delegation_id.to_string())
26 }
27
28 pub fn is_revoked(&self, delegation_id: &str) -> bool {
30 self.revoked.contains(delegation_id)
31 }
32
33 pub fn len(&self) -> usize {
35 self.revoked.len()
36 }
37
38 pub fn is_empty(&self) -> bool {
39 self.revoked.is_empty()
40 }
41
42 pub fn iter(&self) -> impl Iterator<Item = &String> {
44 self.revoked.iter()
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn revoke_then_is_revoked() {
54 let mut r = RevocationSet::new();
55 assert!(r.is_empty());
56 assert!(!r.is_revoked("d1"));
57 assert!(r.revoke("d1"), "首次撤销返回 true");
58 assert!(r.is_revoked("d1"));
59 assert_eq!(r.len(), 1);
60 }
61
62 #[test]
63 fn revoke_is_idempotent() {
64 let mut r = RevocationSet::new();
65 assert!(r.revoke("d1"));
66 assert!(!r.revoke("d1"), "重复撤销是幂等的,不重复计数");
67 assert_eq!(r.len(), 1);
68 }
69
70 #[test]
71 fn revocation_is_one_way_no_unrevoke_api() {
72 let mut r = RevocationSet::new();
74 r.revoke("d1");
75 r.revoke("d2");
76 let before = r.iter().cloned().collect::<Vec<_>>();
77 assert_eq!(before, vec!["d1".to_string(), "d2".to_string()]);
78 assert_eq!(r.len(), 2);
80 }
81}