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, RelativePath};
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 StorageBackingDirectory(StorageBackingDirectorySource),
206}
207
208#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
209#[derive(FidlDecl, Debug, PartialEq, Clone)]
210#[fidl_decl(fidl_table = "finternal::Component")]
211pub struct ComponentSource {
212 pub capability: ComponentCapability,
213 pub moniker: Moniker,
214}
215#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
216#[derive(FidlDecl, Debug, PartialEq, Clone)]
217#[fidl_decl(fidl_table = "finternal::Framework")]
218pub struct FrameworkSource {
219 pub capability: InternalCapability,
220 pub moniker: Moniker,
221}
222#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
223#[derive(FidlDecl, Debug, PartialEq, Clone)]
224#[fidl_decl(fidl_table = "finternal::Builtin")]
225pub struct BuiltinSource {
226 pub capability: InternalCapability,
227}
228#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
229#[derive(FidlDecl, Debug, PartialEq, Clone)]
230#[fidl_decl(fidl_table = "finternal::Namespace")]
231pub struct NamespaceSource {
232 pub capability: ComponentCapability,
233}
234#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
235#[derive(FidlDecl, Debug, PartialEq, Clone)]
236#[fidl_decl(fidl_table = "finternal::Capability")]
237pub struct CapabilityToCapabilitySource {
238 pub source_capability: ComponentCapability,
239 pub moniker: Moniker,
240}
241#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
242#[derive(FidlDecl, Debug, PartialEq, Clone)]
243#[fidl_decl(fidl_table = "finternal::AnonymizedAggregate")]
244pub struct AnonymizedAggregateSource {
245 pub capability: AggregateCapability,
246 pub moniker: Moniker,
247 pub members: Vec<AggregateMember>,
248 pub sources: Sources,
249 pub instances: Vec<ServiceInstance>,
250}
251#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
252#[derive(FidlDecl, Debug, PartialEq, Clone)]
253#[fidl_decl(fidl_table = "fsys::ServiceInstance")]
254pub struct ServiceInstance {
255 pub instance_name: Name,
256 pub child_name: String,
257 pub child_instance_name: Name,
258}
259#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
260#[derive(FidlDecl, Debug, PartialEq, Clone)]
261#[fidl_decl(fidl_table = "finternal::FilteredProvider")]
262pub struct FilteredProviderSource {
263 pub capability: AggregateCapability,
264 pub moniker: Moniker,
265 pub service_capability: ComponentCapability,
266 pub offer_service_decl: OfferServiceDecl,
267}
268#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
269#[derive(FidlDecl, Debug, PartialEq, Clone)]
270#[fidl_decl(fidl_table = "finternal::FilteredAggregateProvider")]
271pub struct FilteredAggregateProviderSource {
272 pub capability: AggregateCapability,
273 pub moniker: Moniker,
274 pub offer_service_decls: Vec<OfferServiceDecl>,
275 pub sources: Sources,
276}
277#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
278#[derive(FidlDecl, Debug, PartialEq, Clone)]
279#[fidl_decl(fidl_table = "finternal::Environment")]
280pub struct EnvironmentSource {
281 pub capability: ComponentCapability,
282 pub moniker: Moniker,
283}
284#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
285#[derive(FidlDecl, Debug, PartialEq, Clone)]
286#[fidl_decl(fidl_table = "finternal::Void")]
287pub struct VoidSource {
288 pub capability: InternalCapability,
289 pub moniker: Moniker,
290}
291
292#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
293#[derive(FidlDecl, Debug, PartialEq, Clone)]
294#[fidl_decl(fidl_table = "finternal::StorageBackingDirectory")]
295pub struct StorageBackingDirectorySource {
296 pub capability: ComponentCapability,
297 pub moniker: Moniker,
298 pub backing_dir_subdir: RelativePath,
299 pub storage_subdir: RelativePath,
300 pub storage_source_moniker: Moniker,
301}
302
303impl CapabilitySource {
304 pub fn source_name(&self) -> Option<&Name> {
305 match self {
306 Self::Component(ComponentSource { capability, .. }) => capability.source_name(),
307 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.source_name()),
308 Self::Builtin(BuiltinSource { capability }) => Some(capability.source_name()),
309 Self::Namespace(NamespaceSource { capability }) => capability.source_name(),
310 Self::Capability(CapabilityToCapabilitySource { .. }) => None,
311 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
312 Some(capability.source_name())
313 }
314 Self::FilteredProvider(FilteredProviderSource { capability, .. })
315 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
316 capability, ..
317 }) => Some(capability.source_name()),
318 Self::Environment(EnvironmentSource { capability, .. }) => capability.source_name(),
319 Self::Void(VoidSource { capability, .. }) => Some(capability.source_name()),
320 Self::RemotedAt(_) => None,
321 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
322 capability.source_name()
323 }
324 }
325 }
326
327 pub fn type_name(&self) -> CapabilityTypeName {
328 match self {
329 Self::Component(ComponentSource { capability, .. }) => capability.type_name(),
330 Self::Framework(FrameworkSource { capability, .. }) => capability.type_name(),
331 Self::Builtin(BuiltinSource { capability }) => capability.type_name(),
332 Self::Namespace(NamespaceSource { capability }) => capability.type_name(),
333 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) => {
334 source_capability.type_name()
335 }
336 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
337 capability.type_name()
338 }
339 Self::FilteredProvider(FilteredProviderSource { capability, .. })
340 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
341 capability, ..
342 }) => capability.type_name(),
343 Self::Environment(EnvironmentSource { capability, .. }) => capability.type_name(),
344 Self::Void(VoidSource { capability, .. }) => capability.type_name(),
345 Self::RemotedAt(_) => unimplemented!(),
346 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
347 capability.type_name()
348 }
349 }
350 }
351
352 pub fn source_moniker(&self) -> ExtendedMoniker {
353 match self {
354 Self::Component(ComponentSource { moniker, .. })
355 | Self::Framework(FrameworkSource { moniker, .. })
356 | Self::Capability(CapabilityToCapabilitySource { moniker, .. })
357 | Self::Environment(EnvironmentSource { moniker, .. })
358 | Self::Void(VoidSource { moniker, .. })
359 | Self::StorageBackingDirectory(StorageBackingDirectorySource { moniker, .. })
360 | Self::AnonymizedAggregate(AnonymizedAggregateSource { moniker, .. })
361 | Self::FilteredProvider(FilteredProviderSource { moniker, .. })
362 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
363 moniker, ..
364 })
365 | Self::RemotedAt(moniker) => ExtendedMoniker::ComponentInstance(moniker.clone()),
366 Self::Builtin(_) | Self::Namespace(_) => ExtendedMoniker::ComponentManager,
367 }
368 }
369}
370
371impl fmt::Display for CapabilitySource {
372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373 write!(
374 f,
375 "{}",
376 match self {
377 Self::Component(ComponentSource { capability, moniker })
378 | Self::StorageBackingDirectory(StorageBackingDirectorySource {
379 capability,
380 moniker,
381 ..
382 }) => {
383 format!("{} '{}'", capability, moniker)
384 }
385 Self::Framework(FrameworkSource { capability, .. }) => capability.to_string(),
386 Self::Builtin(BuiltinSource { capability }) => capability.to_string(),
387 Self::Namespace(NamespaceSource { capability }) => capability.to_string(),
388 Self::FilteredProvider(FilteredProviderSource { capability, .. })
389 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
390 capability,
391 ..
392 }) => capability.to_string(),
393 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) =>
394 format!("{}", source_capability),
395 Self::AnonymizedAggregate(AnonymizedAggregateSource {
396 capability,
397 members,
398 moniker,
399 ..
400 }) => {
401 format!(
402 "{} from component '{}' aggregated from {}",
403 capability,
404 moniker,
405 members.iter().map(|s| format!("{s}")).collect::<Vec<_>>().join(","),
406 )
407 }
408 Self::Environment(EnvironmentSource { capability, .. }) => capability.to_string(),
409 Self::Void(VoidSource { capability, .. }) => capability.to_string(),
410 Self::RemotedAt(moniker) => format!("route left component manager at {}", moniker),
411 }
412 )
413 }
414}
415
416impl TryFrom<CapabilitySource> for Capability {
417 type Error = fidl::Error;
418
419 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
420 Ok(Data::try_from(capability_source)?.into())
421 }
422}
423
424impl TryFrom<CapabilitySource> for Data {
425 type Error = fidl::Error;
426
427 fn try_from(capability_source: CapabilitySource) -> Result<Self, Self::Error> {
428 Ok(Data::Bytes(persist(&capability_source.native_into_fidl())?.into()))
429 }
430}
431
432impl TryFrom<Capability> for CapabilitySource {
433 type Error = fidl::Error;
434
435 fn try_from(capability: Capability) -> Result<Self, Self::Error> {
436 let Capability::Data(data) = capability else {
437 return Err(fidl::Error::InvalidEnumValue);
438 };
439 Self::try_from(data)
440 }
441}
442
443impl TryFrom<Data> for CapabilitySource {
444 type Error = fidl::Error;
445
446 fn try_from(data: Data) -> Result<Self, Self::Error> {
447 let Data::Bytes(bytes) = data else {
448 return Err(fidl::Error::InvalidEnumValue);
449 };
450 Ok(unpersist::<finternal::CapabilitySource>(&bytes)?.fidl_into_native())
451 }
452}
453
454#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
456pub enum AggregateInstance {
457 Child(ChildName),
458 Parent,
459 Self_,
460}
461
462impl fmt::Display for AggregateInstance {
463 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
464 match self {
465 Self::Child(n) => {
466 write!(f, "child `{n}`")
467 }
468 Self::Parent => {
469 write!(f, "parent")
470 }
471 Self::Self_ => {
472 write!(f, "self")
473 }
474 }
475 }
476}
477
478#[derive(Debug)]
482pub struct FilteredAggregateCapabilityRouteData {
483 pub capability_source: CapabilitySource,
485 pub instance_filter: Vec<NameMapping>,
488}
489
490pub trait FilteredAggregateCapabilityProvider: Send + Sync {
495 fn route_instances(
498 &self,
499 ) -> Vec<BoxFuture<'_, Result<FilteredAggregateCapabilityRouteData, RoutingError>>>;
500
501 fn clone_boxed(&self) -> Box<dyn FilteredAggregateCapabilityProvider>;
503}
504
505impl Clone for Box<dyn FilteredAggregateCapabilityProvider> {
506 fn clone(&self) -> Self {
507 self.clone_boxed()
508 }
509}
510
511impl fmt::Debug for Box<dyn FilteredAggregateCapabilityProvider> {
512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513 f.debug_struct("Box<dyn FilteredAggregateCapabilityProvider>").finish()
514 }
515}
516
517#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
521#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
522#[fidl_decl(fidl_union = "finternal::InternalCapability")]
523pub enum InternalCapability {
524 Service(Name),
525 Protocol(Name),
526 Directory(Name),
527 Runner(Name),
528 Config(Name),
529 EventStream(Name),
530 Resolver(Name),
531 Storage(Name),
532 Dictionary(Name),
533}
534
535impl InternalCapability {
536 pub fn new(type_name: CapabilityTypeName, name: Name) -> Self {
537 match type_name {
538 CapabilityTypeName::Directory => InternalCapability::Directory(name),
539 CapabilityTypeName::EventStream => InternalCapability::Directory(name),
540 CapabilityTypeName::Protocol => InternalCapability::Protocol(name),
541 CapabilityTypeName::Resolver => InternalCapability::Resolver(name),
542 CapabilityTypeName::Runner => InternalCapability::Runner(name),
543 CapabilityTypeName::Service => InternalCapability::Service(name),
544 CapabilityTypeName::Storage => InternalCapability::Storage(name),
545 CapabilityTypeName::Dictionary => InternalCapability::Dictionary(name),
546 CapabilityTypeName::Config => InternalCapability::Config(name),
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 type_name(&self) -> CapabilityTypeName {
686 match self {
687 ComponentCapability::Use_(use_) => use_.into(),
688 ComponentCapability::Environment(env) => match env {
689 EnvironmentCapability::Runner(_) => CapabilityTypeName::Runner,
690 EnvironmentCapability::Resolver(_) => CapabilityTypeName::Resolver,
691 EnvironmentCapability::Debug(_) => CapabilityTypeName::Protocol,
692 },
693 ComponentCapability::Expose(expose) => expose.into(),
694 ComponentCapability::Offer(offer) => offer.into(),
695 ComponentCapability::Protocol(_) => CapabilityTypeName::Protocol,
696 ComponentCapability::Directory(_) => CapabilityTypeName::Directory,
697 ComponentCapability::Storage(_) => CapabilityTypeName::Storage,
698 ComponentCapability::Runner(_) => CapabilityTypeName::Runner,
699 ComponentCapability::Config(_) => CapabilityTypeName::Config,
700 ComponentCapability::Resolver(_) => CapabilityTypeName::Resolver,
701 ComponentCapability::Service(_) => CapabilityTypeName::Service,
702 ComponentCapability::EventStream(_) => CapabilityTypeName::EventStream,
703 ComponentCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
704 }
705 }
706
707 pub fn source_path(&self) -> Option<&Path> {
709 match self {
710 ComponentCapability::Storage(_) => None,
711 ComponentCapability::Protocol(protocol) => protocol.source_path.as_ref(),
712 ComponentCapability::Directory(directory) => directory.source_path.as_ref(),
713 ComponentCapability::Runner(runner) => runner.source_path.as_ref(),
714 ComponentCapability::Resolver(resolver) => resolver.source_path.as_ref(),
715 ComponentCapability::Service(service) => service.source_path.as_ref(),
716 _ => None,
717 }
718 }
719
720 pub fn source_name(&self) -> Option<&Name> {
722 match self {
723 ComponentCapability::Storage(storage) => Some(&storage.name),
724 ComponentCapability::Protocol(protocol) => Some(&protocol.name),
725 ComponentCapability::Directory(directory) => Some(&directory.name),
726 ComponentCapability::Runner(runner) => Some(&runner.name),
727 ComponentCapability::Config(config) => Some(&config.name),
728 ComponentCapability::Resolver(resolver) => Some(&resolver.name),
729 ComponentCapability::Service(service) => Some(&service.name),
730 ComponentCapability::EventStream(event) => Some(&event.name),
731 ComponentCapability::Dictionary(dictionary) => Some(&dictionary.name),
732 ComponentCapability::Use_(use_) => match use_ {
733 UseDecl::Protocol(UseProtocolDecl { source_name, .. }) => Some(source_name),
734 UseDecl::Directory(UseDirectoryDecl { source_name, .. }) => Some(source_name),
735 UseDecl::Storage(UseStorageDecl { source_name, .. }) => Some(source_name),
736 UseDecl::Service(UseServiceDecl { source_name, .. }) => Some(source_name),
737 UseDecl::Config(cm_rust::UseConfigurationDecl { source_name, .. }) => {
738 Some(source_name)
739 }
740 _ => None,
741 },
742 ComponentCapability::Environment(env_cap) => match env_cap {
743 EnvironmentCapability::Runner(EnvironmentCapabilityData {
744 source_name, ..
745 }) => Some(source_name),
746 EnvironmentCapability::Resolver(EnvironmentCapabilityData {
747 source_name, ..
748 }) => Some(source_name),
749 EnvironmentCapability::Debug(EnvironmentCapabilityData { source_name, .. }) => {
750 Some(source_name)
751 }
752 },
753 ComponentCapability::Expose(expose) => match expose {
754 ExposeDecl::Protocol(ExposeProtocolDecl { source_name, .. }) => Some(source_name),
755 ExposeDecl::Directory(ExposeDirectoryDecl { source_name, .. }) => Some(source_name),
756 ExposeDecl::Runner(ExposeRunnerDecl { source_name, .. }) => Some(source_name),
757 ExposeDecl::Resolver(ExposeResolverDecl { source_name, .. }) => Some(source_name),
758 ExposeDecl::Service(ExposeServiceDecl { source_name, .. }) => Some(source_name),
759 ExposeDecl::Config(ExposeConfigurationDecl { source_name, .. }) => {
760 Some(source_name)
761 }
762 ExposeDecl::Dictionary(ExposeDictionaryDecl { source_name, .. }) => {
763 Some(source_name)
764 }
765 },
766 ComponentCapability::Offer(offer) => match offer {
767 OfferDecl::Protocol(OfferProtocolDecl { source_name, .. }) => Some(source_name),
768 OfferDecl::Directory(OfferDirectoryDecl { source_name, .. }) => Some(source_name),
769 OfferDecl::Runner(OfferRunnerDecl { source_name, .. }) => Some(source_name),
770 OfferDecl::Storage(OfferStorageDecl { source_name, .. }) => Some(source_name),
771 OfferDecl::Resolver(OfferResolverDecl { source_name, .. }) => Some(source_name),
772 OfferDecl::Service(OfferServiceDecl { source_name, .. }) => Some(source_name),
773 OfferDecl::Config(OfferConfigurationDecl { source_name, .. }) => Some(source_name),
774 OfferDecl::EventStream(OfferEventStreamDecl { source_name, .. }) => {
775 Some(source_name)
776 }
777 OfferDecl::Dictionary(OfferDictionaryDecl { source_name, .. }) => Some(source_name),
778 },
779 }
780 }
781
782 pub fn source_capability_name(&self) -> Option<&Name> {
783 match self {
784 ComponentCapability::Offer(OfferDecl::Protocol(OfferProtocolDecl {
785 source: OfferSource::Capability(name),
786 ..
787 })) => Some(name),
788 ComponentCapability::Expose(ExposeDecl::Protocol(ExposeProtocolDecl {
789 source: ExposeSource::Capability(name),
790 ..
791 })) => Some(name),
792 ComponentCapability::Use_(UseDecl::Protocol(UseProtocolDecl {
793 source: UseSource::Capability(name),
794 ..
795 })) => Some(name),
796 _ => None,
797 }
798 }
799
800 pub fn source_id(&self) -> String {
802 self.source_name()
803 .map(|p| format!("{}", p))
804 .or_else(|| self.source_path().map(|p| format!("{}", p)))
805 .unwrap_or_default()
806 }
807}
808
809impl From<CapabilityDecl> for ComponentCapability {
810 fn from(capability: CapabilityDecl) -> Self {
811 match capability {
812 CapabilityDecl::Service(c) => ComponentCapability::Service(c),
813 CapabilityDecl::Protocol(c) => ComponentCapability::Protocol(c),
814 CapabilityDecl::Directory(c) => ComponentCapability::Directory(c),
815 CapabilityDecl::Storage(c) => ComponentCapability::Storage(c),
816 CapabilityDecl::Runner(c) => ComponentCapability::Runner(c),
817 CapabilityDecl::Resolver(c) => ComponentCapability::Resolver(c),
818 CapabilityDecl::EventStream(c) => ComponentCapability::EventStream(c),
819 CapabilityDecl::Dictionary(c) => ComponentCapability::Dictionary(c),
820 CapabilityDecl::Config(c) => ComponentCapability::Config(c),
821 }
822 }
823}
824
825impl TryInto<CapabilityDecl> for ComponentCapability {
826 type Error = ();
827
828 fn try_into(self) -> Result<CapabilityDecl, Self::Error> {
829 match self {
830 Self::Service(c) => Ok(CapabilityDecl::Service(c)),
831 Self::Protocol(c) => Ok(CapabilityDecl::Protocol(c)),
832 Self::Directory(c) => Ok(CapabilityDecl::Directory(c)),
833 Self::Storage(c) => Ok(CapabilityDecl::Storage(c)),
834 Self::Runner(c) => Ok(CapabilityDecl::Runner(c)),
835 Self::Resolver(c) => Ok(CapabilityDecl::Resolver(c)),
836 Self::EventStream(c) => Ok(CapabilityDecl::EventStream(c)),
837 Self::Dictionary(c) => Ok(CapabilityDecl::Dictionary(c)),
838 Self::Config(c) => Ok(CapabilityDecl::Config(c)),
839 _ => Err(()),
840 }
841 }
842}
843
844impl fmt::Display for ComponentCapability {
845 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
846 write!(f, "{} '{}' from component", self.type_name(), self.source_id())
847 }
848}
849
850#[cfg_attr(
851 feature = "serde",
852 derive(Deserialize, Serialize),
853 serde(tag = "type", rename_all = "snake_case")
854)]
855#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
856#[fidl_decl(fidl_union = "finternal::EnvironmentCapability")]
857pub enum EnvironmentCapability {
858 Runner(EnvironmentCapabilityData),
859 Resolver(EnvironmentCapabilityData),
860 Debug(EnvironmentCapabilityData),
861}
862
863impl EnvironmentCapability {
864 pub fn registration_source(&self) -> &RegistrationSource {
865 match self {
866 Self::Runner(EnvironmentCapabilityData { source, .. })
867 | Self::Resolver(EnvironmentCapabilityData { source, .. })
868 | Self::Debug(EnvironmentCapabilityData { source, .. }) => &source,
869 }
870 }
871}
872
873#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
874#[derive(FidlDecl, Clone, Debug, PartialEq, Eq)]
875#[fidl_decl(fidl_table = "finternal::EnvironmentSource")]
876pub struct EnvironmentCapabilityData {
877 source_name: Name,
878 source: RegistrationSource,
879}
880
881#[cfg_attr(
884 feature = "serde",
885 derive(Deserialize, Serialize),
886 serde(tag = "type", rename_all = "snake_case")
887)]
888#[derive(FidlDecl, Debug, Clone, PartialEq, Eq, Hash)]
889#[fidl_decl(fidl_union = "finternal::AggregateCapability")]
890pub enum AggregateCapability {
891 Service(Name),
892}
893
894impl AggregateCapability {
895 pub fn type_name(&self) -> CapabilityTypeName {
897 match self {
898 AggregateCapability::Service(_) => CapabilityTypeName::Service,
899 }
900 }
901
902 pub fn source_name(&self) -> &Name {
903 match self {
904 AggregateCapability::Service(name) => &name,
905 }
906 }
907}
908
909impl fmt::Display for AggregateCapability {
910 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911 write!(f, "aggregate {} '{}'", self.type_name(), self.source_name())
912 }
913}
914
915impl From<ServiceDecl> for AggregateCapability {
916 fn from(service: ServiceDecl) -> Self {
917 Self::Service(service.name)
918 }
919}
920
921pub type NamespaceCapabilities = Vec<CapabilityDecl>;
923
924pub type BuiltinCapabilities = Vec<CapabilityDecl>;
926
927#[cfg(test)]
928mod tests {
929 use super::*;
930 use cm_rust::StorageDirectorySource;
931
932 #[test]
933 fn capability_type_name() {
934 let storage_capability = ComponentCapability::Storage(StorageDecl {
935 name: "foo".parse().unwrap(),
936 source: StorageDirectorySource::Parent,
937 backing_dir: "bar".parse().unwrap(),
938 subdir: Default::default(),
939 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
940 });
941 assert_eq!(storage_capability.type_name(), CapabilityTypeName::Storage);
942 }
943}