1use crate::error::RoutingError;
6use cm_rust::{
7 CapabilityDecl, CapabilityTypeName, ChildRef, ConfigurationDecl, DictionaryDecl, DirectoryDecl,
8 EventStreamDecl, ExposeConfigurationDecl, ExposeDecl, ExposeDeclCommon, ExposeDictionaryDecl,
9 ExposeDirectoryDecl, ExposeProtocolDecl, ExposeResolverDecl, ExposeRunnerDecl,
10 ExposeServiceDecl, ExposeSource, FidlIntoNative, NameMapping, NativeIntoFidl,
11 OfferConfigurationDecl, OfferDecl, OfferDeclCommon, OfferDictionaryDecl, OfferDirectoryDecl,
12 OfferEventStreamDecl, OfferProtocolDecl, OfferResolverDecl, OfferRunnerDecl, OfferServiceDecl,
13 OfferSource, OfferStorageDecl, ProtocolDecl, RegistrationSource, ResolverDecl, RunnerDecl,
14 ServiceDecl, StorageDecl, UseDecl, UseDeclCommon, UseDirectoryDecl, UseProtocolDecl,
15 UseServiceDecl, UseSource, UseStorageDecl,
16};
17use cm_rust_derive::FidlDecl;
18use cm_types::{Name, Path, RelativePath};
19use derivative::Derivative;
20use fidl::{persist, unpersist};
21use fidl_fuchsia_component_decl as fdecl;
22use fidl_fuchsia_component_internal as finternal;
23use fidl_fuchsia_sys2 as fsys;
24use from_enum::FromEnum;
25use futures::future::BoxFuture;
26use moniker::{ChildName, ExtendedMoniker, Moniker};
27use sandbox::{Capability, Data};
28use std::fmt;
29use thiserror::Error;
30
31#[cfg(feature = "serde")]
32use serde::{Deserialize, Serialize};
33
34#[derive(Debug, Error)]
35pub enum Error {
36 #[error("Invalid framework capability.")]
37 InvalidFrameworkCapability {},
38 #[error("Invalid builtin capability.")]
39 InvalidBuiltinCapability {},
40}
41
42#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
43#[derive(Debug, Hash, PartialEq, Eq, Clone)]
44pub enum AggregateMember {
45 Child(ChildRef),
46 Collection(Name),
47 Parent,
48 Self_,
49}
50
51impl TryFrom<&OfferDecl> for AggregateMember {
52 type Error = ();
53
54 fn try_from(offer: &OfferDecl) -> Result<AggregateMember, ()> {
55 match offer.source() {
56 OfferSource::Framework => Err(()),
58 OfferSource::Parent => Ok(AggregateMember::Parent),
59 OfferSource::Child(child) => Ok(AggregateMember::Child(child.clone())),
60 OfferSource::Collection(name) => Ok(AggregateMember::Collection(name.clone())),
61 OfferSource::Self_ => Ok(AggregateMember::Self_),
62 OfferSource::Capability(_name) => Err(()),
63 OfferSource::Void => Err(()),
64 }
65 }
66}
67
68impl TryFrom<&cm_rust::ExposeDecl> for AggregateMember {
69 type Error = ();
70
71 fn try_from(expose: &cm_rust::ExposeDecl) -> Result<AggregateMember, ()> {
72 match expose.source() {
73 cm_rust::ExposeSource::Framework => Err(()),
75 cm_rust::ExposeSource::Child(child) => Ok(AggregateMember::Child(cm_rust::ChildRef {
76 name: child.clone().into(),
77 collection: None,
78 })),
79 cm_rust::ExposeSource::Collection(name) => {
80 Ok(AggregateMember::Collection(name.clone()))
81 }
82 cm_rust::ExposeSource::Self_ => Ok(AggregateMember::Self_),
83 cm_rust::ExposeSource::Capability(_name) => Err(()),
84 cm_rust::ExposeSource::Void => Err(()),
85 }
86 }
87}
88
89impl TryFrom<&cm_rust::UseDecl> for AggregateMember {
90 type Error = ();
91
92 fn try_from(use_: &cm_rust::UseDecl) -> Result<AggregateMember, ()> {
93 match use_.source() {
94 cm_rust::UseSource::Parent => Ok(AggregateMember::Parent),
95 cm_rust::UseSource::Framework => Err(()),
96 cm_rust::UseSource::Debug => Err(()),
97 cm_rust::UseSource::Self_ => Ok(AggregateMember::Self_),
98 cm_rust::UseSource::Capability(_) => Err(()),
99 cm_rust::UseSource::Child(name) => {
100 Ok(AggregateMember::Child(ChildRef { name: name.clone().into(), collection: None }))
101 }
102 cm_rust::UseSource::Collection(name) => Ok(AggregateMember::Collection(name.clone())),
103 cm_rust::UseSource::Environment => Err(()),
104 }
105 }
106}
107
108impl fmt::Display for AggregateMember {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 match self {
111 Self::Child(n) => {
112 write!(f, "child `{n}`")
113 }
114 Self::Collection(n) => {
115 write!(f, "collection `{n}`")
116 }
117 Self::Parent => {
118 write!(f, "parent")
119 }
120 Self::Self_ => {
121 write!(f, "self")
122 }
123 }
124 }
125}
126
127impl FidlIntoNative<AggregateMember> for finternal::AggregateMember {
128 fn fidl_into_native(self) -> AggregateMember {
129 match self {
130 finternal::AggregateMember::Self_(_) => AggregateMember::Self_,
131 finternal::AggregateMember::Parent(_) => AggregateMember::Parent,
132 finternal::AggregateMember::Collection(name) => {
133 AggregateMember::Collection(Name::new(name).unwrap())
134 }
135 finternal::AggregateMember::Child(child_ref) => {
136 AggregateMember::Child(child_ref.fidl_into_native())
137 }
138 }
139 }
140}
141
142impl NativeIntoFidl<finternal::AggregateMember> for AggregateMember {
143 fn native_into_fidl(self) -> finternal::AggregateMember {
144 match self {
145 AggregateMember::Self_ => finternal::AggregateMember::Self_(fdecl::SelfRef {}),
146 AggregateMember::Parent => finternal::AggregateMember::Parent(fdecl::ParentRef {}),
147 AggregateMember::Collection(name) => {
148 finternal::AggregateMember::Collection(name.to_string())
149 }
150 AggregateMember::Child(child_ref) => {
151 finternal::AggregateMember::Child(child_ref.native_into_fidl())
152 }
153 }
154 }
155}
156
157#[cfg_attr(
159 feature = "serde",
160 derive(Deserialize, Serialize),
161 serde(tag = "type", rename_all = "snake_case")
162)]
163#[derive(FidlDecl, Debug, Derivative)]
164#[derivative(Clone(bound = ""), PartialEq)]
165#[fidl_decl(fidl_union = "finternal::CapabilitySource")]
166pub enum CapabilitySource {
167 Component(ComponentSource),
170 Framework(FrameworkSource),
173 Builtin(BuiltinSource),
177 Namespace(NamespaceSource),
181 Capability(CapabilityToCapabilitySource),
183 AnonymizedAggregate(AnonymizedAggregateSource),
186 FilteredProvider(FilteredProviderSource),
189 FilteredAggregateProvider(FilteredAggregateProviderSource),
193 Environment(EnvironmentSource),
195 Void(VoidSource),
198 RemotedAt(RemotedAtSource),
201 StorageBackingDirectory(StorageBackingDirectorySource),
204}
205
206#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
207#[derive(FidlDecl, Debug, PartialEq, Clone)]
208#[fidl_decl(fidl_table = "finternal::Component")]
209pub struct ComponentSource {
210 pub capability: ComponentCapability,
211 pub moniker: Moniker,
212}
213#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
214#[derive(FidlDecl, Debug, PartialEq, Clone)]
215#[fidl_decl(fidl_table = "finternal::Framework")]
216pub struct FrameworkSource {
217 pub capability: InternalCapability,
218 pub moniker: Moniker,
219}
220#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
221#[derive(FidlDecl, Debug, PartialEq, Clone)]
222#[fidl_decl(fidl_table = "finternal::Builtin")]
223pub struct BuiltinSource {
224 pub capability: InternalCapability,
225}
226#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
227#[derive(FidlDecl, Debug, PartialEq, Clone)]
228#[fidl_decl(fidl_table = "finternal::Namespace")]
229pub struct NamespaceSource {
230 pub capability: ComponentCapability,
231}
232#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
233#[derive(FidlDecl, Debug, PartialEq, Clone)]
234#[fidl_decl(fidl_table = "finternal::Capability")]
235pub struct CapabilityToCapabilitySource {
236 pub source_capability: ComponentCapability,
237 pub moniker: Moniker,
238}
239#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
240#[derive(FidlDecl, Debug, PartialEq, Clone)]
241#[fidl_decl(fidl_table = "finternal::AnonymizedAggregate")]
242pub struct AnonymizedAggregateSource {
243 pub capability: AggregateCapability,
244 pub moniker: Moniker,
245 pub members: Vec<AggregateMember>,
246 pub instances: Vec<ServiceInstance>,
247}
248#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
249#[derive(FidlDecl, Debug, PartialEq, Clone)]
250#[fidl_decl(fidl_table = "fsys::ServiceInstance")]
251pub struct ServiceInstance {
252 pub instance_name: Name,
253 pub child_name: String,
254 pub child_instance_name: Name,
255}
256#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
257#[derive(FidlDecl, Debug, PartialEq, Clone)]
258#[fidl_decl(fidl_table = "finternal::FilteredProvider")]
259pub struct FilteredProviderSource {
260 pub capability: AggregateCapability,
261 pub moniker: Moniker,
262 pub service_capability: ComponentCapability,
263 pub offer_service_decl: OfferServiceDecl,
264}
265#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
266#[derive(FidlDecl, Debug, PartialEq, Clone)]
267#[fidl_decl(fidl_table = "finternal::FilteredAggregateProvider")]
268pub struct FilteredAggregateProviderSource {
269 pub capability: AggregateCapability,
270 pub moniker: Moniker,
271 pub offer_service_decls: Vec<OfferServiceDecl>,
272}
273#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
274#[derive(FidlDecl, Debug, PartialEq, Clone)]
275#[fidl_decl(fidl_table = "finternal::Environment")]
276pub struct EnvironmentSource {
277 pub capability: ComponentCapability,
278 pub moniker: Moniker,
279}
280#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
281#[derive(FidlDecl, Debug, PartialEq, Clone)]
282#[fidl_decl(fidl_table = "finternal::Void")]
283pub struct VoidSource {
284 pub capability: InternalCapability,
285 pub moniker: Moniker,
286}
287#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
288#[derive(FidlDecl, Debug, PartialEq, Clone)]
289#[fidl_decl(fidl_table = "finternal::RemotedAt")]
290pub struct RemotedAtSource {
291 pub moniker: Moniker,
292 pub type_name: Option<CapabilityTypeName>,
293}
294
295#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
296#[derive(FidlDecl, Debug, PartialEq, Clone)]
297#[fidl_decl(fidl_table = "finternal::StorageBackingDirectory")]
298pub struct StorageBackingDirectorySource {
299 pub capability: ComponentCapability,
300 pub moniker: Moniker,
301 pub backing_dir_subdir: RelativePath,
302 pub storage_subdir: RelativePath,
303 pub storage_source_moniker: Moniker,
304}
305
306impl CapabilitySource {
307 pub fn source_name(&self) -> Option<&Name> {
308 match self {
309 Self::Component(ComponentSource { capability, .. }) => capability.source_name(),
310 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.source_name()),
311 Self::Builtin(BuiltinSource { capability }) => Some(capability.source_name()),
312 Self::Namespace(NamespaceSource { capability }) => capability.source_name(),
313 Self::Capability(CapabilityToCapabilitySource { .. }) => None,
314 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
315 Some(capability.source_name())
316 }
317 Self::FilteredProvider(FilteredProviderSource { capability, .. })
318 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
319 capability, ..
320 }) => Some(capability.source_name()),
321 Self::Environment(EnvironmentSource { capability, .. }) => capability.source_name(),
322 Self::Void(VoidSource { capability, .. }) => Some(capability.source_name()),
323 Self::RemotedAt(_) => None,
324 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
325 capability.source_name()
326 }
327 }
328 }
329
330 pub fn type_name(&self) -> Option<CapabilityTypeName> {
334 match self {
335 Self::Component(ComponentSource { capability, .. }) => Some(capability.type_name()),
336 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.type_name()),
337 Self::Builtin(BuiltinSource { capability }) => Some(capability.type_name()),
338 Self::Namespace(NamespaceSource { capability }) => Some(capability.type_name()),
339 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) => {
340 Some(source_capability.type_name())
341 }
342 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
343 Some(capability.type_name())
344 }
345 Self::FilteredProvider(FilteredProviderSource { capability, .. })
346 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
347 capability, ..
348 }) => Some(capability.type_name()),
349 Self::Environment(EnvironmentSource { capability, .. }) => Some(capability.type_name()),
350 Self::Void(VoidSource { capability, .. }) => Some(capability.type_name()),
351 Self::RemotedAt(RemotedAtSource { type_name, .. }) => type_name.clone(),
352 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
353 Some(capability.type_name())
354 }
355 }
356 }
357
358 pub fn source_moniker(&self) -> ExtendedMoniker {
359 match self {
360 Self::Component(ComponentSource { moniker, .. })
361 | Self::Framework(FrameworkSource { moniker, .. })
362 | Self::Capability(CapabilityToCapabilitySource { moniker, .. })
363 | Self::Environment(EnvironmentSource { moniker, .. })
364 | Self::Void(VoidSource { moniker, .. })
365 | Self::StorageBackingDirectory(StorageBackingDirectorySource { moniker, .. })
366 | Self::AnonymizedAggregate(AnonymizedAggregateSource { moniker, .. })
367 | Self::FilteredProvider(FilteredProviderSource { moniker, .. })
368 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
369 moniker, ..
370 })
371 | Self::RemotedAt(RemotedAtSource { moniker, .. }) => {
372 ExtendedMoniker::ComponentInstance(moniker.clone())
373 }
374 Self::Builtin(_) | Self::Namespace(_) => ExtendedMoniker::ComponentManager,
375 }
376 }
377}
378
379impl fmt::Display for CapabilitySource {
380 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
381 write!(
382 f,
383 "{}",
384 match self {
385 Self::Component(ComponentSource { capability, moniker })
386 | Self::StorageBackingDirectory(StorageBackingDirectorySource {
387 capability,
388 moniker,
389 ..
390 }) => {
391 format!("{} '{}'", capability, moniker)
392 }
393 Self::Framework(FrameworkSource { capability, .. }) => capability.to_string(),
394 Self::Builtin(BuiltinSource { capability }) => capability.to_string(),
395 Self::Namespace(NamespaceSource { capability }) => capability.to_string(),
396 Self::FilteredProvider(FilteredProviderSource { capability, .. })
397 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
398 capability,
399 ..
400 }) => capability.to_string(),
401 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) =>
402 format!("{}", source_capability),
403 Self::AnonymizedAggregate(AnonymizedAggregateSource {
404 capability,
405 members,
406 moniker,
407 ..
408 }) => {
409 format!(
410 "{} from component '{}' aggregated from {}",
411 capability,
412 moniker,
413 members.iter().map(|s| format!("{s}")).collect::<Vec<_>>().join(","),
414 )
415 }
416 Self::Environment(EnvironmentSource { capability, .. }) => capability.to_string(),
417 Self::Void(VoidSource { capability, .. }) => capability.to_string(),
418 Self::RemotedAt(RemotedAtSource { moniker, type_name }) => format!(
419 "{} route left component manager at {}",
420 type_name.map(|t| t.to_string()).unwrap_or_else(|| "unknown".to_string()),
421 moniker
422 ),
423 }
424 )
425 }
426}
427
428impl TryFrom<CapabilitySource> for Capability {
429 type Error = fidl::Error;
430
431 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
432 Ok(Data::try_from(capability_source)?.into())
433 }
434}
435
436impl TryFrom<CapabilitySource> for Data {
437 type Error = fidl::Error;
438
439 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
440 Ok(Data::Bytes(persist(&capability_source.native_into_fidl())?.into()))
441 }
442}
443
444impl TryFrom<Capability> for CapabilitySource {
445 type Error = fidl::Error;
446
447 fn try_from(capability: Capability) -> Result<Self, Self::Error> {
448 let Capability::Data(data) = capability else {
449 return Err(fidl::Error::InvalidEnumValue);
450 };
451 Self::try_from(data)
452 }
453}
454
455impl TryFrom<Data> for CapabilitySource {
456 type Error = fidl::Error;
457
458 fn try_from(data: Data) -> Result<Self, Self::Error> {
459 let Data::Bytes(bytes) = data else {
460 return Err(fidl::Error::InvalidEnumValue);
461 };
462 Ok(unpersist::<finternal::CapabilitySource>(&bytes)?.fidl_into_native())
463 }
464}
465
466#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
468pub enum AggregateInstance {
469 Child(ChildName),
470 Parent,
471 Self_,
472}
473
474impl fmt::Display for AggregateInstance {
475 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
476 match self {
477 Self::Child(n) => {
478 write!(f, "child `{n}`")
479 }
480 Self::Parent => {
481 write!(f, "parent")
482 }
483 Self::Self_ => {
484 write!(f, "self")
485 }
486 }
487 }
488}
489
490#[derive(Debug)]
494pub struct FilteredAggregateCapabilityRouteData {
495 pub capability_source: CapabilitySource,
497 pub instance_filter: Vec<NameMapping>,
500}
501
502pub trait FilteredAggregateCapabilityProvider: Send + Sync {
507 fn route_instances(
510 &self,
511 ) -> Vec<BoxFuture<'_, Result<FilteredAggregateCapabilityRouteData, RoutingError>>>;
512
513 fn clone_boxed(&self) -> Box<dyn FilteredAggregateCapabilityProvider>;
515}
516
517impl Clone for Box<dyn FilteredAggregateCapabilityProvider> {
518 fn clone(&self) -> Self {
519 self.clone_boxed()
520 }
521}
522
523impl fmt::Debug for Box<dyn FilteredAggregateCapabilityProvider> {
524 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525 f.debug_struct("Box<dyn FilteredAggregateCapabilityProvider>").finish()
526 }
527}
528
529#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
533#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
534#[fidl_decl(fidl_union = "finternal::InternalCapability")]
535pub enum InternalCapability {
536 Service(Name),
537 Protocol(Name),
538 Directory(Name),
539 Runner(Name),
540 Config(Name),
541 EventStream(InternalEventStreamCapability),
542 Resolver(Name),
543 Storage(Name),
544 Dictionary(Name),
545}
546
547#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
548#[derive(FidlDecl, Debug, PartialEq, Clone, Eq)]
549#[fidl_decl(fidl_table = "finternal::InternalEventStreamCapability")]
550pub struct InternalEventStreamCapability {
551 pub name: Name,
552 pub route_metadata: EventStreamRouteMetadata,
553}
554
555#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
556#[derive(FidlDecl, Default, Debug, PartialEq, Clone, Eq)]
557#[fidl_decl(fidl_table = "finternal::EventStreamRouteMetadata")]
558pub struct EventStreamRouteMetadata {
559 pub scope_moniker: Option<String>,
560 pub scope: Option<Box<[cm_rust::EventScope]>>,
561}
562
563impl InternalCapability {
564 pub fn new(type_name: CapabilityTypeName, name: Name) -> Self {
565 match type_name {
566 CapabilityTypeName::Directory => InternalCapability::Directory(name),
567 CapabilityTypeName::EventStream => InternalCapability::Directory(name),
568 CapabilityTypeName::Protocol => InternalCapability::Protocol(name),
569 CapabilityTypeName::Resolver => InternalCapability::Resolver(name),
570 CapabilityTypeName::Runner => InternalCapability::Runner(name),
571 CapabilityTypeName::Service => InternalCapability::Service(name),
572 CapabilityTypeName::Storage => InternalCapability::Storage(name),
573 CapabilityTypeName::Dictionary => InternalCapability::Dictionary(name),
574 CapabilityTypeName::Config => InternalCapability::Config(name),
575 }
576 }
577
578 pub fn type_name(&self) -> CapabilityTypeName {
580 match self {
581 InternalCapability::Service(_) => CapabilityTypeName::Service,
582 InternalCapability::Protocol(_) => CapabilityTypeName::Protocol,
583 InternalCapability::Directory(_) => CapabilityTypeName::Directory,
584 InternalCapability::Runner(_) => CapabilityTypeName::Runner,
585 InternalCapability::Config(_) => CapabilityTypeName::Config,
586 InternalCapability::EventStream(_) => CapabilityTypeName::EventStream,
587 InternalCapability::Resolver(_) => CapabilityTypeName::Resolver,
588 InternalCapability::Storage(_) => CapabilityTypeName::Storage,
589 InternalCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
590 }
591 }
592
593 pub fn source_name(&self) -> &Name {
594 match self {
595 InternalCapability::Service(name) => &name,
596 InternalCapability::Protocol(name) => &name,
597 InternalCapability::Directory(name) => &name,
598 InternalCapability::Runner(name) => &name,
599 InternalCapability::Config(name) => &name,
600 InternalCapability::EventStream(InternalEventStreamCapability { name, .. }) => &name,
601 InternalCapability::Resolver(name) => &name,
602 InternalCapability::Storage(name) => &name,
603 InternalCapability::Dictionary(name) => &name,
604 }
605 }
606
607 pub fn matches_protocol(&self, name: &Name) -> bool {
609 match self {
610 Self::Protocol(source_name) => source_name == name,
611 _ => false,
612 }
613 }
614}
615
616impl fmt::Display for InternalCapability {
617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618 write!(f, "{} '{}' from component manager", self.type_name(), self.source_name())
619 }
620}
621
622impl From<CapabilityDecl> for InternalCapability {
623 fn from(capability: CapabilityDecl) -> Self {
624 match capability {
625 CapabilityDecl::Service(c) => c.into(),
626 CapabilityDecl::Protocol(c) => c.into(),
627 CapabilityDecl::Directory(c) => c.into(),
628 CapabilityDecl::Storage(c) => c.into(),
629 CapabilityDecl::Runner(c) => c.into(),
630 CapabilityDecl::Resolver(c) => c.into(),
631 CapabilityDecl::EventStream(c) => c.into(),
632 CapabilityDecl::Dictionary(c) => c.into(),
633 CapabilityDecl::Config(c) => c.into(),
634 }
635 }
636}
637
638impl From<ServiceDecl> for InternalCapability {
639 fn from(service: ServiceDecl) -> Self {
640 Self::Service(service.name)
641 }
642}
643
644impl From<ProtocolDecl> for InternalCapability {
645 fn from(protocol: ProtocolDecl) -> Self {
646 Self::Protocol(protocol.name)
647 }
648}
649
650impl From<DirectoryDecl> for InternalCapability {
651 fn from(directory: DirectoryDecl) -> Self {
652 Self::Directory(directory.name)
653 }
654}
655
656impl From<RunnerDecl> for InternalCapability {
657 fn from(runner: RunnerDecl) -> Self {
658 Self::Runner(runner.name)
659 }
660}
661
662impl From<ResolverDecl> for InternalCapability {
663 fn from(resolver: ResolverDecl) -> Self {
664 Self::Resolver(resolver.name)
665 }
666}
667
668impl From<EventStreamDecl> for InternalCapability {
669 fn from(event: EventStreamDecl) -> Self {
670 Self::EventStream(InternalEventStreamCapability {
671 name: event.name,
672 route_metadata: Default::default(),
673 })
674 }
675}
676
677impl From<StorageDecl> for InternalCapability {
678 fn from(storage: StorageDecl) -> Self {
679 Self::Storage(storage.name)
680 }
681}
682
683impl From<ConfigurationDecl> for InternalCapability {
684 fn from(config: ConfigurationDecl) -> Self {
685 Self::Config(config.name)
686 }
687}
688
689impl From<DictionaryDecl> for InternalCapability {
690 fn from(dictionary: DictionaryDecl) -> Self {
691 Self::Dictionary(dictionary.name)
692 }
693}
694
695#[cfg_attr(
697 feature = "serde",
698 derive(Deserialize, Serialize),
699 serde(tag = "type", rename_all = "snake_case")
700)]
701#[derive(FidlDecl, FromEnum, Clone, Debug, PartialEq, Eq)]
702#[fidl_decl(fidl_union = "finternal::ComponentCapability")]
703pub enum ComponentCapability {
704 Use_(UseDecl),
705 Environment(EnvironmentCapability),
707 Expose(ExposeDecl),
708 Offer(OfferDecl),
709 Protocol(ProtocolDecl),
710 Directory(DirectoryDecl),
711 Storage(StorageDecl),
712 Runner(RunnerDecl),
713 Resolver(ResolverDecl),
714 Service(ServiceDecl),
715 EventStream(EventStreamDecl),
716 Dictionary(DictionaryDecl),
717 Config(ConfigurationDecl),
718}
719
720impl ComponentCapability {
721 pub fn type_name(&self) -> CapabilityTypeName {
723 match self {
724 ComponentCapability::Use_(use_) => use_.into(),
725 ComponentCapability::Environment(env) => match env {
726 EnvironmentCapability::Runner(_) => CapabilityTypeName::Runner,
727 EnvironmentCapability::Resolver(_) => CapabilityTypeName::Resolver,
728 EnvironmentCapability::Debug(_) => CapabilityTypeName::Protocol,
729 },
730 ComponentCapability::Expose(expose) => expose.into(),
731 ComponentCapability::Offer(offer) => offer.into(),
732 ComponentCapability::Protocol(_) => CapabilityTypeName::Protocol,
733 ComponentCapability::Directory(_) => CapabilityTypeName::Directory,
734 ComponentCapability::Storage(_) => CapabilityTypeName::Storage,
735 ComponentCapability::Runner(_) => CapabilityTypeName::Runner,
736 ComponentCapability::Config(_) => CapabilityTypeName::Config,
737 ComponentCapability::Resolver(_) => CapabilityTypeName::Resolver,
738 ComponentCapability::Service(_) => CapabilityTypeName::Service,
739 ComponentCapability::EventStream(_) => CapabilityTypeName::EventStream,
740 ComponentCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
741 }
742 }
743
744 pub fn source_path(&self) -> Option<&Path> {
746 match self {
747 ComponentCapability::Storage(_) => None,
748 ComponentCapability::Protocol(protocol) => protocol.source_path.as_ref(),
749 ComponentCapability::Directory(directory) => directory.source_path.as_ref(),
750 ComponentCapability::Runner(runner) => runner.source_path.as_ref(),
751 ComponentCapability::Resolver(resolver) => resolver.source_path.as_ref(),
752 ComponentCapability::Service(service) => service.source_path.as_ref(),
753 _ => None,
754 }
755 }
756
757 pub fn source_name(&self) -> Option<&Name> {
759 match self {
760 ComponentCapability::Storage(storage) => Some(&storage.name),
761 ComponentCapability::Protocol(protocol) => Some(&protocol.name),
762 ComponentCapability::Directory(directory) => Some(&directory.name),
763 ComponentCapability::Runner(runner) => Some(&runner.name),
764 ComponentCapability::Config(config) => Some(&config.name),
765 ComponentCapability::Resolver(resolver) => Some(&resolver.name),
766 ComponentCapability::Service(service) => Some(&service.name),
767 ComponentCapability::EventStream(event) => Some(&event.name),
768 ComponentCapability::Dictionary(dictionary) => Some(&dictionary.name),
769 ComponentCapability::Use_(use_) => match use_ {
770 UseDecl::Protocol(UseProtocolDecl { source_name, .. }) => Some(source_name),
771 UseDecl::Directory(UseDirectoryDecl { source_name, .. }) => Some(source_name),
772 UseDecl::Storage(UseStorageDecl { source_name, .. }) => Some(source_name),
773 UseDecl::Service(UseServiceDecl { source_name, .. }) => Some(source_name),
774 UseDecl::Config(cm_rust::UseConfigurationDecl { source_name, .. }) => {
775 Some(source_name)
776 }
777 _ => None,
778 },
779 ComponentCapability::Environment(env_cap) => match env_cap {
780 EnvironmentCapability::Runner(EnvironmentCapabilityData {
781 source_name, ..
782 }) => Some(source_name),
783 EnvironmentCapability::Resolver(EnvironmentCapabilityData {
784 source_name, ..
785 }) => Some(source_name),
786 EnvironmentCapability::Debug(EnvironmentCapabilityData { source_name, .. }) => {
787 Some(source_name)
788 }
789 },
790 ComponentCapability::Expose(expose) => match expose {
791 ExposeDecl::Protocol(ExposeProtocolDecl { source_name, .. }) => Some(source_name),
792 ExposeDecl::Directory(ExposeDirectoryDecl { source_name, .. }) => Some(source_name),
793 ExposeDecl::Runner(ExposeRunnerDecl { source_name, .. }) => Some(source_name),
794 ExposeDecl::Resolver(ExposeResolverDecl { source_name, .. }) => Some(source_name),
795 ExposeDecl::Service(ExposeServiceDecl { source_name, .. }) => Some(source_name),
796 ExposeDecl::Config(ExposeConfigurationDecl { source_name, .. }) => {
797 Some(source_name)
798 }
799 ExposeDecl::Dictionary(ExposeDictionaryDecl { source_name, .. }) => {
800 Some(source_name)
801 }
802 },
803 ComponentCapability::Offer(offer) => match offer {
804 OfferDecl::Protocol(OfferProtocolDecl { source_name, .. }) => Some(source_name),
805 OfferDecl::Directory(OfferDirectoryDecl { source_name, .. }) => Some(source_name),
806 OfferDecl::Runner(OfferRunnerDecl { source_name, .. }) => Some(source_name),
807 OfferDecl::Storage(OfferStorageDecl { source_name, .. }) => Some(source_name),
808 OfferDecl::Resolver(OfferResolverDecl { source_name, .. }) => Some(source_name),
809 OfferDecl::Service(OfferServiceDecl { source_name, .. }) => Some(source_name),
810 OfferDecl::Config(OfferConfigurationDecl { source_name, .. }) => Some(source_name),
811 OfferDecl::EventStream(OfferEventStreamDecl { source_name, .. }) => {
812 Some(source_name)
813 }
814 OfferDecl::Dictionary(OfferDictionaryDecl { source_name, .. }) => Some(source_name),
815 },
816 }
817 }
818
819 pub fn source_capability_name(&self) -> Option<&Name> {
820 match self {
821 ComponentCapability::Offer(OfferDecl::Protocol(OfferProtocolDecl {
822 source: OfferSource::Capability(name),
823 ..
824 })) => Some(name),
825 ComponentCapability::Expose(ExposeDecl::Protocol(ExposeProtocolDecl {
826 source: ExposeSource::Capability(name),
827 ..
828 })) => Some(name),
829 ComponentCapability::Use_(UseDecl::Protocol(UseProtocolDecl {
830 source: UseSource::Capability(name),
831 ..
832 })) => Some(name),
833 _ => None,
834 }
835 }
836
837 pub fn source_id(&self) -> String {
839 self.source_name()
840 .map(|p| format!("{}", p))
841 .or_else(|| self.source_path().map(|p| format!("{}", p)))
842 .unwrap_or_default()
843 }
844}
845
846impl From<CapabilityDecl> for ComponentCapability {
847 fn from(capability: CapabilityDecl) -> Self {
848 match capability {
849 CapabilityDecl::Service(c) => ComponentCapability::Service(c),
850 CapabilityDecl::Protocol(c) => ComponentCapability::Protocol(c),
851 CapabilityDecl::Directory(c) => ComponentCapability::Directory(c),
852 CapabilityDecl::Storage(c) => ComponentCapability::Storage(c),
853 CapabilityDecl::Runner(c) => ComponentCapability::Runner(c),
854 CapabilityDecl::Resolver(c) => ComponentCapability::Resolver(c),
855 CapabilityDecl::EventStream(c) => ComponentCapability::EventStream(c),
856 CapabilityDecl::Dictionary(c) => ComponentCapability::Dictionary(c),
857 CapabilityDecl::Config(c) => ComponentCapability::Config(c),
858 }
859 }
860}
861
862impl TryInto<CapabilityDecl> for ComponentCapability {
863 type Error = ();
864
865 fn try_into(self) -> Result<CapabilityDecl, Self::Error> {
866 match self {
867 Self::Service(c) => Ok(CapabilityDecl::Service(c)),
868 Self::Protocol(c) => Ok(CapabilityDecl::Protocol(c)),
869 Self::Directory(c) => Ok(CapabilityDecl::Directory(c)),
870 Self::Storage(c) => Ok(CapabilityDecl::Storage(c)),
871 Self::Runner(c) => Ok(CapabilityDecl::Runner(c)),
872 Self::Resolver(c) => Ok(CapabilityDecl::Resolver(c)),
873 Self::EventStream(c) => Ok(CapabilityDecl::EventStream(c)),
874 Self::Dictionary(c) => Ok(CapabilityDecl::Dictionary(c)),
875 Self::Config(c) => Ok(CapabilityDecl::Config(c)),
876 _ => Err(()),
877 }
878 }
879}
880
881impl fmt::Display for ComponentCapability {
882 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883 write!(f, "{} '{}' from component", self.type_name(), self.source_id())
884 }
885}
886
887#[cfg_attr(
888 feature = "serde",
889 derive(Deserialize, Serialize),
890 serde(tag = "type", rename_all = "snake_case")
891)]
892#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
893#[fidl_decl(fidl_union = "finternal::EnvironmentCapability")]
894pub enum EnvironmentCapability {
895 Runner(EnvironmentCapabilityData),
896 Resolver(EnvironmentCapabilityData),
897 Debug(EnvironmentCapabilityData),
898}
899
900impl EnvironmentCapability {
901 pub fn registration_source(&self) -> &RegistrationSource {
902 match self {
903 Self::Runner(EnvironmentCapabilityData { source, .. })
904 | Self::Resolver(EnvironmentCapabilityData { source, .. })
905 | Self::Debug(EnvironmentCapabilityData { source, .. }) => &source,
906 }
907 }
908}
909
910#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
911#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
912#[fidl_decl(fidl_table = "finternal::EnvironmentSource")]
913pub struct EnvironmentCapabilityData {
914 source_name: Name,
915 source: RegistrationSource,
916}
917
918#[cfg_attr(
921 feature = "serde",
922 derive(Deserialize, Serialize),
923 serde(tag = "type", rename_all = "snake_case")
924)]
925#[derive(FidlDecl, Debug, Clone, PartialEq, Eq, Hash)]
926#[fidl_decl(fidl_union = "finternal::AggregateCapability")]
927pub enum AggregateCapability {
928 Service(Name),
929}
930
931impl AggregateCapability {
932 pub fn type_name(&self) -> CapabilityTypeName {
934 match self {
935 AggregateCapability::Service(_) => CapabilityTypeName::Service,
936 }
937 }
938
939 pub fn source_name(&self) -> &Name {
940 match self {
941 AggregateCapability::Service(name) => &name,
942 }
943 }
944}
945
946impl fmt::Display for AggregateCapability {
947 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
948 write!(f, "aggregate {} '{}'", self.type_name(), self.source_name())
949 }
950}
951
952impl From<ServiceDecl> for AggregateCapability {
953 fn from(service: ServiceDecl) -> Self {
954 Self::Service(service.name)
955 }
956}
957
958pub type NamespaceCapabilities = Vec<CapabilityDecl>;
960
961pub type BuiltinCapabilities = Vec<CapabilityDecl>;
963
964#[cfg(test)]
965mod tests {
966 use super::*;
967 use cm_rust::StorageDirectorySource;
968
969 #[test]
970 fn capability_type_name() {
971 let storage_capability = ComponentCapability::Storage(StorageDecl {
972 name: "foo".parse().unwrap(),
973 source: StorageDirectorySource::Parent,
974 backing_dir: "bar".parse().unwrap(),
975 subdir: Default::default(),
976 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
977 });
978 assert_eq!(storage_capability.type_name(), CapabilityTypeName::Storage);
979 }
980}