runtime_capabilities/
router.rs1use crate::{CapabilityBound, WeakInstanceToken};
6use async_trait::async_trait;
7use capability_source::CapabilitySource;
8use fidl_fuchsia_component_runtime::RouteRequest;
9use router_error::RouterError;
10use std::fmt;
11use std::sync::Arc;
12
13#[async_trait]
16pub trait Routable<T>: Send + Sync
17where
18 T: CapabilityBound,
19{
20 async fn route(
21 &self,
22 request: RouteRequest,
23 target: WeakInstanceToken,
25 ) -> Result<Option<T>, RouterError>;
26
27 async fn route_debug(
30 &self,
31 request: RouteRequest,
32 target: WeakInstanceToken,
34 ) -> Result<CapabilitySource, RouterError>;
35}
36
37#[derive(Clone)]
45pub struct Router<T: CapabilityBound> {
46 routable: Arc<dyn Routable<T>>,
47}
48
49impl CapabilityBound for Router<crate::Connector> {
50 fn debug_typename() -> &'static str {
51 "ConnectorRouter"
52 }
53}
54impl CapabilityBound for Router<crate::Data> {
55 fn debug_typename() -> &'static str {
56 "DataRouter"
57 }
58}
59impl CapabilityBound for Router<crate::Dictionary> {
60 fn debug_typename() -> &'static str {
61 "DictionaryRouter"
62 }
63}
64
65impl CapabilityBound for Router<crate::DirConnector> {
66 fn debug_typename() -> &'static str {
67 "DirConnectorRouter"
68 }
69}
70
71impl<T: CapabilityBound> fmt::Debug for Router<T> {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.debug_struct("Router").field("routable", &"[some routable object]").finish()
75 }
76}
77
78#[async_trait]
79impl<T: CapabilityBound> Routable<T> for Router<T> {
80 async fn route(
81 &self,
82 request: RouteRequest,
83 target: WeakInstanceToken,
84 ) -> Result<Option<T>, RouterError> {
85 Router::route(self, request, target).await
86 }
87
88 async fn route_debug(
89 &self,
90 request: RouteRequest,
91 target: WeakInstanceToken,
92 ) -> Result<CapabilitySource, RouterError> {
93 Router::route_debug(self, request, target).await
94 }
95}
96
97impl<T: CapabilityBound> Router<T> {
98 pub fn new(routable: impl Routable<T> + 'static) -> Self {
100 Self { routable: Arc::new(routable) }
101 }
102
103 pub fn new_error(error: impl Into<RouterError>) -> Self {
105 let v: RouterError = error.into();
106 Self::new(ErrRouter { v })
107 }
108
109 pub fn new_debug(source: CapabilitySource) -> Self {
111 Self::new(DebugRouter { source })
112 }
113
114 pub async fn route(
116 &self,
117 request: RouteRequest,
118 target: WeakInstanceToken,
119 ) -> Result<Option<T>, RouterError> {
120 self.routable.route(request, target).await
121 }
122
123 pub async fn route_debug(
125 &self,
126 request: RouteRequest,
127 target: WeakInstanceToken,
128 ) -> Result<CapabilitySource, RouterError> {
129 self.routable.route_debug(request, target).await
130 }
131}
132
133impl<T: Clone + CapabilityBound> Router<T> {
134 pub fn new_ok(c: impl Into<T>) -> Self {
137 let v: T = c.into();
138 Self::new(OkRouter { v })
139 }
140}
141
142#[derive(Clone)]
143struct OkRouter<T: Clone + CapabilityBound> {
144 v: T,
145}
146
147#[async_trait]
148impl<T: Clone + CapabilityBound> Routable<T> for OkRouter<T> {
149 async fn route(
150 &self,
151 _request: RouteRequest,
152 _target: WeakInstanceToken,
153 ) -> Result<Option<T>, RouterError> {
154 Ok(Some(self.v.clone()))
155 }
156
157 async fn route_debug(
158 &self,
159 _request: RouteRequest,
160 _target: WeakInstanceToken,
161 ) -> Result<CapabilitySource, RouterError> {
162 panic!("OkRouter does not handle debug routes");
163 }
164}
165
166#[derive(Clone)]
167struct DebugRouter {
168 source: CapabilitySource,
169}
170
171#[async_trait]
172impl<T: CapabilityBound> Routable<T> for DebugRouter {
173 async fn route(
174 &self,
175 _request: RouteRequest,
176 _target: WeakInstanceToken,
177 ) -> Result<Option<T>, RouterError> {
178 panic!("DebugRouter does not handle non-debug routes");
179 }
180
181 async fn route_debug(
182 &self,
183 _request: RouteRequest,
184 _target: WeakInstanceToken,
185 ) -> Result<CapabilitySource, RouterError> {
186 Ok(self.source.clone())
187 }
188}
189
190#[derive(Clone)]
191struct ErrRouter {
192 v: RouterError,
193}
194
195#[async_trait]
196impl<T: CapabilityBound> Routable<T> for ErrRouter {
197 async fn route(
198 &self,
199 _request: RouteRequest,
200 _target: WeakInstanceToken,
201 ) -> Result<Option<T>, RouterError> {
202 Err(self.v.clone())
203 }
204
205 async fn route_debug(
206 &self,
207 _request: RouteRequest,
208 _target: WeakInstanceToken,
209 ) -> Result<CapabilitySource, RouterError> {
210 Err(self.v.clone())
211 }
212}