blob: 29e88b59c2ee85ce036e003f1692e94b201f2538 [file] [log] [blame]
// Copyright 2019 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 {
cm_rust_derive::{
ExposeDeclCommon, ExposeDeclCommonAlwaysRequired, FidlDecl, OfferDeclCommon,
OfferDeclCommonNoAvailability, UseDeclCommon,
},
cm_types::{AllowedOffers, BorrowedSeparatedPath, LongName, Name, Path, RelativePath},
fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_data as fdata, fidl_fuchsia_io as fio,
fidl_fuchsia_process as fprocess,
from_enum::FromEnum,
std::collections::{BTreeMap, HashMap},
std::fmt,
std::hash::Hash,
thiserror::Error,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
mod serde_ext;
/// Converts a fidl object into its corresponding native representation.
pub trait FidlIntoNative<T> {
fn fidl_into_native(self) -> T;
}
impl<Native, Fidl> FidlIntoNative<Vec<Native>> for Vec<Fidl>
where
Fidl: FidlIntoNative<Native>,
{
fn fidl_into_native(self) -> Vec<Native> {
self.into_iter().map(|s| s.fidl_into_native()).collect()
}
}
pub trait NativeIntoFidl<T> {
fn native_into_fidl(self) -> T;
}
impl<Native, Fidl> NativeIntoFidl<Vec<Fidl>> for Vec<Native>
where
Native: NativeIntoFidl<Fidl>,
{
fn native_into_fidl(self) -> Vec<Fidl> {
self.into_iter().map(|s| s.native_into_fidl()).collect()
}
}
impl FidlIntoNative<Name> for String {
fn fidl_into_native(self) -> Name {
// cm_fidl_validator should have already validated this
self.parse().unwrap()
}
}
impl NativeIntoFidl<String> for Name {
fn native_into_fidl(self) -> String {
self.to_string()
}
}
impl FidlIntoNative<LongName> for String {
fn fidl_into_native(self) -> LongName {
// cm_fidl_validator should have already validated this
self.parse().unwrap()
}
}
impl NativeIntoFidl<String> for LongName {
fn native_into_fidl(self) -> String {
self.to_string()
}
}
impl FidlIntoNative<Path> for String {
fn fidl_into_native(self) -> Path {
// cm_fidl_validator should have already validated this
self.parse().unwrap()
}
}
impl NativeIntoFidl<String> for Path {
fn native_into_fidl(self) -> String {
self.to_string()
}
}
impl FidlIntoNative<RelativePath> for String {
fn fidl_into_native(self) -> RelativePath {
// cm_fidl_validator should have already validated this
self.parse().unwrap()
}
}
impl NativeIntoFidl<String> for RelativePath {
fn native_into_fidl(self) -> String {
self.to_string()
}
}
impl NativeIntoFidl<Option<String>> for RelativePath {
fn native_into_fidl(self) -> Option<String> {
if self.is_dot() {
None
} else {
Some(self.to_string())
}
}
}
/// Generates `FidlIntoNative` and `NativeIntoFidl` implementations that leaves the input unchanged.
macro_rules! fidl_translations_identical {
($into_type:ty) => {
impl FidlIntoNative<$into_type> for $into_type {
fn fidl_into_native(self) -> $into_type {
self
}
}
impl NativeIntoFidl<$into_type> for $into_type {
fn native_into_fidl(self) -> Self {
self
}
}
};
}
/// Generates `FidlIntoNative` and `NativeIntoFidl` implementations that
/// delegate to existing `Into` implementations.
macro_rules! fidl_translations_from_into {
($native_type:ty, $fidl_type:ty) => {
impl FidlIntoNative<$native_type> for $fidl_type {
fn fidl_into_native(self) -> $native_type {
self.into()
}
}
impl NativeIntoFidl<$fidl_type> for $native_type {
fn native_into_fidl(self) -> $fidl_type {
self.into()
}
}
};
}
/// Generates `FidlIntoNative` and `NativeIntoFidl` implementations for
/// an symmetrical enum types.
/// `fidl_type` should be the FIDL type while `native_type` should be
/// the Rust native type defined elsewhere in this file.
/// Each field of the enums must be provided in the `variant` fieldset.
macro_rules! fidl_translations_symmetrical_enums {
($fidl_type:ty , $native_type:ty, $($variant: ident),*) => {
impl FidlIntoNative<$native_type> for $fidl_type {
fn fidl_into_native(self) -> $native_type {
match self {
$( <$fidl_type>::$variant => <$native_type>::$variant, )*
}
}
}
impl NativeIntoFidl<$fidl_type> for $native_type {
fn native_into_fidl(self) -> $fidl_type {
match self {
$( <$native_type>::$variant => <$fidl_type>::$variant, )*
}
}
}
};
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Default)]
#[fidl_decl(fidl_table = "fdecl::Component")]
pub struct ComponentDecl {
pub program: Option<ProgramDecl>,
pub uses: Vec<UseDecl>,
pub exposes: Vec<ExposeDecl>,
pub offers: Vec<OfferDecl>,
pub capabilities: Vec<CapabilityDecl>,
pub children: Vec<ChildDecl>,
pub collections: Vec<CollectionDecl>,
pub facets: Option<fdata::Dictionary>,
pub environments: Vec<EnvironmentDecl>,
pub config: Option<ConfigDecl>,
}
impl ComponentDecl {
/// Returns the runner used by this component, or `None` if this is a non-executable component.
#[cfg(fuchsia_api_level_at_least = "HEAD")]
pub fn get_runner(&self) -> Option<UseRunnerDecl> {
self.program
.as_ref()
.and_then(|p| p.runner.as_ref())
.map(|r| UseRunnerDecl {
source: UseSource::Environment,
source_name: r.clone(),
source_dictionary: Default::default(),
})
.or_else(|| {
self.uses.iter().find_map(|u| match u {
UseDecl::Runner(r) => Some(r.clone()),
_ => None,
})
})
}
/// Returns the `StorageDecl` corresponding to `storage_name`.
pub fn find_storage_source<'a>(&'a self, storage_name: &Name) -> Option<&'a StorageDecl> {
self.capabilities.iter().find_map(|c| match c {
CapabilityDecl::Storage(s) if &s.name == storage_name => Some(s),
_ => None,
})
}
/// Returns the `ProtocolDecl` corresponding to `protocol_name`.
pub fn find_protocol_source<'a>(&'a self, protocol_name: &Name) -> Option<&'a ProtocolDecl> {
self.capabilities.iter().find_map(|c| match c {
CapabilityDecl::Protocol(r) if &r.name == protocol_name => Some(r),
_ => None,
})
}
/// Returns the `DirectoryDecl` corresponding to `directory_name`.
pub fn find_directory_source<'a>(&'a self, directory_name: &Name) -> Option<&'a DirectoryDecl> {
self.capabilities.iter().find_map(|c| match c {
CapabilityDecl::Directory(r) if &r.name == directory_name => Some(r),
_ => None,
})
}
/// Returns the `RunnerDecl` corresponding to `runner_name`.
pub fn find_runner_source<'a>(&'a self, runner_name: &Name) -> Option<&'a RunnerDecl> {
self.capabilities.iter().find_map(|c| match c {
CapabilityDecl::Runner(r) if &r.name == runner_name => Some(r),
_ => None,
})
}
/// Returns the `ResolverDecl` corresponding to `resolver_name`.
pub fn find_resolver_source<'a>(&'a self, resolver_name: &Name) -> Option<&'a ResolverDecl> {
self.capabilities.iter().find_map(|c| match c {
CapabilityDecl::Resolver(r) if &r.name == resolver_name => Some(r),
_ => None,
})
}
/// Returns the `CollectionDecl` corresponding to `collection_name`.
pub fn find_collection<'a>(&'a self, collection_name: &str) -> Option<&'a CollectionDecl> {
self.collections.iter().find(|c| c.name == collection_name)
}
/// Indicates whether the capability specified by `target_name` is exposed to the framework.
pub fn is_protocol_exposed_to_framework(&self, in_target_name: &Name) -> bool {
self.exposes.iter().any(|expose| match expose {
ExposeDecl::Protocol(ExposeProtocolDecl { target, target_name, .. })
if target == &ExposeTarget::Framework =>
{
target_name == in_target_name
}
_ => false,
})
}
/// Indicates whether the capability specified by `source_name` is requested.
pub fn uses_protocol(&self, source_name: &Name) -> bool {
self.uses.iter().any(|use_decl| match use_decl {
UseDecl::Protocol(ls) => &ls.source_name == source_name,
_ => false,
})
}
}
pub use cm_types::Availability;
fidl_translations_symmetrical_enums!(
fdecl::Availability,
Availability,
Required,
Optional,
SameAsTarget,
Transitional
);
pub use cm_types::DeliveryType;
impl FidlIntoNative<DeliveryType> for fdecl::DeliveryType {
fn fidl_into_native(self) -> DeliveryType {
self.try_into().unwrap()
}
}
impl NativeIntoFidl<fdecl::DeliveryType> for DeliveryType {
fn native_into_fidl(self) -> fdecl::DeliveryType {
self.into()
}
}
pub trait SourcePath {
fn source_path(&self) -> BorrowedSeparatedPath<'_>;
fn is_from_dictionary(&self) -> bool {
!self.source_path().dirname.is_dot()
}
}
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(tag = "type", rename_all = "snake_case")
)]
#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::Use")]
pub enum UseDecl {
Service(UseServiceDecl),
Protocol(UseProtocolDecl),
Directory(UseDirectoryDecl),
Storage(UseStorageDecl),
EventStream(UseEventStreamDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Runner(UseRunnerDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Config(UseConfigurationDecl),
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseService", source_path = "dictionary")]
pub struct UseServiceDecl {
pub source: UseSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target_path: Path,
pub dependency_type: DependencyType,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseProtocol", source_path = "dictionary")]
pub struct UseProtocolDecl {
pub source: UseSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target_path: Path,
pub dependency_type: DependencyType,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseDirectory", source_path = "dictionary")]
pub struct UseDirectoryDecl {
pub source: UseSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target_path: Path,
#[cfg_attr(
feature = "serde",
serde(
deserialize_with = "serde_ext::deserialize_fio_operations",
serialize_with = "serde_ext::serialize_fio_operations"
)
)]
pub rights: fio::Operations,
#[fidl_decl(default_preserve_none)]
pub subdir: RelativePath,
pub dependency_type: DependencyType,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseStorage", source_path = "name_only")]
pub struct UseStorageDecl {
pub source_name: Name,
pub target_path: Path,
#[fidl_decl(default)]
pub availability: Availability,
}
impl SourceName for UseStorageDecl {
fn source_name(&self) -> &Name {
&self.source_name
}
}
impl UseDeclCommon for UseStorageDecl {
fn source(&self) -> &UseSource {
&UseSource::Parent
}
fn availability(&self) -> &Availability {
&self.availability
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::EventSubscription")]
pub struct EventSubscription {
pub event_name: String,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq, Hash)]
#[fidl_decl(fidl_table = "fdecl::UseEventStream", source_path = "name_only")]
pub struct UseEventStreamDecl {
pub source_name: Name,
pub source: UseSource,
pub scope: Option<Vec<EventScope>>,
pub target_path: Path,
pub filter: Option<BTreeMap<String, DictionaryValue>>,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseRunner", source_path = "dictionary")]
pub struct UseRunnerDecl {
pub source: UseSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
impl SourceName for UseRunnerDecl {
fn source_name(&self) -> &Name {
&self.source_name
}
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
impl UseDeclCommon for UseRunnerDecl {
fn source(&self) -> &UseSource {
&self.source
}
fn availability(&self) -> &Availability {
&Availability::Required
}
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseConfiguration", source_path = "name_only")]
pub struct UseConfigurationDecl {
pub source: UseSource,
pub source_name: Name,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
pub type_: ConfigValueType,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
impl SourceName for UseConfigurationDecl {
fn source_name(&self) -> &Name {
&self.source_name
}
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
impl UseDeclCommon for UseConfigurationDecl {
fn source(&self) -> &UseSource {
&self.source
}
fn availability(&self) -> &Availability {
&self.availability
}
}
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(tag = "type", rename_all = "snake_case")
)]
#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::Offer")]
pub enum OfferDecl {
Service(OfferServiceDecl),
Protocol(OfferProtocolDecl),
Directory(OfferDirectoryDecl),
Storage(OfferStorageDecl),
Runner(OfferRunnerDecl),
Resolver(OfferResolverDecl),
EventStream(OfferEventStreamDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Dictionary(OfferDictionaryDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Config(OfferConfigurationDecl),
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferEventStream", source_path = "name_only")]
pub struct OfferEventStreamDecl {
pub source: OfferSource,
pub scope: Option<Vec<EventScope>>,
pub source_name: Name,
pub target: OfferTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NameMapping {
pub source_name: String,
pub target_name: String,
}
impl NativeIntoFidl<fdecl::NameMapping> for NameMapping {
fn native_into_fidl(self) -> fdecl::NameMapping {
fdecl::NameMapping { source_name: self.source_name, target_name: self.target_name }
}
}
impl FidlIntoNative<NameMapping> for fdecl::NameMapping {
fn fidl_into_native(self) -> NameMapping {
NameMapping { source_name: self.source_name, target_name: self.target_name }
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferService", source_path = "dictionary")]
pub struct OfferServiceDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
pub source_instance_filter: Option<Vec<String>>,
pub renamed_instances: Option<Vec<NameMapping>>,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferProtocol", source_path = "dictionary")]
pub struct OfferProtocolDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
pub dependency_type: DependencyType,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferDirectory", source_path = "dictionary")]
pub struct OfferDirectoryDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
pub dependency_type: DependencyType,
#[cfg_attr(
feature = "serde",
serde(
deserialize_with = "serde_ext::deserialize_opt_fio_operations",
serialize_with = "serde_ext::serialize_opt_fio_operations"
)
)]
pub rights: Option<fio::Operations>,
#[fidl_decl(default_preserve_none)]
pub subdir: RelativePath,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferStorage", source_path = "name_only")]
pub struct OfferStorageDecl {
pub source: OfferSource,
pub source_name: Name,
pub target: OfferTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferRunner", source_path = "dictionary")]
pub struct OfferRunnerDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommonNoAvailability, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferResolver", source_path = "dictionary")]
pub struct OfferResolverDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferDictionary", source_path = "dictionary")]
pub struct OfferDictionaryDecl {
pub source: OfferSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: OfferTarget,
pub target_name: Name,
pub dependency_type: DependencyType,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferConfiguration", source_path = "name_only")]
pub struct OfferConfigurationDecl {
pub source: OfferSource,
pub source_name: Name,
pub target: OfferTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
impl SourceName for OfferDecl {
fn source_name(&self) -> &Name {
match &self {
OfferDecl::Service(o) => o.source_name(),
OfferDecl::Protocol(o) => o.source_name(),
OfferDecl::Directory(o) => o.source_name(),
OfferDecl::Storage(o) => o.source_name(),
OfferDecl::Runner(o) => o.source_name(),
OfferDecl::Resolver(o) => o.source_name(),
OfferDecl::EventStream(o) => o.source_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.source_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.source_name(),
}
}
}
impl SourcePath for OfferDecl {
fn source_path(&self) -> BorrowedSeparatedPath<'_> {
match &self {
OfferDecl::Service(o) => o.source_path(),
OfferDecl::Protocol(o) => o.source_path(),
OfferDecl::Directory(o) => o.source_path(),
OfferDecl::Storage(o) => o.source_path(),
OfferDecl::Runner(o) => o.source_path(),
OfferDecl::Resolver(o) => o.source_path(),
OfferDecl::EventStream(o) => o.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.source_path(),
}
}
}
impl UseDeclCommon for UseDecl {
fn source(&self) -> &UseSource {
match &self {
UseDecl::Service(u) => u.source(),
UseDecl::Protocol(u) => u.source(),
UseDecl::Directory(u) => u.source(),
UseDecl::Storage(u) => u.source(),
UseDecl::EventStream(u) => u.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(u) => u.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(u) => u.source(),
}
}
fn availability(&self) -> &Availability {
match &self {
UseDecl::Service(u) => u.availability(),
UseDecl::Protocol(u) => u.availability(),
UseDecl::Directory(u) => u.availability(),
UseDecl::Storage(u) => u.availability(),
UseDecl::EventStream(u) => u.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(u) => u.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(u) => u.availability(),
}
}
}
impl OfferDeclCommon for OfferDecl {
fn target_name(&self) -> &Name {
match &self {
OfferDecl::Service(o) => o.target_name(),
OfferDecl::Protocol(o) => o.target_name(),
OfferDecl::Directory(o) => o.target_name(),
OfferDecl::Storage(o) => o.target_name(),
OfferDecl::Runner(o) => o.target_name(),
OfferDecl::Resolver(o) => o.target_name(),
OfferDecl::EventStream(o) => o.target_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.target_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.target_name(),
}
}
fn target(&self) -> &OfferTarget {
match &self {
OfferDecl::Service(o) => o.target(),
OfferDecl::Protocol(o) => o.target(),
OfferDecl::Directory(o) => o.target(),
OfferDecl::Storage(o) => o.target(),
OfferDecl::Runner(o) => o.target(),
OfferDecl::Resolver(o) => o.target(),
OfferDecl::EventStream(o) => o.target(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.target(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.target(),
}
}
fn source(&self) -> &OfferSource {
match &self {
OfferDecl::Service(o) => o.source(),
OfferDecl::Protocol(o) => o.source(),
OfferDecl::Directory(o) => o.source(),
OfferDecl::Storage(o) => o.source(),
OfferDecl::Runner(o) => o.source(),
OfferDecl::Resolver(o) => o.source(),
OfferDecl::EventStream(o) => o.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.source(),
}
}
fn availability(&self) -> &Availability {
match &self {
OfferDecl::Service(o) => o.availability(),
OfferDecl::Protocol(o) => o.availability(),
OfferDecl::Directory(o) => o.availability(),
OfferDecl::Storage(o) => o.availability(),
OfferDecl::Runner(o) => o.availability(),
OfferDecl::Resolver(o) => o.availability(),
OfferDecl::EventStream(o) => o.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(o) => o.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(o) => o.availability(),
}
}
}
impl SourceName for OfferRunnerDecl {
fn source_name(&self) -> &Name {
&self.source_name
}
}
impl OfferDeclCommon for OfferRunnerDecl {
fn target_name(&self) -> &Name {
&self.target_name
}
fn target(&self) -> &OfferTarget {
&self.target
}
fn source(&self) -> &OfferSource {
&self.source
}
fn availability(&self) -> &Availability {
&Availability::Required
}
}
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(tag = "type", rename_all = "snake_case")
)]
#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::Expose")]
pub enum ExposeDecl {
Service(ExposeServiceDecl),
Protocol(ExposeProtocolDecl),
Directory(ExposeDirectoryDecl),
Runner(ExposeRunnerDecl),
Resolver(ExposeResolverDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Dictionary(ExposeDictionaryDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Config(ExposeConfigurationDecl),
}
impl SourceName for ExposeDecl {
fn source_name(&self) -> &Name {
match self {
Self::Service(e) => e.source_name(),
Self::Protocol(e) => e.source_name(),
Self::Directory(e) => e.source_name(),
Self::Runner(e) => e.source_name(),
Self::Resolver(e) => e.source_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.source_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.source_name(),
}
}
}
impl SourcePath for ExposeDecl {
fn source_path(&self) -> BorrowedSeparatedPath<'_> {
match self {
Self::Service(e) => e.source_path(),
Self::Protocol(e) => e.source_path(),
Self::Directory(e) => e.source_path(),
Self::Runner(e) => e.source_path(),
Self::Resolver(e) => e.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.source_path(),
}
}
}
impl ExposeDeclCommon for ExposeDecl {
fn source(&self) -> &ExposeSource {
match self {
Self::Service(e) => e.source(),
Self::Protocol(e) => e.source(),
Self::Directory(e) => e.source(),
Self::Runner(e) => e.source(),
Self::Resolver(e) => e.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.source(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.source(),
}
}
fn target(&self) -> &ExposeTarget {
match self {
Self::Service(e) => e.target(),
Self::Protocol(e) => e.target(),
Self::Directory(e) => e.target(),
Self::Runner(e) => e.target(),
Self::Resolver(e) => e.target(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.target(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.target(),
}
}
fn target_name(&self) -> &Name {
match self {
Self::Service(e) => e.target_name(),
Self::Protocol(e) => e.target_name(),
Self::Directory(e) => e.target_name(),
Self::Runner(e) => e.target_name(),
Self::Resolver(e) => e.target_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.target_name(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.target_name(),
}
}
fn availability(&self) -> &Availability {
match self {
Self::Service(e) => e.availability(),
Self::Protocol(e) => e.availability(),
Self::Directory(e) => e.availability(),
Self::Runner(e) => e.availability(),
Self::Resolver(e) => e.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Dictionary(e) => e.availability(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Config(e) => e.availability(),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeService", source_path = "dictionary")]
pub struct ExposeServiceDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeProtocol", source_path = "dictionary")]
pub struct ExposeProtocolDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeDirectory", source_path = "dictionary")]
pub struct ExposeDirectoryDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
#[cfg_attr(
feature = "serde",
serde(
deserialize_with = "serde_ext::deserialize_opt_fio_operations",
serialize_with = "serde_ext::serialize_opt_fio_operations"
)
)]
pub rights: Option<fio::Operations>,
#[fidl_decl(default_preserve_none)]
pub subdir: RelativePath,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeRunner", source_path = "dictionary")]
pub struct ExposeRunnerDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeResolver", source_path = "dictionary")]
pub struct ExposeResolverDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeDictionary", source_path = "dictionary")]
pub struct ExposeDictionaryDecl {
pub source: ExposeSource,
pub source_name: Name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[fidl_decl(default_preserve_none)]
pub source_dictionary: RelativePath,
pub target: ExposeTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeConfiguration", source_path = "name_only")]
pub struct ExposeConfigurationDecl {
pub source: ExposeSource,
pub source_name: Name,
pub target: ExposeTarget,
pub target_name: Name,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(tag = "type", rename_all = "snake_case")
)]
#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::Capability")]
pub enum CapabilityDecl {
Service(ServiceDecl),
Protocol(ProtocolDecl),
Directory(DirectoryDecl),
Storage(StorageDecl),
Runner(RunnerDecl),
Resolver(ResolverDecl),
EventStream(EventStreamDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Dictionary(DictionaryDecl),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Config(ConfigurationDecl),
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Service")]
pub struct ServiceDecl {
pub name: Name,
pub source_path: Option<Path>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Protocol")]
pub struct ProtocolDecl {
pub name: Name,
pub source_path: Option<Path>,
#[fidl_decl(default)]
pub delivery: DeliveryType,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Directory")]
pub struct DirectoryDecl {
pub name: Name,
pub source_path: Option<Path>,
#[cfg_attr(
feature = "serde",
serde(
deserialize_with = "serde_ext::deserialize_fio_operations",
serialize_with = "serde_ext::serialize_fio_operations"
)
)]
pub rights: fio::Operations,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Storage")]
pub struct StorageDecl {
pub name: Name,
pub source: StorageDirectorySource,
pub backing_dir: Name,
#[fidl_decl(default_preserve_none)]
pub subdir: RelativePath,
#[cfg_attr(feature = "serde", serde(with = "serde_ext::StorageId"))]
pub storage_id: fdecl::StorageId,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Runner")]
pub struct RunnerDecl {
pub name: Name,
pub source_path: Option<Path>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Resolver")]
pub struct ResolverDecl {
pub name: Name,
pub source_path: Option<Path>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::EventStream")]
pub struct EventStreamDecl {
pub name: Name,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Dictionary")]
pub struct DictionaryDecl {
pub name: Name,
pub source: Option<DictionarySource>,
pub source_dictionary: Option<RelativePath>,
}
#[cfg(fuchsia_api_level_at_least = "HEAD")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Configuration")]
pub struct ConfigurationDecl {
pub name: Name,
pub value: ConfigValue,
}
impl CapabilityDecl {
pub fn name(&self) -> &Name {
match self {
CapabilityDecl::Directory(decl) => &decl.name,
CapabilityDecl::Protocol(decl) => &decl.name,
CapabilityDecl::Resolver(decl) => &decl.name,
CapabilityDecl::Runner(decl) => &decl.name,
CapabilityDecl::Service(decl) => &decl.name,
CapabilityDecl::Storage(decl) => &decl.name,
CapabilityDecl::EventStream(decl) => &decl.name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Dictionary(decl) => &decl.name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Config(decl) => &decl.name,
}
}
pub fn path(&self) -> Option<&Path> {
match self {
CapabilityDecl::Directory(decl) => decl.source_path.as_ref(),
CapabilityDecl::Protocol(decl) => decl.source_path.as_ref(),
CapabilityDecl::Resolver(decl) => decl.source_path.as_ref(),
CapabilityDecl::Runner(decl) => decl.source_path.as_ref(),
CapabilityDecl::Service(decl) => decl.source_path.as_ref(),
CapabilityDecl::Storage(_) => None,
CapabilityDecl::EventStream(_) => None,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Dictionary(_) => None,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Config(_) => None,
}
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Child")]
pub struct ChildDecl {
pub name: LongName,
pub url: String,
pub startup: fdecl::StartupMode,
pub on_terminate: Option<fdecl::OnTerminate>,
pub environment: Option<String>,
pub config_overrides: Option<Vec<ConfigOverride>>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ChildRef {
pub name: LongName,
pub collection: Option<Name>,
}
impl std::fmt::Display for ChildRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(collection) = &self.collection {
write!(f, "{}:{}", collection, self.name)
} else {
write!(f, "{}", self.name)
}
}
}
impl FidlIntoNative<ChildRef> for fdecl::ChildRef {
fn fidl_into_native(self) -> ChildRef {
// cm_fidl_validator should have already validated this
ChildRef {
name: self.name.parse().unwrap(),
collection: self.collection.map(|c| c.parse().unwrap()),
}
}
}
impl NativeIntoFidl<fdecl::ChildRef> for ChildRef {
fn native_into_fidl(self) -> fdecl::ChildRef {
fdecl::ChildRef {
name: self.name.to_string(),
collection: self.collection.map(|c| c.to_string()),
}
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Collection")]
pub struct CollectionDecl {
pub name: Name,
pub durability: fdecl::Durability,
pub environment: Option<String>,
#[fidl_decl(default)]
pub allowed_offers: AllowedOffers,
#[fidl_decl(default)]
pub allow_long_names: bool,
pub persistent_storage: Option<bool>,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Environment")]
pub struct EnvironmentDecl {
pub name: String,
pub extends: fdecl::EnvironmentExtends,
pub runners: Vec<RunnerRegistration>,
pub resolvers: Vec<ResolverRegistration>,
pub debug_capabilities: Vec<DebugRegistration>,
pub stop_timeout_ms: Option<u32>,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigOverride")]
pub struct ConfigOverride {
pub key: String,
pub value: ConfigValue,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigSchema")]
pub struct ConfigDecl {
pub fields: Vec<ConfigField>,
pub checksum: ConfigChecksum,
pub value_source: ConfigValueSource,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_union = "fdecl::ConfigChecksum")]
pub enum ConfigChecksum {
Sha256([u8; 32]),
}
#[derive(FidlDecl, Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigSourceCapabilities")]
pub struct ConfigSourceCapabilities {}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_union = "fdecl::ConfigValueSource")]
pub enum ConfigValueSource {
PackagePath(String),
Capabilities(ConfigSourceCapabilities),
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigField")]
pub struct ConfigField {
pub key: String,
pub type_: ConfigValueType,
// This field will not be present in compiled manifests which predate F12.
#[fidl_decl(default)]
pub mutability: ConfigMutability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConfigNestedValueType {
Bool,
Uint8,
Int8,
Uint16,
Int16,
Uint32,
Int32,
Uint64,
Int64,
String { max_size: u32 },
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConfigValueType {
Bool,
Uint8,
Int8,
Uint16,
Int16,
Uint32,
Int32,
Uint64,
Int64,
String { max_size: u32 },
Vector { nested_type: ConfigNestedValueType, max_count: u32 },
}
impl ConfigValueType {
pub fn get_max_size(&self) -> Option<u32> {
match self {
ConfigValueType::String { max_size } => Some(*max_size),
ConfigValueType::Bool
| ConfigValueType::Uint8
| ConfigValueType::Int8
| ConfigValueType::Uint16
| ConfigValueType::Int16
| ConfigValueType::Uint32
| ConfigValueType::Int32
| ConfigValueType::Uint64
| ConfigValueType::Int64
| ConfigValueType::Vector { .. } => None,
}
}
pub fn get_nested_type(&self) -> Option<ConfigNestedValueType> {
match self {
ConfigValueType::Vector { nested_type, .. } => Some(nested_type.clone()),
ConfigValueType::Bool
| ConfigValueType::Uint8
| ConfigValueType::Int8
| ConfigValueType::Uint16
| ConfigValueType::Int16
| ConfigValueType::Uint32
| ConfigValueType::Int32
| ConfigValueType::Uint64
| ConfigValueType::Int64
| ConfigValueType::String { .. } => None,
}
}
pub fn get_max_count(&self) -> Option<u32> {
match self {
ConfigValueType::Vector { max_count, .. } => Some(*max_count),
ConfigValueType::Bool
| ConfigValueType::Uint8
| ConfigValueType::Int8
| ConfigValueType::Uint16
| ConfigValueType::Int16
| ConfigValueType::Uint32
| ConfigValueType::Int32
| ConfigValueType::Uint64
| ConfigValueType::Int64
| ConfigValueType::String { .. } => None,
}
}
}
impl FidlIntoNative<ConfigNestedValueType> for fdecl::ConfigType {
fn fidl_into_native(mut self) -> ConfigNestedValueType {
match self.layout {
fdecl::ConfigTypeLayout::Bool => ConfigNestedValueType::Bool,
fdecl::ConfigTypeLayout::Uint8 => ConfigNestedValueType::Uint8,
fdecl::ConfigTypeLayout::Uint16 => ConfigNestedValueType::Uint16,
fdecl::ConfigTypeLayout::Uint32 => ConfigNestedValueType::Uint32,
fdecl::ConfigTypeLayout::Uint64 => ConfigNestedValueType::Uint64,
fdecl::ConfigTypeLayout::Int8 => ConfigNestedValueType::Int8,
fdecl::ConfigTypeLayout::Int16 => ConfigNestedValueType::Int16,
fdecl::ConfigTypeLayout::Int32 => ConfigNestedValueType::Int32,
fdecl::ConfigTypeLayout::Int64 => ConfigNestedValueType::Int64,
fdecl::ConfigTypeLayout::String => {
let max_size =
if let fdecl::LayoutConstraint::MaxSize(s) = self.constraints.remove(0) {
s
} else {
panic!("Unexpected constraint on String layout type for config field");
};
ConfigNestedValueType::String { max_size }
}
fdecl::ConfigTypeLayout::Vector => {
panic!("Nested vectors are not supported in structured config")
}
fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
}
}
}
impl NativeIntoFidl<fdecl::ConfigType> for ConfigNestedValueType {
fn native_into_fidl(self) -> fdecl::ConfigType {
let layout = match self {
ConfigNestedValueType::Bool => fdecl::ConfigTypeLayout::Bool,
ConfigNestedValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
ConfigNestedValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
ConfigNestedValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
ConfigNestedValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
ConfigNestedValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
ConfigNestedValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
ConfigNestedValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
ConfigNestedValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
ConfigNestedValueType::String { .. } => fdecl::ConfigTypeLayout::String,
};
let constraints = match self {
ConfigNestedValueType::String { max_size } => {
vec![fdecl::LayoutConstraint::MaxSize(max_size)]
}
_ => vec![],
};
fdecl::ConfigType { layout, constraints, parameters: Some(vec![]) }
}
}
impl FidlIntoNative<ConfigValueType> for fdecl::ConfigType {
fn fidl_into_native(mut self) -> ConfigValueType {
match self.layout {
fdecl::ConfigTypeLayout::Bool => ConfigValueType::Bool,
fdecl::ConfigTypeLayout::Uint8 => ConfigValueType::Uint8,
fdecl::ConfigTypeLayout::Uint16 => ConfigValueType::Uint16,
fdecl::ConfigTypeLayout::Uint32 => ConfigValueType::Uint32,
fdecl::ConfigTypeLayout::Uint64 => ConfigValueType::Uint64,
fdecl::ConfigTypeLayout::Int8 => ConfigValueType::Int8,
fdecl::ConfigTypeLayout::Int16 => ConfigValueType::Int16,
fdecl::ConfigTypeLayout::Int32 => ConfigValueType::Int32,
fdecl::ConfigTypeLayout::Int64 => ConfigValueType::Int64,
fdecl::ConfigTypeLayout::String => {
let max_size = if let fdecl::LayoutConstraint::MaxSize(s) =
self.constraints.remove(0)
{
s
} else {
panic!("Unexpected constraint on String layout type for config field. Expected MaxSize.");
};
ConfigValueType::String { max_size }
}
fdecl::ConfigTypeLayout::Vector => {
let max_count = if let fdecl::LayoutConstraint::MaxSize(c) =
self.constraints.remove(0)
{
c
} else {
panic!("Unexpected constraint on Vector layout type for config field. Expected MaxSize.");
};
let mut parameters =
self.parameters.expect("Config field must have parameters set");
let nested_type = if let fdecl::LayoutParameter::NestedType(nested_type) =
parameters.remove(0)
{
nested_type.fidl_into_native()
} else {
panic!("Unexpected parameter on Vector layout type for config field. Expected NestedType.");
};
ConfigValueType::Vector { max_count, nested_type }
}
fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
}
}
}
impl NativeIntoFidl<fdecl::ConfigType> for ConfigValueType {
fn native_into_fidl(self) -> fdecl::ConfigType {
let layout = match self {
ConfigValueType::Bool => fdecl::ConfigTypeLayout::Bool,
ConfigValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
ConfigValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
ConfigValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
ConfigValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
ConfigValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
ConfigValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
ConfigValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
ConfigValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
ConfigValueType::String { .. } => fdecl::ConfigTypeLayout::String,
ConfigValueType::Vector { .. } => fdecl::ConfigTypeLayout::Vector,
};
let (constraints, parameters) = match self {
ConfigValueType::String { max_size } => {
(vec![fdecl::LayoutConstraint::MaxSize(max_size)], vec![])
}
ConfigValueType::Vector { max_count, nested_type } => {
let nested_type = nested_type.native_into_fidl();
(
vec![fdecl::LayoutConstraint::MaxSize(max_count)],
vec![fdecl::LayoutParameter::NestedType(nested_type)],
)
}
_ => (vec![], vec![]),
};
fdecl::ConfigType { layout, constraints, parameters: Some(parameters) }
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
// TODO(https://fxbug.dev/42075220) uncomment once bitflags is updated
// pub struct ConfigMutability: <fdecl::ConfigMutability as bitflags::BitFlags>::Bits {
pub struct ConfigMutability: u32 {
const PARENT = fdecl::ConfigMutability::PARENT.bits();
}
}
#[cfg(feature = "serde")]
bitflags_serde_legacy::impl_traits!(ConfigMutability);
impl NativeIntoFidl<fdecl::ConfigMutability> for ConfigMutability {
fn native_into_fidl(self) -> fdecl::ConfigMutability {
fdecl::ConfigMutability::from_bits_allow_unknown(self.bits())
}
}
impl FidlIntoNative<ConfigMutability> for fdecl::ConfigMutability {
fn fidl_into_native(self) -> ConfigMutability {
ConfigMutability::from_bits_retain(self.bits())
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigValuesData")]
pub struct ConfigValuesData {
pub values: Vec<ConfigValueSpec>,
pub checksum: ConfigChecksum,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_table = "fdecl::ConfigValueSpec")]
pub struct ConfigValueSpec {
pub value: ConfigValue,
}
#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_union = "fdecl::ConfigValue")]
pub enum ConfigValue {
Single(ConfigSingleValue),
Vector(ConfigVectorValue),
}
impl ConfigValue {
/// Return the type of this value.
pub fn ty(&self) -> ConfigValueType {
match self {
Self::Single(sv) => sv.ty(),
Self::Vector(vv) => vv.ty(),
}
}
/// Check if this value matches the type of another value.
pub fn matches_type(&self, other: &ConfigValue) -> bool {
match (self, other) {
(ConfigValue::Single(a), ConfigValue::Single(b)) => {
std::mem::discriminant(a) == std::mem::discriminant(b)
}
(ConfigValue::Vector(a), ConfigValue::Vector(b)) => {
std::mem::discriminant(a) == std::mem::discriminant(b)
}
_ => false,
}
}
}
impl From<&str> for ConfigValue {
fn from(value: &str) -> Self {
ConfigValue::Single(value.to_string().into())
}
}
impl From<Vec<&str>> for ConfigValue {
fn from(value: Vec<&str>) -> Self {
let value: Vec<_> = value.into_iter().map(|s| s.to_string()).collect();
ConfigValue::Vector(value.into())
}
}
macro_rules! generate_configvalue_from {
($name:expr, $type:ty) => {
impl From<$type> for ConfigValue {
fn from(value: $type) -> Self {
$name(value.into())
}
}
};
}
generate_configvalue_from!(ConfigValue::Single, bool);
generate_configvalue_from!(ConfigValue::Single, u8);
generate_configvalue_from!(ConfigValue::Single, u16);
generate_configvalue_from!(ConfigValue::Single, u32);
generate_configvalue_from!(ConfigValue::Single, u64);
generate_configvalue_from!(ConfigValue::Single, i8);
generate_configvalue_from!(ConfigValue::Single, i16);
generate_configvalue_from!(ConfigValue::Single, i32);
generate_configvalue_from!(ConfigValue::Single, i64);
generate_configvalue_from!(ConfigValue::Single, String);
generate_configvalue_from!(ConfigValue::Vector, Vec<bool>);
generate_configvalue_from!(ConfigValue::Vector, Vec<u8>);
generate_configvalue_from!(ConfigValue::Vector, Vec<u16>);
generate_configvalue_from!(ConfigValue::Vector, Vec<u32>);
generate_configvalue_from!(ConfigValue::Vector, Vec<u64>);
generate_configvalue_from!(ConfigValue::Vector, Vec<i8>);
generate_configvalue_from!(ConfigValue::Vector, Vec<i16>);
generate_configvalue_from!(ConfigValue::Vector, Vec<i32>);
generate_configvalue_from!(ConfigValue::Vector, Vec<i64>);
generate_configvalue_from!(ConfigValue::Vector, Vec<String>);
impl fmt::Display for ConfigValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConfigValue::Single(sv) => sv.fmt(f),
ConfigValue::Vector(lv) => lv.fmt(f),
}
}
}
#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_union = "fdecl::ConfigSingleValue")]
pub enum ConfigSingleValue {
Bool(bool),
Uint8(u8),
Uint16(u16),
Uint32(u32),
Uint64(u64),
Int8(i8),
Int16(i16),
Int32(i32),
Int64(i64),
String(String),
}
impl ConfigSingleValue {
fn ty(&self) -> ConfigValueType {
match self {
ConfigSingleValue::Bool(_) => ConfigValueType::Bool,
ConfigSingleValue::Uint8(_) => ConfigValueType::Uint8,
ConfigSingleValue::Uint16(_) => ConfigValueType::Uint16,
ConfigSingleValue::Uint32(_) => ConfigValueType::Uint32,
ConfigSingleValue::Uint64(_) => ConfigValueType::Uint64,
ConfigSingleValue::Int8(_) => ConfigValueType::Int8,
ConfigSingleValue::Int16(_) => ConfigValueType::Int16,
ConfigSingleValue::Int32(_) => ConfigValueType::Int32,
ConfigSingleValue::Int64(_) => ConfigValueType::Int64,
// We substitute the max size limit because the value itself doesn't carry the info.
ConfigSingleValue::String(_) => ConfigValueType::String { max_size: std::u32::MAX },
}
}
}
impl fmt::Display for ConfigSingleValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ConfigSingleValue::*;
match self {
Bool(v) => write!(f, "{}", v),
Uint8(v) => write!(f, "{}", v),
Uint16(v) => write!(f, "{}", v),
Uint32(v) => write!(f, "{}", v),
Uint64(v) => write!(f, "{}", v),
Int8(v) => write!(f, "{}", v),
Int16(v) => write!(f, "{}", v),
Int32(v) => write!(f, "{}", v),
Int64(v) => write!(f, "{}", v),
String(v) => write!(f, "\"{}\"", v),
}
}
}
#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[fidl_decl(fidl_union = "fdecl::ConfigVectorValue")]
pub enum ConfigVectorValue {
BoolVector(Vec<bool>),
Uint8Vector(Vec<u8>),
Uint16Vector(Vec<u16>),
Uint32Vector(Vec<u32>),
Uint64Vector(Vec<u64>),
Int8Vector(Vec<i8>),
Int16Vector(Vec<i16>),
Int32Vector(Vec<i32>),
Int64Vector(Vec<i64>),
StringVector(Vec<String>),
}
impl ConfigVectorValue {
fn ty(&self) -> ConfigValueType {
// We substitute the max size limit because the value itself doesn't carry the info.
match self {
ConfigVectorValue::BoolVector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Bool,
max_count: std::u32::MAX,
},
ConfigVectorValue::Uint8Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Uint8,
max_count: std::u32::MAX,
},
ConfigVectorValue::Uint16Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Uint16,
max_count: std::u32::MAX,
},
ConfigVectorValue::Uint32Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Uint32,
max_count: std::u32::MAX,
},
ConfigVectorValue::Uint64Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Uint64,
max_count: std::u32::MAX,
},
ConfigVectorValue::Int8Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Int8,
max_count: std::u32::MAX,
},
ConfigVectorValue::Int16Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Int16,
max_count: std::u32::MAX,
},
ConfigVectorValue::Int32Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Int32,
max_count: std::u32::MAX,
},
ConfigVectorValue::Int64Vector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::Int64,
max_count: std::u32::MAX,
},
ConfigVectorValue::StringVector(_) => ConfigValueType::Vector {
nested_type: ConfigNestedValueType::String { max_size: std::u32::MAX },
max_count: std::u32::MAX,
},
}
}
}
impl fmt::Display for ConfigVectorValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ConfigVectorValue::*;
macro_rules! print_list {
($f:ident, $list:ident) => {{
$f.write_str("[")?;
for (i, item) in $list.iter().enumerate() {
if i > 0 {
$f.write_str(", ")?;
}
write!($f, "{}", item)?;
}
$f.write_str("]")
}};
}
match self {
BoolVector(l) => print_list!(f, l),
Uint8Vector(l) => print_list!(f, l),
Uint16Vector(l) => print_list!(f, l),
Uint32Vector(l) => print_list!(f, l),
Uint64Vector(l) => print_list!(f, l),
Int8Vector(l) => print_list!(f, l),
Int16Vector(l) => print_list!(f, l),
Int32Vector(l) => print_list!(f, l),
Int64Vector(l) => print_list!(f, l),
StringVector(l) => {
f.write_str("[")?;
for (i, item) in l.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "\"{}\"", item)?;
}
f.write_str("]")
}
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::RunnerRegistration")]
pub struct RunnerRegistration {
pub source_name: Name,
pub target_name: Name,
pub source: RegistrationSource,
}
impl SourceName for RunnerRegistration {
fn source_name(&self) -> &Name {
&self.source_name
}
}
impl RegistrationDeclCommon for RunnerRegistration {
const TYPE: &'static str = "runner";
fn source(&self) -> &RegistrationSource {
&self.source
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ResolverRegistration")]
pub struct ResolverRegistration {
pub resolver: Name,
pub source: RegistrationSource,
pub scheme: String,
}
impl SourceName for ResolverRegistration {
fn source_name(&self) -> &Name {
&self.resolver
}
}
impl RegistrationDeclCommon for ResolverRegistration {
const TYPE: &'static str = "resolver";
fn source(&self) -> &RegistrationSource {
&self.source
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::DebugRegistration")]
pub enum DebugRegistration {
Protocol(DebugProtocolRegistration),
}
impl RegistrationDeclCommon for DebugRegistration {
const TYPE: &'static str = "debug_protocol";
fn source(&self) -> &RegistrationSource {
match self {
DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source,
}
}
}
impl SourceName for DebugRegistration {
fn source_name(&self) -> &Name {
match self {
DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source_name,
}
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::DebugProtocolRegistration")]
pub struct DebugProtocolRegistration {
pub source_name: Name,
pub source: RegistrationSource,
pub target_name: Name,
}
#[derive(FidlDecl, Debug, Clone, PartialEq)]
#[fidl_decl(fidl_table = "fdecl::Program")]
pub struct ProgramDecl {
pub runner: Option<Name>,
pub info: fdata::Dictionary,
}
impl Default for ProgramDecl {
fn default() -> Self {
Self { runner: None, info: fdata::Dictionary::default().clone() }
}
}
fidl_translations_identical!([u8; 32]);
fidl_translations_identical!(u8);
fidl_translations_identical!(u16);
fidl_translations_identical!(u32);
fidl_translations_identical!(u64);
fidl_translations_identical!(i8);
fidl_translations_identical!(i16);
fidl_translations_identical!(i32);
fidl_translations_identical!(i64);
fidl_translations_identical!(bool);
fidl_translations_identical!(String);
fidl_translations_identical!(Vec<Name>);
fidl_translations_identical!(fdecl::StartupMode);
fidl_translations_identical!(fdecl::OnTerminate);
fidl_translations_identical!(fdecl::Durability);
fidl_translations_identical!(fdata::Dictionary);
fidl_translations_identical!(fio::Operations);
fidl_translations_identical!(fdecl::EnvironmentExtends);
fidl_translations_identical!(fdecl::StorageId);
fidl_translations_identical!(Vec<fprocess::HandleInfo>);
fidl_translations_from_into!(cm_types::AllowedOffers, fdecl::AllowedOffers);
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DependencyType {
Strong,
Weak,
}
fidl_translations_symmetrical_enums!(fdecl::DependencyType, DependencyType, Strong, Weak);
impl UseDecl {
pub fn path(&self) -> Option<&Path> {
match self {
UseDecl::Service(d) => Some(&d.target_path),
UseDecl::Protocol(d) => Some(&d.target_path),
UseDecl::Directory(d) => Some(&d.target_path),
UseDecl::Storage(d) => Some(&d.target_path),
UseDecl::EventStream(d) => Some(&d.target_path),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(_) => None,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(_) => None,
}
}
pub fn name(&self) -> Option<&Name> {
match self {
UseDecl::Storage(storage_decl) => Some(&storage_decl.source_name),
UseDecl::EventStream(_) => None,
UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Directory(_) => None,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(_) => None,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(_) => None,
}
}
}
impl SourceName for UseDecl {
fn source_name(&self) -> &Name {
match self {
UseDecl::Storage(storage_decl) => &storage_decl.source_name,
UseDecl::Service(service_decl) => &service_decl.source_name,
UseDecl::Protocol(protocol_decl) => &protocol_decl.source_name,
UseDecl::Directory(directory_decl) => &directory_decl.source_name,
UseDecl::EventStream(event_stream_decl) => &event_stream_decl.source_name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(runner_decl) => &runner_decl.source_name,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(u) => &u.source_name,
}
}
}
impl SourcePath for UseDecl {
fn source_path(&self) -> BorrowedSeparatedPath<'_> {
match self {
UseDecl::Service(u) => u.source_path(),
UseDecl::Protocol(u) => u.source_path(),
UseDecl::Directory(u) => u.source_path(),
UseDecl::Storage(u) => u.source_path(),
UseDecl::EventStream(u) => u.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(u) => u.source_path(),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(u) => u.source_path(),
}
}
}
/// The trait for all declarations that have a source name.
pub trait SourceName {
fn source_name(&self) -> &Name;
}
/// The common properties of a [Use](fdecl::Use) declaration.
pub trait UseDeclCommon: SourceName + SourcePath + Send + Sync {
fn source(&self) -> &UseSource;
fn availability(&self) -> &Availability;
}
/// The common properties of a Registration-with-environment declaration.
pub trait RegistrationDeclCommon: SourceName + Send + Sync {
/// The name of the registration type, for error messages.
const TYPE: &'static str;
fn source(&self) -> &RegistrationSource;
}
/// The common properties of an [Offer](fdecl::Offer) declaration.
pub trait OfferDeclCommon: SourceName + SourcePath + fmt::Debug + Send + Sync {
fn target_name(&self) -> &Name;
fn target(&self) -> &OfferTarget;
fn source(&self) -> &OfferSource;
fn availability(&self) -> &Availability;
}
/// The common properties of an [Expose](fdecl::Expose) declaration.
pub trait ExposeDeclCommon: SourceName + SourcePath + fmt::Debug + Send + Sync {
fn target_name(&self) -> &Name;
fn target(&self) -> &ExposeTarget;
fn source(&self) -> &ExposeSource;
fn availability(&self) -> &Availability;
}
/// A named capability type.
///
/// `CapabilityTypeName` provides a user friendly type encoding for a capability.
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CapabilityTypeName {
Directory,
EventStream,
Protocol,
Resolver,
Runner,
Service,
Storage,
Dictionary,
Config,
}
impl std::str::FromStr for CapabilityTypeName {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"directory" => Ok(CapabilityTypeName::Directory),
"event_stream" => Ok(CapabilityTypeName::EventStream),
"protocol" => Ok(CapabilityTypeName::Protocol),
"resolver" => Ok(CapabilityTypeName::Resolver),
"runner" => Ok(CapabilityTypeName::Runner),
"service" => Ok(CapabilityTypeName::Service),
"storage" => Ok(CapabilityTypeName::Storage),
"dictionary" => Ok(CapabilityTypeName::Dictionary),
"configuration" => Ok(CapabilityTypeName::Config),
_ => Err(Error::ParseCapabilityTypeName { raw: s.to_string() }),
}
}
}
impl fmt::Display for CapabilityTypeName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let display_name = match &self {
CapabilityTypeName::Directory => "directory",
CapabilityTypeName::EventStream => "event_stream",
CapabilityTypeName::Protocol => "protocol",
CapabilityTypeName::Resolver => "resolver",
CapabilityTypeName::Runner => "runner",
CapabilityTypeName::Service => "service",
CapabilityTypeName::Storage => "storage",
CapabilityTypeName::Dictionary => "dictionary",
CapabilityTypeName::Config => "configuration",
};
write!(f, "{}", display_name)
}
}
impl From<&UseDecl> for CapabilityTypeName {
fn from(use_decl: &UseDecl) -> Self {
match use_decl {
UseDecl::Service(_) => Self::Service,
UseDecl::Protocol(_) => Self::Protocol,
UseDecl::Directory(_) => Self::Directory,
UseDecl::Storage(_) => Self::Storage,
UseDecl::EventStream(_) => Self::EventStream,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Runner(_) => Self::Runner,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseDecl::Config(_) => Self::Config,
}
}
}
impl From<&OfferDecl> for CapabilityTypeName {
fn from(offer_decl: &OfferDecl) -> Self {
match offer_decl {
OfferDecl::Service(_) => Self::Service,
OfferDecl::Protocol(_) => Self::Protocol,
OfferDecl::Directory(_) => Self::Directory,
OfferDecl::Storage(_) => Self::Storage,
OfferDecl::Runner(_) => Self::Runner,
OfferDecl::Resolver(_) => Self::Resolver,
OfferDecl::EventStream(_) => Self::EventStream,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Dictionary(_) => Self::Dictionary,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
OfferDecl::Config(_) => Self::Config,
}
}
}
impl From<&ExposeDecl> for CapabilityTypeName {
fn from(expose_decl: &ExposeDecl) -> Self {
match expose_decl {
ExposeDecl::Service(_) => Self::Service,
ExposeDecl::Protocol(_) => Self::Protocol,
ExposeDecl::Directory(_) => Self::Directory,
ExposeDecl::Runner(_) => Self::Runner,
ExposeDecl::Resolver(_) => Self::Resolver,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
ExposeDecl::Dictionary(_) => Self::Dictionary,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
ExposeDecl::Config(_) => Self::Config,
}
}
}
impl From<&CapabilityDecl> for CapabilityTypeName {
fn from(capability: &CapabilityDecl) -> Self {
match capability {
CapabilityDecl::Service(_) => Self::Service,
CapabilityDecl::Protocol(_) => Self::Protocol,
CapabilityDecl::Directory(_) => Self::Directory,
CapabilityDecl::Storage(_) => Self::Storage,
CapabilityDecl::Runner(_) => Self::Runner,
CapabilityDecl::Resolver(_) => Self::Resolver,
CapabilityDecl::EventStream(_) => Self::EventStream,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Dictionary(_) => Self::Dictionary,
#[cfg(fuchsia_api_level_at_least = "HEAD")]
CapabilityDecl::Config(_) => Self::Config,
}
}
}
impl From<CapabilityTypeName> for fio::DirentType {
fn from(value: CapabilityTypeName) -> Self {
match value {
CapabilityTypeName::Directory => fio::DirentType::Directory,
CapabilityTypeName::EventStream => fio::DirentType::Service,
CapabilityTypeName::Protocol => fio::DirentType::Service,
CapabilityTypeName::Service => fio::DirentType::Directory,
CapabilityTypeName::Storage => fio::DirentType::Directory,
CapabilityTypeName::Dictionary => fio::DirentType::Directory,
// The below don't appear in exposed or used dir
CapabilityTypeName::Resolver
| CapabilityTypeName::Runner
| CapabilityTypeName::Config => fio::DirentType::Unknown,
}
}
}
// TODO: Runners and third parties can use this to parse `facets`.
impl FidlIntoNative<HashMap<String, DictionaryValue>> for fdata::Dictionary {
fn fidl_into_native(self) -> HashMap<String, DictionaryValue> {
from_fidl_dict(self)
}
}
impl NativeIntoFidl<fdata::Dictionary> for HashMap<String, DictionaryValue> {
fn native_into_fidl(self) -> fdata::Dictionary {
to_fidl_dict(self)
}
}
impl FidlIntoNative<BTreeMap<String, DictionaryValue>> for fdata::Dictionary {
fn fidl_into_native(self) -> BTreeMap<String, DictionaryValue> {
from_fidl_dict_btree(self)
}
}
impl NativeIntoFidl<fdata::Dictionary> for BTreeMap<String, DictionaryValue> {
fn native_into_fidl(self) -> fdata::Dictionary {
to_fidl_dict_btree(self)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DictionaryValue {
Str(String),
StrVec(Vec<String>),
Null,
}
impl FidlIntoNative<DictionaryValue> for Option<Box<fdata::DictionaryValue>> {
fn fidl_into_native(self) -> DictionaryValue {
// Temporarily allow unreachable patterns while fuchsia.data.DictionaryValue
// is migrated from `strict` to `flexible`.
// TODO(https://fxbug.dev/42173900): Remove this.
#[allow(unreachable_patterns)]
match self {
Some(v) => match *v {
fdata::DictionaryValue::Str(s) => DictionaryValue::Str(s),
fdata::DictionaryValue::StrVec(ss) => DictionaryValue::StrVec(ss),
_ => DictionaryValue::Null,
},
None => DictionaryValue::Null,
}
}
}
impl NativeIntoFidl<Option<Box<fdata::DictionaryValue>>> for DictionaryValue {
fn native_into_fidl(self) -> Option<Box<fdata::DictionaryValue>> {
match self {
DictionaryValue::Str(s) => Some(Box::new(fdata::DictionaryValue::Str(s))),
DictionaryValue::StrVec(ss) => Some(Box::new(fdata::DictionaryValue::StrVec(ss))),
DictionaryValue::Null => None,
}
}
}
fn from_fidl_dict(dict: fdata::Dictionary) -> HashMap<String, DictionaryValue> {
match dict.entries {
Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
_ => HashMap::new(),
}
}
fn to_fidl_dict(dict: HashMap<String, DictionaryValue>) -> fdata::Dictionary {
fdata::Dictionary {
entries: Some(
dict.into_iter()
.map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
.collect(),
),
..Default::default()
}
}
fn from_fidl_dict_btree(dict: fdata::Dictionary) -> BTreeMap<String, DictionaryValue> {
match dict.entries {
Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
_ => BTreeMap::new(),
}
}
fn to_fidl_dict_btree(dict: BTreeMap<String, DictionaryValue>) -> fdata::Dictionary {
fdata::Dictionary {
entries: Some(
dict.into_iter()
.map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
.collect(),
),
..Default::default()
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum UseSource {
Parent,
Framework,
Debug,
Self_,
Capability(Name),
Child(String),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Environment,
}
impl std::fmt::Display for UseSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Framework => write!(f, "framework"),
Self::Parent => write!(f, "parent"),
Self::Debug => write!(f, "debug environment"),
Self::Self_ => write!(f, "self"),
Self::Capability(c) => write!(f, "capability `{}`", c),
Self::Child(c) => write!(f, "child `#{}`", c),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
Self::Environment => write!(f, "environment"),
}
}
}
impl FidlIntoNative<UseSource> for fdecl::Ref {
fn fidl_into_native(self) -> UseSource {
match self {
fdecl::Ref::Parent(_) => UseSource::Parent,
fdecl::Ref::Framework(_) => UseSource::Framework,
fdecl::Ref::Debug(_) => UseSource::Debug,
fdecl::Ref::Self_(_) => UseSource::Self_,
// cm_fidl_validator should have already validated this
fdecl::Ref::Capability(c) => UseSource::Capability(c.name.parse().unwrap()),
fdecl::Ref::Child(c) => UseSource::Child(c.name),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
fdecl::Ref::Environment(_) => UseSource::Environment,
_ => panic!("invalid UseSource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for UseSource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
UseSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
UseSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
UseSource::Debug => fdecl::Ref::Debug(fdecl::DebugRef {}),
UseSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
UseSource::Capability(name) => {
fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
}
UseSource::Child(name) => fdecl::Ref::Child(fdecl::ChildRef { name, collection: None }),
#[cfg(fuchsia_api_level_at_least = "HEAD")]
UseSource::Environment => fdecl::Ref::Environment(fdecl::EnvironmentRef {}),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum EventScope {
Child(ChildRef),
Collection(Name),
}
impl FidlIntoNative<EventScope> for fdecl::Ref {
fn fidl_into_native(self) -> EventScope {
match self {
fdecl::Ref::Child(c) => {
if let Some(_) = c.collection {
panic!("Dynamic children scopes are not supported for EventStreams");
} else {
EventScope::Child(ChildRef { name: c.name.parse().unwrap(), collection: None })
}
}
fdecl::Ref::Collection(collection) => {
// cm_fidl_validator should have already validated this
EventScope::Collection(collection.name.parse().unwrap())
}
_ => panic!("invalid EventScope variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for EventScope {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
EventScope::Child(child) => fdecl::Ref::Child(child.native_into_fidl()),
EventScope::Collection(name) => {
fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
}
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OfferSource {
Framework,
Parent,
Child(ChildRef),
Collection(Name),
Self_,
Capability(Name),
Void,
}
impl std::fmt::Display for OfferSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Framework => write!(f, "framework"),
Self::Parent => write!(f, "parent"),
Self::Child(c) => write!(f, "child `#{}`", c),
Self::Collection(c) => write!(f, "collection `#{}`", c),
Self::Self_ => write!(f, "self"),
Self::Capability(c) => write!(f, "capability `{}`", c),
Self::Void => write!(f, "void"),
}
}
}
impl FidlIntoNative<OfferSource> for fdecl::Ref {
fn fidl_into_native(self) -> OfferSource {
match self {
fdecl::Ref::Parent(_) => OfferSource::Parent,
fdecl::Ref::Self_(_) => OfferSource::Self_,
fdecl::Ref::Child(c) => OfferSource::Child(c.fidl_into_native()),
// cm_fidl_validator should have already validated this
fdecl::Ref::Collection(c) => OfferSource::Collection(c.name.parse().unwrap()),
fdecl::Ref::Framework(_) => OfferSource::Framework,
// cm_fidl_validator should have already validated this
fdecl::Ref::Capability(c) => OfferSource::Capability(c.name.parse().unwrap()),
fdecl::Ref::VoidType(_) => OfferSource::Void,
_ => panic!("invalid OfferSource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for OfferSource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
OfferSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
OfferSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
OfferSource::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
OfferSource::Collection(name) => {
fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
}
OfferSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
OfferSource::Capability(name) => {
fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
}
OfferSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExposeSource {
Self_,
Child(String),
Collection(Name),
Framework,
Capability(Name),
Void,
}
impl std::fmt::Display for ExposeSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Framework => write!(f, "framework"),
Self::Child(c) => write!(f, "child `#{}`", c),
Self::Collection(c) => write!(f, "collection `#{}`", c),
Self::Self_ => write!(f, "self"),
Self::Capability(c) => write!(f, "capability `{}`", c),
Self::Void => write!(f, "void"),
}
}
}
impl FidlIntoNative<ExposeSource> for fdecl::Ref {
fn fidl_into_native(self) -> ExposeSource {
match self {
fdecl::Ref::Self_(_) => ExposeSource::Self_,
fdecl::Ref::Child(c) => ExposeSource::Child(c.name),
// cm_fidl_validator should have already validated this
fdecl::Ref::Collection(c) => ExposeSource::Collection(c.name.parse().unwrap()),
fdecl::Ref::Framework(_) => ExposeSource::Framework,
// cm_fidl_validator should have already validated this
fdecl::Ref::Capability(c) => ExposeSource::Capability(c.name.parse().unwrap()),
fdecl::Ref::VoidType(_) => ExposeSource::Void,
_ => panic!("invalid ExposeSource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for ExposeSource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
ExposeSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
ExposeSource::Child(child_name) => {
fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
}
ExposeSource::Collection(name) => {
fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
}
ExposeSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
ExposeSource::Capability(name) => {
fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
}
ExposeSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ExposeTarget {
Parent,
Framework,
}
impl std::fmt::Display for ExposeTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Framework => write!(f, "framework"),
Self::Parent => write!(f, "parent"),
}
}
}
impl FidlIntoNative<ExposeTarget> for fdecl::Ref {
fn fidl_into_native(self) -> ExposeTarget {
match self {
fdecl::Ref::Parent(_) => ExposeTarget::Parent,
fdecl::Ref::Framework(_) => ExposeTarget::Framework,
_ => panic!("invalid ExposeTarget variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for ExposeTarget {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
ExposeTarget::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
ExposeTarget::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
}
}
}
/// A source for a service.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceSource<T> {
/// The provider of the service, relative to a component.
pub source: T,
/// The name of the service.
pub source_name: Name,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StorageDirectorySource {
Parent,
Self_,
Child(String),
}
impl FidlIntoNative<StorageDirectorySource> for fdecl::Ref {
fn fidl_into_native(self) -> StorageDirectorySource {
match self {
fdecl::Ref::Parent(_) => StorageDirectorySource::Parent,
fdecl::Ref::Self_(_) => StorageDirectorySource::Self_,
fdecl::Ref::Child(c) => StorageDirectorySource::Child(c.name),
_ => panic!("invalid OfferDirectorySource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for StorageDirectorySource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
StorageDirectorySource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
StorageDirectorySource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
StorageDirectorySource::Child(child_name) => {
fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
}
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DictionarySource {
Parent,
Self_,
Child(ChildRef),
}
impl FidlIntoNative<DictionarySource> for fdecl::Ref {
fn fidl_into_native(self) -> DictionarySource {
match self {
Self::Parent(_) => DictionarySource::Parent,
Self::Self_(_) => DictionarySource::Self_,
Self::Child(c) => DictionarySource::Child(c.fidl_into_native()),
_ => panic!("invalid OfferDictionarySource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for DictionarySource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
Self::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
Self::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
Self::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RegistrationSource {
Parent,
Self_,
Child(String),
}
impl FidlIntoNative<RegistrationSource> for fdecl::Ref {
fn fidl_into_native(self) -> RegistrationSource {
match self {
fdecl::Ref::Parent(_) => RegistrationSource::Parent,
fdecl::Ref::Self_(_) => RegistrationSource::Self_,
fdecl::Ref::Child(c) => RegistrationSource::Child(c.name),
_ => panic!("invalid RegistrationSource variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for RegistrationSource {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
RegistrationSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
RegistrationSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
RegistrationSource::Child(child_name) => {
fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
}
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum OfferTarget {
Child(ChildRef),
Collection(Name),
Capability(Name),
}
impl std::fmt::Display for OfferTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Child(c) => write!(f, "child `#{}`", c),
Self::Collection(c) => write!(f, "collection `#{}`", c),
Self::Capability(c) => write!(f, "capability `#{}`", c),
}
}
}
impl FidlIntoNative<OfferTarget> for fdecl::Ref {
fn fidl_into_native(self) -> OfferTarget {
match self {
fdecl::Ref::Child(c) => OfferTarget::Child(c.fidl_into_native()),
// cm_fidl_validator should have already validated this
fdecl::Ref::Collection(c) => OfferTarget::Collection(c.name.parse().unwrap()),
fdecl::Ref::Capability(c) => OfferTarget::Capability(c.name.parse().unwrap()),
_ => panic!("invalid OfferTarget variant"),
}
}
}
impl NativeIntoFidl<fdecl::Ref> for OfferTarget {
fn native_into_fidl(self) -> fdecl::Ref {
match self {
OfferTarget::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
OfferTarget::Collection(collection_name) => {
fdecl::Ref::Collection(fdecl::CollectionRef {
name: collection_name.native_into_fidl(),
})
}
OfferTarget::Capability(capability_name) => {
fdecl::Ref::Capability(fdecl::CapabilityRef {
name: capability_name.native_into_fidl(),
})
}
}
}
}
/// Converts the contents of a CM-FIDL declaration and produces the equivalent CM-Rust
/// struct.
/// This function applies cm_fidl_validator to check correctness.
impl TryFrom<fdecl::Component> for ComponentDecl {
type Error = Error;
fn try_from(decl: fdecl::Component) -> Result<Self, Self::Error> {
cm_fidl_validator::validate(&decl).map_err(|err| Error::Validate { err })?;
Ok(decl.fidl_into_native())
}
}
// Converts the contents of a CM-Rust declaration into a CM_FIDL declaration
impl From<ComponentDecl> for fdecl::Component {
fn from(decl: ComponentDecl) -> Self {
decl.native_into_fidl()
}
}
/// Errors produced by cm_rust.
#[derive(Debug, Error, Clone)]
pub enum Error {
#[error("Fidl validation failed: {}", err)]
Validate {
#[source]
err: cm_fidl_validator::error::ErrorList,
},
#[error("Invalid capability path: {}", raw)]
InvalidCapabilityPath { raw: String },
#[error("Invalid capability type name: {}", raw)]
ParseCapabilityTypeName { raw: String },
}
#[cfg(test)]
mod tests {
use {super::*, difference::Changeset, fidl_fuchsia_component_decl as fdecl};
fn offer_source_static_child(name: &str) -> OfferSource {
OfferSource::Child(ChildRef { name: name.parse().unwrap(), collection: None })
}
fn offer_target_static_child(name: &str) -> OfferTarget {
OfferTarget::Child(ChildRef { name: name.parse().unwrap(), collection: None })
}
macro_rules! test_try_from_decl {
(
$(
$test_name:ident => {
input = $input:expr,
result = $result:expr,
},
)+
) => {
$(
#[test]
fn $test_name() {
{
let res = ComponentDecl::try_from($input).expect("try_from failed");
if res != $result {
let a = format!("{:#?}", res);
let e = format!("{:#?}", $result);
panic!("Conversion from fidl to cm_rust did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
}
}
{
let res = fdecl::Component::try_from($result).expect("try_from failed");
if res != $input {
let a = format!("{:#?}", res);
let e = format!("{:#?}", $input);
panic!("Conversion from cm_rust to fidl did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
}
}
}
)+
}
}
macro_rules! test_fidl_into_and_from {
(
$(
$test_name:ident => {
input = $input:expr,
input_type = $input_type:ty,
result = $result:expr,
result_type = $result_type:ty,
},
)+
) => {
$(
#[test]
fn $test_name() {
{
let res: Vec<$result_type> =
$input.into_iter().map(|e| e.fidl_into_native()).collect();
assert_eq!(res, $result);
}
{
let res: Vec<$input_type> =
$result.into_iter().map(|e| e.native_into_fidl()).collect();
assert_eq!(res, $input);
}
}
)+
}
}
macro_rules! test_fidl_into {
(
$(
$test_name:ident => {
input = $input:expr,
result = $result:expr,
},
)+
) => {
$(
#[test]
fn $test_name() {
test_fidl_into_helper($input, $result);
}
)+
}
}
fn test_fidl_into_helper<T, U>(input: T, expected_res: U)
where
T: FidlIntoNative<U>,
U: std::cmp::PartialEq + std::fmt::Debug,
{
let res: U = input.fidl_into_native();
assert_eq!(res, expected_res);
}
test_try_from_decl! {
try_from_empty => {
input = fdecl::Component {
program: None,
uses: None,
exposes: None,
offers: None,
capabilities: None,
children: None,
collections: None,
facets: None,
environments: None,
..Default::default()
},
result = ComponentDecl {
program: None,
uses: vec![],
exposes: vec![],
offers: vec![],
capabilities: vec![],
children: vec![],
collections: vec![],
facets: None,
environments: vec![],
config: None,
},
},
try_from_all => {
input = fdecl::Component {
program: Some(fdecl::Program {
runner: Some("elf".to_string()),
info: Some(fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "args".to_string(),
value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
},
fdata::DictionaryEntry {
key: "binary".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
},
]),
..Default::default()
}),
..Default::default()
}),
uses: Some(vec![
fdecl::Use::Service(fdecl::UseService {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_path: Some("/svc/mynetstack".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Use::Protocol(fdecl::UseProtocol {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("legacy_netstack".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_path: Some("/svc/legacy_mynetstack".to_string()),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Use::Protocol(fdecl::UseProtocol {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Child(fdecl::ChildRef { name: "echo".to_string(), collection: None})),
source_name: Some("echo_service".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_path: Some("/svc/echo_service".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Use::Directory(fdecl::UseDirectory {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Framework(fdecl::FrameworkRef {})),
source_name: Some("dir".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_path: Some("/data".to_string()),
rights: Some(fio::Operations::CONNECT),
subdir: Some("foo/bar".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Use::Storage(fdecl::UseStorage {
source_name: Some("cache".to_string()),
target_path: Some("/cache".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Use::Storage(fdecl::UseStorage {
source_name: Some("temp".to_string()),
target_path: Some("/temp".to_string()),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Use::EventStream(fdecl::UseEventStream {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
collection: None,
name: "netstack".to_string(),
})),
source_name: Some("stopped".to_string()),
scope: Some(vec![
fdecl::Ref::Child(fdecl::ChildRef {
collection: None,
name:"a".to_string(),
}), fdecl::Ref::Collection(fdecl::CollectionRef {
name:"b".to_string(),
})]),
target_path: Some("/svc/test".to_string()),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Use::Runner(fdecl::UseRunner {
source: Some(fdecl::Ref::Environment(fdecl::EnvironmentRef {})),
source_name: Some("elf".to_string()),
source_dictionary: Some("in/dict".to_string()),
..Default::default()
}),
fdecl::Use::Config(fdecl::UseConfiguration {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef)),
source_name: Some("fuchsia.config.MyConfig".to_string()),
target_name: Some("my_config".to_string()),
availability: Some(fdecl::Availability::Required),
type_: Some(fdecl::ConfigType{
layout: fdecl::ConfigTypeLayout::Bool,
parameters: Some(Vec::new()),
constraints: Vec::new(),
}),
..Default::default()
}),
]),
exposes: Some(vec![
fdecl::Expose::Protocol(fdecl::ExposeProtocol {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("legacy_netstack".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_name: Some("legacy_mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Expose::Directory(fdecl::ExposeDirectory {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("dir".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_name: Some("data".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
rights: Some(fio::Operations::CONNECT),
subdir: Some("foo/bar".to_string()),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Expose::Runner(fdecl::ExposeRunner {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("elf".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
target_name: Some("elf".to_string()),
..Default::default()
}),
fdecl::Expose::Resolver(fdecl::ExposeResolver{
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("pkg".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
target_name: Some("pkg".to_string()),
..Default::default()
}),
fdecl::Expose::Service(fdecl::ExposeService {
source: Some(fdecl::Ref::Collection(fdecl::CollectionRef {
name: "modular".to_string(),
})),
source_name: Some("netstack1".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_name: Some("mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Expose::Service(fdecl::ExposeService {
source: Some(fdecl::Ref::Collection(fdecl::CollectionRef {
name: "modular".to_string(),
})),
source_name: Some("netstack2".to_string()),
source_dictionary: None,
target_name: Some("mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Expose::Dictionary(fdecl::ExposeDictionary {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("bundle".to_string()),
source_dictionary: Some("in/dict".to_string()),
target_name: Some("mybundle".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
]),
offers: Some(vec![
fdecl::Offer::Protocol(fdecl::OfferProtocol {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("legacy_netstack".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("legacy_mynetstack".to_string()),
dependency_type: Some(fdecl::DependencyType::Weak),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Offer::Directory(fdecl::OfferDirectory {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("dir".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Collection(
fdecl::CollectionRef { name: "modular".to_string() }
)),
target_name: Some("data".to_string()),
rights: Some(fio::Operations::CONNECT),
subdir: None,
dependency_type: Some(fdecl::DependencyType::Strong),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Offer::Storage(fdecl::OfferStorage {
source_name: Some("cache".to_string()),
source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
target: Some(fdecl::Ref::Collection(
fdecl::CollectionRef { name: "modular".to_string() }
)),
target_name: Some("cache".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Offer::Runner(fdecl::OfferRunner {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("elf".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("elf2".to_string()),
..Default::default()
}),
fdecl::Offer::Resolver(fdecl::OfferResolver{
source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
source_name: Some("pkg".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("pkg".to_string()),
..Default::default()
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack1".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mynetstack1".to_string()),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack2".to_string()),
source_dictionary: None,
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mynetstack2".to_string()),
availability: Some(fdecl::Availability::Optional),
..Default::default()
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack3".to_string()),
source_dictionary: None,
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mynetstack3".to_string()),
source_instance_filter: Some(vec!["allowedinstance".to_string()]),
renamed_instances: Some(vec![fdecl::NameMapping{source_name: "default".to_string(), target_name: "allowedinstance".to_string()}]),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
fdecl::Offer::Dictionary(fdecl::OfferDictionary {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("bundle".to_string()),
source_dictionary: Some("in/dict".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mybundle".to_string()),
dependency_type: Some(fdecl::DependencyType::Weak),
availability: Some(fdecl::Availability::Required),
..Default::default()
}),
]),
capabilities: Some(vec![
fdecl::Capability::Service(fdecl::Service {
name: Some("netstack".to_string()),
source_path: Some("/netstack".to_string()),
..Default::default()
}),
fdecl::Capability::Protocol(fdecl::Protocol {
name: Some("netstack2".to_string()),
source_path: Some("/netstack2".to_string()),
delivery: Some(fdecl::DeliveryType::Immediate),
..Default::default()
}),
fdecl::Capability::Directory(fdecl::Directory {
name: Some("data".to_string()),
source_path: Some("/data".to_string()),
rights: Some(fio::Operations::CONNECT),
..Default::default()
}),
fdecl::Capability::Storage(fdecl::Storage {
name: Some("cache".to_string()),
backing_dir: Some("data".to_string()),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
subdir: Some("cache".to_string()),
storage_id: Some(fdecl::StorageId::StaticInstanceId),
..Default::default()
}),
fdecl::Capability::Runner(fdecl::Runner {
name: Some("elf".to_string()),
source_path: Some("/elf".to_string()),
..Default::default()
}),
fdecl::Capability::Resolver(fdecl::Resolver {
name: Some("pkg".to_string()),
source_path: Some("/pkg_resolver".to_string()),
..Default::default()
}),
fdecl::Capability::Dictionary(fdecl::Dictionary {
name: Some("dict1".to_string()),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_dictionary: Some("in/other".to_string()),
..Default::default()
}),
fdecl::Capability::Dictionary(fdecl::Dictionary {
name: Some("dict2".to_string()),
source: None,
source_dictionary: None,
..Default::default()
}),
]),
children: Some(vec![
fdecl::Child {
name: Some("netstack".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm"
.to_string()),
startup: Some(fdecl::StartupMode::Lazy),
on_terminate: None,
environment: None,
..Default::default()
},
fdecl::Child {
name: Some("gtest".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string()),
startup: Some(fdecl::StartupMode::Lazy),
on_terminate: Some(fdecl::OnTerminate::None),
environment: None,
..Default::default()
},
fdecl::Child {
name: Some("echo".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/echo#meta/echo.cm"
.to_string()),
startup: Some(fdecl::StartupMode::Eager),
on_terminate: Some(fdecl::OnTerminate::Reboot),
environment: Some("test_env".to_string()),
..Default::default()
},
]),
collections: Some(vec![
fdecl::Collection {
name: Some("modular".to_string()),
durability: Some(fdecl::Durability::Transient),
environment: None,
allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
allow_long_names: Some(true),
persistent_storage: None,
..Default::default()
},
fdecl::Collection {
name: Some("tests".to_string()),
durability: Some(fdecl::Durability::Transient),
environment: Some("test_env".to_string()),
allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
allow_long_names: Some(true),
persistent_storage: Some(true),
..Default::default()
},
]),
facets: Some(fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "author".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
},
]),
..Default::default()
}),
environments: Some(vec![
fdecl::Environment {
name: Some("test_env".to_string()),
extends: Some(fdecl::EnvironmentExtends::Realm),
runners: Some(vec![
fdecl::RunnerRegistration {
source_name: Some("runner".to_string()),
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "gtest".to_string(),
collection: None,
})),
target_name: Some("gtest-runner".to_string()),
..Default::default()
}
]),
resolvers: Some(vec![
fdecl::ResolverRegistration {
resolver: Some("pkg_resolver".to_string()),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
scheme: Some("fuchsia-pkg".to_string()),
..Default::default()
}
]),
debug_capabilities: Some(vec![
fdecl::DebugRegistration::Protocol(fdecl::DebugProtocolRegistration {
source_name: Some("some_protocol".to_string()),
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "gtest".to_string(),
collection: None,
})),
target_name: Some("some_protocol".to_string()),
..Default::default()
})
]),
stop_timeout_ms: Some(4567),
..Default::default()
}
]),
config: Some(fdecl::ConfigSchema{
fields: Some(vec![
fdecl::ConfigField {
key: Some("enable_logging".to_string()),
type_: Some(fdecl::ConfigType {
layout: fdecl::ConfigTypeLayout::Bool,
parameters: Some(vec![]),
constraints: vec![],
}),
mutability: Some(Default::default()),
..Default::default()
}
]),
checksum: Some(fdecl::ConfigChecksum::Sha256([
0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
])),
value_source: Some(
fdecl::ConfigValueSource::PackagePath("fake.cvf".to_string())
),
..Default::default()
}),
..Default::default()
},
result = {
ComponentDecl {
program: Some(ProgramDecl {
runner: Some("elf".parse().unwrap()),
info: fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "args".to_string(),
value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
},
fdata::DictionaryEntry{
key: "binary".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
},
]),
..Default::default()
},
}),
uses: vec![
UseDecl::Service(UseServiceDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Parent,
source_name: "netstack".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_path: "/svc/mynetstack".parse().unwrap(),
availability: Availability::Required,
}),
UseDecl::Protocol(UseProtocolDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Parent,
source_name: "legacy_netstack".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_path: "/svc/legacy_mynetstack".parse().unwrap(),
availability: Availability::Optional,
}),
UseDecl::Protocol(UseProtocolDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Child("echo".to_string()),
source_name: "echo_service".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_path: "/svc/echo_service".parse().unwrap(),
availability: Availability::Required,
}),
UseDecl::Directory(UseDirectoryDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Framework,
source_name: "dir".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_path: "/data".parse().unwrap(),
rights: fio::Operations::CONNECT,
subdir: "foo/bar".parse().unwrap(),
availability: Availability::Required,
}),
UseDecl::Storage(UseStorageDecl {
source_name: "cache".parse().unwrap(),
target_path: "/cache".parse().unwrap(),
availability: Availability::Required,
}),
UseDecl::Storage(UseStorageDecl {
source_name: "temp".parse().unwrap(),
target_path: "/temp".parse().unwrap(),
availability: Availability::Optional,
}),
UseDecl::EventStream(UseEventStreamDecl {
source: UseSource::Child("netstack".to_string()),
scope: Some(vec![EventScope::Child(ChildRef{ name: "a".parse().unwrap(), collection: None}), EventScope::Collection("b".parse().unwrap())]),
source_name: "stopped".parse().unwrap(),
target_path: "/svc/test".parse().unwrap(),
filter: None,
availability: Availability::Optional,
}),
UseDecl::Runner(UseRunnerDecl {
source: UseSource::Environment,
source_name: "elf".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
}),
UseDecl::Config(UseConfigurationDecl {
source: UseSource::Parent,
source_name: "fuchsia.config.MyConfig".parse().unwrap(),
target_name: "my_config".parse().unwrap(),
availability: Availability::Required,
type_: ConfigValueType::Bool,
}),
],
exposes: vec![
ExposeDecl::Protocol(ExposeProtocolDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "legacy_netstack".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_name: "legacy_mynetstack".parse().unwrap(),
target: ExposeTarget::Parent,
availability: Availability::Required,
}),
ExposeDecl::Directory(ExposeDirectoryDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "dir".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_name: "data".parse().unwrap(),
target: ExposeTarget::Parent,
rights: Some(fio::Operations::CONNECT),
subdir: "foo/bar".parse().unwrap(),
availability: Availability::Optional,
}),
ExposeDecl::Runner(ExposeRunnerDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "elf".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: ExposeTarget::Parent,
target_name: "elf".parse().unwrap(),
}),
ExposeDecl::Resolver(ExposeResolverDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "pkg".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: ExposeTarget::Parent,
target_name: "pkg".parse().unwrap(),
}),
ExposeDecl::Service(ExposeServiceDecl {
source: ExposeSource::Collection("modular".parse().unwrap()),
source_name: "netstack1".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_name: "mynetstack".parse().unwrap(),
target: ExposeTarget::Parent,
availability: Availability::Required,
}),
ExposeDecl::Service(ExposeServiceDecl {
source: ExposeSource::Collection("modular".parse().unwrap()),
source_name: "netstack2".parse().unwrap(),
source_dictionary: ".".parse().unwrap(),
target_name: "mynetstack".parse().unwrap(),
target: ExposeTarget::Parent,
availability: Availability::Required,
}),
ExposeDecl::Dictionary(ExposeDictionaryDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "bundle".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target_name: "mybundle".parse().unwrap(),
target: ExposeTarget::Parent,
availability: Availability::Required,
}),
],
offers: vec![
OfferDecl::Protocol(OfferProtocolDecl {
source: OfferSource::Parent,
source_name: "legacy_netstack".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: offer_target_static_child("echo"),
target_name: "legacy_mynetstack".parse().unwrap(),
dependency_type: DependencyType::Weak,
availability: Availability::Required,
}),
OfferDecl::Directory(OfferDirectoryDecl {
source: OfferSource::Parent,
source_name: "dir".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: OfferTarget::Collection("modular".parse().unwrap()),
target_name: "data".parse().unwrap(),
rights: Some(fio::Operations::CONNECT),
subdir: ".".parse().unwrap(),
dependency_type: DependencyType::Strong,
availability: Availability::Optional,
}),
OfferDecl::Storage(OfferStorageDecl {
source_name: "cache".parse().unwrap(),
source: OfferSource::Self_,
target: OfferTarget::Collection("modular".parse().unwrap()),
target_name: "cache".parse().unwrap(),
availability: Availability::Required,
}),
OfferDecl::Runner(OfferRunnerDecl {
source: OfferSource::Parent,
source_name: "elf".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: offer_target_static_child("echo"),
target_name: "elf2".parse().unwrap(),
}),
OfferDecl::Resolver(OfferResolverDecl {
source: OfferSource::Parent,
source_name: "pkg".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: offer_target_static_child("echo"),
target_name: "pkg".parse().unwrap(),
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack1".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
source_instance_filter: None,
renamed_instances: None,
target: offer_target_static_child("echo"),
target_name: "mynetstack1".parse().unwrap(),
availability: Availability::Required,
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack2".parse().unwrap(),
source_dictionary: ".".parse().unwrap(),
source_instance_filter: None,
renamed_instances: None,
target: offer_target_static_child("echo"),
target_name: "mynetstack2".parse().unwrap(),
availability: Availability::Optional,
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack3".parse().unwrap(),
source_dictionary: ".".parse().unwrap(),
source_instance_filter: Some(vec!["allowedinstance".to_string()]),
renamed_instances: Some(vec![NameMapping{source_name: "default".to_string(), target_name: "allowedinstance".to_string()}]),
target: offer_target_static_child("echo"),
target_name: "mynetstack3".parse().unwrap(),
availability: Availability::Required,
}),
OfferDecl::Dictionary(OfferDictionaryDecl {
source: OfferSource::Parent,
source_name: "bundle".parse().unwrap(),
source_dictionary: "in/dict".parse().unwrap(),
target: offer_target_static_child("echo"),
target_name: "mybundle".parse().unwrap(),
dependency_type: DependencyType::Weak,
availability: Availability::Required,
}),
],
capabilities: vec![
CapabilityDecl::Service(ServiceDecl {
name: "netstack".parse().unwrap(),
source_path: Some("/netstack".parse().unwrap()),
}),
CapabilityDecl::Protocol(ProtocolDecl {
name: "netstack2".parse().unwrap(),
source_path: Some("/netstack2".parse().unwrap()),
delivery: DeliveryType::Immediate,
}),
CapabilityDecl::Directory(DirectoryDecl {
name: "data".parse().unwrap(),
source_path: Some("/data".parse().unwrap()),
rights: fio::Operations::CONNECT,
}),
CapabilityDecl::Storage(StorageDecl {
name: "cache".parse().unwrap(),
backing_dir: "data".parse().unwrap(),
source: StorageDirectorySource::Parent,
subdir: "cache".parse().unwrap(),
storage_id: fdecl::StorageId::StaticInstanceId,
}),
CapabilityDecl::Runner(RunnerDecl {
name: "elf".parse().unwrap(),
source_path: Some("/elf".parse().unwrap()),
}),
CapabilityDecl::Resolver(ResolverDecl {
name: "pkg".parse().unwrap(),
source_path: Some("/pkg_resolver".parse().unwrap()),
}),
CapabilityDecl::Dictionary(DictionaryDecl {
name: "dict1".parse().unwrap(),
source: Some(DictionarySource::Parent),
source_dictionary: Some("in/other".parse().unwrap()),
}),
CapabilityDecl::Dictionary(DictionaryDecl {
name: "dict2".parse().unwrap(),
source: None,
source_dictionary: None,
}),
],
children: vec![
ChildDecl {
name: "netstack".parse().unwrap(),
url: "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm".to_string(),
startup: fdecl::StartupMode::Lazy,
on_terminate: None,
environment: None,
config_overrides: None,
},
ChildDecl {
name: "gtest".parse().unwrap(),
url: "fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string(),
startup: fdecl::StartupMode::Lazy,
on_terminate: Some(fdecl::OnTerminate::None),
environment: None,
config_overrides: None,
},
ChildDecl {
name: "echo".parse().unwrap(),
url: "fuchsia-pkg://fuchsia.com/echo#meta/echo.cm".to_string(),
startup: fdecl::StartupMode::Eager,
on_terminate: Some(fdecl::OnTerminate::Reboot),
environment: Some("test_env".to_string()),
config_overrides: None,
},
],
collections: vec![
CollectionDecl {
name: "modular".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: true,
persistent_storage: None,
},
CollectionDecl {
name: "tests".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: Some("test_env".to_string()),
allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
allow_long_names: true,
persistent_storage: Some(true),
},
],
facets: Some(fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "author".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
},
]),
..Default::default()
}),
environments: vec![
EnvironmentDecl {
name: "test_env".parse().unwrap(),
extends: fdecl::EnvironmentExtends::Realm,
runners: vec![
RunnerRegistration {
source_name: "runner".parse().unwrap(),
source: RegistrationSource::Child("gtest".to_string()),
target_name: "gtest-runner".parse().unwrap(),
}
],
resolvers: vec![
ResolverRegistration {
resolver: "pkg_resolver".parse().unwrap(),
source: RegistrationSource::Parent,
scheme: "fuchsia-pkg".to_string(),
}
],
debug_capabilities: vec![
DebugRegistration::Protocol(DebugProtocolRegistration {
source_name: "some_protocol".parse().unwrap(),
source: RegistrationSource::Child("gtest".to_string()),
target_name: "some_protocol".parse().unwrap(),
})
],
stop_timeout_ms: Some(4567),
}
],
config: Some(ConfigDecl {
fields: vec![
ConfigField {
key: "enable_logging".to_string(),
type_: ConfigValueType::Bool,
mutability: ConfigMutability::default(),
}
],
checksum: ConfigChecksum::Sha256([
0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
]),
value_source: ConfigValueSource::PackagePath("fake.cvf".to_string())
}),
}
},
},
}
test_fidl_into_and_from! {
fidl_into_and_from_use_source => {
input = vec![
fdecl::Ref::Parent(fdecl::ParentRef{}),
fdecl::Ref::Framework(fdecl::FrameworkRef{}),
fdecl::Ref::Debug(fdecl::DebugRef{}),
fdecl::Ref::Capability(fdecl::CapabilityRef {name: "capability".to_string()}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
}),
fdecl::Ref::Environment(fdecl::EnvironmentRef{}),
],
input_type = fdecl::Ref,
result = vec![
UseSource::Parent,
UseSource::Framework,
UseSource::Debug,
UseSource::Capability("capability".parse().unwrap()),
UseSource::Child("foo".to_string()),
UseSource::Environment,
],
result_type = UseSource,
},
fidl_into_and_from_expose_source => {
input = vec![
fdecl::Ref::Self_(fdecl::SelfRef {}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
}),
fdecl::Ref::Framework(fdecl::FrameworkRef {}),
fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
],
input_type = fdecl::Ref,
result = vec![
ExposeSource::Self_,
ExposeSource::Child("foo".to_string()),
ExposeSource::Framework,
ExposeSource::Collection("foo".parse().unwrap()),
],
result_type = ExposeSource,
},
fidl_into_and_from_offer_source => {
input = vec![
fdecl::Ref::Self_(fdecl::SelfRef {}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
}),
fdecl::Ref::Framework(fdecl::FrameworkRef {}),
fdecl::Ref::Capability(fdecl::CapabilityRef { name: "foo".to_string() }),
fdecl::Ref::Parent(fdecl::ParentRef {}),
fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
fdecl::Ref::VoidType(fdecl::VoidRef {}),
],
input_type = fdecl::Ref,
result = vec![
OfferSource::Self_,
offer_source_static_child("foo"),
OfferSource::Framework,
OfferSource::Capability("foo".parse().unwrap()),
OfferSource::Parent,
OfferSource::Collection("foo".parse().unwrap()),
OfferSource::Void,
],
result_type = OfferSource,
},
fidl_into_and_from_dictionary_source => {
input = vec![
fdecl::Ref::Self_(fdecl::SelfRef {}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
}),
fdecl::Ref::Parent(fdecl::ParentRef {}),
],
input_type = fdecl::Ref,
result = vec![
DictionarySource::Self_,
DictionarySource::Child(ChildRef {
name: "foo".parse().unwrap(),
collection: None,
}),
DictionarySource::Parent,
],
result_type = DictionarySource,
},
fidl_into_and_from_capability_without_path => {
input = vec![
fdecl::Protocol {
name: Some("foo_protocol".to_string()),
source_path: None,
delivery: Some(fdecl::DeliveryType::Immediate),
..Default::default()
},
],
input_type = fdecl::Protocol,
result = vec![
ProtocolDecl {
name: "foo_protocol".parse().unwrap(),
source_path: None,
delivery: DeliveryType::Immediate,
}
],
result_type = ProtocolDecl,
},
fidl_into_and_from_storage_capability => {
input = vec![
fdecl::Storage {
name: Some("minfs".to_string()),
backing_dir: Some("minfs".into()),
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
})),
subdir: None,
storage_id: Some(fdecl::StorageId::StaticInstanceIdOrMoniker),
..Default::default()
},
],
input_type = fdecl::Storage,
result = vec![
StorageDecl {
name: "minfs".parse().unwrap(),
backing_dir: "minfs".parse().unwrap(),
source: StorageDirectorySource::Child("foo".to_string()),
subdir: ".".parse().unwrap(),
storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
},
],
result_type = StorageDecl,
},
fidl_into_and_from_storage_capability_restricted => {
input = vec![
fdecl::Storage {
name: Some("minfs".to_string()),
backing_dir: Some("minfs".into()),
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".into(),
collection: None,
})),
subdir: None,
storage_id: Some(fdecl::StorageId::StaticInstanceId),
..Default::default()
},
],
input_type = fdecl::Storage,
result = vec![
StorageDecl {
name: "minfs".parse().unwrap(),
backing_dir: "minfs".parse().unwrap(),
source: StorageDirectorySource::Child("foo".to_string()),
subdir: ".".parse().unwrap(),
storage_id: fdecl::StorageId::StaticInstanceId,
},
],
result_type = StorageDecl,
},
}
test_fidl_into! {
all_with_omitted_defaults => {
input = fdecl::Component {
program: Some(fdecl::Program {
runner: Some("elf".to_string()),
info: Some(fdata::Dictionary {
entries: Some(vec![]),
..Default::default()
}),
..Default::default()
}),
uses: Some(vec![]),
exposes: Some(vec![]),
offers: Some(vec![]),
capabilities: Some(vec![]),
children: Some(vec![]),
collections: Some(vec![
fdecl::Collection {
name: Some("modular".to_string()),
durability: Some(fdecl::Durability::Transient),
environment: None,
allowed_offers: None,
allow_long_names: None,
persistent_storage: None,
..Default::default()
},
fdecl::Collection {
name: Some("tests".to_string()),
durability: Some(fdecl::Durability::Transient),
environment: Some("test_env".to_string()),
allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
allow_long_names: None,
persistent_storage: Some(false),
..Default::default()
},
fdecl::Collection {
name: Some("dyn_offers".to_string()),
durability: Some(fdecl::Durability::Transient),
allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
allow_long_names: None,
persistent_storage: Some(true),
..Default::default()
},
fdecl::Collection {
name: Some("long_child_names".to_string()),
durability: Some(fdecl::Durability::Transient),
allowed_offers: None,
allow_long_names: Some(true),
persistent_storage: None,
..Default::default()
},
]),
facets: Some(fdata::Dictionary{
entries: Some(vec![]),
..Default::default()
}),
environments: Some(vec![]),
..Default::default()
},
result = {
ComponentDecl {
program: Some(ProgramDecl {
runner: Some("elf".parse().unwrap()),
info: fdata::Dictionary {
entries: Some(vec![]),
..Default::default()
},
}),
uses: vec![],
exposes: vec![],
offers: vec![],
capabilities: vec![],
children: vec![],
collections: vec![
CollectionDecl {
name: "modular".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: false,
persistent_storage: None,
},
CollectionDecl {
name: "tests".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: Some("test_env".to_string()),
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: false,
persistent_storage: Some(false),
},
CollectionDecl {
name: "dyn_offers".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
allow_long_names: false,
persistent_storage: Some(true),
},
CollectionDecl {
name: "long_child_names".parse().unwrap(),
durability: fdecl::Durability::Transient,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: true,
persistent_storage: None,
},
],
facets: Some(fdata::Dictionary{
entries: Some(vec![]),
..Default::default()
}),
environments: vec![],
config: None,
}
},
},
}
#[test]
fn default_expose_availability() {
let source = fdecl::Ref::Self_(fdecl::SelfRef {});
let source_name = "source";
let target = fdecl::Ref::Parent(fdecl::ParentRef {});
let target_name = "target";
assert_eq!(
*fdecl::ExposeService {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
availability: None,
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
assert_eq!(
*fdecl::ExposeProtocol {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
assert_eq!(
*fdecl::ExposeDirectory {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
assert_eq!(
*fdecl::ExposeRunner {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
assert_eq!(
*fdecl::ExposeResolver {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
assert_eq!(
*fdecl::ExposeDictionary {
source: Some(source.clone()),
source_name: Some(source_name.into()),
target: Some(target.clone()),
target_name: Some(target_name.into()),
..Default::default()
}
.fidl_into_native()
.availability(),
Availability::Required
);
}
#[test]
fn default_delivery_type() {
assert_eq!(
fdecl::Protocol {
name: Some("foo".to_string()),
source_path: Some("/foo".to_string()),
delivery: None,
..Default::default()
}
.fidl_into_native()
.delivery,
DeliveryType::Immediate
)
}
#[test]
fn on_readable_delivery_type() {
assert_eq!(
fdecl::Protocol {
name: Some("foo".to_string()),
source_path: Some("/foo".to_string()),
delivery: Some(fdecl::DeliveryType::OnReadable),
..Default::default()
}
.fidl_into_native()
.delivery,
DeliveryType::OnReadable
)
}
#[test]
fn config_value_matches_type() {
let bool_true = ConfigValue::Single(ConfigSingleValue::Bool(true));
let bool_false = ConfigValue::Single(ConfigSingleValue::Bool(false));
let uint8_zero = ConfigValue::Single(ConfigSingleValue::Uint8(0));
let vec_bool_true = ConfigValue::Vector(ConfigVectorValue::BoolVector(vec![true]));
let vec_bool_false = ConfigValue::Vector(ConfigVectorValue::BoolVector(vec![false]));
assert!(bool_true.matches_type(&bool_false));
assert!(vec_bool_true.matches_type(&vec_bool_false));
assert!(!bool_true.matches_type(&uint8_zero));
assert!(!bool_true.matches_type(&vec_bool_true));
}
}