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}
201
202#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
203#[derive(FidlDecl, Debug, PartialEq, Clone)]
204#[fidl_decl(fidl_table = "finternal::Component")]
205pub struct ComponentSource {
206 pub capability: ComponentCapability,
207 pub moniker: Moniker,
208}
209#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
210#[derive(FidlDecl, Debug, PartialEq, Clone)]
211#[fidl_decl(fidl_table = "finternal::Framework")]
212pub struct FrameworkSource {
213 pub capability: InternalCapability,
214 pub moniker: Moniker,
215}
216#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
217#[derive(FidlDecl, Debug, PartialEq, Clone)]
218#[fidl_decl(fidl_table = "finternal::Builtin")]
219pub struct BuiltinSource {
220 pub capability: InternalCapability,
221}
222#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
223#[derive(FidlDecl, Debug, PartialEq, Clone)]
224#[fidl_decl(fidl_table = "finternal::Namespace")]
225pub struct NamespaceSource {
226 pub capability: ComponentCapability,
227}
228#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
229#[derive(FidlDecl, Debug, PartialEq, Clone)]
230#[fidl_decl(fidl_table = "finternal::Capability")]
231pub struct CapabilityToCapabilitySource {
232 pub source_capability: ComponentCapability,
233 pub moniker: Moniker,
234}
235#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
236#[derive(FidlDecl, Debug, PartialEq, Clone)]
237#[fidl_decl(fidl_table = "finternal::AnonymizedAggregate")]
238pub struct AnonymizedAggregateSource {
239 pub capability: AggregateCapability,
240 pub moniker: Moniker,
241 pub members: Vec<AggregateMember>,
242 pub sources: Sources,
243 pub instances: Vec<ServiceInstance>,
244}
245#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
246#[derive(FidlDecl, Debug, PartialEq, Clone)]
247#[fidl_decl(fidl_table = "fsys::ServiceInstance")]
248pub struct ServiceInstance {
249 pub instance_name: Name,
250 pub child_name: String,
251 pub child_instance_name: Name,
252}
253#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
254#[derive(FidlDecl, Debug, PartialEq, Clone)]
255#[fidl_decl(fidl_table = "finternal::FilteredProvider")]
256pub struct FilteredProviderSource {
257 pub capability: AggregateCapability,
258 pub moniker: Moniker,
259 pub service_capability: ComponentCapability,
260 pub offer_service_decl: OfferServiceDecl,
261}
262#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
263#[derive(FidlDecl, Debug, PartialEq, Clone)]
264#[fidl_decl(fidl_table = "finternal::FilteredAggregateProvider")]
265pub struct FilteredAggregateProviderSource {
266 pub capability: AggregateCapability,
267 pub moniker: Moniker,
268 pub offer_service_decls: Vec<OfferServiceDecl>,
269 pub sources: Sources,
270}
271#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
272#[derive(FidlDecl, Debug, PartialEq, Clone)]
273#[fidl_decl(fidl_table = "finternal::Environment")]
274pub struct EnvironmentSource {
275 pub capability: ComponentCapability,
276 pub moniker: Moniker,
277}
278#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
279#[derive(FidlDecl, Debug, PartialEq, Clone)]
280#[fidl_decl(fidl_table = "finternal::Void")]
281pub struct VoidSource {
282 pub capability: InternalCapability,
283 pub moniker: Moniker,
284}
285
286impl CapabilitySource {
287 pub fn can_be_in_namespace(&self) -> bool {
290 match self {
291 Self::Component(ComponentSource { capability, .. }) => capability.can_be_in_namespace(),
292 Self::Framework(FrameworkSource { capability, .. }) => capability.can_be_in_namespace(),
293 Self::Builtin(BuiltinSource { capability }) => capability.can_be_in_namespace(),
294 Self::Namespace(NamespaceSource { capability }) => capability.can_be_in_namespace(),
295 Self::Capability(CapabilityToCapabilitySource { .. }) => true,
296 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
297 capability.can_be_in_namespace()
298 }
299 Self::FilteredProvider(FilteredProviderSource { capability, .. })
300 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
301 capability, ..
302 }) => capability.can_be_in_namespace(),
303 Self::Environment(EnvironmentSource { capability, .. }) => {
304 capability.can_be_in_namespace()
305 }
306 Self::Void(VoidSource { capability, .. }) => capability.can_be_in_namespace(),
307 }
308 }
309
310 pub fn source_name(&self) -> Option<&Name> {
311 match self {
312 Self::Component(ComponentSource { capability, .. }) => capability.source_name(),
313 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.source_name()),
314 Self::Builtin(BuiltinSource { capability }) => Some(capability.source_name()),
315 Self::Namespace(NamespaceSource { capability }) => capability.source_name(),
316 Self::Capability(CapabilityToCapabilitySource { .. }) => None,
317 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
318 Some(capability.source_name())
319 }
320 Self::FilteredProvider(FilteredProviderSource { capability, .. })
321 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
322 capability, ..
323 }) => Some(capability.source_name()),
324 Self::Environment(EnvironmentSource { capability, .. }) => capability.source_name(),
325 Self::Void(VoidSource { capability, .. }) => Some(capability.source_name()),
326 }
327 }
328
329 pub fn type_name(&self) -> CapabilityTypeName {
330 match self {
331 Self::Component(ComponentSource { capability, .. }) => capability.type_name(),
332 Self::Framework(FrameworkSource { capability, .. }) => capability.type_name(),
333 Self::Builtin(BuiltinSource { capability }) => capability.type_name(),
334 Self::Namespace(NamespaceSource { capability }) => capability.type_name(),
335 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) => {
336 source_capability.type_name()
337 }
338 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
339 capability.type_name()
340 }
341 Self::FilteredProvider(FilteredProviderSource { capability, .. })
342 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
343 capability, ..
344 }) => capability.type_name(),
345 Self::Environment(EnvironmentSource { capability, .. }) => capability.type_name(),
346 Self::Void(VoidSource { capability, .. }) => capability.type_name(),
347 }
348 }
349
350 pub fn source_moniker(&self) -> ExtendedMoniker {
351 match self {
352 Self::Component(ComponentSource { moniker, .. })
353 | Self::Framework(FrameworkSource { moniker, .. })
354 | Self::Capability(CapabilityToCapabilitySource { moniker, .. })
355 | Self::Environment(EnvironmentSource { moniker, .. })
356 | Self::Void(VoidSource { moniker, .. })
357 | Self::AnonymizedAggregate(AnonymizedAggregateSource { moniker, .. })
358 | Self::FilteredProvider(FilteredProviderSource { moniker, .. })
359 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
360 moniker, ..
361 }) => ExtendedMoniker::ComponentInstance(moniker.clone()),
362 Self::Builtin(_) | Self::Namespace(_) => ExtendedMoniker::ComponentManager,
363 }
364 }
365}
366
367impl fmt::Display for CapabilitySource {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 write!(
370 f,
371 "{}",
372 match self {
373 Self::Component(ComponentSource { capability, moniker }) => {
374 format!("{} '{}'", capability, moniker)
375 }
376 Self::Framework(FrameworkSource { capability, .. }) => capability.to_string(),
377 Self::Builtin(BuiltinSource { capability }) => capability.to_string(),
378 Self::Namespace(NamespaceSource { capability }) => capability.to_string(),
379 Self::FilteredProvider(FilteredProviderSource { capability, .. })
380 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
381 capability,
382 ..
383 }) => capability.to_string(),
384 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) =>
385 format!("{}", source_capability),
386 Self::AnonymizedAggregate(AnonymizedAggregateSource {
387 capability,
388 members,
389 moniker,
390 ..
391 }) => {
392 format!(
393 "{} from component '{}' aggregated from {}",
394 capability,
395 moniker,
396 members.iter().map(|s| format!("{s}")).collect::<Vec<_>>().join(","),
397 )
398 }
399 Self::Environment(EnvironmentSource { capability, .. }) => capability.to_string(),
400 Self::Void(VoidSource { capability, .. }) => capability.to_string(),
401 }
402 )
403 }
404}
405
406impl TryFrom<CapabilitySource> for Capability {
407 type Error = fidl::Error;
408
409 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
410 Ok(Data::try_from(capability_source)?.into())
411 }
412}
413
414impl TryFrom<CapabilitySource> for Data {
415 type Error = fidl::Error;
416
417 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
418 Ok(Data::Bytes(persist(&capability_source.native_into_fidl())?))
419 }
420}
421
422impl TryFrom<Capability> for CapabilitySource {
423 type Error = fidl::Error;
424
425 fn try_from(capability: Capability) -> Result<Self, Self::Error> {
426 let Capability::Data(data) = capability else {
427 return Err(fidl::Error::InvalidEnumValue);
428 };
429 Self::try_from(data)
430 }
431}
432
433impl TryFrom<Data> for CapabilitySource {
434 type Error = fidl::Error;
435
436 fn try_from(data: Data) -> Result<Self, Self::Error> {
437 let Data::Bytes(bytes) = data else {
438 return Err(fidl::Error::InvalidEnumValue);
439 };
440 Ok(unpersist::<finternal::CapabilitySource>(&bytes)?.fidl_into_native())
441 }
442}
443
444#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
446pub enum AggregateInstance {
447 Child(ChildName),
448 Parent,
449 Self_,
450}
451
452impl fmt::Display for AggregateInstance {
453 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454 match self {
455 Self::Child(n) => {
456 write!(f, "child `{n}`")
457 }
458 Self::Parent => {
459 write!(f, "parent")
460 }
461 Self::Self_ => {
462 write!(f, "self")
463 }
464 }
465 }
466}
467
468#[derive(Debug)]
472pub struct FilteredAggregateCapabilityRouteData {
473 pub capability_source: CapabilitySource,
475 pub instance_filter: Vec<NameMapping>,
478}
479
480pub trait FilteredAggregateCapabilityProvider: Send + Sync {
485 fn route_instances(
488 &self,
489 ) -> Vec<BoxFuture<'_, Result<FilteredAggregateCapabilityRouteData, RoutingError>>>;
490
491 fn clone_boxed(&self) -> Box<dyn FilteredAggregateCapabilityProvider>;
493}
494
495impl Clone for Box<dyn FilteredAggregateCapabilityProvider> {
496 fn clone(&self) -> Self {
497 self.clone_boxed()
498 }
499}
500
501impl fmt::Debug for Box<dyn FilteredAggregateCapabilityProvider> {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 f.debug_struct("Box<dyn FilteredAggregateCapabilityProvider>").finish()
504 }
505}
506
507#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
511#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
512#[fidl_decl(fidl_union = "finternal::InternalCapability")]
513pub enum InternalCapability {
514 Service(Name),
515 Protocol(Name),
516 Directory(Name),
517 Runner(Name),
518 Config(Name),
519 EventStream(Name),
520 Resolver(Name),
521 Storage(Name),
522 Dictionary(Name),
523}
524
525impl InternalCapability {
526 pub fn new(type_name: CapabilityTypeName, name: Name) -> Self {
527 match type_name {
528 CapabilityTypeName::Directory => InternalCapability::Directory(name),
529 CapabilityTypeName::EventStream => InternalCapability::Directory(name),
530 CapabilityTypeName::Protocol => InternalCapability::Protocol(name),
531 CapabilityTypeName::Resolver => InternalCapability::Resolver(name),
532 CapabilityTypeName::Runner => InternalCapability::Runner(name),
533 CapabilityTypeName::Service => InternalCapability::Service(name),
534 CapabilityTypeName::Storage => InternalCapability::Storage(name),
535 CapabilityTypeName::Dictionary => InternalCapability::Dictionary(name),
536 CapabilityTypeName::Config => InternalCapability::Config(name),
537 }
538 }
539
540 pub fn can_be_in_namespace(&self) -> bool {
542 matches!(
543 self,
544 InternalCapability::Service(_)
545 | InternalCapability::Protocol(_)
546 | InternalCapability::Directory(_)
547 )
548 }
549
550 pub fn type_name(&self) -> CapabilityTypeName {
552 match self {
553 InternalCapability::Service(_) => CapabilityTypeName::Service,
554 InternalCapability::Protocol(_) => CapabilityTypeName::Protocol,
555 InternalCapability::Directory(_) => CapabilityTypeName::Directory,
556 InternalCapability::Runner(_) => CapabilityTypeName::Runner,
557 InternalCapability::Config(_) => CapabilityTypeName::Config,
558 InternalCapability::EventStream(_) => CapabilityTypeName::EventStream,
559 InternalCapability::Resolver(_) => CapabilityTypeName::Resolver,
560 InternalCapability::Storage(_) => CapabilityTypeName::Storage,
561 InternalCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
562 }
563 }
564
565 pub fn source_name(&self) -> &Name {
566 match self {
567 InternalCapability::Service(name) => &name,
568 InternalCapability::Protocol(name) => &name,
569 InternalCapability::Directory(name) => &name,
570 InternalCapability::Runner(name) => &name,
571 InternalCapability::Config(name) => &name,
572 InternalCapability::EventStream(name) => &name,
573 InternalCapability::Resolver(name) => &name,
574 InternalCapability::Storage(name) => &name,
575 InternalCapability::Dictionary(name) => &name,
576 }
577 }
578
579 pub fn matches_protocol(&self, name: &Name) -> bool {
581 match self {
582 Self::Protocol(source_name) => source_name == name,
583 _ => false,
584 }
585 }
586}
587
588impl fmt::Display for InternalCapability {
589 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590 write!(f, "{} '{}' from component manager", self.type_name(), self.source_name())
591 }
592}
593
594impl From<CapabilityDecl> for InternalCapability {
595 fn from(capability: CapabilityDecl) -> Self {
596 match capability {
597 CapabilityDecl::Service(c) => InternalCapability::Service(c.name),
598 CapabilityDecl::Protocol(c) => InternalCapability::Protocol(c.name),
599 CapabilityDecl::Directory(c) => InternalCapability::Directory(c.name),
600 CapabilityDecl::Storage(c) => InternalCapability::Storage(c.name),
601 CapabilityDecl::Runner(c) => InternalCapability::Runner(c.name),
602 CapabilityDecl::Resolver(c) => InternalCapability::Resolver(c.name),
603 CapabilityDecl::EventStream(c) => InternalCapability::EventStream(c.name),
604 CapabilityDecl::Dictionary(c) => InternalCapability::Dictionary(c.name),
605 CapabilityDecl::Config(c) => InternalCapability::Config(c.name),
606 }
607 }
608}
609
610impl From<ServiceDecl> for InternalCapability {
611 fn from(service: ServiceDecl) -> Self {
612 Self::Service(service.name)
613 }
614}
615
616impl From<ProtocolDecl> for InternalCapability {
617 fn from(protocol: ProtocolDecl) -> Self {
618 Self::Protocol(protocol.name)
619 }
620}
621
622impl From<DirectoryDecl> for InternalCapability {
623 fn from(directory: DirectoryDecl) -> Self {
624 Self::Directory(directory.name)
625 }
626}
627
628impl From<RunnerDecl> for InternalCapability {
629 fn from(runner: RunnerDecl) -> Self {
630 Self::Runner(runner.name)
631 }
632}
633
634impl From<ResolverDecl> for InternalCapability {
635 fn from(resolver: ResolverDecl) -> Self {
636 Self::Resolver(resolver.name)
637 }
638}
639
640impl From<EventStreamDecl> for InternalCapability {
641 fn from(event: EventStreamDecl) -> Self {
642 Self::EventStream(event.name)
643 }
644}
645
646impl From<StorageDecl> for InternalCapability {
647 fn from(storage: StorageDecl) -> Self {
648 Self::Storage(storage.name)
649 }
650}
651
652impl From<cm_rust::ConfigurationDecl> for InternalCapability {
653 fn from(config: cm_rust::ConfigurationDecl) -> Self {
654 Self::Config(config.name)
655 }
656}
657
658#[cfg_attr(
660 feature = "serde",
661 derive(Deserialize, Serialize),
662 serde(tag = "type", rename_all = "snake_case")
663)]
664#[derive(FidlDecl, FromEnum, Clone, Debug, PartialEq, Eq)]
665#[fidl_decl(fidl_union = "finternal::ComponentCapability")]
666pub enum ComponentCapability {
667 Use_(UseDecl),
668 Environment(EnvironmentCapability),
670 Expose(ExposeDecl),
671 Offer(OfferDecl),
672 Protocol(ProtocolDecl),
673 Directory(DirectoryDecl),
674 Storage(StorageDecl),
675 Runner(RunnerDecl),
676 Resolver(ResolverDecl),
677 Service(ServiceDecl),
678 EventStream(EventStreamDecl),
679 Dictionary(DictionaryDecl),
680 Config(ConfigurationDecl),
681}
682
683impl ComponentCapability {
684 pub fn can_be_in_namespace(&self) -> bool {
686 match self {
687 ComponentCapability::Use_(use_) => {
688 matches!(use_, UseDecl::Protocol(_) | UseDecl::Directory(_) | UseDecl::Service(_))
689 }
690 ComponentCapability::Expose(expose) => matches!(
691 expose,
692 ExposeDecl::Protocol(_) | ExposeDecl::Directory(_) | ExposeDecl::Service(_)
693 ),
694 ComponentCapability::Offer(offer) => matches!(
695 offer,
696 OfferDecl::Protocol(_) | OfferDecl::Directory(_) | OfferDecl::Service(_)
697 ),
698 ComponentCapability::Protocol(_)
699 | ComponentCapability::Directory(_)
700 | ComponentCapability::Service(_) => true,
701 _ => false,
702 }
703 }
704
705 pub fn type_name(&self) -> CapabilityTypeName {
707 match self {
708 ComponentCapability::Use_(use_) => use_.into(),
709 ComponentCapability::Environment(env) => match env {
710 EnvironmentCapability::Runner(_) => CapabilityTypeName::Runner,
711 EnvironmentCapability::Resolver(_) => CapabilityTypeName::Resolver,
712 EnvironmentCapability::Debug(_) => CapabilityTypeName::Protocol,
713 },
714 ComponentCapability::Expose(expose) => expose.into(),
715 ComponentCapability::Offer(offer) => offer.into(),
716 ComponentCapability::Protocol(_) => CapabilityTypeName::Protocol,
717 ComponentCapability::Directory(_) => CapabilityTypeName::Directory,
718 ComponentCapability::Storage(_) => CapabilityTypeName::Storage,
719 ComponentCapability::Runner(_) => CapabilityTypeName::Runner,
720 ComponentCapability::Config(_) => CapabilityTypeName::Config,
721 ComponentCapability::Resolver(_) => CapabilityTypeName::Resolver,
722 ComponentCapability::Service(_) => CapabilityTypeName::Service,
723 ComponentCapability::EventStream(_) => CapabilityTypeName::EventStream,
724 ComponentCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
725 }
726 }
727
728 pub fn source_path(&self) -> Option<&Path> {
730 match self {
731 ComponentCapability::Storage(_) => None,
732 ComponentCapability::Protocol(protocol) => protocol.source_path.as_ref(),
733 ComponentCapability::Directory(directory) => directory.source_path.as_ref(),
734 ComponentCapability::Runner(runner) => runner.source_path.as_ref(),
735 ComponentCapability::Resolver(resolver) => resolver.source_path.as_ref(),
736 ComponentCapability::Service(service) => service.source_path.as_ref(),
737 _ => None,
738 }
739 }
740
741 pub fn source_name(&self) -> Option<&Name> {
743 match self {
744 ComponentCapability::Storage(storage) => Some(&storage.name),
745 ComponentCapability::Protocol(protocol) => Some(&protocol.name),
746 ComponentCapability::Directory(directory) => Some(&directory.name),
747 ComponentCapability::Runner(runner) => Some(&runner.name),
748 ComponentCapability::Config(config) => Some(&config.name),
749 ComponentCapability::Resolver(resolver) => Some(&resolver.name),
750 ComponentCapability::Service(service) => Some(&service.name),
751 ComponentCapability::EventStream(event) => Some(&event.name),
752 ComponentCapability::Dictionary(dictionary) => Some(&dictionary.name),
753 ComponentCapability::Use_(use_) => match use_ {
754 UseDecl::Protocol(UseProtocolDecl { source_name, .. }) => Some(source_name),
755 UseDecl::Directory(UseDirectoryDecl { source_name, .. }) => Some(source_name),
756 UseDecl::Storage(UseStorageDecl { source_name, .. }) => Some(source_name),
757 UseDecl::Service(UseServiceDecl { source_name, .. }) => Some(source_name),
758 UseDecl::Config(cm_rust::UseConfigurationDecl { source_name, .. }) => {
759 Some(source_name)
760 }
761 _ => None,
762 },
763 ComponentCapability::Environment(env_cap) => match env_cap {
764 EnvironmentCapability::Runner(EnvironmentCapabilityData {
765 source_name, ..
766 }) => Some(source_name),
767 EnvironmentCapability::Resolver(EnvironmentCapabilityData {
768 source_name, ..
769 }) => Some(source_name),
770 EnvironmentCapability::Debug(EnvironmentCapabilityData { source_name, .. }) => {
771 Some(source_name)
772 }
773 },
774 ComponentCapability::Expose(expose) => match expose {
775 ExposeDecl::Protocol(ExposeProtocolDecl { source_name, .. }) => Some(source_name),
776 ExposeDecl::Directory(ExposeDirectoryDecl { source_name, .. }) => Some(source_name),
777 ExposeDecl::Runner(ExposeRunnerDecl { source_name, .. }) => Some(source_name),
778 ExposeDecl::Resolver(ExposeResolverDecl { source_name, .. }) => Some(source_name),
779 ExposeDecl::Service(ExposeServiceDecl { source_name, .. }) => Some(source_name),
780 ExposeDecl::Config(ExposeConfigurationDecl { source_name, .. }) => {
781 Some(source_name)
782 }
783 ExposeDecl::Dictionary(ExposeDictionaryDecl { source_name, .. }) => {
784 Some(source_name)
785 }
786 },
787 ComponentCapability::Offer(offer) => match offer {
788 OfferDecl::Protocol(OfferProtocolDecl { source_name, .. }) => Some(source_name),
789 OfferDecl::Directory(OfferDirectoryDecl { source_name, .. }) => Some(source_name),
790 OfferDecl::Runner(OfferRunnerDecl { source_name, .. }) => Some(source_name),
791 OfferDecl::Storage(OfferStorageDecl { source_name, .. }) => Some(source_name),
792 OfferDecl::Resolver(OfferResolverDecl { source_name, .. }) => Some(source_name),
793 OfferDecl::Service(OfferServiceDecl { source_name, .. }) => Some(source_name),
794 OfferDecl::Config(OfferConfigurationDecl { source_name, .. }) => Some(source_name),
795 OfferDecl::EventStream(OfferEventStreamDecl { source_name, .. }) => {
796 Some(source_name)
797 }
798 OfferDecl::Dictionary(OfferDictionaryDecl { source_name, .. }) => Some(source_name),
799 },
800 }
801 }
802
803 pub fn source_capability_name(&self) -> Option<&Name> {
804 match self {
805 ComponentCapability::Offer(OfferDecl::Protocol(OfferProtocolDecl {
806 source: OfferSource::Capability(name),
807 ..
808 })) => Some(name),
809 ComponentCapability::Expose(ExposeDecl::Protocol(ExposeProtocolDecl {
810 source: ExposeSource::Capability(name),
811 ..
812 })) => Some(name),
813 ComponentCapability::Use_(UseDecl::Protocol(UseProtocolDecl {
814 source: UseSource::Capability(name),
815 ..
816 })) => Some(name),
817 _ => None,
818 }
819 }
820
821 pub fn source_id(&self) -> String {
823 self.source_name()
824 .map(|p| format!("{}", p))
825 .or_else(|| self.source_path().map(|p| format!("{}", p)))
826 .unwrap_or_default()
827 }
828}
829
830impl From<CapabilityDecl> for ComponentCapability {
831 fn from(capability: CapabilityDecl) -> Self {
832 match capability {
833 CapabilityDecl::Service(c) => ComponentCapability::Service(c),
834 CapabilityDecl::Protocol(c) => ComponentCapability::Protocol(c),
835 CapabilityDecl::Directory(c) => ComponentCapability::Directory(c),
836 CapabilityDecl::Storage(c) => ComponentCapability::Storage(c),
837 CapabilityDecl::Runner(c) => ComponentCapability::Runner(c),
838 CapabilityDecl::Resolver(c) => ComponentCapability::Resolver(c),
839 CapabilityDecl::EventStream(c) => ComponentCapability::EventStream(c),
840 CapabilityDecl::Dictionary(c) => ComponentCapability::Dictionary(c),
841 CapabilityDecl::Config(c) => ComponentCapability::Config(c),
842 }
843 }
844}
845
846impl fmt::Display for ComponentCapability {
847 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
848 write!(f, "{} '{}' from component", self.type_name(), self.source_id())
849 }
850}
851
852#[cfg_attr(
853 feature = "serde",
854 derive(Deserialize, Serialize),
855 serde(tag = "type", rename_all = "snake_case")
856)]
857#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
858#[fidl_decl(fidl_union = "finternal::EnvironmentCapability")]
859pub enum EnvironmentCapability {
860 Runner(EnvironmentCapabilityData),
861 Resolver(EnvironmentCapabilityData),
862 Debug(EnvironmentCapabilityData),
863}
864
865impl EnvironmentCapability {
866 pub fn registration_source(&self) -> &RegistrationSource {
867 match self {
868 Self::Runner(EnvironmentCapabilityData { source, .. })
869 | Self::Resolver(EnvironmentCapabilityData { source, .. })
870 | Self::Debug(EnvironmentCapabilityData { source, .. }) => &source,
871 }
872 }
873}
874
875#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
876#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
877#[fidl_decl(fidl_table = "finternal::EnvironmentSource")]
878pub struct EnvironmentCapabilityData {
879 source_name: Name,
880 source: RegistrationSource,
881}
882
883#[cfg_attr(
886 feature = "serde",
887 derive(Deserialize, Serialize),
888 serde(tag = "type", rename_all = "snake_case")
889)]
890#[derive(FidlDecl, Debug, Clone, PartialEq, Eq, Hash)]
891#[fidl_decl(fidl_union = "finternal::AggregateCapability")]
892pub enum AggregateCapability {
893 Service(Name),
894}
895
896impl AggregateCapability {
897 pub fn can_be_in_namespace(&self) -> bool {
899 matches!(self, AggregateCapability::Service(_))
900 }
901
902 pub fn type_name(&self) -> CapabilityTypeName {
904 match self {
905 AggregateCapability::Service(_) => CapabilityTypeName::Service,
906 }
907 }
908
909 pub fn source_name(&self) -> &Name {
910 match self {
911 AggregateCapability::Service(name) => &name,
912 }
913 }
914}
915
916impl fmt::Display for AggregateCapability {
917 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
918 write!(f, "aggregate {} '{}'", self.type_name(), self.source_name())
919 }
920}
921
922impl From<ServiceDecl> for AggregateCapability {
923 fn from(service: ServiceDecl) -> Self {
924 Self::Service(service.name)
925 }
926}
927
928pub type NamespaceCapabilities = Vec<CapabilityDecl>;
930
931pub type BuiltinCapabilities = Vec<CapabilityDecl>;
933
934#[cfg(test)]
935mod tests {
936 use super::*;
937 use cm_rust::StorageDirectorySource;
938
939 #[test]
940 fn capability_type_name() {
941 let storage_capability = ComponentCapability::Storage(StorageDecl {
942 name: "foo".parse().unwrap(),
943 source: StorageDirectorySource::Parent,
944 backing_dir: "bar".parse().unwrap(),
945 subdir: Default::default(),
946 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
947 });
948 assert_eq!(storage_capability.type_name(), CapabilityTypeName::Storage);
949 }
950}