mfm_machine/
live_io_registry.rs1use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::live_io::LiveIoTransportFactory;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct RegistryError {
10 pub message: String,
12}
13
14impl RegistryError {
15 pub fn new(message: impl Into<String>) -> Self {
17 Self {
18 message: message.into(),
19 }
20 }
21}
22
23impl std::fmt::Display for RegistryError {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", self.message)
26 }
27}
28
29impl std::error::Error for RegistryError {}
30
31pub trait TransportRegistry: Send + Sync {
33 fn register(&mut self, factory: Arc<dyn LiveIoTransportFactory>) -> Result<(), RegistryError>;
37
38 fn resolve(&self, namespace_group: &str) -> Option<Arc<dyn LiveIoTransportFactory>>;
40
41 fn all(&self) -> Vec<Arc<dyn LiveIoTransportFactory>>;
43}
44
45#[derive(Clone, Default)]
47pub struct HashMapTransportRegistry {
48 routes: HashMap<String, Arc<dyn LiveIoTransportFactory>>,
49}
50
51impl HashMapTransportRegistry {
52 pub fn new() -> Self {
54 Self::default()
55 }
56}
57
58impl TransportRegistry for HashMapTransportRegistry {
59 fn register(&mut self, factory: Arc<dyn LiveIoTransportFactory>) -> Result<(), RegistryError> {
60 let group = factory.namespace_group().trim();
61 if group.is_empty() {
62 return Err(RegistryError::new(
63 "transport namespace group must not be empty",
64 ));
65 }
66 if self.routes.contains_key(group) {
67 return Err(RegistryError::new(format!(
68 "duplicate transport namespace group: {group}",
69 )));
70 }
71 self.routes.insert(group.to_string(), factory);
72 Ok(())
73 }
74
75 fn resolve(&self, namespace_group: &str) -> Option<Arc<dyn LiveIoTransportFactory>> {
76 self.routes.get(namespace_group).cloned()
77 }
78
79 fn all(&self) -> Vec<Arc<dyn LiveIoTransportFactory>> {
80 self.routes.values().cloned().collect()
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 use crate::live_io::{LiveIoEnv, LiveIoTransport};
89
90 struct DummyFactory {
91 group: &'static str,
92 }
93
94 impl LiveIoTransportFactory for DummyFactory {
95 fn namespace_group(&self) -> &str {
96 self.group
97 }
98
99 fn make(&self, _env: LiveIoEnv) -> Box<dyn LiveIoTransport> {
100 panic!("not used")
101 }
102 }
103
104 #[test]
105 fn duplicate_namespace_group_is_rejected() {
106 let mut reg = HashMapTransportRegistry::new();
107 reg.register(Arc::new(DummyFactory { group: "local.fs" }))
108 .expect("first registration");
109 let err = reg
110 .register(Arc::new(DummyFactory { group: "local.fs" }))
111 .expect_err("expected duplicate error");
112 assert!(err.message.contains("duplicate"));
113 }
114}