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