vertep_runtime/
transport.rs1use std::collections::BTreeMap;
12use std::sync::{Arc, RwLock};
13
14use vertep_core::session::SCXML_EVENT_PROCESSOR;
15
16use crate::address::Address;
17use crate::mailbox::{Envelope, Mailbox};
18
19#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct TransportError(pub String);
22
23impl core::fmt::Display for TransportError {
24 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25 write!(f, "transport error: {}", self.0)
26 }
27}
28
29impl std::error::Error for TransportError {}
30
31pub trait Transport: Send + Sync {
34 fn type_iri(&self) -> &str;
36 fn aliases(&self) -> Vec<String> {
38 Vec::new()
39 }
40 fn location(&self, address: &Address) -> String {
42 address.as_str().to_owned()
43 }
44 fn deliver(&self, mailbox: &dyn Mailbox, env: Envelope) -> Result<(), TransportError>;
50}
51
52#[derive(Clone, Copy, Debug, Default)]
55pub struct LocalTransport;
56
57impl Transport for LocalTransport {
58 fn type_iri(&self) -> &str {
59 SCXML_EVENT_PROCESSOR
60 }
61
62 fn aliases(&self) -> Vec<String> {
63 vec!["scxml".to_owned()]
64 }
65
66 fn deliver(&self, mailbox: &dyn Mailbox, env: Envelope) -> Result<(), TransportError> {
67 mailbox
68 .enqueue(env)
69 .map_err(|e| TransportError(e.to_string()))
70 }
71}
72
73pub trait Resolver: Send + Sync {
75 fn resolve(&self, address: &Address) -> Option<Arc<dyn Mailbox>>;
77}
78
79#[derive(Clone, Debug, PartialEq, Eq)]
81pub struct ResolveError(pub String);
82
83impl core::fmt::Display for ResolveError {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 write!(f, "cannot resolve {}", self.0)
86 }
87}
88
89impl std::error::Error for ResolveError {}
90
91#[derive(Default)]
94pub struct Directory {
95 resolvers: RwLock<BTreeMap<String, Arc<dyn Resolver>>>,
96}
97
98impl std::fmt::Debug for Directory {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 let schemes: Vec<String> = self
101 .resolvers
102 .read()
103 .map(|r| r.keys().cloned().collect())
104 .unwrap_or_default();
105 f.debug_struct("Directory")
106 .field("schemes", &schemes)
107 .finish()
108 }
109}
110
111impl Directory {
112 pub fn register(&self, scheme: &str, resolver: Arc<dyn Resolver>) {
114 if let Ok(mut r) = self.resolvers.write() {
115 r.insert(scheme.to_ascii_lowercase(), resolver);
116 }
117 }
118
119 pub fn resolve(&self, address: &Address) -> Result<Arc<dyn Mailbox>, ResolveError> {
125 let r = self
126 .resolvers
127 .read()
128 .ok()
129 .and_then(|r| r.get(&address.scheme().to_ascii_lowercase()).cloned());
130 r.and_then(|r| r.resolve(address))
131 .ok_or_else(|| ResolveError(address.as_str().to_owned()))
132 }
133}
134
135#[derive(Clone, Default)]
137pub struct Transports {
138 by_type: BTreeMap<String, Arc<dyn Transport>>,
139 primary: Vec<Arc<dyn Transport>>,
140}
141
142impl std::fmt::Debug for Transports {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 f.debug_struct("Transports")
145 .field("types", &self.by_type.keys().collect::<Vec<_>>())
146 .finish()
147 }
148}
149
150impl Transports {
151 pub fn local() -> Self {
153 let mut t = Transports::default();
154 t.register(Arc::new(LocalTransport));
155 t
156 }
157
158 pub fn register(&mut self, t: Arc<dyn Transport>) {
160 self.by_type.insert(t.type_iri().to_owned(), t.clone());
161 for a in t.aliases() {
162 self.by_type.insert(a, t.clone());
163 }
164 self.primary.push(t);
165 }
166
167 pub fn get(&self, type_: &str) -> Option<&Arc<dyn Transport>> {
169 self.by_type.get(type_)
170 }
171
172 pub fn send_types(&self) -> Vec<String> {
174 self.by_type.keys().cloned().collect()
175 }
176
177 pub fn ioprocessors(&self, address: &Address) -> vertep_core::datamodel::Value {
180 use vertep_core::datamodel::Value;
181 let mut entries = Vec::new();
182 for (name, t) in &self.by_type {
183 entries.push((
184 name.clone(),
185 Value::Object(vec![(
186 "location".to_owned(),
187 Value::String(t.location(address)),
188 )]),
189 ));
190 }
191 Value::Object(entries)
192 }
193}