runtime_capabilities/
router.rs1use crate::{Capability, CapabilityBound, Data, Dictionary, WeakInstanceToken};
6use async_trait::async_trait;
7use futures::future::BoxFuture;
8use router_error::RouterError;
9use std::fmt;
10use std::fmt::Debug;
11use std::sync::Arc;
12
13#[derive(Debug)]
15pub struct Request {
16 pub metadata: Dictionary,
18}
19
20impl Request {
21 pub fn try_clone(&self) -> Result<Self, RouterError> {
25 self.metadata
26 .enumerate()
27 .find_map(|(_, v)| {
28 match v {
29 Capability::Dictionary(_) => Some(Err::<Self, _>(RouterError::InvalidArgs)),
32 _ => None,
33 }
34 })
35 .transpose()?;
36 let metadata = self.metadata.shallow_copy().map_err(|()| RouterError::InvalidArgs)?;
37 Ok(Self { metadata })
38 }
39}
40
41#[async_trait]
44pub trait Routable<T>: Send + Sync
45where
46 T: CapabilityBound,
47{
48 async fn route(
49 &self,
50 request: Option<Request>,
51 debug: bool,
52 target: WeakInstanceToken,
54 ) -> Result<RouterResponse<T>, RouterError>;
55}
56
57#[derive(Debug)]
59pub enum RouterResponse<T: CapabilityBound> {
60 Capability(T),
62
63 Unavailable,
65
66 Debug(Data),
68}
69
70impl<T: CapabilityBound> From<T> for RouterResponse<T> {
71 fn from(val: T) -> Self {
72 Self::Capability(val)
73 }
74}
75
76#[derive(Clone)]
88pub struct Router<T: CapabilityBound> {
89 routable: Arc<dyn Routable<T>>,
90}
91
92impl CapabilityBound for Router<crate::Connector> {
93 fn debug_typename() -> &'static str {
94 "ConnectorRouter"
95 }
96}
97impl CapabilityBound for Router<crate::Data> {
98 fn debug_typename() -> &'static str {
99 "DataRouter"
100 }
101}
102impl CapabilityBound for Router<crate::Dictionary> {
103 fn debug_typename() -> &'static str {
104 "DictionaryRouter"
105 }
106}
107
108impl CapabilityBound for Router<crate::DirConnector> {
109 fn debug_typename() -> &'static str {
110 "DirConnectorRouter"
111 }
112}
113
114impl<T: CapabilityBound> fmt::Debug for Router<T> {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 f.debug_struct("Router").field("routable", &"[some routable object]").finish()
118 }
119}
120
121impl<T: CapabilityBound, F> Routable<T> for F
124where
125 F: Fn(
126 Option<Request>,
127 bool,
128 WeakInstanceToken,
129 ) -> BoxFuture<'static, Result<RouterResponse<T>, RouterError>>
130 + Send
131 + Sync
132 + 'static,
133{
134 fn route<'a, 'b>(
136 &'a self,
137 request: Option<Request>,
138 debug: bool,
139 target: WeakInstanceToken,
140 ) -> BoxFuture<'b, Result<RouterResponse<T>, RouterError>>
141 where
142 'a: 'b,
143 Self: 'b,
144 {
145 self(request, debug, target)
146 }
147}
148
149#[async_trait]
150impl<T: CapabilityBound> Routable<T> for Router<T> {
151 async fn route(
152 &self,
153 request: Option<Request>,
154 debug: bool,
155 target: WeakInstanceToken,
156 ) -> Result<RouterResponse<T>, RouterError> {
157 Router::route(self, request, debug, target).await
158 }
159}
160
161impl<T: CapabilityBound> Router<T> {
162 pub fn new(routable: impl Routable<T> + 'static) -> Self {
164 Self { routable: Arc::new(routable) }
165 }
166
167 pub fn new_error(error: impl Into<RouterError>) -> Self {
169 let v: RouterError = error.into();
170 Self::new(ErrRouter { v })
171 }
172
173 pub fn new_debug(data: impl Into<Data>) -> Self {
175 let v: Data = data.into();
176 Self::new(DebugRouter { v })
177 }
178
179 pub async fn route(
181 &self,
182 request: Option<Request>,
183 debug: bool,
184 target: WeakInstanceToken,
185 ) -> Result<RouterResponse<T>, RouterError> {
186 self.routable.route(request, debug, target).await
187 }
188}
189
190impl<T: Clone + CapabilityBound> Router<T> {
191 pub fn new_ok(c: impl Into<T>) -> Self {
194 let v: T = c.into();
195 Self::new(OkRouter { v })
196 }
197}
198
199#[derive(Clone)]
200struct OkRouter<T: Clone + CapabilityBound> {
201 v: T,
202}
203
204#[async_trait]
205impl<T: Clone + CapabilityBound> Routable<T> for OkRouter<T> {
206 async fn route(
207 &self,
208 _request: Option<Request>,
209 debug: bool,
210 _target: WeakInstanceToken,
211 ) -> Result<RouterResponse<T>, RouterError> {
212 assert!(!debug, "OkRouter does not handle debug routes");
213 Ok(RouterResponse::Capability(self.v.clone()))
214 }
215}
216
217#[derive(Clone)]
218struct DebugRouter {
219 v: Data,
220}
221
222#[async_trait]
223impl<T: CapabilityBound> Routable<T> for DebugRouter {
224 async fn route(
225 &self,
226 _request: Option<Request>,
227 _debug: bool,
228 _target: WeakInstanceToken,
229 ) -> Result<RouterResponse<T>, RouterError> {
230 Ok(RouterResponse::Debug(self.v.clone()))
231 }
232}
233
234#[derive(Clone)]
235struct ErrRouter {
236 v: RouterError,
237}
238
239#[async_trait]
240impl<T: CapabilityBound> Routable<T> for ErrRouter {
241 async fn route(
242 &self,
243 _request: Option<Request>,
244 _debug: bool,
245 _target: WeakInstanceToken,
246 ) -> Result<RouterResponse<T>, RouterError> {
247 Err(self.v.clone())
248 }
249}