blob: 92099d17893ffd971cc1438cea1bfd79a3257415 [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_fidl_validator,
cm_rust_derive::{
CapabilityDeclCommon, ExposeDeclCommon, FidlDecl, OfferDeclCommon,
OfferDeclCommonNoAvailability, UseDeclCommon,
},
cm_types, fidl_fuchsia_component_config as fconfig, fidl_fuchsia_component_decl as fdecl,
fidl_fuchsia_data as fdata, fidl_fuchsia_io as fio, fidl_fuchsia_process as fprocess,
from_enum::FromEnum,
lazy_static::lazy_static,
std::collections::hash_map::Entry,
std::collections::HashMap,
std::convert::{From, TryFrom},
std::fmt,
std::path::PathBuf,
std::str::FromStr,
thiserror::Error,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
mod serde_ext;
lazy_static! {
static ref DATA_TYPENAME: CapabilityName = CapabilityName("Data".to_string());
static ref CACHE_TYPENAME: CapabilityName = CapabilityName("Cache".to_string());
static ref META_TYPENAME: CapabilityName = CapabilityName("Meta".to_string());
}
/// Converts a fidl object into its corresponding native representation.
pub trait FidlIntoNative<T> {
fn fidl_into_native(self) -> T;
}
pub trait NativeIntoFidl<T> {
fn native_into_fidl(self) -> T;
}
/// 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.
pub fn get_runner(&self) -> Option<&CapabilityName> {
self.program.as_ref().and_then(|p| p.runner.as_ref())
}
/// Returns the `StorageDecl` corresponding to `storage_name`.
pub fn find_storage_source<'a>(
&'a self,
storage_name: &CapabilityName,
) -> 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: &CapabilityName,
) -> 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: &CapabilityName,
) -> 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: &CapabilityName,
) -> 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: &CapabilityName,
) -> 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: &CapabilityName) -> 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: &CapabilityName) -> bool {
self.uses.iter().any(|use_decl| match use_decl {
UseDecl::Protocol(ls) => &ls.source_name == source_name,
_ => false,
})
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Availability {
Required,
Optional,
SameAsTarget,
}
// TODO(dgonyeo): remove this once we've soft migrated to the availability field being required.
impl Default for Availability {
fn default() -> Self {
Availability::Required
}
}
fidl_translations_symmetrical_enums!(
fdecl::Availability,
Availability,
Required,
Optional,
SameAsTarget
);
#[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),
Event(UseEventDecl),
EventStreamDeprecated(UseEventStreamDeprecatedDecl),
EventStream(UseEventStreamDecl),
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseService")]
pub struct UseServiceDecl {
pub source: UseSource,
pub source_name: CapabilityName,
pub target_path: CapabilityPath,
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")]
pub struct UseProtocolDecl {
pub source: UseSource,
pub source_name: CapabilityName,
pub target_path: CapabilityPath,
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")]
pub struct UseDirectoryDecl {
pub source: UseSource,
pub source_name: CapabilityName,
pub target_path: CapabilityPath,
#[cfg_attr(
feature = "serde",
serde(
deserialize_with = "serde_ext::deserialize_fio_operations",
serialize_with = "serde_ext::serialize_fio_operations"
)
)]
pub rights: fio::Operations,
pub subdir: Option<PathBuf>,
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")]
pub struct UseStorageDecl {
pub source_name: CapabilityName,
pub target_path: CapabilityPath,
#[fidl_decl(default)]
pub availability: Availability,
}
impl SourceName for UseStorageDecl {
fn source_name(&self) -> &CapabilityName {
&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, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseEvent")]
pub struct UseEventDecl {
pub source: UseSource,
pub source_name: CapabilityName,
pub target_name: CapabilityName,
pub filter: Option<HashMap<String, DictionaryValue>>,
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::EventSubscription")]
pub struct EventSubscription {
pub event_name: String,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum EventMode {
Async,
Sync,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::UseEventStreamDeprecated")]
pub struct UseEventStreamDeprecatedDecl {
pub name: CapabilityName,
pub subscriptions: Vec<EventSubscription>,
#[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::UseEventStream")]
pub struct UseEventStreamDecl {
pub source_name: CapabilityName,
pub source: UseSource,
pub scope: Option<Vec<EventScope>>,
pub target_path: CapabilityPath,
#[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::Offer")]
pub enum OfferDecl {
Service(OfferServiceDecl),
Protocol(OfferProtocolDecl),
Directory(OfferDirectoryDecl),
Storage(OfferStorageDecl),
Runner(OfferRunnerDecl),
Resolver(OfferResolverDecl),
Event(OfferEventDecl),
EventStream(OfferEventStreamDecl),
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferEventStream")]
pub struct OfferEventStreamDecl {
pub source: OfferSource,
pub scope: Option<Vec<EventScope>>,
pub filter: Option<HashMap<String, DictionaryValue>>,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
#[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,
}
pub fn name_mappings_to_map(name_mappings: Vec<NameMapping>) -> HashMap<String, Vec<String>> {
let mut m = HashMap::<String, Vec<String>>::new();
for mapping in name_mappings.iter() {
match m.entry(mapping.clone().source_name) {
Entry::Occupied(mut entry) => {
let val = entry.get_mut();
val.push(mapping.clone().target_name);
}
Entry::Vacant(entry) => {
entry.insert(vec![mapping.clone().target_name]);
}
}
}
m
}
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 }
}
}
impl NativeIntoFidl<Vec<fdecl::NameMapping>> for Vec<NameMapping> {
fn native_into_fidl(self) -> Vec<fdecl::NameMapping> {
self.into_iter().map(|s| s.native_into_fidl()).collect()
}
}
impl FidlIntoNative<Vec<NameMapping>> for Vec<fdecl::NameMapping> {
fn fidl_into_native(self) -> Vec<NameMapping> {
self.into_iter().map(|s| s.fidl_into_native()).collect()
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferService")]
pub struct OfferServiceDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
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")]
pub struct OfferProtocolDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
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")]
pub struct OfferDirectoryDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
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>,
pub subdir: Option<PathBuf>,
#[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")]
pub struct OfferStorageDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
#[fidl_decl(default)]
pub availability: Availability,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommonNoAvailability, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferRunner")]
pub struct OfferRunnerDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommonNoAvailability, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferResolver")]
pub struct OfferResolverDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::OfferEvent")]
pub struct OfferEventDecl {
pub source: OfferSource,
pub source_name: CapabilityName,
pub target: OfferTarget,
pub target_name: CapabilityName,
pub filter: Option<HashMap<String, DictionaryValue>>,
#[fidl_decl(default)]
pub availability: Availability,
}
impl SourceName for OfferDecl {
fn source_name(&self) -> &CapabilityName {
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::Event(o) => o.source_name(),
OfferDecl::EventStream(o) => o.source_name(),
}
}
}
impl OfferDeclCommon for OfferDecl {
fn target_name(&self) -> &CapabilityName {
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::Event(o) => o.target_name(),
OfferDecl::EventStream(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::Event(o) => o.target(),
OfferDecl::EventStream(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::Event(o) => o.source(),
OfferDecl::EventStream(o) => o.source(),
}
}
fn availability(&self) -> Option<&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::Event(o) => o.availability(),
OfferDecl::EventStream(o) => o.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::Expose")]
pub enum ExposeDecl {
Service(ExposeServiceDecl),
Protocol(ExposeProtocolDecl),
Directory(ExposeDirectoryDecl),
Runner(ExposeRunnerDecl),
Resolver(ExposeResolverDecl),
EventStream(ExposeEventStreamDecl),
}
impl SourceName for ExposeDecl {
fn source_name(&self) -> &CapabilityName {
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(),
Self::EventStream(e) => e.source_name(),
}
}
}
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(),
Self::EventStream(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(),
Self::EventStream(e) => e.target(),
}
}
fn target_name(&self) -> &CapabilityName {
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(),
Self::EventStream(e) => e.target_name(),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeService")]
pub struct ExposeServiceDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeProtocol")]
pub struct ExposeProtocolDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeDirectory")]
pub struct ExposeDirectoryDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
#[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>,
pub subdir: Option<PathBuf>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeRunner")]
pub struct ExposeRunnerDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeResolver")]
pub struct ExposeResolverDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ExposeEventStream")]
pub struct ExposeEventStreamDecl {
pub source: ExposeSource,
pub source_name: CapabilityName,
pub target: ExposeTarget,
pub target_name: CapabilityName,
pub scope: Option<Vec<EventScope>>,
}
#[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),
Event(EventDecl),
EventStream(EventStreamDecl),
}
impl CapabilityDeclCommon for CapabilityDecl {
fn name(&self) -> &CapabilityName {
match self {
Self::Service(c) => c.name(),
Self::Protocol(c) => c.name(),
Self::Directory(c) => c.name(),
Self::Storage(c) => c.name(),
Self::Runner(c) => c.name(),
Self::Resolver(c) => c.name(),
Self::Event(c) => c.name(),
Self::EventStream(c) => c.name(),
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Service")]
pub struct ServiceDecl {
pub name: CapabilityName,
pub source_path: Option<CapabilityPath>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Protocol")]
pub struct ProtocolDecl {
pub name: CapabilityName,
pub source_path: Option<CapabilityPath>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Directory")]
pub struct DirectoryDecl {
pub name: CapabilityName,
pub source_path: Option<CapabilityPath>,
#[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, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Storage")]
pub struct StorageDecl {
pub name: CapabilityName,
pub source: StorageDirectorySource,
pub backing_dir: CapabilityName,
pub subdir: Option<PathBuf>,
#[cfg_attr(feature = "serde", serde(with = "serde_ext::StorageId"))]
pub storage_id: fdecl::StorageId,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Runner")]
pub struct RunnerDecl {
pub name: CapabilityName,
pub source_path: Option<CapabilityPath>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Resolver")]
pub struct ResolverDecl {
pub name: CapabilityName,
pub source_path: Option<CapabilityPath>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Event")]
pub struct EventDecl {
pub name: CapabilityName,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(FidlDecl, CapabilityDeclCommon, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::EventStream")]
pub struct EventStreamDecl {
pub name: CapabilityName,
}
impl CapabilityDecl {
pub fn name(&self) -> &CapabilityName {
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::Event(decl) => decl.name(),
CapabilityDecl::EventStream(decl) => decl.name(),
}
}
pub fn path(&self) -> Option<&CapabilityPath> {
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::Event(_) => None,
CapabilityDecl::EventStream(_) => None,
}
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Child")]
pub struct ChildDecl {
pub name: String,
pub url: String,
pub startup: fdecl::StartupMode,
pub on_terminate: Option<fdecl::OnTerminate>,
pub environment: Option<String>,
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ChildRef {
pub name: String,
pub collection: Option<String>,
}
impl FidlIntoNative<ChildRef> for fdecl::ChildRef {
fn fidl_into_native(self) -> ChildRef {
ChildRef { name: self.name, collection: self.collection }
}
}
impl NativeIntoFidl<fdecl::ChildRef> for ChildRef {
fn native_into_fidl(self) -> fdecl::ChildRef {
fdecl::ChildRef { name: self.name, collection: self.collection }
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::Collection")]
pub struct CollectionDecl {
pub name: String,
pub durability: fdecl::Durability,
pub environment: Option<String>,
#[fidl_decl(default)]
pub allowed_offers: cm_types::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)]
#[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)]
#[fidl_decl(fidl_union = "fdecl::ConfigChecksum")]
pub enum ConfigChecksum {
Sha256([u8; 32]),
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fdecl::ConfigValueSource")]
pub enum ConfigValueSource {
PackagePath(String),
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fdecl::ConfigField")]
pub struct ConfigField {
pub key: String,
pub type_: ConfigValueType,
}
#[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 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) }
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fconfig::ValuesData")]
pub struct ValuesData {
pub values: Vec<ValueSpec>,
pub checksum: ConfigChecksum,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_table = "fconfig::ValueSpec")]
pub struct ValueSpec {
pub value: Value,
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fconfig::Value")]
pub enum Value {
Single(SingleValue),
Vector(VectorValue),
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Single(sv) => sv.fmt(f),
Value::Vector(lv) => lv.fmt(f),
}
}
}
#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fconfig::SingleValue")]
pub enum SingleValue {
Bool(bool),
Uint8(u8),
Uint16(u16),
Uint32(u32),
Uint64(u64),
Int8(i8),
Int16(i16),
Int32(i32),
Int64(i64),
String(String),
}
impl fmt::Display for SingleValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use SingleValue::*;
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(FidlDecl, Debug, Clone, PartialEq, Eq)]
#[fidl_decl(fidl_union = "fconfig::VectorValue")]
pub enum VectorValue {
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 fmt::Display for VectorValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use VectorValue::*;
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: CapabilityName,
pub target_name: CapabilityName,
pub source: RegistrationSource,
}
impl SourceName for RunnerRegistration {
fn source_name(&self) -> &CapabilityName {
&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: CapabilityName,
pub source: RegistrationSource,
pub scheme: String,
}
impl SourceName for ResolverRegistration {
fn source_name(&self) -> &CapabilityName {
&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) -> &CapabilityName {
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: CapabilityName,
pub source: RegistrationSource,
pub target_name: CapabilityName,
}
#[derive(FidlDecl, Debug, Clone, PartialEq)]
#[fidl_decl(fidl_table = "fdecl::Program")]
pub struct ProgramDecl {
pub runner: Option<CapabilityName>,
pub info: fdata::Dictionary,
}
impl Default for ProgramDecl {
fn default() -> Self {
Self { runner: None, info: fdata::Dictionary::EMPTY.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!(Vec<u8>);
fidl_translations_identical!(Vec<u16>);
fidl_translations_identical!(Vec<u32>);
fidl_translations_identical!(Vec<u64>);
fidl_translations_identical!(Vec<i8>);
fidl_translations_identical!(Vec<i16>);
fidl_translations_identical!(Vec<i32>);
fidl_translations_identical!(Vec<i64>);
fidl_translations_identical!(bool);
fidl_translations_identical!(Vec<bool>);
fidl_translations_identical!(String);
fidl_translations_identical!(Vec<String>);
fidl_translations_identical!(Vec<CapabilityName>);
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>);
impl FidlIntoNative<Vec<EventScope>> for Vec<fidl_fuchsia_component_decl::Ref> {
fn fidl_into_native(self) -> Vec<EventScope> {
self.into_iter().map(|s| s.fidl_into_native()).collect()
}
}
impl NativeIntoFidl<Vec<fidl_fuchsia_component_decl::Ref>> for Vec<EventScope> {
fn native_into_fidl(self) -> Vec<fidl_fuchsia_component_decl::Ref> {
self.into_iter().map(|s| s.native_into_fidl()).collect()
}
}
impl FidlIntoNative<Vec<UseSource>> for Vec<fidl_fuchsia_component_decl::Ref> {
fn fidl_into_native(self) -> Vec<UseSource> {
self.into_iter().map(|s| s.fidl_into_native()).collect()
}
}
impl NativeIntoFidl<Vec<fidl_fuchsia_component_decl::Ref>> for Vec<UseSource> {
fn native_into_fidl(self) -> Vec<fidl_fuchsia_component_decl::Ref> {
self.into_iter().map(|s| s.native_into_fidl()).collect()
}
}
fidl_translations_from_into!(cm_types::AllowedOffers, fdecl::AllowedOffers);
fidl_translations_from_into!(CapabilityName, String);
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DependencyType {
Strong,
Weak,
WeakForMigration,
}
fidl_translations_symmetrical_enums!(
fdecl::DependencyType,
DependencyType,
Strong,
Weak,
WeakForMigration
);
/// A path to a capability.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CapabilityPath {
/// The directory containing the last path element, e.g. `/svc/foo` in `/svc/foo/bar`.
pub dirname: String,
/// The last path element: e.g. `bar` in `/svc/foo/bar`.
pub basename: String,
}
impl CapabilityPath {
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.to_string())
}
/// Splits the path according to "/", ignoring empty path components
pub fn split(&self) -> Vec<String> {
self.to_string().split("/").map(|s| s.to_string()).filter(|s| !s.is_empty()).collect()
}
}
impl FromStr for CapabilityPath {
type Err = Error;
fn from_str(path: &str) -> Result<CapabilityPath, Error> {
cm_types::Path::validate(path)
.map_err(|_| Error::InvalidCapabilityPath { raw: path.to_string() })?;
let idx = path.rfind('/').expect("path validation is wrong");
Ok(CapabilityPath {
dirname: if idx == 0 { "/".to_string() } else { path[0..idx].to_string() },
basename: path[idx + 1..].to_string(),
})
}
}
impl TryFrom<&str> for CapabilityPath {
type Error = Error;
fn try_from(path: &str) -> Result<CapabilityPath, Error> {
Self::from_str(path)
}
}
impl fmt::Display for CapabilityPath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if &self.dirname == "/" {
write!(f, "/{}", self.basename)
} else {
write!(f, "{}/{}", self.dirname, self.basename)
}
}
}
impl UseDecl {
pub fn path(&self) -> Option<&CapabilityPath> {
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),
UseDecl::Event(_) | UseDecl::EventStreamDeprecated(_) => None,
}
}
pub fn name(&self) -> Option<&CapabilityName> {
match self {
UseDecl::Event(event_decl) => Some(&event_decl.source_name),
UseDecl::Storage(storage_decl) => Some(&storage_decl.source_name),
UseDecl::EventStreamDeprecated(event_stream_decl) => Some(&event_stream_decl.name),
UseDecl::EventStream(_) => None,
UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Directory(_) => None,
}
}
}
impl SourceName for UseDecl {
fn source_name(&self) -> &CapabilityName {
match self {
UseDecl::Event(event_decl) => &event_decl.source_name,
UseDecl::Storage(storage_decl) => &storage_decl.source_name,
UseDecl::EventStreamDeprecated(event_stream_decl) => &event_stream_decl.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,
}
}
}
/// A named capability.
///
/// Unlike a `CapabilityPath`, a `CapabilityName` doesn't encode any form
/// of hierarchy.
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct CapabilityName(pub String);
impl CapabilityName {
pub fn str(&self) -> &str {
&self.0
}
}
impl From<CapabilityName> for String {
fn from(name: CapabilityName) -> String {
name.0
}
}
impl From<&str> for CapabilityName {
fn from(name: &str) -> CapabilityName {
CapabilityName(name.to_string())
}
}
impl From<String> for CapabilityName {
fn from(name: String) -> CapabilityName {
CapabilityName(name)
}
}
impl From<cm_types::Name> for CapabilityName {
fn from(name: cm_types::Name) -> CapabilityName {
name.as_str().into()
}
}
impl<'a> PartialEq<&'a str> for CapabilityName {
fn eq(&self, other: &&'a str) -> bool {
self.0 == *other
}
}
impl fmt::Display for CapabilityName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
/// The trait for all declarations that have a source name.
pub trait SourceName {
fn source_name(&self) -> &CapabilityName;
}
/// The common properties of a [Use](fdecl::Use) declaration.
pub trait UseDeclCommon: SourceName + 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 + Send + Sync {
fn target_name(&self) -> &CapabilityName;
fn target(&self) -> &OfferTarget;
fn source(&self) -> &OfferSource;
fn availability(&self) -> Option<&Availability>;
}
/// The common properties of an [Expose](fdecl::Expose) declaration.
pub trait ExposeDeclCommon: SourceName + Send + Sync {
fn target_name(&self) -> &CapabilityName;
fn target(&self) -> &ExposeTarget;
fn source(&self) -> &ExposeSource;
}
/// The common properties of a [Capability](fdecl::Capability) declaration.
pub trait CapabilityDeclCommon: Send + Sync {
fn name(&self) -> &CapabilityName;
}
/// 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, PartialEq, Eq, Hash)]
pub enum CapabilityTypeName {
Directory,
Event,
EventStreamDeprecated,
EventStream,
Protocol,
Resolver,
Runner,
Service,
Storage,
}
impl fmt::Display for CapabilityTypeName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let display_name = match &self {
CapabilityTypeName::Directory => "directory",
CapabilityTypeName::Event => "event",
CapabilityTypeName::EventStreamDeprecated => "event_stream_deprecated",
CapabilityTypeName::EventStream => "event_stream",
CapabilityTypeName::Protocol => "protocol",
CapabilityTypeName::Resolver => "resolver",
CapabilityTypeName::Runner => "runner",
CapabilityTypeName::Service => "service",
CapabilityTypeName::Storage => "storage",
};
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::Event(_) => Self::Event,
UseDecl::EventStreamDeprecated(_) => Self::EventStreamDeprecated,
UseDecl::EventStream(_) => Self::EventStream,
}
}
}
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,
ExposeDecl::EventStream(_) => Self::EventStream,
}
}
}
// 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<CapabilityPath> for String {
fn fidl_into_native(self) -> CapabilityPath {
self.as_str().parse().unwrap()
}
}
impl NativeIntoFidl<String> for CapabilityPath {
fn native_into_fidl(self) -> String {
self.to_string()
}
}
impl FidlIntoNative<PathBuf> for String {
fn fidl_into_native(self) -> PathBuf {
PathBuf::from(self)
}
}
impl NativeIntoFidl<String> for PathBuf {
fn native_into_fidl(self) -> String {
self.into_os_string().into_string().expect("invalid utf8")
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
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/92247): 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(),
),
..fdata::Dictionary::EMPTY
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UseSource {
Parent,
Framework,
Debug,
Self_,
Capability(CapabilityName),
Child(String),
}
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_,
fdecl::Ref::Capability(c) => UseSource::Capability(c.name.into()),
fdecl::Ref::Child(c) => UseSource::Child(c.name),
_ => 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_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EventScope {
Child(ChildRef),
Collection(String),
}
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, collection: None })
}
}
fdecl::Ref::Collection(collection) => EventScope::Collection(collection.name),
_ => 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 }),
}
}
}
#[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(String),
Self_,
Capability(CapabilityName),
Void,
}
impl OfferSource {
pub fn static_child(name: String) -> Self {
Self::Child(ChildRef { name, collection: None })
}
}
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()),
fdecl::Ref::Collection(c) => OfferSource::Collection(c.name),
fdecl::Ref::Framework(_) => OfferSource::Framework,
fdecl::Ref::Capability(c) => OfferSource::Capability(c.name.into()),
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 }),
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(String),
Framework,
Capability(CapabilityName),
}
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),
fdecl::Ref::Collection(c) => ExposeSource::Collection(c.name),
fdecl::Ref::Framework(_) => ExposeSource::Framework,
fdecl::Ref::Capability(c) => ExposeSource::Capability(c.name.into()),
_ => 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 }),
ExposeSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
ExposeSource::Capability(name) => {
fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
}
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ExposeTarget {
Parent,
Framework,
}
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: CapabilityName,
}
#[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 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(String),
}
impl OfferTarget {
pub fn static_child(name: String) -> Self {
Self::Child(ChildRef { name, collection: None })
}
}
impl FidlIntoNative<OfferTarget> for fdecl::Ref {
fn fidl_into_native(self) -> OfferTarget {
match self {
fdecl::Ref::Child(c) => OfferTarget::Child(c.fidl_into_native()),
fdecl::Ref::Collection(c) => OfferTarget::Collection(c.name),
_ => 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 })
}
}
}
}
/// 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 TryFrom<ComponentDecl> for fdecl::Component {
type Error = Error;
fn try_from(decl: ComponentDecl) -> Result<Self, Self::Error> {
Ok(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 },
}
#[cfg(test)]
mod tests {
use {super::*, fidl_fuchsia_component_decl as fdecl, maplit::hashmap, std::convert::TryInto};
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");
assert_eq!(res, $result);
}
{
let res = fdecl::Component::try_from($result).expect("try_from failed");
assert_eq!(res, $input);
}
}
)+
}
}
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);
}
macro_rules! test_capability_path {
(
$(
$test_name:ident => {
input = $input:expr,
result = $result:expr,
},
)+
) => {
$(
#[test]
fn $test_name() {
test_capability_path_helper($input, $result);
}
)+
}
}
fn test_capability_path_helper(input: &str, result: Result<CapabilityPath, Error>) {
let res = CapabilityPath::try_from(input);
assert_eq!(format!("{:?}", res), format!("{:?}", result));
if let Ok(p) = res {
assert_eq!(&p.to_string(), input);
}
}
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,
..fdecl::Component::EMPTY
},
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()))),
},
]),
..fdata::Dictionary::EMPTY
}),
..fdecl::Program::EMPTY
}),
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()),
target_path: Some("/svc/mynetstack".to_string()),
availability: Some(fdecl::Availability::Required),
..fdecl::UseService::EMPTY
}),
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()),
target_path: Some("/svc/legacy_mynetstack".to_string()),
availability: Some(fdecl::Availability::Optional),
..fdecl::UseProtocol::EMPTY
}),
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()),
target_path: Some("/svc/echo_service".to_string()),
availability: Some(fdecl::Availability::Required),
..fdecl::UseProtocol::EMPTY
}),
fdecl::Use::Directory(fdecl::UseDirectory {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Framework(fdecl::FrameworkRef {})),
source_name: Some("dir".to_string()),
target_path: Some("/data".to_string()),
rights: Some(fio::Operations::CONNECT),
subdir: Some("foo/bar".to_string()),
availability: Some(fdecl::Availability::Required),
..fdecl::UseDirectory::EMPTY
}),
fdecl::Use::Storage(fdecl::UseStorage {
source_name: Some("cache".to_string()),
target_path: Some("/cache".to_string()),
availability: Some(fdecl::Availability::Required),
..fdecl::UseStorage::EMPTY
}),
fdecl::Use::Storage(fdecl::UseStorage {
source_name: Some("temp".to_string()),
target_path: Some("/temp".to_string()),
availability: Some(fdecl::Availability::Optional),
..fdecl::UseStorage::EMPTY
}),
fdecl::Use::Event(fdecl::UseEvent {
dependency_type: Some(fdecl::DependencyType::Strong),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("directory_ready".to_string()),
target_name: Some("diagnostics_ready".to_string()),
filter: Some(fdata::Dictionary{
entries: Some(vec![
fdata::DictionaryEntry {
key: "path".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("/diagnostics".to_string()))),
},
]),
..fdata::Dictionary::EMPTY
}),
availability: Some(fdecl::Availability::Required),
..fdecl::UseEvent::EMPTY
}),
fdecl::Use::EventStream(fdecl::UseEventStream {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
collection: None,
name: "test".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),
..fdecl::UseEventStream::EMPTY
}),
]),
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()),
target_name: Some("legacy_mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
..fdecl::ExposeProtocol::EMPTY
}),
fdecl::Expose::Directory(fdecl::ExposeDirectory {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("dir".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()),
..fdecl::ExposeDirectory::EMPTY
}),
fdecl::Expose::Runner(fdecl::ExposeRunner {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("elf".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
target_name: Some("elf".to_string()),
..fdecl::ExposeRunner::EMPTY
}),
fdecl::Expose::Resolver(fdecl::ExposeResolver{
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("pkg".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
target_name: Some("pkg".to_string()),
..fdecl::ExposeResolver::EMPTY
}),
fdecl::Expose::Service(fdecl::ExposeService {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("netstack1".to_string()),
target_name: Some("mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
..fdecl::ExposeService::EMPTY
}),
fdecl::Expose::Service(fdecl::ExposeService {
source: Some(fdecl::Ref::Child(fdecl::ChildRef {
name: "netstack".to_string(),
collection: None,
})),
source_name: Some("netstack2".to_string()),
target_name: Some("mynetstack".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
..fdecl::ExposeService::EMPTY
}),
fdecl::Expose::EventStream (
fdecl::ExposeEventStream {
source: Some(fdecl::Ref::Self_(fdecl::SelfRef{})),
source_name: Some("diagnostics_ready".to_string()),
target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
scope: Some(vec![fdecl::Ref::Child(fdecl::ChildRef{name: "netstack".to_string(), collection: None})]),
target_name: Some("diagnostics_ready".to_string()),
..fdecl::ExposeEventStream::EMPTY
}
)
]),
offers: Some(vec![
fdecl::Offer::Protocol(fdecl::OfferProtocol {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("legacy_netstack".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::WeakForMigration),
availability: Some(fdecl::Availability::Required),
..fdecl::OfferProtocol::EMPTY
}),
fdecl::Offer::Directory(fdecl::OfferDirectory {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("dir".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),
..fdecl::OfferDirectory::EMPTY
}),
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),
..fdecl::OfferStorage::EMPTY
}),
fdecl::Offer::Runner(fdecl::OfferRunner {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("elf".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("elf2".to_string()),
..fdecl::OfferRunner::EMPTY
}),
fdecl::Offer::Resolver(fdecl::OfferResolver{
source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
source_name: Some("pkg".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("pkg".to_string()),
..fdecl::OfferResolver::EMPTY
}),
fdecl::Offer::Event(fdecl::OfferEvent {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("started".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mystarted".to_string()),
filter: Some(fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "path".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("/a".to_string()))),
},
]),
..fdata::Dictionary::EMPTY
}),
availability: Some(fdecl::Availability::Optional),
..fdecl::OfferEvent::EMPTY
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack1".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),
..fdecl::OfferService::EMPTY
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack2".to_string()),
target: Some(fdecl::Ref::Child(
fdecl::ChildRef {
name: "echo".to_string(),
collection: None,
}
)),
target_name: Some("mynetstack2".to_string()),
availability: Some(fdecl::Availability::Optional),
..fdecl::OfferService::EMPTY
}),
fdecl::Offer::Service(fdecl::OfferService {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
source_name: Some("netstack3".to_string()),
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),
..fdecl::OfferService::EMPTY
}),
fdecl::Offer::EventStream (
fdecl::OfferEventStream {
source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
source_name: Some("diagnostics_ready".to_string()),
target: Some(fdecl::Ref::Child(fdecl::ChildRef {name: "netstack".to_string(), collection: None})),
scope: Some(vec![fdecl::Ref::Child(fdecl::ChildRef{name: "netstack".to_string(), collection: None})]),
target_name: Some("diagnostics_ready".to_string()),
availability: Some(fdecl::Availability::Optional),
..fdecl::OfferEventStream::EMPTY
}
)
]),
capabilities: Some(vec![
fdecl::Capability::Service(fdecl::Service {
name: Some("netstack".to_string()),
source_path: Some("/netstack".to_string()),
..fdecl::Service::EMPTY
}),
fdecl::Capability::Protocol(fdecl::Protocol {
name: Some("netstack2".to_string()),
source_path: Some("/netstack2".to_string()),
..fdecl::Protocol::EMPTY
}),
fdecl::Capability::Directory(fdecl::Directory {
name: Some("data".to_string()),
source_path: Some("/data".to_string()),
rights: Some(fio::Operations::CONNECT),
..fdecl::Directory::EMPTY
}),
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),
..fdecl::Storage::EMPTY
}),
fdecl::Capability::Runner(fdecl::Runner {
name: Some("elf".to_string()),
source_path: Some("/elf".to_string()),
..fdecl::Runner::EMPTY
}),
fdecl::Capability::Resolver(fdecl::Resolver {
name: Some("pkg".to_string()),
source_path: Some("/pkg_resolver".to_string()),
..fdecl::Resolver::EMPTY
}),
]),
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,
..fdecl::Child::EMPTY
},
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,
..fdecl::Child::EMPTY
},
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()),
..fdecl::Child::EMPTY
},
]),
collections: Some(vec![
fdecl::Collection {
name: Some("modular".to_string()),
durability: Some(fdecl::Durability::Persistent),
environment: None,
allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
allow_long_names: Some(true),
persistent_storage: None,
..fdecl::Collection::EMPTY
},
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),
..fdecl::Collection::EMPTY
},
]),
facets: Some(fdata::Dictionary {
entries: Some(vec![
fdata::DictionaryEntry {
key: "author".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
},
]),
..fdata::Dictionary::EMPTY
}),
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()),
..fdecl::RunnerRegistration::EMPTY
}
]),
resolvers: Some(vec![
fdecl::ResolverRegistration {
resolver: Some("pkg_resolver".to_string()),
source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
scheme: Some("fuchsia-pkg".to_string()),
..fdecl::ResolverRegistration::EMPTY
}
]),
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()),
..fdecl::DebugProtocolRegistration::EMPTY
})
]),
stop_timeout_ms: Some(4567),
..fdecl::Environment::EMPTY
}
]),
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![],
}),
..fdecl::ConfigField::EMPTY
}
]),
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())
),
..fdecl::ConfigSchema::EMPTY
}),
..fdecl::Component::EMPTY
},
result = {
ComponentDecl {
program: Some(ProgramDecl {
runner: Some("elf".try_into().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()))),
},
]),
..fdata::Dictionary::EMPTY
},
}),
uses: vec![
UseDecl::Service(UseServiceDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Parent,
source_name: "netstack".try_into().unwrap(),
target_path: "/svc/mynetstack".try_into().unwrap(),
availability: Availability::Required,
}),
UseDecl::Protocol(UseProtocolDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Parent,
source_name: "legacy_netstack".try_into().unwrap(),
target_path: "/svc/legacy_mynetstack".try_into().unwrap(),
availability: Availability::Optional,
}),
UseDecl::Protocol(UseProtocolDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Child("echo".to_string()),
source_name: "echo_service".try_into().unwrap(),
target_path: "/svc/echo_service".try_into().unwrap(),
availability: Availability::Required,
}),
UseDecl::Directory(UseDirectoryDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Framework,
source_name: "dir".try_into().unwrap(),
target_path: "/data".try_into().unwrap(),
rights: fio::Operations::CONNECT,
subdir: Some("foo/bar".into()),
availability: Availability::Required,
}),
UseDecl::Storage(UseStorageDecl {
source_name: "cache".into(),
target_path: "/cache".try_into().unwrap(),
availability: Availability::Required,
}),
UseDecl::Storage(UseStorageDecl {
source_name: "temp".into(),
target_path: "/temp".try_into().unwrap(),
availability: Availability::Optional,
}),
UseDecl::Event(UseEventDecl {
dependency_type: DependencyType::Strong,
source: UseSource::Parent,
source_name: "directory_ready".into(),
target_name: "diagnostics_ready".into(),
filter: Some(hashmap!{"path".to_string() => DictionaryValue::Str("/diagnostics".to_string())}),
availability: Availability::Required,
}),
UseDecl::EventStream(UseEventStreamDecl {
source: UseSource::Child("test".to_string()),
scope: Some(vec![EventScope::Child(ChildRef{ name: "a".to_string(), collection: None}), EventScope::Collection("b".to_string())]),
source_name: CapabilityName::from("stopped"),
target_path: CapabilityPath::from_str("/svc/test").unwrap(),
availability: Availability::Optional,
}),
],
exposes: vec![
ExposeDecl::Protocol(ExposeProtocolDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "legacy_netstack".try_into().unwrap(),
target_name: "legacy_mynetstack".try_into().unwrap(),
target: ExposeTarget::Parent,
}),
ExposeDecl::Directory(ExposeDirectoryDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "dir".try_into().unwrap(),
target_name: "data".try_into().unwrap(),
target: ExposeTarget::Parent,
rights: Some(fio::Operations::CONNECT),
subdir: Some("foo/bar".into()),
}),
ExposeDecl::Runner(ExposeRunnerDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "elf".try_into().unwrap(),
target: ExposeTarget::Parent,
target_name: "elf".try_into().unwrap(),
}),
ExposeDecl::Resolver(ExposeResolverDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "pkg".try_into().unwrap(),
target: ExposeTarget::Parent,
target_name: "pkg".try_into().unwrap(),
}),
ExposeDecl::Service(ExposeServiceDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "netstack1".try_into().unwrap(),
target_name: "mynetstack".try_into().unwrap(),
target: ExposeTarget::Parent,
}),
ExposeDecl::Service(ExposeServiceDecl {
source: ExposeSource::Child("netstack".to_string()),
source_name: "netstack2".try_into().unwrap(),
target_name: "mynetstack".try_into().unwrap(),
target: ExposeTarget::Parent,
}),
ExposeDecl::EventStream (
ExposeEventStreamDecl {
source: ExposeSource::Self_,
source_name: CapabilityName::from("diagnostics_ready".to_string()),
target: ExposeTarget::Parent,
scope: Some(vec![EventScope::Child(ChildRef{ name: "netstack".to_string(), collection: None})]),
target_name: CapabilityName::from("diagnostics_ready".to_string()),
}
)
],
offers: vec![
OfferDecl::Protocol(OfferProtocolDecl {
source: OfferSource::Parent,
source_name: "legacy_netstack".try_into().unwrap(),
target: OfferTarget::static_child("echo".to_string()),
target_name: "legacy_mynetstack".try_into().unwrap(),
dependency_type: DependencyType::WeakForMigration,
availability: Availability::Required,
}),
OfferDecl::Directory(OfferDirectoryDecl {
source: OfferSource::Parent,
source_name: "dir".try_into().unwrap(),
target: OfferTarget::Collection("modular".to_string()),
target_name: "data".try_into().unwrap(),
rights: Some(fio::Operations::CONNECT),
subdir: None,
dependency_type: DependencyType::Strong,
availability: Availability::Optional,
}),
OfferDecl::Storage(OfferStorageDecl {
source_name: "cache".try_into().unwrap(),
source: OfferSource::Self_,
target: OfferTarget::Collection("modular".to_string()),
target_name: "cache".try_into().unwrap(),
availability: Availability::Required,
}),
OfferDecl::Runner(OfferRunnerDecl {
source: OfferSource::Parent,
source_name: "elf".try_into().unwrap(),
target: OfferTarget::static_child("echo".to_string()),
target_name: "elf2".try_into().unwrap(),
}),
OfferDecl::Resolver(OfferResolverDecl {
source: OfferSource::Parent,
source_name: "pkg".try_into().unwrap(),
target: OfferTarget::static_child("echo".to_string()),
target_name: "pkg".try_into().unwrap(),
}),
OfferDecl::Event(OfferEventDecl {
source: OfferSource::Parent,
source_name: "started".into(),
target: OfferTarget::static_child("echo".to_string()),
target_name: "mystarted".into(),
filter: Some(hashmap!{"path".to_string() => DictionaryValue::Str("/a".to_string())}),
availability: Availability::Optional,
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack1".try_into().unwrap(),
source_instance_filter: None,
renamed_instances: None,
target: OfferTarget::static_child("echo".to_string()),
target_name: "mynetstack1".try_into().unwrap(),
availability: Availability::Required,
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack2".try_into().unwrap(),
source_instance_filter: None,
renamed_instances: None,
target: OfferTarget::static_child("echo".to_string()),
target_name: "mynetstack2".try_into().unwrap(),
availability: Availability::Optional,
}),
OfferDecl::Service(OfferServiceDecl {
source: OfferSource::Parent,
source_name: "netstack3".try_into().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: OfferTarget::static_child("echo".to_string()),
target_name: "mynetstack3".try_into().unwrap(),
availability: Availability::Required,
}),
OfferDecl::EventStream (
OfferEventStreamDecl {
source: OfferSource::Parent,
source_name: CapabilityName::from("diagnostics_ready".to_string()),
target: OfferTarget::Child(ChildRef{name: "netstack".to_string(), collection: None}),
scope: Some(vec![EventScope::Child(ChildRef{ name: "netstack".to_string(), collection: None})]),
target_name: CapabilityName::from("diagnostics_ready".to_string()),
filter: None,
availability: Availability::Optional,
}
)
],
capabilities: vec![
CapabilityDecl::Service(ServiceDecl {
name: "netstack".into(),
source_path: Some("/netstack".try_into().unwrap()),
}),
CapabilityDecl::Protocol(ProtocolDecl {
name: "netstack2".into(),
source_path: Some("/netstack2".try_into().unwrap()),
}),
CapabilityDecl::Directory(DirectoryDecl {
name: "data".into(),
source_path: Some("/data".try_into().unwrap()),
rights: fio::Operations::CONNECT,
}),
CapabilityDecl::Storage(StorageDecl {
name: "cache".into(),
backing_dir: "data".try_into().unwrap(),
source: StorageDirectorySource::Parent,
subdir: Some("cache".try_into().unwrap()),
storage_id: fdecl::StorageId::StaticInstanceId,
}),
CapabilityDecl::Runner(RunnerDecl {
name: "elf".into(),
source_path: Some("/elf".try_into().unwrap()),
}),
CapabilityDecl::Resolver(ResolverDecl {
name: "pkg".into(),
source_path: Some("/pkg_resolver".try_into().unwrap()),
}),
],
children: vec![
ChildDecl {
name: "netstack".to_string(),
url: "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm".to_string(),
startup: fdecl::StartupMode::Lazy,
on_terminate: None,
environment: None,
},
ChildDecl {
name: "gtest".to_string(),
url: "fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string(),
startup: fdecl::StartupMode::Lazy,
on_terminate: Some(fdecl::OnTerminate::None),
environment: None,
},
ChildDecl {
name: "echo".to_string(),
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()),
},
],
collections: vec![
CollectionDecl {
name: "modular".to_string(),
durability: fdecl::Durability::Persistent,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: true,
persistent_storage: None,
},
CollectionDecl {
name: "tests".to_string(),
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()))),
},
]),
..fdata::Dictionary::EMPTY
}),
environments: vec![
EnvironmentDecl {
name: "test_env".into(),
extends: fdecl::EnvironmentExtends::Realm,
runners: vec![
RunnerRegistration {
source_name: "runner".into(),
source: RegistrationSource::Child("gtest".to_string()),
target_name: "gtest-runner".into(),
}
],
resolvers: vec![
ResolverRegistration {
resolver: "pkg_resolver".into(),
source: RegistrationSource::Parent,
scheme: "fuchsia-pkg".to_string(),
}
],
debug_capabilities: vec![
DebugRegistration::Protocol(DebugProtocolRegistration {
source_name: "some_protocol".into(),
source: RegistrationSource::Child("gtest".to_string()),
target_name: "some_protocol".into(),
})
],
stop_timeout_ms: Some(4567),
}
],
config: Some(ConfigDecl {
fields: vec![
ConfigField {
key: "enable_logging".to_string(),
type_: ConfigValueType::Bool
}
],
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_capability_path! {
capability_path_one_part => {
input = "/foo",
result = Ok(CapabilityPath{dirname: "/".to_string(), basename: "foo".to_string()}),
},
capability_path_two_parts => {
input = "/foo/bar",
result = Ok(CapabilityPath{dirname: "/foo".to_string(), basename: "bar".to_string()}),
},
capability_path_many_parts => {
input = "/foo/bar/long/path",
result = Ok(CapabilityPath{
dirname: "/foo/bar/long".to_string(),
basename: "path".to_string()
}),
},
capability_path_invalid_empty_part => {
input = "/foo/bar//long/path",
result = Err(Error::InvalidCapabilityPath{raw: "/foo/bar//long/path".to_string()}),
},
capability_path_invalid_empty => {
input = "",
result = Err(Error::InvalidCapabilityPath{raw: "".to_string()}),
},
capability_path_invalid_root => {
input = "/",
result = Err(Error::InvalidCapabilityPath{raw: "/".to_string()}),
},
capability_path_invalid_relative => {
input = "foo/bar",
result = Err(Error::InvalidCapabilityPath{raw: "foo/bar".to_string()}),
},
capability_path_invalid_trailing => {
input = "/foo/bar/",
result = Err(Error::InvalidCapabilityPath{raw: "/foo/bar/".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".to_string(),
collection: None,
}),
],
input_type = fdecl::Ref,
result = vec![
UseSource::Parent,
UseSource::Framework,
UseSource::Debug,
UseSource::Capability(CapabilityName("capability".to_string())),
UseSource::Child("foo".to_string()),
],
result_type = UseSource,
},
fidl_into_and_from_expose_source => {
input = vec![
fdecl::Ref::Self_(fdecl::SelfRef {}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".to_string(),
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".to_string()),
],
result_type = ExposeSource,
},
fidl_into_and_from_offer_source => {
input = vec![
fdecl::Ref::Self_(fdecl::SelfRef {}),
fdecl::Ref::Child(fdecl::ChildRef {
name: "foo".to_string(),
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_,
OfferSource::static_child("foo".to_string()),
OfferSource::Framework,
OfferSource::Capability(CapabilityName("foo".to_string())),
OfferSource::Parent,
OfferSource::Collection("foo".to_string()),
OfferSource::Void,
],
result_type = OfferSource,
},
fidl_into_and_from_capability_without_path => {
input = vec![
fdecl::Protocol {
name: Some("foo_protocol".to_string()),
source_path: None,
..fdecl::Protocol::EMPTY
},
],
input_type = fdecl::Protocol,
result = vec![
ProtocolDecl {
name: "foo_protocol".into(),
source_path: None,
}
],
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".to_string(),
collection: None,
})),
subdir: None,
storage_id: Some(fdecl::StorageId::StaticInstanceIdOrMoniker),
..fdecl::Storage::EMPTY
},
],
input_type = fdecl::Storage,
result = vec![
StorageDecl {
name: "minfs".into(),
backing_dir: "minfs".into(),
source: StorageDirectorySource::Child("foo".to_string()),
subdir: None,
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".to_string(),
collection: None,
})),
subdir: None,
storage_id: Some(fdecl::StorageId::StaticInstanceId),
..fdecl::Storage::EMPTY
},
],
input_type = fdecl::Storage,
result = vec![
StorageDecl {
name: "minfs".into(),
backing_dir: "minfs".into(),
source: StorageDirectorySource::Child("foo".to_string()),
subdir: None,
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![]),
..fdata::Dictionary::EMPTY
}),
..fdecl::Program::EMPTY
}),
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::Persistent),
environment: None,
allowed_offers: None,
allow_long_names: None,
persistent_storage: None,
..fdecl::Collection::EMPTY
},
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),
..fdecl::Collection::EMPTY
},
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),
..fdecl::Collection::EMPTY
},
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,
..fdecl::Collection::EMPTY
},
]),
facets: Some(fdata::Dictionary{
entries: Some(vec![]),
..fdata::Dictionary::EMPTY
}),
environments: Some(vec![]),
..fdecl::Component::EMPTY
},
result = {
ComponentDecl {
program: Some(ProgramDecl {
runner: Some("elf".try_into().unwrap()),
info: fdata::Dictionary {
entries: Some(vec![]),
..fdata::Dictionary::EMPTY
},
}),
uses: vec![],
exposes: vec![],
offers: vec![],
capabilities: vec![],
children: vec![],
collections: vec![
CollectionDecl {
name: "modular".to_string(),
durability: fdecl::Durability::Persistent,
environment: None,
allowed_offers: cm_types::AllowedOffers::StaticOnly,
allow_long_names: false,
persistent_storage: None,
},
CollectionDecl {
name: "tests".to_string(),
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".to_string(),
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".to_string(),
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![]),
..fdata::Dictionary::EMPTY
}),
environments: vec![],
config: None,
}
},
},
}
}