| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| crate::{ |
| component_instance::{ |
| ComponentInstanceInterface, WeakComponentInstanceInterface, |
| WeakExtendedInstanceInterface, |
| }, |
| error::RoutingError, |
| }, |
| async_trait::async_trait, |
| cm_rust::{ |
| CapabilityDecl, CapabilityName, CapabilityPath, CapabilityTypeName, DirectoryDecl, |
| EventDecl, EventStreamDecl, ExposeDecl, ExposeDirectoryDecl, ExposeEventStreamDecl, |
| ExposeProtocolDecl, ExposeResolverDecl, ExposeRunnerDecl, ExposeServiceDecl, ExposeSource, |
| OfferDecl, OfferDirectoryDecl, OfferEventDecl, OfferEventStreamDecl, OfferProtocolDecl, |
| OfferResolverDecl, OfferRunnerDecl, OfferServiceDecl, OfferSource, OfferStorageDecl, |
| ProtocolDecl, RegistrationSource, ResolverDecl, RunnerDecl, ServiceDecl, StorageDecl, |
| UseDecl, UseDirectoryDecl, UseEventDecl, UseProtocolDecl, UseServiceDecl, UseSource, |
| UseStorageDecl, |
| }, |
| derivative::Derivative, |
| from_enum::FromEnum, |
| std::{ |
| collections::HashMap, |
| fmt, |
| path::PathBuf, |
| sync::{Arc, Weak}, |
| }, |
| thiserror::Error, |
| }; |
| |
| #[derive(Debug, Error)] |
| pub enum Error { |
| #[error("Invalid framework capability.")] |
| InvalidFrameworkCapability {}, |
| #[error("Invalid builtin capability.")] |
| InvalidBuiltinCapability {}, |
| } |
| |
| /// Describes the source of a capability, as determined by `find_capability_source` |
| #[derive(Debug, Derivative)] |
| #[derivative(Clone(bound = ""))] |
| pub enum CapabilitySourceInterface<C: ComponentInstanceInterface> { |
| /// This capability originates from the component instance for the given Realm. |
| /// point. |
| Component { capability: ComponentCapability, component: WeakComponentInstanceInterface<C> }, |
| /// This capability originates from "framework". It's implemented by component manager and is |
| /// scoped to the realm of the source. |
| Framework { capability: InternalCapability, component: WeakComponentInstanceInterface<C> }, |
| /// This capability originates from the parent of the root component, and is built in to |
| /// component manager. `top_instance` is the instance at the top of the tree, i.e. the |
| /// instance representing component manager. |
| Builtin { capability: InternalCapability, top_instance: Weak<C::TopInstance> }, |
| /// This capability originates from the parent of the root component, and is offered from |
| /// component manager's namespace. `top_instance` is the instance at the top of the tree, i.e. |
| /// the instance representing component manager. |
| Namespace { capability: ComponentCapability, top_instance: Weak<C::TopInstance> }, |
| /// This capability is provided by the framework based on some other capability. |
| Capability { |
| source_capability: ComponentCapability, |
| component: WeakComponentInstanceInterface<C>, |
| }, |
| /// This capability is an aggregate of capabilities provided by components in a collection. |
| Collection { |
| capability: AggregateCapability, |
| capability_provider: Box<dyn AggregateCapabilityProvider<C>>, |
| collection_name: String, |
| component: WeakComponentInstanceInterface<C>, |
| }, |
| FilteredService { |
| capability: ComponentCapability, |
| component: WeakComponentInstanceInterface<C>, |
| source_instance_filter: Vec<String>, |
| instance_name_source_to_target: HashMap<String, Vec<String>>, |
| }, |
| } |
| |
| impl<C: ComponentInstanceInterface> CapabilitySourceInterface<C> { |
| /// Returns whether the given CapabilitySourceInterface can be available in a component's |
| /// namespace. |
| pub fn can_be_in_namespace(&self) -> bool { |
| match self { |
| Self::Component { capability, .. } => capability.can_be_in_namespace(), |
| Self::Framework { capability, .. } => capability.can_be_in_namespace(), |
| Self::Builtin { capability, .. } => capability.can_be_in_namespace(), |
| Self::Namespace { capability, .. } => capability.can_be_in_namespace(), |
| Self::Capability { .. } => true, |
| Self::Collection { capability, .. } => capability.can_be_in_namespace(), |
| Self::FilteredService { capability, .. } => capability.can_be_in_namespace(), |
| } |
| } |
| |
| pub fn source_name(&self) -> Option<&CapabilityName> { |
| match self { |
| Self::Component { capability, .. } => capability.source_name(), |
| Self::Framework { capability, .. } => Some(capability.source_name()), |
| Self::Builtin { capability, .. } => Some(capability.source_name()), |
| Self::Namespace { capability, .. } => capability.source_name(), |
| Self::Capability { .. } => None, |
| Self::Collection { capability, .. } => Some(capability.source_name()), |
| Self::FilteredService { capability, .. } => capability.source_name(), |
| } |
| } |
| |
| pub fn type_name(&self) -> CapabilityTypeName { |
| match self { |
| Self::Component { capability, .. } => capability.type_name(), |
| Self::Framework { capability, .. } => capability.type_name(), |
| Self::Builtin { capability, .. } => capability.type_name(), |
| Self::Namespace { capability, .. } => capability.type_name(), |
| Self::Capability { source_capability, .. } => source_capability.type_name(), |
| Self::Collection { capability, .. } => capability.type_name(), |
| Self::FilteredService { capability, .. } => capability.type_name(), |
| } |
| } |
| |
| pub fn source_instance(&self) -> WeakExtendedInstanceInterface<C> { |
| match self { |
| Self::Component { component, .. } |
| | Self::Framework { component, .. } |
| | Self::Capability { component, .. } |
| | Self::FilteredService { component, .. } |
| | Self::Collection { component, .. } => { |
| WeakExtendedInstanceInterface::Component(component.clone()) |
| } |
| Self::Builtin { top_instance, .. } | Self::Namespace { top_instance, .. } => { |
| WeakExtendedInstanceInterface::AboveRoot(top_instance.clone()) |
| } |
| } |
| } |
| } |
| |
| impl<C: ComponentInstanceInterface> fmt::Display for CapabilitySourceInterface<C> { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!( |
| f, |
| "{}", |
| match self { |
| CapabilitySourceInterface::Component { capability, component } => { |
| format!("{} '{}'", capability, component.abs_moniker) |
| } |
| CapabilitySourceInterface::Framework { capability, .. } => capability.to_string(), |
| CapabilitySourceInterface::Builtin { capability, .. } => capability.to_string(), |
| CapabilitySourceInterface::Namespace { capability, .. } => capability.to_string(), |
| CapabilitySourceInterface::Capability { source_capability, .. } => |
| format!("{}", source_capability), |
| CapabilitySourceInterface::Collection { |
| capability, |
| collection_name, |
| component, |
| .. |
| } => { |
| format!( |
| "{} from collection '#{}' of component '{}'", |
| capability, collection_name, &component.abs_moniker |
| ) |
| } |
| Self::FilteredService { capability, component, .. } => { |
| format!("{} '{}'", capability, component.abs_moniker) |
| } |
| } |
| ) |
| } |
| } |
| |
| /// Information returned by the route_storage_capability function on the source of a storage |
| /// capability. |
| #[derive(Debug, Derivative)] |
| #[derivative(Clone(bound = ""))] |
| pub struct StorageCapabilitySource<C: ComponentInstanceInterface> { |
| /// The component that's providing the backing directory capability for this storage |
| /// capability. If None, then the backing directory comes from component_manager's namespace. |
| pub storage_provider: Option<Arc<C>>, |
| |
| /// The path to the backing directory in the providing component's outgoing directory (or |
| /// component_manager's namespace). |
| pub backing_directory_path: CapabilityPath, |
| |
| /// The subdirectory inside of the backing directory capability to use, if any |
| pub backing_directory_subdir: Option<PathBuf>, |
| |
| /// The subdirectory inside of the backing directory's sub-directory to use, if any. The |
| /// difference between this and backing_directory_subdir is that backing_directory_subdir is |
| /// appended to backing_directory_path first, and component_manager will create this subdir if |
| /// it doesn't exist but won't create backing_directory_subdir. |
| pub storage_subdir: Option<PathBuf>, |
| } |
| |
| impl<C: ComponentInstanceInterface> PartialEq for StorageCapabilitySource<C> { |
| fn eq(&self, other: &Self) -> bool { |
| let self_source_component = self.storage_provider.as_ref().map(|s| s.instanced_moniker()); |
| let other_source_component = other.storage_provider.as_ref().map(|s| s.instanced_moniker()); |
| self_source_component == other_source_component |
| && self.backing_directory_path == other.backing_directory_path |
| && self.backing_directory_subdir == other.backing_directory_subdir |
| && self.storage_subdir == other.storage_subdir |
| } |
| } |
| |
| /// A provider of a capability from an aggregation of zero or more instances of a capability. |
| /// |
| /// This trait type-erases the capability type, so it can be handled and hosted generically. |
| #[async_trait] |
| pub trait AggregateCapabilityProvider<C: ComponentInstanceInterface>: Send + Sync { |
| /// Lists the instances of the capability. |
| /// |
| /// This is an opaque identifier that is only meaningful for a subsequent |
| /// call to `route_instance`. |
| async fn list_instances(&self) -> Result<Vec<String>, RoutingError>; |
| |
| /// Route the given `instance` of the capability to its source. |
| async fn route_instance( |
| &self, |
| instance: &str, |
| ) -> Result<CapabilitySourceInterface<C>, RoutingError>; |
| |
| /// Trait-object compatible clone. |
| fn clone_boxed(&self) -> Box<dyn AggregateCapabilityProvider<C>>; |
| } |
| |
| impl<C: ComponentInstanceInterface> Clone for Box<dyn AggregateCapabilityProvider<C>> { |
| fn clone(&self) -> Self { |
| self.clone_boxed() |
| } |
| } |
| |
| impl<C> fmt::Debug for Box<dyn AggregateCapabilityProvider<C>> { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| f.debug_struct("Box<dyn AggregateCapabilityProvider>").finish() |
| } |
| } |
| |
| /// Describes a capability provided by the component manager which could be a framework capability |
| /// scoped to a realm, a built-in global capability, or a capability from component manager's own |
| /// namespace. |
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub enum InternalCapability { |
| Service(CapabilityName), |
| Protocol(CapabilityName), |
| Directory(CapabilityName), |
| Runner(CapabilityName), |
| Event(CapabilityName), |
| EventStream(CapabilityName), |
| Resolver(CapabilityName), |
| Storage(CapabilityName), |
| } |
| |
| impl InternalCapability { |
| /// Returns whether the given InternalCapability can be available in a component's namespace. |
| pub fn can_be_in_namespace(&self) -> bool { |
| matches!( |
| self, |
| InternalCapability::Service(_) |
| | InternalCapability::Protocol(_) |
| | InternalCapability::Directory(_) |
| ) |
| } |
| |
| /// Returns a name for the capability type. |
| pub fn type_name(&self) -> CapabilityTypeName { |
| match self { |
| InternalCapability::Service(_) => CapabilityTypeName::Service, |
| InternalCapability::Protocol(_) => CapabilityTypeName::Protocol, |
| InternalCapability::Directory(_) => CapabilityTypeName::Directory, |
| InternalCapability::Runner(_) => CapabilityTypeName::Runner, |
| InternalCapability::Event(_) => CapabilityTypeName::Event, |
| InternalCapability::EventStream(_) => CapabilityTypeName::EventStream, |
| InternalCapability::Resolver(_) => CapabilityTypeName::Resolver, |
| InternalCapability::Storage(_) => CapabilityTypeName::Storage, |
| } |
| } |
| |
| pub fn source_name(&self) -> &CapabilityName { |
| match self { |
| InternalCapability::Service(name) => &name, |
| InternalCapability::Protocol(name) => &name, |
| InternalCapability::Directory(name) => &name, |
| InternalCapability::Runner(name) => &name, |
| InternalCapability::Event(name) => &name, |
| InternalCapability::EventStream(name) => &name, |
| InternalCapability::Resolver(name) => &name, |
| InternalCapability::Storage(name) => &name, |
| } |
| } |
| |
| /// Returns true if this is a protocol with name that matches `name`. |
| pub fn matches_protocol(&self, name: &CapabilityName) -> bool { |
| match self { |
| Self::Protocol(source_name) => source_name == name, |
| _ => false, |
| } |
| } |
| } |
| |
| impl fmt::Display for InternalCapability { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{} '{}' from component manager", self.type_name(), self.source_name()) |
| } |
| } |
| |
| impl From<ServiceDecl> for InternalCapability { |
| fn from(service: ServiceDecl) -> Self { |
| Self::Service(service.name) |
| } |
| } |
| |
| impl From<ProtocolDecl> for InternalCapability { |
| fn from(protocol: ProtocolDecl) -> Self { |
| Self::Protocol(protocol.name) |
| } |
| } |
| |
| impl From<DirectoryDecl> for InternalCapability { |
| fn from(directory: DirectoryDecl) -> Self { |
| Self::Directory(directory.name) |
| } |
| } |
| |
| impl From<RunnerDecl> for InternalCapability { |
| fn from(runner: RunnerDecl) -> Self { |
| Self::Runner(runner.name) |
| } |
| } |
| |
| impl From<ResolverDecl> for InternalCapability { |
| fn from(resolver: ResolverDecl) -> Self { |
| Self::Resolver(resolver.name) |
| } |
| } |
| |
| impl From<EventDecl> for InternalCapability { |
| fn from(event: EventDecl) -> Self { |
| Self::Event(event.name) |
| } |
| } |
| |
| impl From<EventStreamDecl> for InternalCapability { |
| fn from(event: EventStreamDecl) -> Self { |
| Self::EventStream(event.name) |
| } |
| } |
| |
| impl From<StorageDecl> for InternalCapability { |
| fn from(storage: StorageDecl) -> Self { |
| Self::Storage(storage.name) |
| } |
| } |
| |
| /// A capability being routed from a component. |
| #[derive(FromEnum, Clone, Debug, PartialEq, Eq)] |
| pub enum ComponentCapability { |
| Use(UseDecl), |
| /// Models a capability used from the environment. |
| Environment(EnvironmentCapability), |
| Expose(ExposeDecl), |
| Offer(OfferDecl), |
| Protocol(ProtocolDecl), |
| Directory(DirectoryDecl), |
| Storage(StorageDecl), |
| Runner(RunnerDecl), |
| Resolver(ResolverDecl), |
| Service(ServiceDecl), |
| Event(EventDecl), |
| EventStream(EventStreamDecl), |
| } |
| |
| impl ComponentCapability { |
| /// Returns whether the given ComponentCapability can be available in a component's namespace. |
| pub fn can_be_in_namespace(&self) -> bool { |
| match self { |
| ComponentCapability::Use(use_) => { |
| matches!(use_, UseDecl::Protocol(_) | UseDecl::Directory(_) | UseDecl::Service(_)) |
| } |
| ComponentCapability::Expose(expose) => matches!( |
| expose, |
| ExposeDecl::Protocol(_) | ExposeDecl::Directory(_) | ExposeDecl::Service(_) |
| ), |
| ComponentCapability::Offer(offer) => matches!( |
| offer, |
| OfferDecl::Protocol(_) | OfferDecl::Directory(_) | OfferDecl::Service(_) |
| ), |
| ComponentCapability::Protocol(_) |
| | ComponentCapability::Directory(_) |
| | ComponentCapability::Service(_) => true, |
| _ => false, |
| } |
| } |
| |
| /// Returns a name for the capability type. |
| pub fn type_name(&self) -> CapabilityTypeName { |
| match self { |
| ComponentCapability::Use(use_) => match use_ { |
| UseDecl::Protocol(_) => CapabilityTypeName::Protocol, |
| UseDecl::Directory(_) => CapabilityTypeName::Directory, |
| UseDecl::Service(_) => CapabilityTypeName::Service, |
| UseDecl::Storage(_) => CapabilityTypeName::Storage, |
| UseDecl::Event(_) => CapabilityTypeName::Event, |
| UseDecl::EventStreamDeprecated(_) => CapabilityTypeName::EventStreamDeprecated, |
| UseDecl::EventStream(_) => CapabilityTypeName::EventStream, |
| }, |
| ComponentCapability::Environment(env) => match env { |
| EnvironmentCapability::Runner { .. } => CapabilityTypeName::Runner, |
| EnvironmentCapability::Resolver { .. } => CapabilityTypeName::Resolver, |
| EnvironmentCapability::Debug { .. } => CapabilityTypeName::Protocol, |
| }, |
| ComponentCapability::Expose(expose) => match expose { |
| ExposeDecl::Protocol(_) => CapabilityTypeName::Protocol, |
| ExposeDecl::Directory(_) => CapabilityTypeName::Directory, |
| ExposeDecl::Service(_) => CapabilityTypeName::Service, |
| ExposeDecl::Runner(_) => CapabilityTypeName::Runner, |
| ExposeDecl::Resolver(_) => CapabilityTypeName::Resolver, |
| ExposeDecl::EventStream(_) => CapabilityTypeName::EventStream, |
| }, |
| ComponentCapability::Offer(offer) => match offer { |
| OfferDecl::Protocol(_) => CapabilityTypeName::Protocol, |
| OfferDecl::Directory(_) => CapabilityTypeName::Directory, |
| OfferDecl::Service(_) => CapabilityTypeName::Service, |
| OfferDecl::Storage(_) => CapabilityTypeName::Storage, |
| OfferDecl::Runner(_) => CapabilityTypeName::Runner, |
| OfferDecl::Resolver(_) => CapabilityTypeName::Resolver, |
| OfferDecl::Event(_) => CapabilityTypeName::Event, |
| OfferDecl::EventStream(_) => CapabilityTypeName::EventStream, |
| }, |
| ComponentCapability::Protocol(_) => CapabilityTypeName::Protocol, |
| ComponentCapability::Directory(_) => CapabilityTypeName::Directory, |
| ComponentCapability::Storage(_) => CapabilityTypeName::Storage, |
| ComponentCapability::Runner(_) => CapabilityTypeName::Runner, |
| ComponentCapability::Resolver(_) => CapabilityTypeName::Resolver, |
| ComponentCapability::Service(_) => CapabilityTypeName::Service, |
| ComponentCapability::Event(_) => CapabilityTypeName::Event, |
| ComponentCapability::EventStream(_) => CapabilityTypeName::EventStream, |
| } |
| } |
| |
| /// Return the source path of the capability, if one exists. |
| pub fn source_path(&self) -> Option<&CapabilityPath> { |
| match self { |
| ComponentCapability::Storage(_) => None, |
| ComponentCapability::Protocol(protocol) => protocol.source_path.as_ref(), |
| ComponentCapability::Directory(directory) => directory.source_path.as_ref(), |
| ComponentCapability::Runner(runner) => runner.source_path.as_ref(), |
| ComponentCapability::Resolver(resolver) => resolver.source_path.as_ref(), |
| ComponentCapability::Service(service) => service.source_path.as_ref(), |
| _ => None, |
| } |
| } |
| |
| /// Return the name of the capability, if this is a capability declaration. |
| pub fn source_name(&self) -> Option<&CapabilityName> { |
| match self { |
| ComponentCapability::Storage(storage) => Some(&storage.name), |
| ComponentCapability::Protocol(protocol) => Some(&protocol.name), |
| ComponentCapability::Directory(directory) => Some(&directory.name), |
| ComponentCapability::Runner(runner) => Some(&runner.name), |
| ComponentCapability::Resolver(resolver) => Some(&resolver.name), |
| ComponentCapability::Service(service) => Some(&service.name), |
| ComponentCapability::Event(event) => Some(&event.name), |
| ComponentCapability::EventStream(event) => Some(&event.name), |
| ComponentCapability::Use(use_) => match use_ { |
| UseDecl::Protocol(UseProtocolDecl { source_name, .. }) => Some(source_name), |
| UseDecl::Directory(UseDirectoryDecl { source_name, .. }) => Some(source_name), |
| UseDecl::Event(UseEventDecl { source_name, .. }) => Some(source_name), |
| UseDecl::Storage(UseStorageDecl { source_name, .. }) => Some(source_name), |
| UseDecl::Service(UseServiceDecl { source_name, .. }) => Some(source_name), |
| _ => None, |
| }, |
| ComponentCapability::Environment(env_cap) => match env_cap { |
| EnvironmentCapability::Runner { source_name, .. } => Some(source_name), |
| EnvironmentCapability::Resolver { source_name, .. } => Some(source_name), |
| EnvironmentCapability::Debug { source_name, .. } => Some(source_name), |
| }, |
| ComponentCapability::Expose(expose) => match expose { |
| ExposeDecl::Protocol(ExposeProtocolDecl { source_name, .. }) => Some(source_name), |
| ExposeDecl::Directory(ExposeDirectoryDecl { source_name, .. }) => Some(source_name), |
| ExposeDecl::Runner(ExposeRunnerDecl { source_name, .. }) => Some(source_name), |
| ExposeDecl::Resolver(ExposeResolverDecl { source_name, .. }) => Some(source_name), |
| ExposeDecl::Service(ExposeServiceDecl { source_name, .. }) => Some(source_name), |
| ExposeDecl::EventStream(ExposeEventStreamDecl { source_name, .. }) => { |
| Some(source_name) |
| } |
| }, |
| ComponentCapability::Offer(offer) => match offer { |
| OfferDecl::Protocol(OfferProtocolDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Directory(OfferDirectoryDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Runner(OfferRunnerDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Event(OfferEventDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Storage(OfferStorageDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Resolver(OfferResolverDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::Service(OfferServiceDecl { source_name, .. }) => Some(source_name), |
| OfferDecl::EventStream(OfferEventStreamDecl { source_name, .. }) => { |
| Some(source_name) |
| } |
| }, |
| } |
| } |
| |
| pub fn source_capability_name(&self) -> Option<&CapabilityName> { |
| match self { |
| ComponentCapability::Offer(OfferDecl::Protocol(OfferProtocolDecl { |
| source: OfferSource::Capability(name), |
| .. |
| })) => Some(name), |
| ComponentCapability::Expose(ExposeDecl::Protocol(ExposeProtocolDecl { |
| source: ExposeSource::Capability(name), |
| .. |
| })) => Some(name), |
| ComponentCapability::Use(UseDecl::Protocol(UseProtocolDecl { |
| source: UseSource::Capability(name), |
| .. |
| })) => Some(name), |
| _ => None, |
| } |
| } |
| |
| /// Returns the source path or name of the capability as a string, useful for debugging. |
| pub fn source_id(&self) -> String { |
| self.source_name() |
| .map(|p| format!("{}", p)) |
| .or_else(|| self.source_path().map(|p| format!("{}", p))) |
| .unwrap_or_default() |
| } |
| } |
| |
| impl fmt::Display for ComponentCapability { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{} '{}' from component", self.type_name(), self.source_id()) |
| } |
| } |
| |
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub enum EnvironmentCapability { |
| Runner { source_name: CapabilityName, source: RegistrationSource }, |
| Resolver { source_name: CapabilityName, source: RegistrationSource }, |
| Debug { source_name: CapabilityName, source: RegistrationSource }, |
| } |
| |
| impl EnvironmentCapability { |
| pub fn registration_source(&self) -> &RegistrationSource { |
| match self { |
| Self::Runner { source, .. } |
| | Self::Resolver { source, .. } |
| | Self::Debug { source, .. } => &source, |
| } |
| } |
| } |
| |
| /// Describes a capability provided by component manager that is an aggregation |
| /// of multiple instances of a capability. |
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub enum AggregateCapability { |
| Service(CapabilityName), |
| } |
| |
| impl AggregateCapability { |
| /// Returns true if the AggregateCapability can be available in a component's namespace. |
| pub fn can_be_in_namespace(&self) -> bool { |
| matches!(self, AggregateCapability::Service(_)) |
| } |
| |
| /// Returns a name for the capability type. |
| pub fn type_name(&self) -> CapabilityTypeName { |
| match self { |
| AggregateCapability::Service(_) => CapabilityTypeName::Service, |
| } |
| } |
| |
| pub fn source_name(&self) -> &CapabilityName { |
| match self { |
| AggregateCapability::Service(name) => &name, |
| } |
| } |
| } |
| |
| impl fmt::Display for AggregateCapability { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "aggregate {} '{}'", self.type_name(), self.source_name()) |
| } |
| } |
| |
| impl From<ServiceDecl> for AggregateCapability { |
| fn from(service: ServiceDecl) -> Self { |
| Self::Service(service.name) |
| } |
| } |
| |
| /// The list of declarations for capabilities from component manager's namespace. |
| pub type NamespaceCapabilities = Vec<CapabilityDecl>; |
| |
| /// The list of declarations for capabilities offered by component manager as built-in capabilities. |
| pub type BuiltinCapabilities = Vec<CapabilityDecl>; |
| |
| #[cfg(test)] |
| mod tests { |
| use { |
| super::*, |
| cm_rust::{Availability, DependencyType, StorageDirectorySource}, |
| fidl_fuchsia_component_decl as fdecl, |
| }; |
| |
| #[test] |
| fn capability_type_name() { |
| let storage_capability = ComponentCapability::Storage(StorageDecl { |
| name: "foo".into(), |
| source: StorageDirectorySource::Parent, |
| backing_dir: "bar".into(), |
| subdir: None, |
| storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker, |
| }); |
| assert_eq!(storage_capability.type_name(), CapabilityTypeName::Storage); |
| |
| let event_capability = ComponentCapability::Use(UseDecl::Event(UseEventDecl { |
| dependency_type: DependencyType::Strong, |
| source: cm_rust::UseSource::Parent, |
| source_name: "started".into(), |
| target_name: "started-x".into(), |
| filter: None, |
| availability: Availability::Required, |
| })); |
| assert_eq!(event_capability.type_name(), CapabilityTypeName::Event); |
| } |
| } |