blob: bca85b44a1f82940c89078e2702a940e3119dfb6 [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_json::{self, cm, Error},
fidl_fuchsia_data as fdata, fidl_fuchsia_sys2 as fsys,
serde_json::{Map, Value},
};
/// Converts the contents of a CM file and produces the equivalent FIDL.
/// The mapping between CM-JSON and CM-FIDL is 1-1. The only difference is the language semantics
/// used to express particular data structures.
/// This function also applies cm_fidl_validator to the generated FIDL.
pub fn translate(buffer: &str) -> Result<fsys::ComponentDecl, Error> {
let document: cm::Document = serde_json::from_str(&buffer)?;
let decl = document.cm_into()?;
cm_fidl_validator::validate(&decl).map_err(|e| Error::validate_fidl(e))?;
Ok(decl)
}
/// Converts a cm object into its corresponding fidl representation.
trait CmInto<T> {
fn cm_into(self) -> Result<T, Error>;
}
impl<T, U> CmInto<Option<Vec<U>>> for Option<Vec<T>>
where
T: CmInto<U>,
{
fn cm_into(self) -> Result<Option<Vec<U>>, Error> {
self.and_then(|x| if x.is_empty() { None } else { Some(x.cm_into()) }).transpose()
}
}
impl<T, U> CmInto<Vec<U>> for Vec<T>
where
T: CmInto<U>,
{
fn cm_into(self) -> Result<Vec<U>, Error> {
self.into_iter().map(|x| x.cm_into()).collect()
}
}
impl CmInto<fsys::ComponentDecl> for cm::Document {
fn cm_into(self) -> Result<fsys::ComponentDecl, Error> {
Ok(fsys::ComponentDecl {
program: self.program.cm_into()?,
uses: self.uses.cm_into()?,
exposes: self.exposes.cm_into()?,
offers: self.offers.cm_into()?,
children: self.children.cm_into()?,
collections: self.collections.cm_into()?,
facets: self.facets.cm_into()?,
storage: self.storage.cm_into()?,
runners: self.runners.cm_into()?,
environments: self.environments.cm_into()?,
resolvers: self.resolvers.cm_into()?,
})
}
}
impl CmInto<fsys::UseDecl> for cm::Use {
fn cm_into(self) -> Result<fsys::UseDecl, Error> {
Ok(match self {
cm::Use::Service(s) => fsys::UseDecl::Service(s.cm_into()?),
cm::Use::Protocol(s) => fsys::UseDecl::Protocol(s.cm_into()?),
cm::Use::Directory(d) => fsys::UseDecl::Directory(d.cm_into()?),
cm::Use::Storage(s) => fsys::UseDecl::Storage(s.cm_into()?),
cm::Use::Runner(r) => fsys::UseDecl::Runner(r.cm_into()?),
cm::Use::Event(e) => fsys::UseDecl::Event(e.cm_into()?),
})
}
}
impl CmInto<fsys::ExposeDecl> for cm::Expose {
fn cm_into(self) -> Result<fsys::ExposeDecl, Error> {
Ok(match self {
cm::Expose::Service(s) => fsys::ExposeDecl::Service(s.cm_into()?),
cm::Expose::Protocol(s) => fsys::ExposeDecl::Protocol(s.cm_into()?),
cm::Expose::Directory(d) => fsys::ExposeDecl::Directory(d.cm_into()?),
cm::Expose::Runner(r) => fsys::ExposeDecl::Runner(r.cm_into()?),
cm::Expose::Resolver(r) => fsys::ExposeDecl::Resolver(r.cm_into()?),
})
}
}
impl CmInto<fsys::Ref> for cm::ExposeTarget {
fn cm_into(self) -> Result<fsys::Ref, Error> {
Ok(match self {
cm::ExposeTarget::Realm => fsys::Ref::Realm(fsys::RealmRef {}),
cm::ExposeTarget::Framework => fsys::Ref::Framework(fsys::FrameworkRef {}),
})
}
}
impl CmInto<fsys::DependencyType> for cm::DependencyType {
fn cm_into(self) -> Result<fsys::DependencyType, Error> {
Ok(match self {
cm::DependencyType::Strong => fsys::DependencyType::Strong,
cm::DependencyType::WeakForMigration => fsys::DependencyType::WeakForMigration,
})
}
}
impl CmInto<fsys::OfferDecl> for cm::Offer {
fn cm_into(self) -> Result<fsys::OfferDecl, Error> {
Ok(match self {
cm::Offer::Service(s) => fsys::OfferDecl::Service(s.cm_into()?),
cm::Offer::Protocol(s) => fsys::OfferDecl::Protocol(s.cm_into()?),
cm::Offer::Directory(d) => fsys::OfferDecl::Directory(d.cm_into()?),
cm::Offer::Storage(s) => fsys::OfferDecl::Storage(s.cm_into()?),
cm::Offer::Runner(r) => fsys::OfferDecl::Runner(r.cm_into()?),
cm::Offer::Resolver(r) => fsys::OfferDecl::Resolver(r.cm_into()?),
cm::Offer::Event(e) => fsys::OfferDecl::Event(e.cm_into()?),
})
}
}
impl CmInto<fsys::UseServiceDecl> for cm::UseService {
fn cm_into(self) -> Result<fsys::UseServiceDecl, Error> {
Ok(fsys::UseServiceDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
})
}
}
impl CmInto<fsys::UseProtocolDecl> for cm::UseProtocol {
fn cm_into(self) -> Result<fsys::UseProtocolDecl, Error> {
Ok(fsys::UseProtocolDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
})
}
}
impl CmInto<fsys::UseDirectoryDecl> for cm::UseDirectory {
fn cm_into(self) -> Result<fsys::UseDirectoryDecl, Error> {
Ok(fsys::UseDirectoryDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
rights: self.rights.into(),
subdir: self.subdir.map(|s| s.into()),
})
}
}
impl CmInto<fsys::UseStorageDecl> for cm::UseStorage {
fn cm_into(self) -> Result<fsys::UseStorageDecl, Error> {
Ok(fsys::UseStorageDecl {
type_: Some(self.type_.cm_into()?),
target_path: self.target_path.map(|path| path.into()),
})
}
}
impl CmInto<fsys::UseRunnerDecl> for cm::UseRunner {
fn cm_into(self) -> Result<fsys::UseRunnerDecl, Error> {
Ok(fsys::UseRunnerDecl { source_name: Some(self.source_name.into()) })
}
}
impl CmInto<fsys::UseEventDecl> for cm::UseEvent {
fn cm_into(self) -> Result<fsys::UseEventDecl, Error> {
Ok(fsys::UseEventDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target_name: Some(self.target_name.into()),
filter: self.filter.cm_into()?,
})
}
}
impl CmInto<fsys::ExposeServiceDecl> for cm::ExposeService {
fn cm_into(self) -> Result<fsys::ExposeServiceDecl, Error> {
Ok(fsys::ExposeServiceDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
target: Some(self.target.cm_into()?),
})
}
}
impl CmInto<fsys::ExposeProtocolDecl> for cm::ExposeProtocol {
fn cm_into(self) -> Result<fsys::ExposeProtocolDecl, Error> {
Ok(fsys::ExposeProtocolDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
target: Some(self.target.cm_into()?),
})
}
}
impl CmInto<fsys::ExposeDirectoryDecl> for cm::ExposeDirectory {
fn cm_into(self) -> Result<fsys::ExposeDirectoryDecl, Error> {
Ok(fsys::ExposeDirectoryDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target_path: Some(self.target_path.into()),
target: Some(self.target.cm_into()?),
rights: match self.rights {
Some(rights) => rights.into(),
None => None,
},
subdir: self.subdir.map(|s| s.into()),
})
}
}
impl CmInto<fsys::ExposeRunnerDecl> for cm::ExposeRunner {
fn cm_into(self) -> Result<fsys::ExposeRunnerDecl, Error> {
Ok(fsys::ExposeRunnerDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target: Some(self.target.cm_into()?),
target_name: Some(self.target_name.into()),
})
}
}
impl CmInto<fsys::ExposeResolverDecl> for cm::ExposeResolver {
fn cm_into(self) -> Result<fsys::ExposeResolverDecl, Error> {
Ok(fsys::ExposeResolverDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target: Some(self.target.cm_into()?),
target_name: Some(self.target_name.into()),
})
}
}
impl CmInto<fsys::OfferServiceDecl> for cm::OfferService {
fn cm_into(self) -> Result<fsys::OfferServiceDecl, Error> {
Ok(fsys::OfferServiceDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target: Some(self.target.cm_into()?),
target_path: Some(self.target_path.into()),
})
}
}
impl CmInto<fsys::OfferProtocolDecl> for cm::OfferProtocol {
fn cm_into(self) -> Result<fsys::OfferProtocolDecl, Error> {
Ok(fsys::OfferProtocolDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target: Some(self.target.cm_into()?),
target_path: Some(self.target_path.into()),
dependency_type: Some(self.dependency_type.cm_into()?),
})
}
}
impl CmInto<fsys::OfferDirectoryDecl> for cm::OfferDirectory {
fn cm_into(self) -> Result<fsys::OfferDirectoryDecl, Error> {
Ok(fsys::OfferDirectoryDecl {
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
target: Some(self.target.cm_into()?),
target_path: Some(self.target_path.into()),
rights: match self.rights {
Some(rights) => rights.into(),
None => None,
},
subdir: self.subdir.map(|s| s.into()),
dependency_type: Some(self.dependency_type.cm_into()?),
})
}
}
impl CmInto<fsys::OfferStorageDecl> for cm::OfferStorage {
fn cm_into(self) -> Result<fsys::OfferStorageDecl, Error> {
Ok(fsys::OfferStorageDecl {
type_: Some(self.type_.cm_into()?),
source: Some(self.source.cm_into()?),
target: Some(self.target.cm_into()?),
})
}
}
impl CmInto<fsys::OfferRunnerDecl> for cm::OfferRunner {
fn cm_into(self) -> Result<fsys::OfferRunnerDecl, Error> {
Ok(fsys::OfferRunnerDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target: Some(self.target.cm_into()?),
target_name: Some(self.target_name.into()),
})
}
}
impl CmInto<fsys::OfferResolverDecl> for cm::OfferResolver {
fn cm_into(self) -> Result<fsys::OfferResolverDecl, Error> {
Ok(fsys::OfferResolverDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target: Some(self.target.cm_into()?),
target_name: Some(self.target_name.into()),
})
}
}
impl CmInto<fsys::OfferEventDecl> for cm::OfferEvent {
fn cm_into(self) -> Result<fsys::OfferEventDecl, Error> {
Ok(fsys::OfferEventDecl {
source: Some(self.source.cm_into()?),
source_name: Some(self.source_name.into()),
target: Some(self.target.cm_into()?),
target_name: Some(self.target_name.into()),
filter: self.filter.cm_into()?,
})
}
}
impl CmInto<fsys::StorageType> for cm::StorageType {
fn cm_into(self) -> Result<fsys::StorageType, Error> {
match self {
cm::StorageType::Data => Ok(fsys::StorageType::Data),
cm::StorageType::Cache => Ok(fsys::StorageType::Cache),
cm::StorageType::Meta => Ok(fsys::StorageType::Meta),
}
}
}
impl CmInto<fsys::ChildDecl> for cm::Child {
fn cm_into(self) -> Result<fsys::ChildDecl, Error> {
Ok(fsys::ChildDecl {
name: Some(self.name.into()),
url: Some(self.url.into()),
startup: Some(self.startup.cm_into()?),
environment: self.environment.map(|e| e.into()),
})
}
}
impl CmInto<fsys::CollectionDecl> for cm::Collection {
fn cm_into(self) -> Result<fsys::CollectionDecl, Error> {
Ok(fsys::CollectionDecl {
name: Some(self.name.into()),
durability: Some(self.durability.cm_into()?),
})
}
}
impl CmInto<fsys::StorageDecl> for cm::Storage {
fn cm_into(self) -> Result<fsys::StorageDecl, Error> {
Ok(fsys::StorageDecl {
name: Some(self.name.into()),
source_path: Some(self.source_path.into()),
source: Some(self.source.cm_into()?),
})
}
}
impl CmInto<fsys::RunnerDecl> for cm::Runner {
fn cm_into(self) -> Result<fsys::RunnerDecl, Error> {
Ok(fsys::RunnerDecl {
name: Some(self.name.into()),
source: Some(self.source.cm_into()?),
source_path: Some(self.source_path.into()),
})
}
}
impl CmInto<fsys::ResolverDecl> for cm::Resolver {
fn cm_into(self) -> Result<fsys::ResolverDecl, Error> {
Ok(fsys::ResolverDecl {
name: Some(self.name.into()),
source_path: Some(self.source_path.into()),
})
}
}
impl CmInto<fsys::EnvironmentDecl> for cm::Environment {
fn cm_into(self) -> Result<fsys::EnvironmentDecl, Error> {
Ok(fsys::EnvironmentDecl {
name: Some(self.name.into()),
extends: Some(self.extends.cm_into()?),
resolvers: self.resolvers.cm_into()?,
stop_timeout_ms: self.stop_timeout_ms,
})
}
}
impl CmInto<fsys::EnvironmentExtends> for cm::EnvironmentExtends {
fn cm_into(self) -> Result<fsys::EnvironmentExtends, Error> {
Ok(match self {
cm::EnvironmentExtends::None => fsys::EnvironmentExtends::None,
cm::EnvironmentExtends::Realm => fsys::EnvironmentExtends::Realm,
})
}
}
impl CmInto<fsys::ResolverRegistration> for cm::ResolverRegistration {
fn cm_into(self) -> Result<fsys::ResolverRegistration, Error> {
Ok(fsys::ResolverRegistration {
resolver: Some(self.resolver.into()),
source: Some(self.source.cm_into()?),
scheme: Some(self.scheme.into()),
})
}
}
impl CmInto<fsys::RealmRef> for cm::RealmRef {
fn cm_into(self) -> Result<fsys::RealmRef, Error> {
Ok(fsys::RealmRef {})
}
}
impl CmInto<fsys::SelfRef> for cm::SelfRef {
fn cm_into(self) -> Result<fsys::SelfRef, Error> {
Ok(fsys::SelfRef {})
}
}
impl CmInto<fsys::ChildRef> for cm::ChildRef {
fn cm_into(self) -> Result<fsys::ChildRef, Error> {
Ok(fsys::ChildRef { name: self.name.into(), collection: None })
}
}
impl CmInto<fsys::CollectionRef> for cm::CollectionRef {
fn cm_into(self) -> Result<fsys::CollectionRef, Error> {
Ok(fsys::CollectionRef { name: self.name.into() })
}
}
impl CmInto<fsys::StorageRef> for cm::StorageRef {
fn cm_into(self) -> Result<fsys::StorageRef, Error> {
Ok(fsys::StorageRef { name: self.name.into() })
}
}
impl CmInto<fsys::FrameworkRef> for cm::FrameworkRef {
fn cm_into(self) -> Result<fsys::FrameworkRef, Error> {
Ok(fsys::FrameworkRef {})
}
}
impl CmInto<fsys::Ref> for cm::Ref {
fn cm_into(self) -> Result<fsys::Ref, Error> {
Ok(match self {
cm::Ref::Realm(r) => fsys::Ref::Realm(r.cm_into()?),
cm::Ref::Self_(s) => fsys::Ref::Self_(s.cm_into()?),
cm::Ref::Child(c) => fsys::Ref::Child(c.cm_into()?),
cm::Ref::Collection(c) => fsys::Ref::Collection(c.cm_into()?),
cm::Ref::Storage(r) => fsys::Ref::Storage(r.cm_into()?),
cm::Ref::Framework(f) => fsys::Ref::Framework(f.cm_into()?),
})
}
}
impl CmInto<fsys::Durability> for cm::Durability {
fn cm_into(self) -> Result<fsys::Durability, Error> {
Ok(match self {
cm::Durability::Persistent => fsys::Durability::Persistent,
cm::Durability::Transient => fsys::Durability::Transient,
})
}
}
impl CmInto<fsys::StartupMode> for cm::StartupMode {
fn cm_into(self) -> Result<fsys::StartupMode, Error> {
Ok(match self {
cm::StartupMode::Lazy => fsys::StartupMode::Lazy,
cm::StartupMode::Eager => fsys::StartupMode::Eager,
})
}
}
impl CmInto<Option<fsys::Object>> for Option<Map<String, Value>> {
fn cm_into(self) -> Result<Option<fsys::Object>, Error> {
match self {
Some(from) => {
let obj = object_from_map(from)?;
Ok(Some(obj))
}
None => Ok(None),
}
}
}
impl CmInto<Option<fdata::Dictionary>> for Option<Map<String, Value>> {
fn cm_into(self) -> Result<Option<fdata::Dictionary>, Error> {
match self {
Some(from) => Ok(Some(dictionary_from_map(from)?)),
None => Ok(None),
}
}
}
fn object_from_map(in_obj: Map<String, Value>) -> Result<fsys::Object, Error> {
let mut out = fsys::Object { entries: vec![] };
for (k, v) in in_obj {
if let Some(value) = convert_value(v)? {
out.entries.push(fsys::Entry { key: k, value: Some(value) });
}
}
Ok(out)
}
fn dictionary_from_map(in_obj: Map<String, Value>) -> Result<fdata::Dictionary, Error> {
let mut entries = vec![];
for (key, v) in in_obj {
let value = match v {
Value::Null => None,
Value::String(s) => Some(Box::new(fdata::DictionaryValue::Str(s.clone()))),
Value::Array(arr) => {
let mut strs = vec![];
for val in arr {
match val {
Value::String(s) => strs.push(s.clone()),
_ => return Err(Error::Parse(format!("Value must be string"))),
};
}
Some(Box::new(fdata::DictionaryValue::StrVec(strs)))
}
_ => return Err(Error::Parse(format!("Value must be string or list of strings"))),
};
entries.push(fdata::DictionaryEntry { key, value });
}
Ok(fdata::Dictionary { entries: Some(entries) })
}
fn convert_value(v: Value) -> Result<Option<Box<fsys::Value>>, Error> {
Ok(match v {
Value::Null => None,
Value::Bool(b) => Some(Box::new(fsys::Value::Bit(b))),
Value::Number(n) => {
if let Some(i) = n.as_i64() {
Some(Box::new(fsys::Value::Inum(i)))
} else if let Some(f) = n.as_f64() {
Some(Box::new(fsys::Value::Fnum(f)))
} else {
return Err(Error::Parse(format!("Number is out of range: {}", n)));
}
}
Value::String(s) => Some(Box::new(fsys::Value::Str(s.clone()))),
Value::Array(a) => {
let mut values = vec![];
for v in a {
if let Some(value) = convert_value(v)? {
values.push(Some(value));
}
}
let vector = fsys::Vector { values };
Some(Box::new(fsys::Value::Vec(vector)))
}
Value::Object(o) => {
let obj = object_from_map(o)?;
Some(Box::new(fsys::Value::Obj(obj)))
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use fidl_fuchsia_io2 as fio2;
use serde_json::json;
use test_util::assert_matches;
fn translate_test(input: serde_json::value::Value, expected_output: fsys::ComponentDecl) {
let component_decl = translate(&format!("{}", input)).expect("translation failed");
assert_eq!(component_decl, expected_output);
}
fn new_component_decl() -> fsys::ComponentDecl {
fsys::ComponentDecl {
program: None,
uses: None,
exposes: None,
offers: None,
facets: None,
children: None,
collections: None,
storage: None,
runners: None,
environments: None,
resolvers: None,
}
}
macro_rules! test_translate {
(
$(
$test_name:ident => {
input = $input:expr,
output = $output:expr,
},
)+
) => {
$(
#[test]
fn $test_name() {
translate_test($input, $output);
}
)+
}
}
#[test]
fn test_translate_invalid_cm_fails() {
let input = json!({
"exposes": [
{
}
]
});
let res = translate(&format!("{}", input));
assert_matches!(res, Err(Error::Parse(_)));
}
test_translate! {
test_translate_empty => {
input = json!({}),
output = new_component_decl(),
},
test_translate_program => {
input = json!({
"program": {
"binary": "bin/app"
}
}),
output = {
let program = fdata::Dictionary{entries: Some(vec![
fdata::DictionaryEntry{
key: "binary".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
}
])};
let mut decl = new_component_decl();
decl.program = Some(program);
decl
},
},
test_translate_object_primitive => {
input = json!({
"facets": {
"string": "bar",
"int": -42,
"float": 3.14,
"bool": true,
"ignore": null
}
}),
output = {
let facets = fsys::Object{entries: vec![
fsys::Entry{
key: "bool".to_string(),
value: Some(Box::new(fsys::Value::Bit(true))),
},
fsys::Entry{
key: "float".to_string(),
value: Some(Box::new(fsys::Value::Fnum(3.14))),
},
fsys::Entry{
key: "int".to_string(),
value: Some(Box::new(fsys::Value::Inum(-42))),
},
fsys::Entry{
key: "string".to_string(),
value: Some(Box::new(fsys::Value::Str("bar".to_string()))),
},
]};
let mut decl = new_component_decl();
decl.facets = Some(facets);
decl
},
},
test_translate_object_nested => {
input = json!({
"facets": {
"obj": {
"array": [
{
"string": "bar"
},
-42
],
},
"bool": true
}
}),
output = {
let obj_inner = fsys::Object{entries: vec![
fsys::Entry{
key: "string".to_string(),
value: Some(Box::new(fsys::Value::Str("bar".to_string()))),
},
]};
let vector = fsys::Vector{values: vec![
Some(Box::new(fsys::Value::Obj(obj_inner))),
Some(Box::new(fsys::Value::Inum(-42)))
]};
let obj_outer = fsys::Object{entries: vec![
fsys::Entry{
key: "array".to_string(),
value: Some(Box::new(fsys::Value::Vec(vector))),
},
]};
let facets = fsys::Object{entries: vec![
fsys::Entry{
key: "bool".to_string(),
value: Some(Box::new(fsys::Value::Bit(true))),
},
fsys::Entry{
key: "obj".to_string(),
value: Some(Box::new(fsys::Value::Obj(obj_outer))),
},
]};
let mut decl = new_component_decl();
decl.facets = Some(facets);
decl
},
},
test_translate_uses => {
input = json!({
"uses": [
{
"service": {
"source": {
"realm": {}
},
"source_path": "/fonts/CoolFonts",
"target_path": "/svc/fuchsia.fonts.Provider"
}
},
{
"service": {
"source": {
"framework": {}
},
"source_path": "/svc/fuchsia.sys2.Realm",
"target_path": "/svc/fuchsia.sys2.Realm"
}
},
{
"protocol": {
"source": {
"realm": {}
},
"source_path": "/fonts/CoolFonts",
"target_path": "/svc/fuchsia.fonts.Provider2"
}
},
{
"protocol": {
"source": {
"framework": {}
},
"source_path": "/svc/fuchsia.sys2.Realm",
"target_path": "/svc/fuchsia.sys2.Realm2"
}
},
{
"directory": {
"source": {
"realm": {}
},
"source_path": "/data/assets",
"target_path": "/data",
"rights": ["connect", "write_bytes"]
}
},
{
"directory": {
"source": {
"framework": {}
},
"source_path": "/pkg",
"target_path": "/pkg",
"rights": ["connect", "read_bytes"],
"subdir": "config/data"
}
},
{
"storage": {
"type": "cache",
"target_path": "/cache"
}
},
{
"runner": {
"source_name": "elf"
}
},
{
"event": {
"source": {
"realm": {}
},
"source_name": "capability_ready",
"target_name": "capability_ready_from_realm",
"filter": {
"path": "/diagnostics"
}
}
},
{
"event": {
"source": {
"framework": {}
},
"source_name": "started",
"target_name": "started"
}
}
]
}),
output = {
let uses = vec![
fsys::UseDecl::Service(fsys::UseServiceDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_path: Some("/fonts/CoolFonts".to_string()),
target_path: Some("/svc/fuchsia.fonts.Provider".to_string()),
}),
fsys::UseDecl::Service(fsys::UseServiceDecl {
source: Some(fsys::Ref::Framework(fsys::FrameworkRef {})),
source_path: Some("/svc/fuchsia.sys2.Realm".to_string()),
target_path: Some("/svc/fuchsia.sys2.Realm".to_string()),
}),
fsys::UseDecl::Protocol(fsys::UseProtocolDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_path: Some("/fonts/CoolFonts".to_string()),
target_path: Some("/svc/fuchsia.fonts.Provider2".to_string()),
}),
fsys::UseDecl::Protocol(fsys::UseProtocolDecl {
source: Some(fsys::Ref::Framework(fsys::FrameworkRef {})),
source_path: Some("/svc/fuchsia.sys2.Realm".to_string()),
target_path: Some("/svc/fuchsia.sys2.Realm2".to_string()),
}),
fsys::UseDecl::Directory(fsys::UseDirectoryDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_path: Some("/data/assets".to_string()),
target_path: Some("/data".to_string()),
rights: Some(fio2::Operations::Connect | fio2::Operations::WriteBytes),
subdir: None,
}),
fsys::UseDecl::Directory(fsys::UseDirectoryDecl {
source: Some(fsys::Ref::Framework(fsys::FrameworkRef {})),
source_path: Some("/pkg".to_string()),
target_path: Some("/pkg".to_string()),
rights: Some(fio2::Operations::Connect | fio2::Operations::ReadBytes),
subdir: Some("config/data".to_string()),
}),
fsys::UseDecl::Storage(fsys::UseStorageDecl {
type_: Some(fsys::StorageType::Cache),
target_path: Some("/cache".to_string()),
}),
fsys::UseDecl::Runner(fsys::UseRunnerDecl {
source_name: Some("elf".to_string()),
}),
fsys::UseDecl::Event(fsys::UseEventDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_name: Some("capability_ready".to_string()),
target_name: Some("capability_ready_from_realm".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()))),
}]),
}),
}),
fsys::UseDecl::Event(fsys::UseEventDecl {
source: Some(fsys::Ref::Framework(fsys::FrameworkRef {})),
source_name: Some("started".to_string()),
target_name: Some("started".to_string()),
filter: None,
}),
];
let mut decl = new_component_decl();
decl.uses = Some(uses);
decl
},
},
test_translate_exposes => {
input = json!({
"exposes": [
{
"service": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/loggers/fuchsia.logger.Log1",
"target_path": "/svc/fuchsia.logger.Log",
"target": "realm"
}
},
{
"service": {
"source": {
"self": {}
},
"source_path": "/loggers/fuchsia.logger.Log2",
"target_path": "/svc/fuchsia.logger.Log",
"target": "realm"
}
},
{
"protocol": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/loggers/fuchsia.logger.LegacyLog",
"target_path": "/svc/fuchsia.logger.LegacyLog",
"target": "realm"
}
},
{
"directory": {
"source": {
"self": {}
},
"source_path": "/volumes/blobfs",
"target_path": "/volumes/blobfs",
"target": "framework",
"rights": ["connect"]
}
},
{
"directory": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/data",
"target_path": "/data",
"target": "realm",
"rights": ["connect"],
"subdir": "logs"
}
},
{
"runner": {
"source": {
"child": {
"name": "logger"
}
},
"source_name": "elf",
"target": "realm",
"target_name": "elf"
}
},
{
"resolver": {
"source": {
"child": {
"name": "logger"
}
},
"source_name": "pkg_resolver",
"target": "realm",
"target_name": "pkg_resolver",
}
},
],
"children": [
{
"name": "logger",
"url": "fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm",
"startup": "lazy"
}
]
}),
output = {
let exposes = vec![
fsys::ExposeDecl::Service(fsys::ExposeServiceDecl {
source_path: Some("/loggers/fuchsia.logger.Log1".to_string()),
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
target_path: Some("/svc/fuchsia.logger.Log".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
}),
fsys::ExposeDecl::Service(fsys::ExposeServiceDecl {
source_path: Some("/loggers/fuchsia.logger.Log2".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef {})),
target_path: Some("/svc/fuchsia.logger.Log".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
}),
fsys::ExposeDecl::Protocol(fsys::ExposeProtocolDecl {
source_path: Some("/loggers/fuchsia.logger.LegacyLog".to_string()),
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
target_path: Some("/svc/fuchsia.logger.LegacyLog".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
}),
fsys::ExposeDecl::Directory(fsys::ExposeDirectoryDecl {
source_path: Some("/volumes/blobfs".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
target_path: Some("/volumes/blobfs".to_string()),
target: Some(fsys::Ref::Framework(fsys::FrameworkRef {})),
rights: Some(fio2::Operations::Connect),
subdir: None,
}),
fsys::ExposeDecl::Directory(fsys::ExposeDirectoryDecl {
source_path: Some("/data".to_string()),
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
target_path: Some("/data".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
rights: Some(fio2::Operations::Connect),
subdir: Some("logs".to_string()),
}),
fsys::ExposeDecl::Runner(fsys::ExposeRunnerDecl {
source_name: Some("elf".to_string()),
source: Some(fsys::Ref::Child(fsys::ChildRef{
name: "logger".to_string(),
collection: None,
})),
target_name: Some("elf".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
}),
fsys::ExposeDecl::Resolver(fsys::ExposeResolverDecl {
source_name: Some("pkg_resolver".to_string()),
source: Some(fsys::Ref::Child(fsys::ChildRef{
name: "logger".to_string(),
collection: None,
})),
target_name: Some("pkg_resolver".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
}),
];
let children = vec![
fsys::ChildDecl{
name: Some("logger".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm".to_string()),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
},
];
let mut decl = new_component_decl();
decl.exposes = Some(exposes);
decl.children = Some(children);
decl
},
},
test_translate_offers => {
input = json!({
"offers": [
{
"directory": {
"source": {
"realm": {}
},
"source_path": "/data/assets",
"target": {
"child": {
"name": "logger"
}
},
"target_path": "/data/realm_assets",
"dependency_type": "strong"
},
},
{
"directory": {
"source": {
"self": {}
},
"source_path": "/data/config",
"target": {
"collection": {
"name": "modular"
}
},
"target_path": "/data/config",
"rights": ["connect"],
"subdir": "fonts",
"dependency_type": "weak_for_migration"
}
},
{
"service": {
"source": {
"self": {}
},
"source_path": "/svc/fuchsia.netstack.Netstack",
"target": {
"child": {
"name": "logger"
}
},
"target_path": "/svc/fuchsia.netstack.Netstack"
}
},
{
"service": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/svc/fuchsia.logger.Log1",
"target": {
"collection": {
"name": "modular"
}
},
"target_path": "/svc/fuchsia.logger.Log"
}
},
{
"service": {
"source": {
"self": {}
},
"source_path": "/svc/fuchsia.logger.Log2",
"target": {
"collection": {
"name": "modular"
}
},
"target_path": "/svc/fuchsia.logger.Log"
}
},
{
"protocol": {
"source": {
"self": {}
},
"source_path": "/svc/fuchsia.netstack.LegacyNetstack",
"target": {
"child": {
"name": "logger"
}
},
"target_path": "/svc/fuchsia.netstack.LegacyNetstack",
"dependency_type": "strong"
}
},
{
"protocol": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/svc/fuchsia.logger.LegacyLog",
"target": {
"collection": {
"name": "modular"
}
},
"target_path": "/svc/fuchsia.logger.LegacySysLog",
"dependency_type": "weak_for_migration"
}
},
{
"storage": {
"type": "data",
"source": {
"storage": {
"name": "memfs"
}
},
"target": {
"collection": {
"name": "modular"
}
}
}
},
{
"storage": {
"type": "data",
"source": {
"storage": {
"name": "memfs"
}
},
"target": {
"child": {
"name": "logger"
}
}
}
},
{
"storage": {
"type": "meta",
"source": {
"realm": {}
},
"target": {
"collection": {
"name": "modular"
}
}
}
},
{
"storage": {
"type": "meta",
"source": {
"realm": {}
},
"target": {
"child": {
"name": "logger"
}
}
}
},
{
"runner": {
"source": {
"realm": {}
},
"source_name": "elf",
"target": {
"child": {
"name": "logger"
}
},
"target_name": "elf"
}
},
{
"resolver": {
"source": {
"realm": {}
},
"source_name": "pkg_resolver",
"target": {
"child": {
"name": "logger"
}
},
"target_name": "pkg_resolver",
}
},
{
"event": {
"source_name": "capability_ready",
"source": {
"realm": {}
},
"target": {
"child": {
"name": "logger"
}
},
"target_name": "capability_ready_diagnostics",
"filter": {
"path": "/diagnostics"
}
}
}
],
"children": [
{
"name": "logger",
"url": "fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm",
"startup": "lazy"
},
{
"name": "netstack",
"url": "fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm",
"startup": "eager"
}
],
"collections": [
{
"name": "modular",
"durability": "persistent"
}
],
"storage": [
{
"name": "memfs",
"source_path": "/memfs",
"source": {
"self": {}
}
}
],
}),
output = {
let offers = vec![
fsys::OfferDecl::Directory(fsys::OfferDirectoryDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_path: Some("/data/assets".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
target_path: Some("/data/realm_assets".to_string()),
rights: None,
subdir: None,
dependency_type: Some(fsys::DependencyType::Strong),
}),
fsys::OfferDecl::Directory(fsys::OfferDirectoryDecl {
source: Some(fsys::Ref::Self_(fsys::SelfRef {})),
source_path: Some("/data/config".to_string()),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef {
name: "modular".to_string(),
}
)),
target_path: Some("/data/config".to_string()),
rights: Some(fio2::Operations::Connect),
subdir: Some("fonts".to_string()),
dependency_type: Some(fsys::DependencyType::WeakForMigration),
}),
fsys::OfferDecl::Service(fsys::OfferServiceDecl {
source: Some(fsys::Ref::Self_(fsys::SelfRef {})),
source_path: Some("/svc/fuchsia.netstack.Netstack".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
target_path: Some("/svc/fuchsia.netstack.Netstack".to_string()),
}),
fsys::OfferDecl::Service(fsys::OfferServiceDecl {
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
source_path: Some("/svc/fuchsia.logger.Log1".to_string()),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef {
name: "modular".to_string(),
}
)),
target_path: Some("/svc/fuchsia.logger.Log".to_string()),
}),
fsys::OfferDecl::Service(fsys::OfferServiceDecl {
source: Some(fsys::Ref::Self_(fsys::SelfRef {})),
source_path: Some("/svc/fuchsia.logger.Log2".to_string()),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef {
name: "modular".to_string(),
}
)),
target_path: Some("/svc/fuchsia.logger.Log".to_string()),
}),
fsys::OfferDecl::Protocol(fsys::OfferProtocolDecl {
source: Some(fsys::Ref::Self_(fsys::SelfRef {})),
source_path: Some("/svc/fuchsia.netstack.LegacyNetstack".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
target_path: Some("/svc/fuchsia.netstack.LegacyNetstack".to_string()),
dependency_type: Some(fsys::DependencyType::Strong),
}),
fsys::OfferDecl::Protocol(fsys::OfferProtocolDecl {
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
source_path: Some("/svc/fuchsia.logger.LegacyLog".to_string()),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef {
name: "modular".to_string(),
}
)),
target_path: Some("/svc/fuchsia.logger.LegacySysLog".to_string()),
dependency_type: Some(fsys::DependencyType::WeakForMigration),
}),
fsys::OfferDecl::Storage(fsys::OfferStorageDecl {
type_: Some(fsys::StorageType::Data),
source: Some(fsys::Ref::Storage(fsys::StorageRef {
name: "memfs".to_string(),
})),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef { name: "modular".to_string() }
)),
}),
fsys::OfferDecl::Storage(fsys::OfferStorageDecl {
type_: Some(fsys::StorageType::Data),
source: Some(fsys::Ref::Storage(fsys::StorageRef {
name: "memfs".to_string(),
})),
target: Some(fsys::Ref::Child(
fsys::ChildRef { name: "logger".to_string(), collection: None }
)),
}),
fsys::OfferDecl::Storage(fsys::OfferStorageDecl {
type_: Some(fsys::StorageType::Meta),
source: Some(fsys::Ref::Realm(fsys::RealmRef { })),
target: Some(fsys::Ref::Collection(
fsys::CollectionRef { name: "modular".to_string() }
)),
}),
fsys::OfferDecl::Storage(fsys::OfferStorageDecl {
type_: Some(fsys::StorageType::Meta),
source: Some(fsys::Ref::Realm(fsys::RealmRef { })),
target: Some(fsys::Ref::Child(
fsys::ChildRef { name: "logger".to_string(), collection: None }
)),
}),
fsys::OfferDecl::Runner(fsys::OfferRunnerDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_name: Some("elf".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
target_name: Some("elf".to_string()),
}),
fsys::OfferDecl::Resolver(fsys::OfferResolverDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_name: Some("pkg_resolver".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
target_name: Some("pkg_resolver".to_string()),
}),
fsys::OfferDecl::Event(fsys::OfferEventDecl {
source_name: Some("capability_ready".to_string()),
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "logger".to_string(),
collection: None,
}
)),
filter: Some(fdata::Dictionary {
entries: Some(vec![fdata::DictionaryEntry {
key: "path".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("/diagnostics".to_string()))),
}]),
}),
target_name: Some("capability_ready_diagnostics".to_string()),
}),
];
let children = vec![
fsys::ChildDecl{
name: Some("logger".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm".to_string()),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
},
fsys::ChildDecl{
name: Some("netstack".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm".to_string()),
startup: Some(fsys::StartupMode::Eager),
environment: None,
},
];
let collections = vec![
fsys::CollectionDecl{
name: Some("modular".to_string()),
durability: Some(fsys::Durability::Persistent),
},
];
let storages = vec![
fsys::StorageDecl {
name: Some("memfs".to_string()),
source_path: Some("/memfs".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
},
];
let mut decl = new_component_decl();
decl.offers = Some(offers);
decl.children = Some(children);
decl.collections = Some(collections);
decl.storage = Some(storages);
decl
},
},
test_translate_environments => {
input = json!({
"children": [
{
"name": "echo_server",
"url": "fuchsia-pkg://fuchsia.com/echo_server/stable#meta/echo_server.cm",
"startup": "lazy",
"environment": "test_env",
},
],
"environments": [
{
"name": "test_env",
"extends": "none",
"resolvers": [
{
"resolver": "pkg_resolver",
"source": {
"realm": {},
},
"scheme": "fuchsia-pkg",
}
],
"__stop_timeout_ms": 9876,
},
{
"name": "env",
"extends": "realm",
}
]
}),
output = {
let children = vec![
fsys::ChildDecl {
name: Some("echo_server".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/echo_server/stable#meta/echo_server.cm".to_string()),
startup: Some(fsys::StartupMode::Lazy),
environment: Some("test_env".to_string()),
},
];
let environments = vec![
fsys::EnvironmentDecl {
name: Some("test_env".to_string()),
extends: Some(fsys::EnvironmentExtends::None),
resolvers: Some(vec![
fsys::ResolverRegistration {
resolver: Some("pkg_resolver".to_string()),
source: Some(fsys::Ref::Realm(fsys::RealmRef{})),
scheme: Some("fuchsia-pkg".to_string()),
}
]),
stop_timeout_ms: Some(9876),
},
fsys::EnvironmentDecl {
name: Some("env".to_string()),
extends: Some(fsys::EnvironmentExtends::Realm),
resolvers: None,
stop_timeout_ms: None,
},
];
let mut decl = new_component_decl();
decl.children = Some(children);
decl.environments = Some(environments);
decl
},
},
test_translate_children => {
input = json!({
"children": [
{
"name": "logger",
"url": "fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm",
"startup": "lazy"
},
{
"name": "echo_server",
"url": "fuchsia-pkg://fuchsia.com/echo_server/stable#meta/echo_server.cm",
"startup": "eager"
}
],
}),
output = {
let children = vec![
fsys::ChildDecl{
name: Some("logger".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm".to_string()),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
},
fsys::ChildDecl{
name: Some("echo_server".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/echo_server/stable#meta/echo_server.cm".to_string()),
startup: Some(fsys::StartupMode::Eager),
environment: None,
},
];
let mut decl = new_component_decl();
decl.children = Some(children);
decl
},
},
test_translate_collections => {
input = json!({
"collections": [
{
"name": "modular",
"durability": "persistent"
},
{
"name": "tests",
"durability": "transient"
}
]
}),
output = {
let collections = vec![
fsys::CollectionDecl{
name: Some("modular".to_string()),
durability: Some(fsys::Durability::Persistent),
},
fsys::CollectionDecl{
name: Some("tests".to_string()),
durability: Some(fsys::Durability::Transient),
},
];
let mut decl = new_component_decl();
decl.collections = Some(collections);
decl
},
},
test_translate_facets => {
input = json!({
"facets": {
"authors": [
"me",
"you"
],
"title": "foo",
"year": 2018
}
}),
output = {
let vector = fsys::Vector{values: vec![
Some(Box::new(fsys::Value::Str("me".to_string()))),
Some(Box::new(fsys::Value::Str("you".to_string()))),
]};
let facets = fsys::Object{entries: vec![
fsys::Entry{
key: "authors".to_string(),
value: Some(Box::new(fsys::Value::Vec(vector))),
},
fsys::Entry{
key: "title".to_string(),
value: Some(Box::new(fsys::Value::Str("foo".to_string()))),
},
fsys::Entry{
key: "year".to_string(),
value: Some(Box::new(fsys::Value::Inum(2018))),
},
]};
let mut decl = new_component_decl();
decl.facets = Some(facets);
decl
},
},
test_translate_storage => {
input = json!({
"storage": [
{
"name": "memfs",
"source": {
"self": {}
},
"source_path": "/memfs"
}
]
}),
output = {
let storages = vec![
fsys::StorageDecl {
name: Some("memfs".to_string()),
source_path: Some("/memfs".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
},
];
let mut decl = new_component_decl();
decl.storage = Some(storages);
decl
},
},
test_translate_runners => {
input = json!({
"runners": [
{
"name": "elf",
"source": {
"self": {}
},
"source_path": "/elf"
}
]
}),
output = {
let runners = vec![
fsys::RunnerDecl {
name: Some("elf".to_string()),
source_path: Some("/elf".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
},
];
let mut decl = new_component_decl();
decl.runners = Some(runners);
decl
},
},
test_translate_resolvers => {
input = json!({
"resolvers": [
{
"name": "pkg_resolver",
"source_path": "/resolver",
},
]
}),
output = {
let resolvers = vec![
fsys::ResolverDecl {
name: Some("pkg_resolver".to_string()),
source_path: Some("/resolver".to_string()),
},
];
let mut decl = new_component_decl();
decl.resolvers = Some(resolvers);
decl
},
},
test_translate_all_sections => {
input = json!({
"program": {
"binary": "bin/app"
},
"uses": [
{
"service": {
"source": {
"realm": {}
},
"source_path": "/fonts/CoolFonts",
"target_path": "/svc/fuchsia.fonts.Provider",
}
}
],
"exposes": [
{
"directory": {
"source": {
"self": {}
},
"source_path": "/volumes/blobfs",
"target_path": "/volumes/blobfs",
"target": "realm",
"rights": ["connect"]
}
}
],
"offers": [
{
"service": {
"source": {
"child": {
"name": "logger"
}
},
"source_path": "/svc/fuchsia.logger.Log",
"target": {
"child": {
"name": "netstack"
}
},
"target_path": "/svc/fuchsia.logger.Log"
}
}
],
"children": [
{
"name": "logger",
"url": "fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm",
"startup": "lazy"
},
{
"name": "netstack",
"url": "fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm",
"startup": "eager"
}
],
"collections": [
{
"name": "modular",
"durability": "persistent"
}
],
"facets": {
"author": "Fuchsia",
"year": 2018
},
"storage": [
{
"name": "memfs",
"source_path": "/memfs",
"source": {
"self": {}
}
}
],
"runners": [
{
"name": "elf",
"source": {
"self": {}
},
"source_path": "/elf"
}
],
"environments": [
{
"name": "test_env",
"extends": "realm",
"resolvers": [
{
"resolver": "pkg_resolver",
"source": {
"realm": {},
},
"scheme": "fuchsia-pkg",
}
]
}
],
"resolvers": [
{
"name": "pkg_resolver",
"source_path": "/resolver",
}
],
}),
output = {
let program = fdata::Dictionary {entries: Some(vec![
fdata::DictionaryEntry {
key: "binary".to_string(),
value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
},
])};
let uses = vec![
fsys::UseDecl::Service(fsys::UseServiceDecl {
source: Some(fsys::Ref::Realm(fsys::RealmRef {})),
source_path: Some("/fonts/CoolFonts".to_string()),
target_path: Some("/svc/fuchsia.fonts.Provider".to_string()),
}),
];
let exposes = vec![
fsys::ExposeDecl::Directory(fsys::ExposeDirectoryDecl {
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
source_path: Some("/volumes/blobfs".to_string()),
target_path: Some("/volumes/blobfs".to_string()),
target: Some(fsys::Ref::Realm(fsys::RealmRef {})),
rights: Some(fio2::Operations::Connect),
subdir: None,
}),
];
let offers = vec![
fsys::OfferDecl::Service(fsys::OfferServiceDecl {
source: Some(fsys::Ref::Child(fsys::ChildRef {
name: "logger".to_string(),
collection: None,
})),
source_path: Some("/svc/fuchsia.logger.Log".to_string()),
target: Some(fsys::Ref::Child(
fsys::ChildRef {
name: "netstack".to_string(),
collection: None,
}
)),
target_path: Some("/svc/fuchsia.logger.Log".to_string()),
}),
];
let children = vec![
fsys::ChildDecl {
name: Some("logger".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm".to_string()),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
},
fsys::ChildDecl {
name: Some("netstack".to_string()),
url: Some("fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm".to_string()),
startup: Some(fsys::StartupMode::Eager),
environment: None,
},
];
let collections = vec![
fsys::CollectionDecl {
name: Some("modular".to_string()),
durability: Some(fsys::Durability::Persistent),
},
];
let facets = fsys::Object {entries: vec![
fsys::Entry {
key: "author".to_string(),
value: Some(Box::new(fsys::Value::Str("Fuchsia".to_string()))),
},
fsys::Entry {
key: "year".to_string(),
value: Some(Box::new(fsys::Value::Inum(2018))),
},
]};
let storages = vec![
fsys::StorageDecl {
name: Some("memfs".to_string()),
source_path: Some("/memfs".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
},
];
let runners = vec![
fsys::RunnerDecl {
name: Some("elf".to_string()),
source: Some(fsys::Ref::Self_(fsys::SelfRef{})),
source_path: Some("/elf".to_string()),
},
];
let environments = vec![
fsys::EnvironmentDecl {
name: Some("test_env".to_string()),
extends: Some(fsys::EnvironmentExtends::Realm),
resolvers: Some(vec![
fsys::ResolverRegistration {
resolver: Some("pkg_resolver".to_string()),
source: Some(fsys::Ref::Realm(fsys::RealmRef{})),
scheme: Some("fuchsia-pkg".to_string()),
}
]),
stop_timeout_ms: None,
}
];
let resolvers = vec![
fsys::ResolverDecl {
name: Some("pkg_resolver".to_string()),
source_path: Some("/resolver".to_string()),
}
];
fsys::ComponentDecl {
program: Some(program),
uses: Some(uses),
exposes: Some(exposes),
offers: Some(offers),
children: Some(children),
collections: Some(collections),
facets: Some(facets),
storage: Some(storages),
runners: Some(runners),
environments: Some(environments),
resolvers: Some(resolvers),
}
},
},
}
}