1use crate::{Capability, CapabilityBound, Data, Dict, 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: Dict,
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 Ok(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::DirEntry> {
103 fn debug_typename() -> &'static str {
104 "DirEntryRouter"
105 }
106}
107impl CapabilityBound for Router<crate::Dict> {
108 fn debug_typename() -> &'static str {
109 "DictionaryRouter"
110 }
111}
112
113impl CapabilityBound for Router<crate::DirConnector> {
114 fn debug_typename() -> &'static str {
115 "DirConnectorRouter"
116 }
117}
118
119impl<T: CapabilityBound> fmt::Debug for Router<T> {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.debug_struct("Router").field("routable", &"[some routable object]").finish()
123 }
124}
125
126impl<T: CapabilityBound, F> Routable<T> for F
129where
130 F: Fn(
131 Option<Request>,
132 bool,
133 WeakInstanceToken,
134 ) -> BoxFuture<'static, Result<RouterResponse<T>, RouterError>>
135 + Send
136 + Sync
137 + 'static,
138{
139 fn route<'a, 'b>(
141 &'a self,
142 request: Option<Request>,
143 debug: bool,
144 target: WeakInstanceToken,
145 ) -> BoxFuture<'b, Result<RouterResponse<T>, RouterError>>
146 where
147 'a: 'b,
148 Self: 'b,
149 {
150 self(request, debug, target)
151 }
152}
153
154#[async_trait]
155impl<T: CapabilityBound> Routable<T> for Router<T> {
156 async fn route(
157 &self,
158 request: Option<Request>,
159 debug: bool,
160 target: WeakInstanceToken,
161 ) -> Result<RouterResponse<T>, RouterError> {
162 Router::route(self, request, debug, target).await
163 }
164}
165
166impl<T: CapabilityBound> Router<T> {
167 pub fn new(routable: impl Routable<T> + 'static) -> Self {
169 Self { routable: Arc::new(routable) }
170 }
171
172 pub fn new_error(error: impl Into<RouterError>) -> Self {
174 let v: RouterError = error.into();
175 Self::new(ErrRouter { v })
176 }
177
178 pub fn new_debug(data: impl Into<Data>) -> Self {
180 let v: Data = data.into();
181 Self::new(DebugRouter { v })
182 }
183
184 pub async fn route(
186 &self,
187 request: Option<Request>,
188 debug: bool,
189 target: WeakInstanceToken,
190 ) -> Result<RouterResponse<T>, RouterError> {
191 self.routable.route(request, debug, target).await
192 }
193}
194
195impl<T: Clone + CapabilityBound> Router<T> {
196 pub fn new_ok(c: impl Into<T>) -> Self {
199 let v: T = c.into();
200 Self::new(OkRouter { v })
201 }
202}
203
204#[derive(Clone)]
205struct OkRouter<T: Clone + CapabilityBound> {
206 v: T,
207}
208
209#[async_trait]
210impl<T: Clone + CapabilityBound> Routable<T> for OkRouter<T> {
211 async fn route(
212 &self,
213 _request: Option<Request>,
214 debug: bool,
215 _target: WeakInstanceToken,
216 ) -> Result<RouterResponse<T>, RouterError> {
217 assert!(!debug, "OkRouter does not handle debug routes");
218 Ok(RouterResponse::Capability(self.v.clone()))
219 }
220}
221
222#[derive(Clone)]
223struct DebugRouter {
224 v: Data,
225}
226
227#[async_trait]
228impl<T: CapabilityBound> Routable<T> for DebugRouter {
229 async fn route(
230 &self,
231 _request: Option<Request>,
232 _debug: bool,
233 _target: WeakInstanceToken,
234 ) -> Result<RouterResponse<T>, RouterError> {
235 Ok(RouterResponse::Debug(self.v.clone()))
236 }
237}
238
239#[derive(Clone)]
240struct ErrRouter {
241 v: RouterError,
242}
243
244#[async_trait]
245impl<T: CapabilityBound> Routable<T> for ErrRouter {
246 async fn route(
247 &self,
248 _request: Option<Request>,
249 _debug: bool,
250 _target: WeakInstanceToken,
251 ) -> Result<RouterResponse<T>, RouterError> {
252 Err(self.v.clone())
253 }
254}