1use crate::policy::PolicyError;
6use crate::rights::Rights;
7use async_trait::async_trait;
8use clonable_error::ClonableError;
9use cm_rust::offer::OfferDeclCommon;
10use cm_rust::{CapabilityTypeName, ExposeDeclCommon, GenericRef, SourceName, UseDeclCommon};
11use cm_types::{Availability, Name, RelativePath};
12use fidl_fuchsia_component as fcomponent;
13use itertools::Itertools;
14use moniker::{ChildName, ExtendedMoniker, Moniker};
15use router_error::{Explain, RouterError};
16use std::sync::Arc;
17use thiserror::Error;
18use zx_status as zx;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
25#[derive(Debug, Error, Clone)]
26pub enum ComponentInstanceError {
27 #[error("could not find `{moniker}`")]
28 InstanceNotFound { moniker: Moniker },
29 #[error("component is not executable `{moniker}`")]
30 InstanceNotExecutable { moniker: Moniker },
31 #[error("component manager instance unavailable")]
32 ComponentManagerInstanceUnavailable {},
33 #[error("expected a component instance, but got component manager's instance")]
34 ComponentManagerInstanceUnexpected {},
35 #[error("malformed url `{url}` for `{moniker}`")]
36 MalformedUrl { url: String, moniker: Moniker },
37 #[error("url `{url}` for `{moniker}` does not resolve to an absolute url")]
38 NoAbsoluteUrl { url: String, moniker: Moniker },
39 #[cfg_attr(feature = "serde", serde(skip))]
42 #[error("failed to resolve `{moniker}`:\n\t{err}")]
43 ResolveFailed {
44 moniker: Moniker,
45 #[source]
46 err: ClonableError,
47 },
48 #[cfg_attr(feature = "serde", serde(skip))]
51 #[error("failed to start `{moniker}`:\n\t{err_msg}")]
52 StartFailed {
53 moniker: Moniker,
54 err_msg: String,
58 err_as_zx: zx::Status,
59 },
60 #[error("failed to create storage for `{moniker}`:\n\t{err_msg}")]
61 FailedToCreateStorage { moniker: Moniker, err_msg: String },
62}
63
64impl ComponentInstanceError {
65 pub fn as_zx_status(&self) -> zx::Status {
66 match self {
67 ComponentInstanceError::ResolveFailed { .. }
68 | ComponentInstanceError::InstanceNotFound { .. }
69 | ComponentInstanceError::ComponentManagerInstanceUnavailable {}
70 | ComponentInstanceError::InstanceNotExecutable { .. }
71 | ComponentInstanceError::NoAbsoluteUrl { .. }
72 | ComponentInstanceError::FailedToCreateStorage { .. } => zx::Status::NOT_FOUND,
73 ComponentInstanceError::StartFailed { err_as_zx, .. } => *err_as_zx,
74 ComponentInstanceError::MalformedUrl { .. }
75 | ComponentInstanceError::ComponentManagerInstanceUnexpected { .. } => {
76 zx::Status::INTERNAL
77 }
78 }
79 }
80
81 pub fn instance_not_found(moniker: Moniker) -> ComponentInstanceError {
82 ComponentInstanceError::InstanceNotFound { moniker }
83 }
84
85 pub fn cm_instance_unavailable() -> ComponentInstanceError {
86 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
87 }
88
89 pub fn resolve_failed(moniker: Moniker, err: impl Into<anyhow::Error>) -> Self {
90 Self::ResolveFailed { moniker, err: err.into().into() }
91 }
92}
93
94impl Explain for ComponentInstanceError {
95 fn as_zx_status(&self) -> zx::Status {
96 self.as_zx_status()
97 }
98}
99
100impl From<ComponentInstanceError> for ExtendedMoniker {
101 fn from(err: ComponentInstanceError) -> ExtendedMoniker {
102 match err {
103 ComponentInstanceError::InstanceNotFound { moniker }
104 | ComponentInstanceError::MalformedUrl { moniker, .. }
105 | ComponentInstanceError::NoAbsoluteUrl { moniker, .. }
106 | ComponentInstanceError::InstanceNotExecutable { moniker }
107 | ComponentInstanceError::ResolveFailed { moniker, .. }
108 | ComponentInstanceError::StartFailed { moniker, .. }
109 | ComponentInstanceError::FailedToCreateStorage { moniker, .. } => {
110 ExtendedMoniker::ComponentInstance(moniker)
111 }
112 ComponentInstanceError::ComponentManagerInstanceUnavailable {}
113 | ComponentInstanceError::ComponentManagerInstanceUnexpected {} => {
114 ExtendedMoniker::ComponentManager
115 }
116 }
117 }
118}
119
120impl PartialEq for ComponentInstanceError {
123 fn eq(&self, other: &Self) -> bool {
124 match (self, other) {
125 (
126 Self::InstanceNotFound { moniker: self_moniker },
127 Self::InstanceNotFound { moniker: other_moniker },
128 ) => self_moniker.eq(other_moniker),
129 (
130 Self::ComponentManagerInstanceUnavailable {},
131 Self::ComponentManagerInstanceUnavailable {},
132 ) => true,
133 (Self::ResolveFailed { .. }, Self::ResolveFailed { .. }) => false,
134 _ => false,
135 }
136 }
137}
138
139#[derive(Clone, Copy, Debug, PartialEq)]
140#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
141pub enum RouteVerb {
142 Use,
143 Offer,
144 Expose,
145 Declare,
146 Contain,
147 Register,
148 IncludeInAggregate,
149}
150
151impl std::fmt::Display for RouteVerb {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 match self {
154 RouteVerb::Use => write!(f, "use"),
155 RouteVerb::Offer => write!(f, "offer"),
156 RouteVerb::Expose => write!(f, "expose"),
157 RouteVerb::Declare => write!(f, "declare"),
158 RouteVerb::Contain => write!(f, "contain"),
159 RouteVerb::Register => write!(f, "register in environment"),
160 RouteVerb::IncludeInAggregate => write!(f, "include in aggregate"),
161 }
162 }
163}
164
165impl From<&cm_rust::ExposeDecl> for RouteVerb {
166 fn from(_decl: &cm_rust::ExposeDecl) -> Self {
167 Self::Expose
168 }
169}
170
171impl From<&cm_rust::OfferDecl> for RouteVerb {
172 fn from(_decl: &cm_rust::OfferDecl) -> Self {
173 Self::Offer
174 }
175}
176
177impl From<&cm_rust::UseDecl> for RouteVerb {
178 fn from(_decl: &cm_rust::UseDecl) -> Self {
179 Self::Use
180 }
181}
182
183impl From<&cm_rust::DebugRegistration> for RouteVerb {
184 fn from(_decl: &cm_rust::DebugRegistration) -> Self {
185 Self::Register
186 }
187}
188
189impl From<&cm_rust::RunnerRegistration> for RouteVerb {
190 fn from(_decl: &cm_rust::RunnerRegistration) -> Self {
191 Self::Register
192 }
193}
194
195impl From<&cm_rust::ResolverRegistration> for RouteVerb {
196 fn from(_decl: &cm_rust::ResolverRegistration) -> Self {
197 Self::Register
198 }
199}
200
201#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
203#[derive(Debug, Error, Clone, PartialEq)]
204pub enum RoutingError {
205 #[error(
206 "cannot {verb} {capability_type} {capability_name} from {source} at {moniker} because {source} does not {counter_verb} the capability"
207 )]
208 RouteSourceNotFound {
209 moniker: Moniker,
210 verb: RouteVerb,
211 counter_verb: RouteVerb,
212 source: GenericRef,
213 capability_type: CapabilityTypeName,
214 capability_name: RelativePath,
215 },
216
217 #[error("route request received by `{moniker}` is unexpectedly unset")]
218 RouteRequestUnset { moniker: ExtendedMoniker },
219
220 #[error(
221 "route request received by `{moniker}` has been rejected because the following field is unset: `{missing_field}`"
222 )]
223 RouteRequestMissingField { moniker: ExtendedMoniker, missing_field: String },
224
225 #[error(
226 "failed to parse field `{field}` in route request received by `{moniker}`: {parse_error}"
227 )]
228 RouteRequestFailedToParseField { moniker: ExtendedMoniker, field: String, parse_error: String },
229
230 #[error(
231 "`{target_name:?}` tried to use a storage capability from `{source_moniker}` but it is \
232 not in the component id index. https://fuchsia.dev/go/components/instance-id"
233 )]
234 ComponentNotInIdIndex { source_moniker: Moniker, target_name: Option<ChildName> },
235
236 #[error(
237 "`{moniker}` tried to use {capability_type} `{capability_name}` from the root environment"
238 )]
239 UseFromRootEnvironmentNotAllowed {
240 moniker: Moniker,
241 capability_type: String,
242 capability_name: Name,
243 },
244
245 #[error(
246 "`{moniker}` tried to expose `{capability_id}` from the framework, but no such framework capability was found"
247 )]
248 ExposeFromFrameworkNotFound { moniker: Moniker, capability_id: String },
249
250 #[error("`{capability_id}` was not exposed from `/`")]
251 UseFromRootExposeNotFound { capability_id: String },
252
253 #[error("routing a capability from an unsupported source type `{source_type}` at `{moniker}`")]
254 UnsupportedRouteSource { source_type: String, moniker: ExtendedMoniker },
255
256 #[error("routing a capability of an unsupported type `{type_name}` at `{moniker}`")]
257 UnsupportedCapabilityType { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
258
259 #[error("dynamic dictionaries are not allowed at component `{moniker}`")]
260 DynamicDictionariesNotAllowed { moniker: Moniker },
261
262 #[error("item `{name}` is not present in dictionary at component `{moniker}`")]
263 BedrockNotPresentInDictionary { name: String, moniker: ExtendedMoniker },
264
265 #[error(
266 "routed capability was the wrong type at component `{moniker}`. Was: {actual}, expected: {expected}"
267 )]
268 BedrockWrongCapabilityType { actual: String, expected: String, moniker: ExtendedMoniker },
269
270 #[error("failed to send message for capability `{capability_id}` from component `{moniker}`")]
271 BedrockFailedToSend { moniker: ExtendedMoniker, capability_id: String },
272
273 #[error(
274 "the source of capability `{capability_id}` at component `{moniker}` is unknown because we did not perform any routing tasks to find it"
275 )]
276 SourceUnknown { moniker: ExtendedMoniker, capability_id: String },
277
278 #[error(
279 "failed to route capability because the route source has been shutdown and possibly destroyed"
280 )]
281 RouteSourceShutdown { moniker: Moniker },
282
283 #[error(transparent)]
284 ComponentInstanceError(#[from] ComponentInstanceError),
285
286 #[error(transparent)]
287 EventsRoutingError(#[from] EventsRoutingError),
288
289 #[error(transparent)]
290 RightsRoutingError(#[from] RightsRoutingError),
291
292 #[error(transparent)]
293 AvailabilityRoutingError(#[from] AvailabilityRoutingError),
294
295 #[error(transparent)]
296 PolicyError(#[from] PolicyError),
297
298 #[error(
299 "source capability at component {moniker} is void. \
300 If the offer/expose declaration has `source_availability` set to `unknown`, \
301 the source component instance likely isn't defined in the component declaration"
302 )]
303 SourceCapabilityIsVoid { moniker: ExtendedMoniker },
304
305 #[error(
306 "routes that do not set the `debug` flag are unsupported in the current configuration (at `{moniker}`)."
307 )]
308 NonDebugRoutesUnsupported { moniker: ExtendedMoniker },
309
310 #[error("debug routes are unsupported for external routers (at `{moniker}`).")]
311 DebugRoutesUnsupported { moniker: ExtendedMoniker },
312
313 #[error("{type_name} router unexpectedly returned unavailable for target {moniker}")]
314 RouteUnexpectedUnavailable { type_name: CapabilityTypeName, moniker: ExtendedMoniker },
315
316 #[error("path at `{moniker}` was too long for `{keyword}`: {path}")]
317 PathTooLong { moniker: ExtendedMoniker, path: String, keyword: String },
318
319 #[error(
320 "conflicting dictionary entries detected component `{moniker}`: {}",
321 conflicting_names.iter().map(|n| format!("{}", n)).join(", ")
322 )]
323 ConflictingDictionaryEntries { moniker: ExtendedMoniker, conflicting_names: Vec<Name> },
324
325 #[error("FIDL error encountered while talking to a router implemented by component {moniker}")]
326 RemoteFIDLError { moniker: Moniker },
327
328 #[error("error returned by a router implemented by component {moniker}")]
330 RemoteRouterError { moniker: Moniker, error_code: i32 },
331}
332
333impl Explain for RoutingError {
334 fn as_zx_status(&self) -> zx::Status {
336 match self {
337 RoutingError::UseFromRootEnvironmentNotAllowed { .. }
338 | RoutingError::DynamicDictionariesNotAllowed { .. } => zx::Status::ACCESS_DENIED,
339 RoutingError::RouteRequestMissingField { .. }
340 | RoutingError::RouteRequestFailedToParseField { .. }
341 | RoutingError::RouteRequestUnset { .. }
342 | RoutingError::ComponentNotInIdIndex { .. }
343 | RoutingError::ConflictingDictionaryEntries { .. }
344 | RoutingError::ExposeFromFrameworkNotFound { .. }
345 | RoutingError::UseFromRootExposeNotFound { .. }
346 | RoutingError::UnsupportedRouteSource { .. }
347 | RoutingError::UnsupportedCapabilityType { .. }
348 | RoutingError::EventsRoutingError(_)
349 | RoutingError::BedrockNotPresentInDictionary { .. }
350 | RoutingError::BedrockFailedToSend { .. }
351 | RoutingError::SourceUnknown { .. }
352 | RoutingError::RouteSourceShutdown { .. }
353 | RoutingError::BedrockWrongCapabilityType { .. }
354 | RoutingError::SourceCapabilityIsVoid { .. }
355 | RoutingError::AvailabilityRoutingError(_)
356 | RoutingError::RouteSourceNotFound { .. }
357 | RoutingError::PathTooLong { .. } => zx::Status::NOT_FOUND,
358 RoutingError::NonDebugRoutesUnsupported { .. }
359 | RoutingError::DebugRoutesUnsupported { .. } => zx::Status::NOT_SUPPORTED,
360 RoutingError::ComponentInstanceError(err) => err.as_zx_status(),
361 RoutingError::RightsRoutingError(err) => err.as_zx_status(),
362 RoutingError::PolicyError(err) => err.as_zx_status(),
363 RoutingError::RouteUnexpectedUnavailable { .. } => zx::Status::INTERNAL,
364 RoutingError::RemoteFIDLError { .. } => zx::Status::PEER_CLOSED,
365 RoutingError::RemoteRouterError { error_code, .. } => {
366 zx::Status::err_from_raw(*error_code)
367 }
368 }
369 }
370}
371
372impl From<RoutingError> for ExtendedMoniker {
373 fn from(err: RoutingError) -> ExtendedMoniker {
374 match err {
375 RoutingError::ComponentNotInIdIndex { source_moniker: moniker, .. }
376 | RoutingError::ExposeFromFrameworkNotFound { moniker, .. }
377 | RoutingError::UseFromRootEnvironmentNotAllowed { moniker, .. }
378 | RoutingError::DynamicDictionariesNotAllowed { moniker, .. }
379 | RoutingError::RouteSourceShutdown { moniker }
380 | RoutingError::RemoteFIDLError { moniker }
381 | RoutingError::RouteSourceNotFound { moniker, .. }
382 | RoutingError::RemoteRouterError { moniker, .. } => moniker.into(),
383 RoutingError::PathTooLong { moniker, .. } => moniker,
384
385 RoutingError::BedrockNotPresentInDictionary { moniker, .. }
386 | RoutingError::BedrockFailedToSend { moniker, .. }
387 | RoutingError::SourceUnknown { moniker, .. }
388 | RoutingError::BedrockWrongCapabilityType { moniker, .. }
389 | RoutingError::RouteRequestMissingField { moniker, .. }
390 | RoutingError::RouteRequestFailedToParseField { moniker, .. }
391 | RoutingError::RouteRequestUnset { moniker, .. }
392 | RoutingError::SourceCapabilityIsVoid { moniker, .. }
393 | RoutingError::ConflictingDictionaryEntries { moniker, .. }
394 | RoutingError::NonDebugRoutesUnsupported { moniker }
395 | RoutingError::DebugRoutesUnsupported { moniker }
396 | RoutingError::RouteUnexpectedUnavailable { moniker, .. }
397 | RoutingError::UnsupportedCapabilityType { moniker, .. }
398 | RoutingError::UnsupportedRouteSource { moniker, .. } => moniker,
399 RoutingError::AvailabilityRoutingError(err) => err.into(),
400 RoutingError::ComponentInstanceError(err) => err.into(),
401 RoutingError::EventsRoutingError(err) => err.into(),
402 RoutingError::PolicyError(err) => err.into(),
403 RoutingError::RightsRoutingError(err) => err.into(),
404
405 RoutingError::UseFromRootExposeNotFound { .. } => ExtendedMoniker::ComponentManager,
406 }
407 }
408}
409
410impl From<RoutingError> for RouterError {
411 fn from(value: RoutingError) -> Self {
412 Self::NotFound(Arc::new(value))
413 }
414}
415
416impl TryFrom<RouterError> for RoutingError {
417 type Error = RouterError;
418
419 fn try_from(value: RouterError) -> Result<Self, Self::Error> {
420 match value {
421 RouterError::NotFound(arc_dyn_explain) => {
422 match arc_dyn_explain.as_any().downcast_ref::<Self>() {
423 Some(routing_error) => Ok(routing_error.clone()),
424 None => Err(RouterError::NotFound(arc_dyn_explain)),
425 }
426 }
427 err => Err(err),
428 }
429 }
430}
431
432impl RoutingError {
433 pub fn as_fidl_error(&self) -> fcomponent::Error {
435 fcomponent::Error::ResourceUnavailable
436 }
437
438 pub fn expose_from_framework_not_found(
439 moniker: &Moniker,
440 capability_id: impl Into<String>,
441 ) -> Self {
442 Self::ExposeFromFrameworkNotFound {
443 moniker: moniker.clone(),
444 capability_id: capability_id.into(),
445 }
446 }
447
448 pub fn unsupported_route_source(
449 moniker: impl Into<ExtendedMoniker>,
450 source: impl Into<String>,
451 ) -> Self {
452 Self::UnsupportedRouteSource { source_type: source.into(), moniker: moniker.into() }
453 }
454
455 pub fn unsupported_capability_type(
456 moniker: impl Into<ExtendedMoniker>,
457 type_name: impl Into<CapabilityTypeName>,
458 ) -> Self {
459 Self::UnsupportedCapabilityType { type_name: type_name.into(), moniker: moniker.into() }
460 }
461}
462
463#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
465#[derive(Error, Debug, Clone, PartialEq)]
466pub enum EventsRoutingError {
467 #[error("filter is not a subset at `{moniker}`")]
468 InvalidFilter { moniker: ExtendedMoniker },
469
470 #[error("event routes must end at source with a filter declaration at `{moniker}`")]
471 MissingFilter { moniker: ExtendedMoniker },
472}
473
474impl From<EventsRoutingError> for ExtendedMoniker {
475 fn from(err: EventsRoutingError) -> ExtendedMoniker {
476 match err {
477 EventsRoutingError::InvalidFilter { moniker }
478 | EventsRoutingError::MissingFilter { moniker } => moniker,
479 }
480 }
481}
482
483#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
484#[derive(Debug, Error, Clone, PartialEq)]
485pub enum RightsRoutingError {
486 #[error(
487 "requested rights ({requested}) greater than provided rights ({provided}) at \"{moniker}\""
488 )]
489 Invalid { moniker: ExtendedMoniker, requested: Rights, provided: Rights },
490
491 #[error(
492 "directory routes must end at source with a rights declaration, it's missing at \"{moniker}\""
493 )]
494 MissingRightsSource { moniker: ExtendedMoniker },
495}
496
497impl RightsRoutingError {
498 pub fn as_zx_status(&self) -> zx::Status {
500 match self {
501 RightsRoutingError::Invalid { .. } => zx::Status::ACCESS_DENIED,
502 RightsRoutingError::MissingRightsSource { .. } => zx::Status::NOT_FOUND,
503 }
504 }
505}
506
507impl From<RightsRoutingError> for ExtendedMoniker {
508 fn from(err: RightsRoutingError) -> ExtendedMoniker {
509 match err {
510 RightsRoutingError::Invalid { moniker, .. }
511 | RightsRoutingError::MissingRightsSource { moniker } => moniker,
512 }
513 }
514}
515
516#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
517#[derive(Debug, Error, Clone, PartialEq)]
518pub enum AvailabilityRoutingError {
519 #[error(
520 "availability requested by the target has stronger guarantees than what \
521 is being provided at the source at `{moniker}`"
522 )]
523 TargetHasStrongerAvailability { moniker: ExtendedMoniker },
524
525 #[error("offer uses void source, but target requires the capability at `{moniker}`")]
526 OfferFromVoidToRequiredTarget { moniker: ExtendedMoniker },
527
528 #[error("expose uses void source, but target requires the capability at `{moniker}`")]
529 ExposeFromVoidToRequiredTarget { moniker: ExtendedMoniker },
530}
531
532impl From<availability::TargetHasStrongerAvailability> for AvailabilityRoutingError {
533 fn from(value: availability::TargetHasStrongerAvailability) -> Self {
534 let availability::TargetHasStrongerAvailability { moniker } = value;
535 AvailabilityRoutingError::TargetHasStrongerAvailability { moniker }
536 }
537}
538
539impl From<AvailabilityRoutingError> for ExtendedMoniker {
540 fn from(err: AvailabilityRoutingError) -> ExtendedMoniker {
541 match err {
542 AvailabilityRoutingError::ExposeFromVoidToRequiredTarget { moniker }
543 | AvailabilityRoutingError::OfferFromVoidToRequiredTarget { moniker }
544 | AvailabilityRoutingError::TargetHasStrongerAvailability { moniker } => moniker,
545 }
546 }
547}
548
549#[async_trait]
552pub trait ErrorReporter: Clone + Send + Sync + 'static {
553 async fn report(
554 &self,
555 request: &RouteRequestErrorInfo,
556 err: &RouterError,
557 route_target: Arc<runtime_capabilities::WeakInstanceToken>,
558 );
559}
560
561#[derive(Clone, Debug, PartialEq, Eq)]
563pub struct RouteRequestErrorInfo {
564 capability_type: cm_rust::CapabilityTypeName,
565 name: cm_types::Name,
566 availability: cm_rust::Availability,
567}
568
569impl RouteRequestErrorInfo {
570 pub fn availability(&self) -> cm_rust::Availability {
571 self.availability
572 }
573
574 pub fn name(&self) -> &Name {
575 &self.name
576 }
577
578 pub fn type_name(&self) -> &CapabilityTypeName {
579 &self.capability_type
580 }
581
582 pub fn for_builtin(capability_type: CapabilityTypeName, name: &Name) -> Self {
583 Self { capability_type, name: name.clone(), availability: Availability::Required }
584 }
585}
586
587impl From<&RouteRequestErrorInfo> for runtime_capabilities::RouterErrorInfo {
588 fn from(value: &RouteRequestErrorInfo) -> Self {
589 Self {
590 capability_type: value.capability_type,
591 name: value.name.clone(),
592 availability: value.availability,
593 }
594 }
595}
596
597impl From<runtime_capabilities::RouterErrorInfo> for RouteRequestErrorInfo {
598 fn from(value: runtime_capabilities::RouterErrorInfo) -> Self {
599 Self {
600 capability_type: value.capability_type,
601 name: value.name,
602 availability: value.availability,
603 }
604 }
605}
606
607impl From<&cm_rust::UseDecl> for RouteRequestErrorInfo {
608 fn from(value: &cm_rust::UseDecl) -> Self {
609 RouteRequestErrorInfo {
610 capability_type: value.into(),
611 name: value.source_name().clone(),
612 availability: value.availability().clone(),
613 }
614 }
615}
616
617impl From<&cm_rust::UseConfigurationDecl> for RouteRequestErrorInfo {
618 fn from(value: &cm_rust::UseConfigurationDecl) -> Self {
619 RouteRequestErrorInfo {
620 capability_type: CapabilityTypeName::Config,
621 name: value.source_name().clone(),
622 availability: value.availability().clone(),
623 }
624 }
625}
626
627impl From<&cm_rust::UseEventStreamDecl> for RouteRequestErrorInfo {
628 fn from(value: &cm_rust::UseEventStreamDecl) -> Self {
629 RouteRequestErrorInfo {
630 capability_type: CapabilityTypeName::EventStream,
631 name: value.source_name.clone(),
632 availability: value.availability,
633 }
634 }
635}
636
637impl From<&cm_rust::ExposeDecl> for RouteRequestErrorInfo {
638 fn from(value: &cm_rust::ExposeDecl) -> Self {
639 RouteRequestErrorInfo {
640 capability_type: value.into(),
641 name: value.target_name().clone(),
642 availability: value.availability().clone(),
643 }
644 }
645}
646
647impl From<&cm_rust::offer::OfferDecl> for RouteRequestErrorInfo {
648 fn from(value: &cm_rust::offer::OfferDecl) -> Self {
649 RouteRequestErrorInfo {
650 capability_type: value.into(),
651 name: value.target_name().clone(),
652 availability: value.availability().clone(),
653 }
654 }
655}
656
657impl From<&cm_rust::ResolverRegistration> for RouteRequestErrorInfo {
658 fn from(value: &cm_rust::ResolverRegistration) -> Self {
659 RouteRequestErrorInfo {
660 capability_type: CapabilityTypeName::Resolver,
661 name: value.source_name().clone(),
662 availability: Availability::Required,
663 }
664 }
665}
666
667impl From<&cm_rust::RunnerRegistration> for RouteRequestErrorInfo {
668 fn from(value: &cm_rust::RunnerRegistration) -> Self {
669 RouteRequestErrorInfo {
670 capability_type: CapabilityTypeName::Runner,
671 name: value.source_name().clone(),
672 availability: Availability::Required,
673 }
674 }
675}
676
677impl From<&cm_rust::DebugRegistration> for RouteRequestErrorInfo {
678 fn from(value: &cm_rust::DebugRegistration) -> Self {
679 RouteRequestErrorInfo {
680 capability_type: CapabilityTypeName::Protocol,
681 name: value.source_name().clone(),
682 availability: Availability::Required,
683 }
684 }
685}
686
687impl From<&cm_rust::CapabilityDecl> for RouteRequestErrorInfo {
688 fn from(value: &cm_rust::CapabilityDecl) -> Self {
689 RouteRequestErrorInfo {
690 capability_type: value.into(),
691 name: value.name().clone(),
692 availability: Availability::Required,
693 }
694 }
695}
696
697impl std::fmt::Display for RouteRequestErrorInfo {
698 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
699 write!(f, "{} `{}`", self.capability_type, self.name)
700 }
701}