Skip to main content

encryption/
registry.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3//! 标识 → 实现的存储,各注册表共用(对应 PHP 版 `AbstractRegistry`)。
4
5use std::collections::BTreeMap;
6use std::fmt;
7
8use crate::contract::Identified;
9use crate::error::{Error, Result};
10
11/// 泛型注册表:`Registry<Box<dyn SymmetricCipher>>` 等。
12///
13/// 注册表按 `item.identifier()` 存储;相同标识重复注册以最后一次为准。
14/// `kind` 仅用于错误消息(如 "symmetric cipher")。
15pub struct Registry<T> {
16    kind: &'static str,
17    items: BTreeMap<String, T>,
18}
19
20impl<T: Identified> Registry<T> {
21    /// `kind`:错误消息里的能力名称,如 "symmetric cipher"。
22    pub fn new(kind: &'static str) -> Self {
23        Self {
24            kind,
25            items: BTreeMap::new(),
26        }
27    }
28
29    /// 以 `item.identifier()` 为键注册/覆盖。
30    pub fn register(&mut self, item: T) -> &mut Self {
31        let identifier = item.identifier().to_string();
32        self.items.insert(identifier, item);
33        self
34    }
35
36    pub fn has(&self, identifier: &str) -> bool {
37        self.items.contains_key(identifier)
38    }
39
40    pub fn get(&self, identifier: &str) -> Result<&T> {
41        self.items
42            .get(identifier)
43            .ok_or_else(|| Error::UnknownIdentifier {
44                kind: self.kind,
45                identifier: identifier.to_string(),
46            })
47    }
48
49    /// 已注册标识,按字典序。
50    pub fn identifiers(&self) -> Vec<&str> {
51        self.items.keys().map(String::as_str).collect()
52    }
53}
54
55/// 只打印能力名与标识列表;不要求 `T: Debug`(实现内部持有密钥)。
56impl<T: Identified> fmt::Debug for Registry<T> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_struct("Registry")
59            .field("kind", &self.kind)
60            .field("identifiers", &self.identifiers())
61            .finish()
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[derive(Debug)]
70    struct Dummy(&'static str);
71
72    impl Identified for Dummy {
73        fn identifier(&self) -> &str {
74            self.0
75        }
76    }
77
78    #[test]
79    fn register_get_has_identifiers() {
80        let mut registry = Registry::new("dummy");
81        registry.register(Dummy("a")).register(Dummy("b"));
82
83        assert!(registry.has("a"));
84        assert_eq!(registry.get("a").unwrap().identifier(), "a");
85        assert_eq!(registry.identifiers(), vec!["a", "b"]);
86    }
87
88    #[test]
89    fn unknown_identifier_is_an_error() {
90        let registry: Registry<Dummy> = Registry::new("dummy");
91        let error = registry.get("missing").unwrap_err();
92        assert_eq!(
93            error,
94            Error::UnknownIdentifier {
95                kind: "dummy",
96                identifier: "missing".to_string()
97            }
98        );
99    }
100
101    #[test]
102    fn re_registering_same_identifier_overwrites() {
103        let mut registry = Registry::new("dummy");
104        registry.register(Dummy("a"));
105        registry.register(Dummy("a"));
106        assert_eq!(registry.identifiers(), vec!["a"]);
107    }
108}