1use cm_rust::{
6 CapabilityDecl, CapabilityTypeName, ChildRef, ConfigurationDecl, DictionaryDecl, DirectoryDecl,
7 EventStreamDecl, ExposeConfigurationDecl, ExposeDecl, ExposeDeclCommon, ExposeDictionaryDecl,
8 ExposeDirectoryDecl, ExposeProtocolDecl, ExposeResolverDecl, ExposeRunnerDecl,
9 ExposeServiceDecl, ExposeSource, OfferConfigurationDecl, OfferDecl, OfferDeclCommon,
10 OfferDictionaryDecl, OfferProtocolDecl, OfferResolverDecl, OfferRunnerDecl, OfferServiceDecl,
11 OfferSource, OfferStorageDecl, ProtocolDecl, RegistrationSource, ResolverDecl, RunnerDecl,
12 ServiceDecl, StorageDecl, UseDecl, UseDeclCommon, UseDirectoryDecl, UseProtocolDecl,
13 UseServiceDecl, UseSource, UseStorageDecl,
14};
15use cm_types::{Name, Path, RelativePath};
16use fidl_fuchsia_sys2 as fsys;
17use from_enum::FromEnum;
18use moniker::{ChildName, ExtendedMoniker, Moniker};
19use std::fmt;
20use thiserror::Error;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Error)]
26pub enum Error {
27 #[error("Invalid framework capability.")]
28 InvalidFrameworkCapability {},
29 #[error("Invalid builtin capability.")]
30 InvalidBuiltinCapability {},
31}
32
33#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
34#[derive(Debug, Hash, PartialEq, Eq, Clone)]
35pub enum AggregateMember {
36 Child(ChildRef),
37 Collection(Name),
38 Parent,
39 Self_,
40}
41
42impl TryFrom<&OfferDecl> for AggregateMember {
43 type Error = ();
44
45 fn try_from(offer: &OfferDecl) -> Result<AggregateMember, ()> {
46 match offer.source() {
47 OfferSource::Framework => Err(()),
49 OfferSource::Parent => Ok(AggregateMember::Parent),
50 OfferSource::Child(child) => Ok(AggregateMember::Child(child.clone())),
51 OfferSource::Collection(name) => Ok(AggregateMember::Collection(name.clone())),
52 OfferSource::Self_ => Ok(AggregateMember::Self_),
53 OfferSource::Capability(_name) => Err(()),
54 OfferSource::Void => Err(()),
55 }
56 }
57}
58
59impl TryFrom<&cm_rust::ExposeDecl> for AggregateMember {
60 type Error = ();
61
62 fn try_from(expose: &cm_rust::ExposeDecl) -> Result<AggregateMember, ()> {
63 match expose.source() {
64 cm_rust::ExposeSource::Framework => Err(()),
66 cm_rust::ExposeSource::Child(child) => Ok(AggregateMember::Child(cm_rust::ChildRef {
67 name: child.clone().into(),
68 collection: None,
69 })),
70 cm_rust::ExposeSource::Collection(name) => {
71 Ok(AggregateMember::Collection(name.clone()))
72 }
73 cm_rust::ExposeSource::Self_ => Ok(AggregateMember::Self_),
74 cm_rust::ExposeSource::Capability(_name) => Err(()),
75 cm_rust::ExposeSource::Void => Err(()),
76 }
77 }
78}
79
80impl TryFrom<&cm_rust::UseDecl> for AggregateMember {
81 type Error = ();
82
83 fn try_from(use_: &cm_rust::UseDecl) -> Result<AggregateMember, ()> {
84 match use_.source() {
85 cm_rust::UseSource::Parent => Ok(AggregateMember::Parent),
86 cm_rust::UseSource::Framework => Err(()),
87 cm_rust::UseSource::Debug => Err(()),
88 cm_rust::UseSource::Self_ => Ok(AggregateMember::Self_),
89 cm_rust::UseSource::Capability(_) => Err(()),
90 cm_rust::UseSource::Child(name) => {
91 Ok(AggregateMember::Child(ChildRef { name: name.clone().into(), collection: None }))
92 }
93 cm_rust::UseSource::Collection(name) => Ok(AggregateMember::Collection(name.clone())),
94 cm_rust::UseSource::Environment => Err(()),
95 }
96 }
97}
98
99impl fmt::Display for AggregateMember {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Self::Child(n) => {
103 write!(f, "child `{n}`")
104 }
105 Self::Collection(n) => {
106 write!(f, "collection `{n}`")
107 }
108 Self::Parent => {
109 write!(f, "parent")
110 }
111 Self::Self_ => {
112 write!(f, "self")
113 }
114 }
115 }
116}
117
118#[cfg_attr(
120 feature = "serde",
121 derive(Deserialize, Serialize),
122 serde(tag = "type", rename_all = "snake_case")
123)]
124#[derive(Debug, Clone, PartialEq)]
125pub enum CapabilitySource {
126 Component(ComponentSource),
129 Framework(FrameworkSource),
132 Builtin(BuiltinSource),
136 Namespace(NamespaceSource),
140 Capability(CapabilityToCapabilitySource),
142 AnonymizedAggregate(AnonymizedAggregateSource),
145 FilteredProvider(FilteredProviderSource),
148 FilteredAggregateProvider(FilteredAggregateProviderSource),
152 Environment(EnvironmentSource),
154 Void(VoidSource),
157 RemotedAt(RemotedAtSource),
160 StorageBackingDirectory(StorageBackingDirectorySource),
163}
164
165#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
166#[derive(Debug, PartialEq, Clone)]
167pub struct ComponentSource {
168 pub capability: ComponentCapability,
169 pub moniker: Moniker,
170}
171#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
172#[derive(Debug, PartialEq, Clone)]
173pub struct FrameworkSource {
174 pub capability: InternalCapability,
175 pub moniker: Moniker,
176}
177#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
178#[derive(Debug, PartialEq, Clone)]
179pub struct BuiltinSource {
180 pub capability: InternalCapability,
181}
182#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
183#[derive(Debug, PartialEq, Clone)]
184pub struct NamespaceSource {
185 pub capability: ComponentCapability,
186}
187#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
188#[derive(Debug, PartialEq, Clone)]
189pub struct CapabilityToCapabilitySource {
190 pub source_capability: ComponentCapability,
191 pub moniker: Moniker,
192}
193#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
194#[derive(Debug, PartialEq, Clone)]
195pub struct AnonymizedAggregateSource {
196 pub capability: AggregateCapability,
197 pub moniker: Moniker,
198 pub members: Vec<AggregateMember>,
199 pub instances: Vec<ServiceInstance>,
200}
201#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
202#[derive(Debug, PartialEq, Clone)]
203pub struct ServiceInstance {
204 pub instance_name: Name,
205 pub child_name: String,
206 pub child_instance_name: Name,
207}
208
209impl From<ServiceInstance> for fsys::ServiceInstance {
210 fn from(service_instance: ServiceInstance) -> Self {
211 Self {
212 instance_name: Some(service_instance.instance_name.to_string()),
213 child_name: Some(service_instance.child_name),
214 child_instance_name: Some(service_instance.child_instance_name.to_string()),
215 ..Default::default()
216 }
217 }
218}
219
220#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
221#[derive(Debug, PartialEq, Clone)]
222pub struct FilteredProviderSource {
223 pub capability: AggregateCapability,
224 pub moniker: Moniker,
225 pub service_capability: ComponentCapability,
226 pub offer_service_decl: OfferServiceDecl,
227}
228#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
229#[derive(Debug, PartialEq, Clone)]
230pub struct FilteredAggregateProviderSource {
231 pub capability: AggregateCapability,
232 pub moniker: Moniker,
233 pub offer_service_decls: Vec<OfferServiceDecl>,
234}
235#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
236#[derive(Debug, PartialEq, Clone)]
237pub struct EnvironmentSource {
238 pub capability: ComponentCapability,
239 pub moniker: Moniker,
240}
241#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
242#[derive(Debug, PartialEq, Clone)]
243pub struct VoidSource {
244 pub capability: InternalCapability,
245 pub moniker: Moniker,
246}
247#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
248#[derive(Debug, PartialEq, Clone)]
249pub struct RemotedAtSource {
250 pub moniker: Moniker,
251 pub type_name: Option<CapabilityTypeName>,
252}
253
254#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
255#[derive(Debug, PartialEq, Clone)]
256pub struct StorageBackingDirectorySource {
257 pub capability: ComponentCapability,
258 pub moniker: Moniker,
259 pub backing_dir_subdir: RelativePath,
260 pub storage_subdir: RelativePath,
261 pub storage_source_moniker: Moniker,
262}
263
264impl CapabilitySource {
265 pub fn source_name(&self) -> Option<&Name> {
266 match self {
267 Self::Component(ComponentSource { capability, .. }) => capability.source_name(),
268 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.source_name()),
269 Self::Builtin(BuiltinSource { capability }) => Some(capability.source_name()),
270 Self::Namespace(NamespaceSource { capability }) => capability.source_name(),
271 Self::Capability(CapabilityToCapabilitySource { .. }) => None,
272 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
273 Some(capability.source_name())
274 }
275 Self::FilteredProvider(FilteredProviderSource { capability, .. })
276 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
277 capability, ..
278 }) => Some(capability.source_name()),
279 Self::Environment(EnvironmentSource { capability, .. }) => capability.source_name(),
280 Self::Void(VoidSource { capability, .. }) => Some(capability.source_name()),
281 Self::RemotedAt(_) => None,
282 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
283 capability.source_name()
284 }
285 }
286 }
287
288 pub fn type_name(&self) -> Option<CapabilityTypeName> {
292 match self {
293 Self::Component(ComponentSource { capability, .. }) => Some(capability.type_name()),
294 Self::Framework(FrameworkSource { capability, .. }) => Some(capability.type_name()),
295 Self::Builtin(BuiltinSource { capability }) => Some(capability.type_name()),
296 Self::Namespace(NamespaceSource { capability }) => Some(capability.type_name()),
297 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) => {
298 Some(source_capability.type_name())
299 }
300 Self::AnonymizedAggregate(AnonymizedAggregateSource { capability, .. }) => {
301 Some(capability.type_name())
302 }
303 Self::FilteredProvider(FilteredProviderSource { capability, .. })
304 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
305 capability, ..
306 }) => Some(capability.type_name()),
307 Self::Environment(EnvironmentSource { capability, .. }) => Some(capability.type_name()),
308 Self::Void(VoidSource { capability, .. }) => Some(capability.type_name()),
309 Self::RemotedAt(RemotedAtSource { type_name, .. }) => type_name.clone(),
310 Self::StorageBackingDirectory(StorageBackingDirectorySource { capability, .. }) => {
311 Some(capability.type_name())
312 }
313 }
314 }
315
316 pub fn source_moniker(&self) -> ExtendedMoniker {
317 match self {
318 Self::Component(ComponentSource { moniker, .. })
319 | Self::Framework(FrameworkSource { moniker, .. })
320 | Self::Capability(CapabilityToCapabilitySource { moniker, .. })
321 | Self::Environment(EnvironmentSource { moniker, .. })
322 | Self::Void(VoidSource { moniker, .. })
323 | Self::StorageBackingDirectory(StorageBackingDirectorySource { moniker, .. })
324 | Self::AnonymizedAggregate(AnonymizedAggregateSource { moniker, .. })
325 | Self::FilteredProvider(FilteredProviderSource { moniker, .. })
326 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
327 moniker, ..
328 })
329 | Self::RemotedAt(RemotedAtSource { moniker, .. }) => {
330 ExtendedMoniker::ComponentInstance(moniker.clone())
331 }
332 Self::Builtin(_) | Self::Namespace(_) => ExtendedMoniker::ComponentManager,
333 }
334 }
335}
336
337impl fmt::Display for CapabilitySource {
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 write!(
340 f,
341 "{}",
342 match self {
343 Self::Component(ComponentSource { capability, moniker })
344 | Self::StorageBackingDirectory(StorageBackingDirectorySource {
345 capability,
346 moniker,
347 ..
348 }) => {
349 format!("{} '{}'", capability, moniker)
350 }
351 Self::Framework(FrameworkSource { capability, .. }) => capability.to_string(),
352 Self::Builtin(BuiltinSource { capability }) => capability.to_string(),
353 Self::Namespace(NamespaceSource { capability }) => capability.to_string(),
354 Self::FilteredProvider(FilteredProviderSource { capability, .. })
355 | Self::FilteredAggregateProvider(FilteredAggregateProviderSource {
356 capability,
357 ..
358 }) => capability.to_string(),
359 Self::Capability(CapabilityToCapabilitySource { source_capability, .. }) =>
360 format!("{}", source_capability),
361 Self::AnonymizedAggregate(AnonymizedAggregateSource {
362 capability,
363 members,
364 moniker,
365 ..
366 }) => {
367 format!(
368 "{} from component '{}' aggregated from {}",
369 capability,
370 moniker,
371 members.iter().map(|s| format!("{s}")).collect::<Vec<_>>().join(","),
372 )
373 }
374 Self::Environment(EnvironmentSource { capability, .. }) => capability.to_string(),
375 Self::Void(VoidSource { capability, .. }) => capability.to_string(),
376 Self::RemotedAt(RemotedAtSource { moniker, type_name }) => format!(
377 "{} route left component manager at {}",
378 type_name.map(|t| t.to_string()).unwrap_or_else(|| "unknown".to_string()),
379 moniker
380 ),
381 }
382 )
383 }
384}
385
386#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
388pub enum AggregateInstance {
389 Child(ChildName),
390 Parent,
391 Self_,
392}
393
394impl fmt::Display for AggregateInstance {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396 match self {
397 Self::Child(n) => {
398 write!(f, "child `{n}`")
399 }
400 Self::Parent => {
401 write!(f, "parent")
402 }
403 Self::Self_ => {
404 write!(f, "self")
405 }
406 }
407 }
408}
409
410#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
414#[derive(Clone, Debug, PartialEq, Eq)]
415pub enum InternalCapability {
416 Service(Name),
417 Protocol(Name),
418 Directory(Name),
419 Runner(Name),
420 Config(Name),
421 EventStream(InternalEventStreamCapability),
422 Resolver(Name),
423 Storage(Name),
424 Dictionary(Name),
425}
426
427#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
428#[derive(Debug, PartialEq, Clone, Eq)]
429pub struct InternalEventStreamCapability {
430 pub name: Name,
431 pub scope_moniker: Option<String>,
432 pub scope: Option<Box<[cm_rust::EventScope]>>,
433}
434
435impl InternalCapability {
436 pub fn new(type_name: CapabilityTypeName, name: Name) -> Self {
437 match type_name {
438 CapabilityTypeName::Directory => InternalCapability::Directory(name),
439 CapabilityTypeName::EventStream => InternalCapability::Directory(name),
440 CapabilityTypeName::Protocol => InternalCapability::Protocol(name),
441 CapabilityTypeName::Resolver => InternalCapability::Resolver(name),
442 CapabilityTypeName::Runner => InternalCapability::Runner(name),
443 CapabilityTypeName::Service => InternalCapability::Service(name),
444 CapabilityTypeName::Storage => InternalCapability::Storage(name),
445 CapabilityTypeName::Dictionary => InternalCapability::Dictionary(name),
446 CapabilityTypeName::Config => InternalCapability::Config(name),
447 }
448 }
449
450 pub fn type_name(&self) -> CapabilityTypeName {
452 match self {
453 InternalCapability::Service(_) => CapabilityTypeName::Service,
454 InternalCapability::Protocol(_) => CapabilityTypeName::Protocol,
455 InternalCapability::Directory(_) => CapabilityTypeName::Directory,
456 InternalCapability::Runner(_) => CapabilityTypeName::Runner,
457 InternalCapability::Config(_) => CapabilityTypeName::Config,
458 InternalCapability::EventStream(_) => CapabilityTypeName::EventStream,
459 InternalCapability::Resolver(_) => CapabilityTypeName::Resolver,
460 InternalCapability::Storage(_) => CapabilityTypeName::Storage,
461 InternalCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
462 }
463 }
464
465 pub fn source_name(&self) -> &Name {
466 match self {
467 InternalCapability::Service(name) => &name,
468 InternalCapability::Protocol(name) => &name,
469 InternalCapability::Directory(name) => &name,
470 InternalCapability::Runner(name) => &name,
471 InternalCapability::Config(name) => &name,
472 InternalCapability::EventStream(InternalEventStreamCapability { name, .. }) => &name,
473 InternalCapability::Resolver(name) => &name,
474 InternalCapability::Storage(name) => &name,
475 InternalCapability::Dictionary(name) => &name,
476 }
477 }
478
479 pub fn matches_protocol(&self, name: &Name) -> bool {
481 match self {
482 Self::Protocol(source_name) => source_name == name,
483 _ => false,
484 }
485 }
486}
487
488impl fmt::Display for InternalCapability {
489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490 write!(f, "{} '{}' from component manager", self.type_name(), self.source_name())
491 }
492}
493
494impl From<CapabilityDecl> for InternalCapability {
495 fn from(capability: CapabilityDecl) -> Self {
496 match capability {
497 CapabilityDecl::Service(c) => c.into(),
498 CapabilityDecl::Protocol(c) => c.into(),
499 CapabilityDecl::Directory(c) => c.into(),
500 CapabilityDecl::Storage(c) => c.into(),
501 CapabilityDecl::Runner(c) => c.into(),
502 CapabilityDecl::Resolver(c) => c.into(),
503 CapabilityDecl::EventStream(c) => c.into(),
504 CapabilityDecl::Dictionary(c) => c.into(),
505 CapabilityDecl::Config(c) => c.into(),
506 }
507 }
508}
509
510impl From<ServiceDecl> for InternalCapability {
511 fn from(service: ServiceDecl) -> Self {
512 Self::Service(service.name)
513 }
514}
515
516impl From<ProtocolDecl> for InternalCapability {
517 fn from(protocol: ProtocolDecl) -> Self {
518 Self::Protocol(protocol.name)
519 }
520}
521
522impl From<DirectoryDecl> for InternalCapability {
523 fn from(directory: DirectoryDecl) -> Self {
524 Self::Directory(directory.name)
525 }
526}
527
528impl From<RunnerDecl> for InternalCapability {
529 fn from(runner: RunnerDecl) -> Self {
530 Self::Runner(runner.name)
531 }
532}
533
534impl From<ResolverDecl> for InternalCapability {
535 fn from(resolver: ResolverDecl) -> Self {
536 Self::Resolver(resolver.name)
537 }
538}
539
540impl From<EventStreamDecl> for InternalCapability {
541 fn from(event: EventStreamDecl) -> Self {
542 Self::EventStream(InternalEventStreamCapability {
543 name: event.name,
544 scope_moniker: None,
545 scope: None,
546 })
547 }
548}
549
550impl From<StorageDecl> for InternalCapability {
551 fn from(storage: StorageDecl) -> Self {
552 Self::Storage(storage.name)
553 }
554}
555
556impl From<ConfigurationDecl> for InternalCapability {
557 fn from(config: ConfigurationDecl) -> Self {
558 Self::Config(config.name)
559 }
560}
561
562impl From<DictionaryDecl> for InternalCapability {
563 fn from(dictionary: DictionaryDecl) -> Self {
564 Self::Dictionary(dictionary.name)
565 }
566}
567
568#[cfg_attr(
570 feature = "serde",
571 derive(Deserialize, Serialize),
572 serde(tag = "type", rename_all = "snake_case")
573)]
574#[derive(FromEnum, Clone, Debug, PartialEq, Eq)]
575pub enum ComponentCapability {
576 Use_(UseDecl),
577 Environment(EnvironmentCapability),
579 Expose(ExposeDecl),
580 Offer(OfferDecl),
581 Protocol(ProtocolDecl),
582 Directory(DirectoryDecl),
583 Storage(StorageDecl),
584 Runner(RunnerDecl),
585 Resolver(ResolverDecl),
586 Service(ServiceDecl),
587 EventStream(EventStreamDecl),
588 Dictionary(DictionaryDecl),
589 Config(ConfigurationDecl),
590}
591
592impl ComponentCapability {
593 pub fn type_name(&self) -> CapabilityTypeName {
595 match self {
596 ComponentCapability::Use_(use_) => use_.into(),
597 ComponentCapability::Environment(env) => match env {
598 EnvironmentCapability::Runner(_) => CapabilityTypeName::Runner,
599 EnvironmentCapability::Resolver(_) => CapabilityTypeName::Resolver,
600 EnvironmentCapability::Debug(_) => CapabilityTypeName::Protocol,
601 },
602 ComponentCapability::Expose(expose) => expose.into(),
603 ComponentCapability::Offer(offer) => offer.into(),
604 ComponentCapability::Protocol(_) => CapabilityTypeName::Protocol,
605 ComponentCapability::Directory(_) => CapabilityTypeName::Directory,
606 ComponentCapability::Storage(_) => CapabilityTypeName::Storage,
607 ComponentCapability::Runner(_) => CapabilityTypeName::Runner,
608 ComponentCapability::Config(_) => CapabilityTypeName::Config,
609 ComponentCapability::Resolver(_) => CapabilityTypeName::Resolver,
610 ComponentCapability::Service(_) => CapabilityTypeName::Service,
611 ComponentCapability::EventStream(_) => CapabilityTypeName::EventStream,
612 ComponentCapability::Dictionary(_) => CapabilityTypeName::Dictionary,
613 }
614 }
615
616 pub fn source_path(&self) -> Option<&Path> {
618 match self {
619 ComponentCapability::Storage(_) => None,
620 ComponentCapability::Protocol(protocol) => protocol.source_path.as_ref(),
621 ComponentCapability::Directory(directory) => directory.source_path.as_ref(),
622 ComponentCapability::Runner(runner) => runner.source_path.as_ref(),
623 ComponentCapability::Resolver(resolver) => resolver.source_path.as_ref(),
624 ComponentCapability::Service(service) => service.source_path.as_ref(),
625 _ => None,
626 }
627 }
628
629 pub fn source_name(&self) -> Option<&Name> {
631 match self {
632 ComponentCapability::Storage(storage) => Some(&storage.name),
633 ComponentCapability::Protocol(protocol) => Some(&protocol.name),
634 ComponentCapability::Directory(directory) => Some(&directory.name),
635 ComponentCapability::Runner(runner) => Some(&runner.name),
636 ComponentCapability::Config(config) => Some(&config.name),
637 ComponentCapability::Resolver(resolver) => Some(&resolver.name),
638 ComponentCapability::Service(service) => Some(&service.name),
639 ComponentCapability::EventStream(event) => Some(&event.name),
640 ComponentCapability::Dictionary(dictionary) => Some(&dictionary.name),
641 ComponentCapability::Use_(use_) => match use_ {
642 UseDecl::Protocol(UseProtocolDecl { source_name, .. }) => Some(source_name),
643 UseDecl::Directory(UseDirectoryDecl { source_name, .. }) => Some(source_name),
644 UseDecl::Storage(UseStorageDecl { source_name, .. }) => Some(source_name),
645 UseDecl::Service(UseServiceDecl { source_name, .. }) => Some(source_name),
646 UseDecl::Config(config) => Some(&config.source_name),
647 _ => None,
648 },
649 ComponentCapability::Environment(env_cap) => match env_cap {
650 EnvironmentCapability::Runner(EnvironmentCapabilityData {
651 source_name, ..
652 }) => Some(source_name),
653 EnvironmentCapability::Resolver(EnvironmentCapabilityData {
654 source_name, ..
655 }) => Some(source_name),
656 EnvironmentCapability::Debug(EnvironmentCapabilityData { source_name, .. }) => {
657 Some(source_name)
658 }
659 },
660 ComponentCapability::Expose(expose) => match expose {
661 ExposeDecl::Protocol(ExposeProtocolDecl { source_name, .. }) => Some(source_name),
662 ExposeDecl::Directory(ExposeDirectoryDecl { source_name, .. }) => Some(source_name),
663 ExposeDecl::Runner(ExposeRunnerDecl { source_name, .. }) => Some(source_name),
664 ExposeDecl::Resolver(ExposeResolverDecl { source_name, .. }) => Some(source_name),
665 ExposeDecl::Service(ExposeServiceDecl { source_name, .. }) => Some(source_name),
666 ExposeDecl::Config(ExposeConfigurationDecl { source_name, .. }) => {
667 Some(source_name)
668 }
669 ExposeDecl::Dictionary(ExposeDictionaryDecl { source_name, .. }) => {
670 Some(source_name)
671 }
672 },
673 ComponentCapability::Offer(offer) => match offer {
674 OfferDecl::Protocol(OfferProtocolDecl { source_name, .. }) => Some(source_name),
675 OfferDecl::Directory(directory) => Some(&directory.source_name),
676 OfferDecl::Runner(OfferRunnerDecl { source_name, .. }) => Some(source_name),
677 OfferDecl::Storage(OfferStorageDecl { source_name, .. }) => Some(source_name),
678 OfferDecl::Resolver(OfferResolverDecl { source_name, .. }) => Some(source_name),
679 OfferDecl::Service(service) => Some(&service.source_name),
680 OfferDecl::Config(OfferConfigurationDecl { source_name, .. }) => Some(source_name),
681 OfferDecl::EventStream(event_stream) => Some(&event_stream.source_name),
682 OfferDecl::Dictionary(OfferDictionaryDecl { source_name, .. }) => Some(source_name),
683 },
684 }
685 }
686
687 pub fn source_capability_name(&self) -> Option<&Name> {
688 match self {
689 ComponentCapability::Offer(OfferDecl::Protocol(OfferProtocolDecl {
690 source: OfferSource::Capability(name),
691 ..
692 })) => Some(name),
693 ComponentCapability::Expose(ExposeDecl::Protocol(ExposeProtocolDecl {
694 source: ExposeSource::Capability(name),
695 ..
696 })) => Some(name),
697 ComponentCapability::Use_(UseDecl::Protocol(UseProtocolDecl {
698 source: UseSource::Capability(name),
699 ..
700 })) => Some(name),
701 _ => None,
702 }
703 }
704
705 pub fn source_id(&self) -> String {
707 self.source_name()
708 .map(|p| format!("{}", p))
709 .or_else(|| self.source_path().map(|p| format!("{}", p)))
710 .unwrap_or_default()
711 }
712}
713
714impl From<CapabilityDecl> for ComponentCapability {
715 fn from(capability: CapabilityDecl) -> Self {
716 match capability {
717 CapabilityDecl::Service(c) => ComponentCapability::Service(c),
718 CapabilityDecl::Protocol(c) => ComponentCapability::Protocol(c),
719 CapabilityDecl::Directory(c) => ComponentCapability::Directory(c),
720 CapabilityDecl::Storage(c) => ComponentCapability::Storage(c),
721 CapabilityDecl::Runner(c) => ComponentCapability::Runner(c),
722 CapabilityDecl::Resolver(c) => ComponentCapability::Resolver(c),
723 CapabilityDecl::EventStream(c) => ComponentCapability::EventStream(c),
724 CapabilityDecl::Dictionary(c) => ComponentCapability::Dictionary(c),
725 CapabilityDecl::Config(c) => ComponentCapability::Config(c),
726 }
727 }
728}
729
730impl TryInto<CapabilityDecl> for ComponentCapability {
731 type Error = ();
732
733 fn try_into(self) -> Result<CapabilityDecl, Self::Error> {
734 match self {
735 Self::Service(c) => Ok(CapabilityDecl::Service(c)),
736 Self::Protocol(c) => Ok(CapabilityDecl::Protocol(c)),
737 Self::Directory(c) => Ok(CapabilityDecl::Directory(c)),
738 Self::Storage(c) => Ok(CapabilityDecl::Storage(c)),
739 Self::Runner(c) => Ok(CapabilityDecl::Runner(c)),
740 Self::Resolver(c) => Ok(CapabilityDecl::Resolver(c)),
741 Self::EventStream(c) => Ok(CapabilityDecl::EventStream(c)),
742 Self::Dictionary(c) => Ok(CapabilityDecl::Dictionary(c)),
743 Self::Config(c) => Ok(CapabilityDecl::Config(c)),
744 _ => Err(()),
745 }
746 }
747}
748
749impl fmt::Display for ComponentCapability {
750 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751 write!(f, "{} '{}' from component", self.type_name(), self.source_id())
752 }
753}
754
755#[cfg_attr(
756 feature = "serde",
757 derive(Deserialize, Serialize),
758 serde(tag = "type", rename_all = "snake_case")
759)]
760#[derive(Clone, Debug, PartialEq, Eq)]
761pub enum EnvironmentCapability {
762 Runner(EnvironmentCapabilityData),
763 Resolver(EnvironmentCapabilityData),
764 Debug(EnvironmentCapabilityData),
765}
766
767impl EnvironmentCapability {
768 pub fn registration_source(&self) -> &RegistrationSource {
769 match self {
770 Self::Runner(EnvironmentCapabilityData { source, .. })
771 | Self::Resolver(EnvironmentCapabilityData { source, .. })
772 | Self::Debug(EnvironmentCapabilityData { source, .. }) => &source,
773 }
774 }
775}
776
777#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
778#[derive(Clone, Debug, PartialEq, Eq)]
779pub struct EnvironmentCapabilityData {
780 source_name: Name,
781 source: RegistrationSource,
782}
783
784#[cfg_attr(
787 feature = "serde",
788 derive(Deserialize, Serialize),
789 serde(tag = "type", rename_all = "snake_case")
790)]
791#[derive(Debug, Clone, PartialEq, Eq, Hash)]
792pub enum AggregateCapability {
793 Service(Name),
794}
795
796impl AggregateCapability {
797 pub fn type_name(&self) -> CapabilityTypeName {
799 match self {
800 AggregateCapability::Service(_) => CapabilityTypeName::Service,
801 }
802 }
803
804 pub fn source_name(&self) -> &Name {
805 match self {
806 AggregateCapability::Service(name) => &name,
807 }
808 }
809}
810
811impl fmt::Display for AggregateCapability {
812 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
813 write!(f, "aggregate {} '{}'", self.type_name(), self.source_name())
814 }
815}
816
817impl From<ServiceDecl> for AggregateCapability {
818 fn from(service: ServiceDecl) -> Self {
819 Self::Service(service.name)
820 }
821}
822
823pub type NamespaceCapabilities = Vec<CapabilityDecl>;
825
826pub type BuiltinCapabilities = Vec<CapabilityDecl>;
828
829#[cfg(test)]
830mod tests {
831 use super::*;
832 use cm_rust::StorageDirectorySource;
833 use fidl_fuchsia_component_decl as fdecl;
834
835 #[test]
836 fn capability_type_name() {
837 let storage_capability = ComponentCapability::Storage(StorageDecl {
838 name: "foo".parse().unwrap(),
839 source: StorageDirectorySource::Parent,
840 backing_dir: "bar".parse().unwrap(),
841 subdir: Default::default(),
842 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
843 });
844 assert_eq!(storage_capability.type_name(), CapabilityTypeName::Storage);
845 }
846}