use std::collections::BTreeSet;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RevocationSet {
revoked: BTreeSet<String>,
}
impl RevocationSet {
pub fn new() -> Self {
Self::default()
}
pub fn revoke(&mut self, delegation_id: &str) -> bool {
self.revoked.insert(delegation_id.to_string())
}
pub fn is_revoked(&self, delegation_id: &str) -> bool {
self.revoked.contains(delegation_id)
}
pub fn len(&self) -> usize {
self.revoked.len()
}
pub fn is_empty(&self) -> bool {
self.revoked.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &String> {
self.revoked.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn revoke_then_is_revoked() {
let mut r = RevocationSet::new();
assert!(r.is_empty());
assert!(!r.is_revoked("d1"));
assert!(r.revoke("d1"), "首次撤销返回 true");
assert!(r.is_revoked("d1"));
assert_eq!(r.len(), 1);
}
#[test]
fn revoke_is_idempotent() {
let mut r = RevocationSet::new();
assert!(r.revoke("d1"));
assert!(!r.revoke("d1"), "重复撤销是幂等的,不重复计数");
assert_eq!(r.len(), 1);
}
#[test]
fn revocation_is_one_way_no_unrevoke_api() {
let mut r = RevocationSet::new();
r.revoke("d1");
r.revoke("d2");
let before = r.iter().cloned().collect::<Vec<_>>();
assert_eq!(before, vec!["d1".to_string(), "d2".to_string()]);
assert_eq!(r.len(), 2);
}
}