1use crate::policy::PolicyError;
6use crate::rights::Rights;
7use async_trait::async_trait;
8use clonable_error::ClonableError;
9use cm_rust::{CapabilityTypeName, ExposeDeclCommon, OfferDeclCommon, SourceName, UseDeclCommon};
10use cm_types::{Availability, Name};
11use moniker::{ChildName, ExtendedMoniker, Moniker};
12use router_error::{DowncastErrorForTest, Explain, RouterError};
13use std::sync::Arc;
14use thiserror::Error;
15use {fidl_fuchsia_component as fcomponent, zx_status as zx};
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
22#[derive(Debug, Error, Clone)]
23pub enum ComponentInstanceError {
24 #[error("could not find `{moniker}`")]
25 InstanceNotFound { moniker: Moniker },
26 #[error("component is not executable `{moniker}`")]
27 InstanceNotExecutable { moniker: Moniker },
28 #[error("component manager instance unavailable")]
29 ComponentManagerInstanceUnavailable {},
30 #[error("expected a component instance, but got component manager's instance")]
31 ComponentManagerInstanceUnexpected {},
32 #[error("malformed url `{url}` for `{moniker}`")]
33 MalformedUrl { url: String, moniker: Moniker },
34 #[error("url `{url}` for `{moniker}` does not resolve to an absolute url")]
35 NoAbsoluteUrl { url: String, moniker: Moniker },
36 #[cfg_attr(feature = "serde", serde(skip))]
39 #[error("failed to resolve `{moniker}`:\n\t{err}")]
40 ResolveFailed {
41 moniker: Moniker,
42 #[source]
43 err: ClonableError,
44 },
45}
46
47impl ComponentInstanceError {
48 pub fn as_zx_status(&self) -> zx::Status {
49 match self {
50 ComponentInstanceError::ResolveFailed { .. }
51 | ComponentInstanceError::InstanceNotFound { .. }
52 | ComponentInstanceError::ComponentManagerInstanceUnavailable {}
53 | ComponentInstanceError::InstanceNotExecutable { .. }
54 | ComponentInstanceError::NoAbsoluteUrl { .. } => zx::Status::NOT_FOUND,
55 ComponentInstanceError::MalformedUrl { .. }
56 | ComponentInstanceError::ComponentManagerInstanceUnexpected { .. } => {
57 zx::Status::INTERNAL
58 }
59 }
60 }
61
62 pub fn instance_not_found(moniker: Moniker) -> ComponentInstanceError {
63 ComponentInstanceError::InstanceNotFound { moniker }
64 }
65
66 pub fn cm_instance_unavailable() -> ComponentInstanceError {
67 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
68 }
69
70 pub fn resolve_failed(moniker: Moniker, err: impl Into<anyhow::Error>) -> Self {
71 Self::ResolveFailed { moniker, err: err.into().into() }
72 }
73}
74
75impl Explain for ComponentInstanceError {
76 fn as_zx_status(&self) -> zx::Status {
77 self.as_zx_status()
78 }
79}
80
81impl From<ComponentInstanceError> for ExtendedMoniker {
82 fn from(err: ComponentInstanceError) -> ExtendedMoniker {
83 match err {
84 ComponentInstanceError::InstanceNotFound { moniker }
85 | ComponentInstanceError::MalformedUrl { moniker, .. }
86 | ComponentInstanceError::NoAbsoluteUrl { moniker, .. }
87 | ComponentInstanceError::InstanceNotExecutable { moniker }
88 | ComponentInstanceError::ResolveFailed { moniker, .. } => {
89 ExtendedMoniker::ComponentInstance(moniker)
90 }
91 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
92 | ComponentInstanceError::ComponentManagerInstanceUnexpected {} => {
93 ExtendedMoniker::ComponentManager
94 }
95 }
96 }
97}
98
99impl PartialEq for ComponentInstanceError {
102 fn eq(&self, other: &Self) -> bool {
103 match (self, other) {
104 (
105 Self::InstanceNotFound { moniker: self_moniker },
106 Self::InstanceNotFound { moniker: other_moniker },
107 ) => self_moniker.eq(other_moniker),
108 (
109 Self::ComponentManagerInstanceUnavailable {},
110 Self::ComponentManagerInstanceUnavailable {},
111 ) => true,
112 (Self::ResolveFailed { .. }, Self::ResolveFailed { .. }) => false,
113 _ => false,
114 }
115 }
116}
117
118#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
120#[derive(Debug, Error, Clone, PartialEq)]
121pub enum RoutingError {
122 #[error(
123 "backing directory `{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`"
124 )]
125 StorageFromChildExposeNotFound {
126 child_moniker: ChildName,
127 moniker: Moniker,
128 capability_id: String,
129 },
130
131 #[error(
132 "`{target_name:?}` tried to use a storage capability from `{source_moniker}` but it is \
133 not in the component id index. https://fuchsia.dev/go/components/instance-id"
134 )]
135 ComponentNotInIdIndex { source_moniker: Moniker, target_name: Option<ChildName> },
136
137 #[error("`{capability_id}` is not a built-in capability")]
138 UseFromComponentManagerNotFound { capability_id: String },
139
140 #[error("`{capability_id}` is not a built-in capability")]
141 RegisterFromComponentManagerNotFound { capability_id: String },
142
143 #[error("`{capability_id}` is not a built-in capability")]
144 OfferFromComponentManagerNotFound { capability_id: String },
145
146 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
147 UseFromParentNotFound { moniker: Moniker, capability_id: String },
148
149 #[error("`{capability_id}` was not declared as a capability by `{moniker}`")]
150 UseFromSelfNotFound { moniker: Moniker, capability_id: String },
151
152 #[error("`{moniker}` does not have child `#{child_moniker}`")]
153 UseFromChildInstanceNotFound {
154 child_moniker: ChildName,
155 moniker: Moniker,
156 capability_id: String,
157 },
158
159 #[error(
160 "{capability_type} `{capability_name}` was not registered in environment of `{moniker}`"
161 )]
162 UseFromEnvironmentNotFound { moniker: Moniker, capability_type: String, capability_name: Name },
163
164 #[error(
165 "`{moniker}` tried to use {capability_type} `{capability_name}` from the root environment"
166 )]
167 UseFromRootEnvironmentNotAllowed {
168 moniker: Moniker,
169 capability_type: String,
170 capability_name: Name,
171 },
172
173 #[error("{capability_type} `{capability_name}` was not offered to `{moniker}` by parent")]
174 EnvironmentFromParentNotFound {
175 moniker: Moniker,
176 capability_type: String,
177 capability_name: Name,
178 },
179
180 #[error("`{capability_name}` was not exposed to `{moniker}` from `#{child_moniker}`")]
181 EnvironmentFromChildExposeNotFound {
182 child_moniker: ChildName,
183 moniker: Moniker,
184 capability_type: String,
185 capability_name: Name,
186 },
187
188 #[error("`{moniker}` does not have child `#{child_moniker}`")]
189 EnvironmentFromChildInstanceNotFound {
190 child_moniker: ChildName,
191 moniker: Moniker,
192 capability_name: Name,
193 capability_type: String,
194 },
195
196 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
197 OfferFromParentNotFound { moniker: Moniker, capability_id: String },
198
199 #[error(
200 "cannot offer `{capability_id}` because was not declared as a capability by `{moniker}`"
201 )]
202 OfferFromSelfNotFound { moniker: Moniker, capability_id: String },
203
204 #[error("`{capability_id}` was not offered to `{moniker}` by parent")]
205 StorageFromParentNotFound { moniker: Moniker, capability_id: String },
206
207 #[error("`{moniker}` does not have child `#{child_moniker}`")]
208 OfferFromChildInstanceNotFound {
209 child_moniker: ChildName,
210 moniker: Moniker,
211 capability_id: String,
212 },
213
214 #[error("`{moniker}` does not have collection `#{collection}`")]
215 OfferFromCollectionNotFound { collection: String, moniker: Moniker, capability: Name },
216
217 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
218 OfferFromChildExposeNotFound {
219 child_moniker: ChildName,
220 moniker: Moniker,
221 capability_id: String,
222 },
223
224 #[error("`{capability_id}` is not a framework capability (at component `{moniker}`)")]
226 CapabilityFromFrameworkNotFound { moniker: Moniker, capability_id: String },
227
228 #[error(
229 "A capability was sourced to a base capability `{capability_id}` from `{moniker}`, but this is unsupported"
230 )]
231 CapabilityFromCapabilityNotFound { moniker: Moniker, capability_id: String },
232
233 #[error("`{capability_id}` is not a framework capability")]
235 CapabilityFromComponentManagerNotFound { capability_id: String },
236
237 #[error(
238 "unable to expose `{capability_id}` because it was not declared as a capability by `{moniker}`"
239 )]
240 ExposeFromSelfNotFound { moniker: Moniker, capability_id: String },
241
242 #[error("`{moniker}` does not have child `#{child_moniker}`")]
243 ExposeFromChildInstanceNotFound {
244 child_moniker: ChildName,
245 moniker: Moniker,
246 capability_id: String,
247 },
248
249 #[error("`{moniker}` does not have collection `#{collection}`")]
250 ExposeFromCollectionNotFound { collection: String, moniker: Moniker, capability: Name },
251
252 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
253 ExposeFromChildExposeNotFound {
254 child_moniker: ChildName,
255 moniker: Moniker,
256 capability_id: String,
257 },
258
259 #[error(
260 "`{moniker}` tried to expose `{capability_id}` from the framework, but no such framework capability was found"
261 )]
262 ExposeFromFrameworkNotFound { moniker: Moniker, capability_id: String },
263
264 #[error("`{capability_id}` was not exposed to `{moniker}` from `#{child_moniker}`")]
265 UseFromChildExposeNotFound { child_moniker: ChildName, moniker: Moniker, capability_id: String },
266
267 #[error("`{capability_id}` was not exposed from `/`")]
268 UseFromRootExposeNotFound { capability_id: String },
269
270 #[error("routing a capability from an unsupported source type `{source_type}` at `{moniker}`")]
271 UnsupportedRouteSource { source_type: String, moniker: ExtendedMoniker },
272
273 #[error("routing a capability of an unsupported type `{type_name}` at `{moniker}`")]
274 UnsupportedCapabilityType { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
275
276 #[error(
277 "dictionaries are not yet supported for {cap_type} capabilities at component `{moniker}`"
278 )]
279 DictionariesNotSupported { moniker: Moniker, cap_type: CapabilityTypeName },
280
281 #[error("dynamic dictionaries are not allowed at component `{moniker}`")]
282 DynamicDictionariesNotAllowed { moniker: Moniker },
283
284 #[error("the capability does not support member access at `{moniker}`")]
285 BedrockMemberAccessUnsupported { moniker: ExtendedMoniker },
286
287 #[error("item `{name}` is not present in dictionary at component `{moniker}`")]
288 BedrockNotPresentInDictionary { name: String, moniker: ExtendedMoniker },
289
290 #[error(
291 "routed capability was the wrong type at component `{moniker}`. Was: {actual}, expected: {expected}"
292 )]
293 BedrockWrongCapabilityType { actual: String, expected: String, moniker: ExtendedMoniker },
294
295 #[error(
296 "expected type {type_name} for routed capability at component `{moniker}`, but type was missing"
297 )]
298 BedrockMissingCapabilityType { type_name: String, moniker: ExtendedMoniker },
299
300 #[error("there was an error remoting a capability at component `{moniker}`")]
301 BedrockRemoteCapability { moniker: Moniker },
302
303 #[error("source dictionary was not found in child's exposes at component `{moniker}`")]
304 BedrockSourceDictionaryExposeNotFound { moniker: Moniker },
305
306 #[error("Some capability in the routing chain could not be cloned at `{moniker}`.")]
307 BedrockNotCloneable { moniker: ExtendedMoniker },
308
309 #[error(
310 "a capability in a dictionary extended from a source dictionary collides with \
311 a capability in the source dictionary that has the same key at `{moniker}`"
312 )]
313 BedrockSourceDictionaryCollision { moniker: ExtendedMoniker },
314
315 #[error("failed to send message for capability `{capability_id}` from component `{moniker}`")]
316 BedrockFailedToSend { moniker: ExtendedMoniker, capability_id: String },
317
318 #[error(
319 "failed to route capability because the route source has been shutdown and possibly destroyed"
320 )]
321 RouteSourceShutdown { moniker: Moniker },
322
323 #[error(transparent)]
324 ComponentInstanceError(#[from] ComponentInstanceError),
325
326 #[error(transparent)]
327 EventsRoutingError(#[from] EventsRoutingError),
328
329 #[error(transparent)]
330 RightsRoutingError(#[from] RightsRoutingError),
331
332 #[error(transparent)]
333 AvailabilityRoutingError(#[from] AvailabilityRoutingError),
334
335 #[error(transparent)]
336 PolicyError(#[from] PolicyError),
337
338 #[error(
339 "source capability at component {moniker} is void. \
340 If the offer/expose declaration has `source_availability` set to `unknown`, \
341 the source component instance likely isn't defined in the component declaration"
342 )]
343 SourceCapabilityIsVoid { moniker: Moniker },
344
345 #[error(
346 "routes that do not set the `debug` flag are unsupported in the current configuration (at `{moniker}`)."
347 )]
348 NonDebugRoutesUnsupported { moniker: ExtendedMoniker },
349
350 #[error("debug routes are unsupported for external routers (at `{moniker}`).")]
351 DebugRoutesUnsupported { moniker: ExtendedMoniker },
352
353 #[error("{type_name} router unexpectedly returned debug info for target {moniker}")]
354 RouteUnexpectedDebug { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
355
356 #[error("{type_name} router unexpectedly returned unavailable for target {moniker}")]
357 RouteUnexpectedUnavailable { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
358
359 #[error("{name} at {moniker} is missing porcelain type metadata.")]
360 MissingPorcelainType { name: Name, moniker: Moniker },
361
362 #[error("path at `{moniker}` was too long for `{keyword}`: {path}")]
363 PathTooLong { moniker: ExtendedMoniker, path: String, keyword: String },
364}
365
366impl Explain for RoutingError {
367 fn as_zx_status(&self) -> zx::Status {
369 match self {
370 RoutingError::UseFromRootEnvironmentNotAllowed { .. }
371 | RoutingError::DynamicDictionariesNotAllowed { .. } => zx::Status::ACCESS_DENIED,
372 RoutingError::StorageFromChildExposeNotFound { .. }
373 | RoutingError::ComponentNotInIdIndex { .. }
374 | RoutingError::UseFromComponentManagerNotFound { .. }
375 | RoutingError::RegisterFromComponentManagerNotFound { .. }
376 | RoutingError::OfferFromComponentManagerNotFound { .. }
377 | RoutingError::UseFromParentNotFound { .. }
378 | RoutingError::UseFromSelfNotFound { .. }
379 | RoutingError::UseFromChildInstanceNotFound { .. }
380 | RoutingError::UseFromEnvironmentNotFound { .. }
381 | RoutingError::EnvironmentFromParentNotFound { .. }
382 | RoutingError::EnvironmentFromChildExposeNotFound { .. }
383 | RoutingError::EnvironmentFromChildInstanceNotFound { .. }
384 | RoutingError::OfferFromParentNotFound { .. }
385 | RoutingError::OfferFromSelfNotFound { .. }
386 | RoutingError::StorageFromParentNotFound { .. }
387 | RoutingError::OfferFromChildInstanceNotFound { .. }
388 | RoutingError::OfferFromCollectionNotFound { .. }
389 | RoutingError::OfferFromChildExposeNotFound { .. }
390 | RoutingError::CapabilityFromFrameworkNotFound { .. }
391 | RoutingError::CapabilityFromCapabilityNotFound { .. }
392 | RoutingError::CapabilityFromComponentManagerNotFound { .. }
393 | RoutingError::ExposeFromSelfNotFound { .. }
394 | RoutingError::ExposeFromChildInstanceNotFound { .. }
395 | RoutingError::ExposeFromCollectionNotFound { .. }
396 | RoutingError::ExposeFromChildExposeNotFound { .. }
397 | RoutingError::ExposeFromFrameworkNotFound { .. }
398 | RoutingError::UseFromChildExposeNotFound { .. }
399 | RoutingError::UseFromRootExposeNotFound { .. }
400 | RoutingError::UnsupportedRouteSource { .. }
401 | RoutingError::UnsupportedCapabilityType { .. }
402 | RoutingError::EventsRoutingError(_)
403 | RoutingError::BedrockNotPresentInDictionary { .. }
404 | RoutingError::BedrockSourceDictionaryExposeNotFound { .. }
405 | RoutingError::BedrockSourceDictionaryCollision { .. }
406 | RoutingError::BedrockFailedToSend { .. }
407 | RoutingError::RouteSourceShutdown { .. }
408 | RoutingError::BedrockMissingCapabilityType { .. }
409 | RoutingError::BedrockWrongCapabilityType { .. }
410 | RoutingError::BedrockRemoteCapability { .. }
411 | RoutingError::BedrockNotCloneable { .. }
412 | RoutingError::AvailabilityRoutingError(_)
413 | RoutingError::PathTooLong { .. } => zx::Status::NOT_FOUND,
414 RoutingError::BedrockMemberAccessUnsupported { .. }
415 | RoutingError::NonDebugRoutesUnsupported { .. }
416 | RoutingError::DebugRoutesUnsupported { .. }
417 | RoutingError::DictionariesNotSupported { .. } => zx::Status::NOT_SUPPORTED,
418 RoutingError::ComponentInstanceError(err) => err.as_zx_status(),
419 RoutingError::RightsRoutingError(err) => err.as_zx_status(),
420 RoutingError::PolicyError(err) => err.as_zx_status(),
421 RoutingError::SourceCapabilityIsVoid { .. } => zx::Status::NOT_FOUND,
422 RoutingError::RouteUnexpectedDebug { .. }
423 | RoutingError::RouteUnexpectedUnavailable { .. }
424 | RoutingError::MissingPorcelainType { .. } => zx::Status::INTERNAL,
425 }
426 }
427}
428
429impl From<RoutingError> for ExtendedMoniker {
430 fn from(err: RoutingError) -> ExtendedMoniker {
431 match err {
432 RoutingError::BedrockRemoteCapability { moniker, .. }
433 | RoutingError::BedrockSourceDictionaryExposeNotFound { moniker, .. }
434 | RoutingError::CapabilityFromCapabilityNotFound { moniker, .. }
435 | RoutingError::CapabilityFromFrameworkNotFound { moniker, .. }
436 | RoutingError::ComponentNotInIdIndex { source_moniker: moniker, .. }
437 | RoutingError::DictionariesNotSupported { moniker, .. }
438 | RoutingError::EnvironmentFromChildExposeNotFound { moniker, .. }
439 | RoutingError::EnvironmentFromChildInstanceNotFound { moniker, .. }
440 | RoutingError::EnvironmentFromParentNotFound { moniker, .. }
441 | RoutingError::ExposeFromChildExposeNotFound { moniker, .. }
442 | RoutingError::ExposeFromChildInstanceNotFound { moniker, .. }
443 | RoutingError::ExposeFromCollectionNotFound { moniker, .. }
444 | RoutingError::ExposeFromFrameworkNotFound { moniker, .. }
445 | RoutingError::ExposeFromSelfNotFound { moniker, .. }
446 | RoutingError::OfferFromChildExposeNotFound { moniker, .. }
447 | RoutingError::OfferFromChildInstanceNotFound { moniker, .. }
448 | RoutingError::OfferFromCollectionNotFound { moniker, .. }
449 | RoutingError::OfferFromParentNotFound { moniker, .. }
450 | RoutingError::OfferFromSelfNotFound { moniker, .. }
451 | RoutingError::SourceCapabilityIsVoid { moniker, .. }
452 | RoutingError::StorageFromChildExposeNotFound { moniker, .. }
453 | RoutingError::StorageFromParentNotFound { moniker, .. }
454 | RoutingError::UseFromChildExposeNotFound { moniker, .. }
455 | RoutingError::UseFromChildInstanceNotFound { moniker, .. }
456 | RoutingError::UseFromEnvironmentNotFound { moniker, .. }
457 | RoutingError::UseFromParentNotFound { moniker, .. }
458 | RoutingError::UseFromRootEnvironmentNotAllowed { moniker, .. }
459 | RoutingError::DynamicDictionariesNotAllowed { moniker, .. }
460 | RoutingError::RouteSourceShutdown { moniker }
461 | RoutingError::UseFromSelfNotFound { moniker, .. }
462 | RoutingError::MissingPorcelainType { moniker, .. } => moniker.into(),
463 RoutingError::PathTooLong { moniker, .. } => moniker,
464
465 RoutingError::BedrockMemberAccessUnsupported { moniker }
466 | RoutingError::BedrockNotPresentInDictionary { moniker, .. }
467 | RoutingError::BedrockNotCloneable { moniker }
468 | RoutingError::BedrockSourceDictionaryCollision { moniker }
469 | RoutingError::BedrockFailedToSend { moniker, .. }
470 | RoutingError::BedrockMissingCapabilityType { moniker, .. }
471 | RoutingError::BedrockWrongCapabilityType { moniker, .. }
472 | RoutingError::NonDebugRoutesUnsupported { moniker }
473 | RoutingError::DebugRoutesUnsupported { moniker }
474 | RoutingError::RouteUnexpectedDebug { moniker, .. }
475 | RoutingError::RouteUnexpectedUnavailable { moniker, .. }
476 | RoutingError::UnsupportedCapabilityType { moniker, .. }
477 | RoutingError::UnsupportedRouteSource { moniker, .. } => moniker,
478 RoutingError::AvailabilityRoutingError(err) => err.into(),
479 RoutingError::ComponentInstanceError(err) => err.into(),
480 RoutingError::EventsRoutingError(err) => err.into(),
481 RoutingError::PolicyError(err) => err.into(),
482 RoutingError::RightsRoutingError(err) => err.into(),
483
484 RoutingError::CapabilityFromComponentManagerNotFound { .. }
485 | RoutingError::OfferFromComponentManagerNotFound { .. }
486 | RoutingError::RegisterFromComponentManagerNotFound { .. }
487 | RoutingError::UseFromComponentManagerNotFound { .. }
488 | RoutingError::UseFromRootExposeNotFound { .. } => ExtendedMoniker::ComponentManager,
489 }
490 }
491}
492
493impl From<RoutingError> for RouterError {
494 fn from(value: RoutingError) -> Self {
495 Self::NotFound(Arc::new(value))
496 }
497}
498
499impl From<RouterError> for RoutingError {
500 fn from(value: RouterError) -> Self {
501 match value {
502 RouterError::NotFound(arc_dyn_explain) => {
503 arc_dyn_explain.downcast_for_test::<Self>().clone()
504 }
505 err => panic!("Cannot downcast {err} to RoutingError!"),
506 }
507 }
508}
509
510impl RoutingError {
511 pub fn as_fidl_error(&self) -> fcomponent::Error {
513 fcomponent::Error::ResourceUnavailable
514 }
515
516 pub fn storage_from_child_expose_not_found(
517 child_moniker: &ChildName,
518 moniker: &Moniker,
519 capability_id: impl Into<String>,
520 ) -> Self {
521 Self::StorageFromChildExposeNotFound {
522 child_moniker: child_moniker.clone(),
523 moniker: moniker.clone(),
524 capability_id: capability_id.into(),
525 }
526 }
527
528 pub fn use_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
529 Self::UseFromComponentManagerNotFound { capability_id: capability_id.into() }
530 }
531
532 pub fn register_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
533 Self::RegisterFromComponentManagerNotFound { capability_id: capability_id.into() }
534 }
535
536 pub fn offer_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
537 Self::OfferFromComponentManagerNotFound { capability_id: capability_id.into() }
538 }
539
540 pub fn use_from_parent_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
541 Self::UseFromParentNotFound {
542 moniker: moniker.clone(),
543 capability_id: capability_id.into(),
544 }
545 }
546
547 pub fn use_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
548 Self::UseFromSelfNotFound { moniker: moniker.clone(), capability_id: capability_id.into() }
549 }
550
551 pub fn use_from_child_instance_not_found(
552 child_moniker: &ChildName,
553 moniker: &Moniker,
554 capability_id: impl Into<String>,
555 ) -> Self {
556 Self::UseFromChildInstanceNotFound {
557 child_moniker: child_moniker.clone(),
558 moniker: moniker.clone(),
559 capability_id: capability_id.into(),
560 }
561 }
562
563 pub fn use_from_environment_not_found(
564 moniker: &Moniker,
565 capability_type: impl Into<String>,
566 capability_name: &Name,
567 ) -> Self {
568 Self::UseFromEnvironmentNotFound {
569 moniker: moniker.clone(),
570 capability_type: capability_type.into(),
571 capability_name: capability_name.clone(),
572 }
573 }
574
575 pub fn offer_from_parent_not_found(
576 moniker: &Moniker,
577 capability_id: impl Into<String>,
578 ) -> Self {
579 Self::OfferFromParentNotFound {
580 moniker: moniker.clone(),
581 capability_id: capability_id.into(),
582 }
583 }
584
585 pub fn offer_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
586 Self::OfferFromSelfNotFound {
587 moniker: moniker.clone(),
588 capability_id: capability_id.into(),
589 }
590 }
591
592 pub fn storage_from_parent_not_found(
593 moniker: &Moniker,
594 capability_id: impl Into<String>,
595 ) -> Self {
596 Self::StorageFromParentNotFound {
597 moniker: moniker.clone(),
598 capability_id: capability_id.into(),
599 }
600 }
601
602 pub fn offer_from_child_instance_not_found(
603 child_moniker: &ChildName,
604 moniker: &Moniker,
605 capability_id: impl Into<String>,
606 ) -> Self {
607 Self::OfferFromChildInstanceNotFound {
608 child_moniker: child_moniker.clone(),
609 moniker: moniker.clone(),
610 capability_id: capability_id.into(),
611 }
612 }
613
614 pub fn offer_from_child_expose_not_found(
615 child_moniker: &ChildName,
616 moniker: &Moniker,
617 capability_id: impl Into<String>,
618 ) -> Self {
619 Self::OfferFromChildExposeNotFound {
620 child_moniker: child_moniker.clone(),
621 moniker: moniker.clone(),
622 capability_id: capability_id.into(),
623 }
624 }
625
626 pub fn use_from_child_expose_not_found(
627 child_moniker: &ChildName,
628 moniker: &Moniker,
629 capability_id: impl Into<String>,
630 ) -> Self {
631 Self::UseFromChildExposeNotFound {
632 child_moniker: child_moniker.clone(),
633 moniker: moniker.clone(),
634 capability_id: capability_id.into(),
635 }
636 }
637
638 pub fn expose_from_self_not_found(moniker: &Moniker, capability_id: impl Into<String>) -> Self {
639 Self::ExposeFromSelfNotFound {
640 moniker: moniker.clone(),
641 capability_id: capability_id.into(),
642 }
643 }
644
645 pub fn expose_from_child_instance_not_found(
646 child_moniker: &ChildName,
647 moniker: &Moniker,
648 capability_id: impl Into<String>,
649 ) -> Self {
650 Self::ExposeFromChildInstanceNotFound {
651 child_moniker: child_moniker.clone(),
652 moniker: moniker.clone(),
653 capability_id: capability_id.into(),
654 }
655 }
656
657 pub fn expose_from_child_expose_not_found(
658 child_moniker: &ChildName,
659 moniker: &Moniker,
660 capability_id: impl Into<String>,
661 ) -> Self {
662 Self::ExposeFromChildExposeNotFound {
663 child_moniker: child_moniker.clone(),
664 moniker: moniker.clone(),
665 capability_id: capability_id.into(),
666 }
667 }
668
669 pub fn capability_from_framework_not_found(
670 moniker: &Moniker,
671 capability_id: impl Into<String>,
672 ) -> Self {
673 Self::CapabilityFromFrameworkNotFound {
674 moniker: moniker.clone(),
675 capability_id: capability_id.into(),
676 }
677 }
678
679 pub fn capability_from_capability_not_found(
680 moniker: &Moniker,
681 capability_id: impl Into<String>,
682 ) -> Self {
683 Self::CapabilityFromCapabilityNotFound {
684 moniker: moniker.clone(),
685 capability_id: capability_id.into(),
686 }
687 }
688
689 pub fn capability_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
690 Self::CapabilityFromComponentManagerNotFound { capability_id: capability_id.into() }
691 }
692
693 pub fn expose_from_framework_not_found(
694 moniker: &Moniker,
695 capability_id: impl Into<String>,
696 ) -> Self {
697 Self::ExposeFromFrameworkNotFound {
698 moniker: moniker.clone(),
699 capability_id: capability_id.into(),
700 }
701 }
702
703 pub fn unsupported_route_source(
704 moniker: impl Into<ExtendedMoniker>,
705 source: impl Into<String>,
706 ) -> Self {
707 Self::UnsupportedRouteSource { source_type: source.into(), moniker: moniker.into() }
708 }
709
710 pub fn unsupported_capability_type(
711 moniker: impl Into<ExtendedMoniker>,
712 type_name: impl Into<CapabilityTypeName>,
713 ) -> Self {
714 Self::UnsupportedCapabilityType { type_name: type_name.into(), moniker: moniker.into() }
715 }
716}
717
718#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
720#[derive(Error, Debug, Clone, PartialEq)]
721pub enum EventsRoutingError {
722 #[error("filter is not a subset at `{moniker}`")]
723 InvalidFilter { moniker: ExtendedMoniker },
724
725 #[error("event routes must end at source with a filter declaration at `{moniker}`")]
726 MissingFilter { moniker: ExtendedMoniker },
727}
728
729impl From<EventsRoutingError> for ExtendedMoniker {
730 fn from(err: EventsRoutingError) -> ExtendedMoniker {
731 match err {
732 EventsRoutingError::InvalidFilter { moniker }
733 | EventsRoutingError::MissingFilter { moniker } => moniker,
734 }
735 }
736}
737
738#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
739#[derive(Debug, Error, Clone, PartialEq)]
740pub enum RightsRoutingError {
741 #[error(
742 "requested rights ({requested}) greater than provided rights ({provided}) at \"{moniker}\""
743 )]
744 Invalid { moniker: ExtendedMoniker, requested: Rights, provided: Rights },
745
746 #[error(
747 "directory routes must end at source with a rights declaration, it's missing at \"{moniker}\""
748 )]
749 MissingRightsSource { moniker: ExtendedMoniker },
750}
751
752impl RightsRoutingError {
753 pub fn as_zx_status(&self) -> zx::Status {
755 match self {
756 RightsRoutingError::Invalid { .. } => zx::Status::ACCESS_DENIED,
757 RightsRoutingError::MissingRightsSource { .. } => zx::Status::NOT_FOUND,
758 }
759 }
760}
761
762impl From<RightsRoutingError> for ExtendedMoniker {
763 fn from(err: RightsRoutingError) -> ExtendedMoniker {
764 match err {
765 RightsRoutingError::Invalid { moniker, .. }
766 | RightsRoutingError::MissingRightsSource { moniker } => moniker,
767 }
768 }
769}
770
771#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
772#[derive(Debug, Error, Clone, PartialEq)]
773pub enum AvailabilityRoutingError {
774 #[error(
775 "availability requested by the target has stronger guarantees than what \
776 is being provided at the source at `{moniker}`"
777 )]
778 TargetHasStrongerAvailability { moniker: ExtendedMoniker },
779
780 #[error("offer uses void source, but target requires the capability at `{moniker}`")]
781 OfferFromVoidToRequiredTarget { moniker: ExtendedMoniker },
782
783 #[error("expose uses void source, but target requires the capability at `{moniker}`")]
784 ExposeFromVoidToRequiredTarget { moniker: ExtendedMoniker },
785}
786
787impl From<availability::TargetHasStrongerAvailability> for AvailabilityRoutingError {
788 fn from(value: availability::TargetHasStrongerAvailability) -> Self {
789 let availability::TargetHasStrongerAvailability { moniker } = value;
790 AvailabilityRoutingError::TargetHasStrongerAvailability { moniker }
791 }
792}
793
794impl From<AvailabilityRoutingError> for ExtendedMoniker {
795 fn from(err: AvailabilityRoutingError) -> ExtendedMoniker {
796 match err {
797 AvailabilityRoutingError::ExposeFromVoidToRequiredTarget { moniker }
798 | AvailabilityRoutingError::OfferFromVoidToRequiredTarget { moniker }
799 | AvailabilityRoutingError::TargetHasStrongerAvailability { moniker } => moniker,
800 }
801 }
802}
803
804#[async_trait]
807pub trait ErrorReporter: Clone + Send + Sync + 'static {
808 async fn report(
809 &self,
810 request: &RouteRequestErrorInfo,
811 err: &RouterError,
812 route_target: sandbox::WeakInstanceToken,
813 );
814}
815
816pub struct RouteRequestErrorInfo {
818 capability_type: cm_rust::CapabilityTypeName,
819 name: cm_types::Name,
820 availability: cm_rust::Availability,
821}
822
823impl RouteRequestErrorInfo {
824 pub fn availability(&self) -> cm_rust::Availability {
825 self.availability
826 }
827
828 pub fn for_builtin(capability_type: CapabilityTypeName, name: &Name) -> Self {
829 Self { capability_type, name: name.clone(), availability: Availability::Required }
830 }
831}
832
833impl From<&cm_rust::UseDecl> for RouteRequestErrorInfo {
834 fn from(value: &cm_rust::UseDecl) -> Self {
835 RouteRequestErrorInfo {
836 capability_type: value.into(),
837 name: value.source_name().clone(),
838 availability: value.availability().clone(),
839 }
840 }
841}
842
843impl From<&cm_rust::UseConfigurationDecl> for RouteRequestErrorInfo {
844 fn from(value: &cm_rust::UseConfigurationDecl) -> Self {
845 RouteRequestErrorInfo {
846 capability_type: CapabilityTypeName::Config,
847 name: value.source_name().clone(),
848 availability: value.availability().clone(),
849 }
850 }
851}
852
853impl From<&cm_rust::UseEventStreamDecl> for RouteRequestErrorInfo {
854 fn from(value: &cm_rust::UseEventStreamDecl) -> Self {
855 RouteRequestErrorInfo {
856 capability_type: CapabilityTypeName::EventStream,
857 name: value.source_name.clone(),
858 availability: value.availability,
859 }
860 }
861}
862
863impl From<&cm_rust::ExposeDecl> for RouteRequestErrorInfo {
864 fn from(value: &cm_rust::ExposeDecl) -> Self {
865 RouteRequestErrorInfo {
866 capability_type: value.into(),
867 name: value.target_name().clone(),
868 availability: value.availability().clone(),
869 }
870 }
871}
872
873impl From<&cm_rust::OfferDecl> for RouteRequestErrorInfo {
874 fn from(value: &cm_rust::OfferDecl) -> Self {
875 RouteRequestErrorInfo {
876 capability_type: value.into(),
877 name: value.target_name().clone(),
878 availability: value.availability().clone(),
879 }
880 }
881}
882
883impl From<&cm_rust::ResolverRegistration> for RouteRequestErrorInfo {
884 fn from(value: &cm_rust::ResolverRegistration) -> Self {
885 RouteRequestErrorInfo {
886 capability_type: CapabilityTypeName::Resolver,
887 name: value.source_name().clone(),
888 availability: Availability::Required,
889 }
890 }
891}
892
893impl From<&cm_rust::RunnerRegistration> for RouteRequestErrorInfo {
894 fn from(value: &cm_rust::RunnerRegistration) -> Self {
895 RouteRequestErrorInfo {
896 capability_type: CapabilityTypeName::Runner,
897 name: value.source_name().clone(),
898 availability: Availability::Required,
899 }
900 }
901}
902
903impl From<&cm_rust::DebugRegistration> for RouteRequestErrorInfo {
904 fn from(value: &cm_rust::DebugRegistration) -> Self {
905 RouteRequestErrorInfo {
906 capability_type: CapabilityTypeName::Protocol,
907 name: value.source_name().clone(),
908 availability: Availability::Required,
909 }
910 }
911}
912
913impl From<&cm_rust::CapabilityDecl> for RouteRequestErrorInfo {
914 fn from(value: &cm_rust::CapabilityDecl) -> Self {
915 RouteRequestErrorInfo {
916 capability_type: value.into(),
917 name: value.name().clone(),
918 availability: Availability::Required,
919 }
920 }
921}
922
923impl std::fmt::Display for RouteRequestErrorInfo {
924 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
925 write!(f, "{} `{}`", self.capability_type, self.name)
926 }
927}