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