1use cm_rust_derive::{ExposeDeclCommon, ExposeDeclCommonAlwaysRequired, FidlDecl};
6use cm_types::{AllowedOffers, BorrowedSeparatedPath, LongName, Name, Path, RelativePath, Url};
7use directed_graph::DirectedGraph;
8use fidl_fuchsia_component_decl as fdecl;
9use fidl_fuchsia_data as fdata;
10use fidl_fuchsia_io as fio;
11use fidl_fuchsia_process as fprocess;
12use fidl_fuchsia_sys2 as fsys;
13use from_enum::FromEnum;
14use std::collections::{BTreeMap, HashMap};
15use std::hash::Hash;
16use std::sync::LazyLock;
17use std::{fmt, mem};
18use strum_macros::EnumIter;
19use thiserror::Error;
20
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24#[cfg(feature = "serde")]
25mod serde_ext;
26
27pub mod capability;
28pub mod config;
29pub mod offer;
30pub mod r#use;
31
32pub use crate::capability::*;
33pub use crate::config::*;
34#[allow(unused_imports)]
35pub use crate::offer::*; pub use crate::r#use::*;
37
38pub trait FidlIntoNative<T> {
40 fn fidl_into_native(self) -> T;
41}
42
43impl<Native, Fidl> FidlIntoNative<Box<[Native]>> for Vec<Fidl>
44where
45 Fidl: FidlIntoNative<Native>,
46{
47 fn fidl_into_native(self) -> Box<[Native]> {
48 IntoIterator::into_iter(self).map(|s| s.fidl_into_native()).collect()
49 }
50}
51
52pub trait NativeIntoFidl<T> {
53 fn native_into_fidl(self) -> T;
54}
55
56impl<Native, Fidl> NativeIntoFidl<Vec<Fidl>> for Box<[Native]>
57where
58 Native: NativeIntoFidl<Fidl>,
59{
60 fn native_into_fidl(self) -> Vec<Fidl> {
61 IntoIterator::into_iter(self).map(|s| s.native_into_fidl()).collect()
62 }
63}
64
65impl FidlIntoNative<Name> for String {
66 fn fidl_into_native(self) -> Name {
67 self.parse().unwrap()
69 }
70}
71
72impl NativeIntoFidl<String> for Name {
73 fn native_into_fidl(self) -> String {
74 self.to_string()
75 }
76}
77
78impl FidlIntoNative<LongName> for String {
79 fn fidl_into_native(self) -> LongName {
80 self.parse().unwrap()
82 }
83}
84
85impl NativeIntoFidl<String> for LongName {
86 fn native_into_fidl(self) -> String {
87 self.to_string()
88 }
89}
90
91impl FidlIntoNative<Path> for String {
92 fn fidl_into_native(self) -> Path {
93 self.parse().unwrap()
95 }
96}
97
98impl NativeIntoFidl<String> for Path {
99 fn native_into_fidl(self) -> String {
100 self.to_string()
101 }
102}
103
104impl FidlIntoNative<RelativePath> for String {
105 fn fidl_into_native(self) -> RelativePath {
106 self.parse().unwrap()
108 }
109}
110
111impl NativeIntoFidl<String> for RelativePath {
112 fn native_into_fidl(self) -> String {
113 self.to_string()
114 }
115}
116
117impl NativeIntoFidl<Option<String>> for RelativePath {
118 fn native_into_fidl(self) -> Option<String> {
119 if self.is_dot() { None } else { Some(self.to_string()) }
120 }
121}
122
123impl FidlIntoNative<Url> for String {
124 fn fidl_into_native(self) -> Url {
125 self.parse().unwrap()
127 }
128}
129
130impl NativeIntoFidl<String> for Url {
131 fn native_into_fidl(self) -> String {
132 self.to_string()
133 }
134}
135
136impl<F, N> FidlIntoNative<Box<N>> for F
137where
138 F: FidlIntoNative<N>,
139{
140 fn fidl_into_native(self) -> Box<N> {
141 Box::new(self.fidl_into_native())
142 }
143}
144
145impl<N, F> NativeIntoFidl<F> for Box<N>
146where
147 N: NativeIntoFidl<F>,
148{
149 fn native_into_fidl(self) -> F {
150 (*self).native_into_fidl()
151 }
152}
153
154macro_rules! fidl_translations_identical {
156 ($into_type:ty) => {
157 impl FidlIntoNative<$into_type> for $into_type {
158 fn fidl_into_native(self) -> $into_type {
159 self
160 }
161 }
162 impl NativeIntoFidl<$into_type> for $into_type {
163 fn native_into_fidl(self) -> Self {
164 self
165 }
166 }
167 };
168}
169
170macro_rules! fidl_translations_from_into {
173 ($native_type:ty, $fidl_type:ty) => {
174 impl FidlIntoNative<$native_type> for $fidl_type {
175 fn fidl_into_native(self) -> $native_type {
176 self.into()
177 }
178 }
179 impl NativeIntoFidl<$fidl_type> for $native_type {
180 fn native_into_fidl(self) -> $fidl_type {
181 self.into()
182 }
183 }
184 };
185}
186
187macro_rules! fidl_translations_symmetrical_enums {
193($fidl_type:ty , $native_type:ty, $($variant: ident),*) => {
194 impl FidlIntoNative<$native_type> for $fidl_type {
195 fn fidl_into_native(self) -> $native_type {
196 match self {
197 $( <$fidl_type>::$variant => <$native_type>::$variant, )*
198 }
199 }
200 }
201 impl NativeIntoFidl<$fidl_type> for $native_type {
202 fn native_into_fidl(self) -> $fidl_type {
203 match self {
204 $( <$native_type>::$variant => <$fidl_type>::$variant, )*
205 }
206 }
207 }
208 };
209}
210
211#[derive(FidlDecl, Debug, Clone, PartialEq, Default)]
212#[fidl_decl(fidl_table = "fdecl::Component")]
213pub struct ComponentDecl {
214 pub program: Option<ProgramDecl>,
215 pub uses: Box<[UseDecl]>,
216 pub exposes: Box<[ExposeDecl]>,
217 pub offers: Box<[OfferDecl]>,
218 pub capabilities: Box<[CapabilityDecl]>,
219 pub children: Box<[ChildDecl]>,
220 pub collections: Box<[CollectionDecl]>,
221 pub facets: Option<fdata::Dictionary>,
222 pub environments: Box<[EnvironmentDecl]>,
223 pub config: Option<ConfigDecl>,
224 #[cfg(fuchsia_api_level_at_least = "31")]
225 pub debug_info: Option<DebugInfo>,
226}
227
228impl ComponentDecl {
229 #[cfg(fuchsia_api_level_at_least = "HEAD")]
231 pub fn get_runner(&self) -> Option<UseRunnerDecl> {
232 self.program
233 .as_ref()
234 .and_then(|p| p.runner.as_ref())
235 .map(|r| UseRunnerDecl {
236 source: UseSource::Environment,
237 source_name: r.clone(),
238 source_dictionary: Default::default(),
239 })
240 .or_else(|| {
241 self.uses.iter().find_map(|u| match u {
242 UseDecl::Runner(r) => Some(r.clone()),
243 _ => None,
244 })
245 })
246 }
247
248 pub fn find_storage_source<'a>(&'a self, storage_name: &Name) -> Option<&'a StorageDecl> {
250 self.capabilities.iter().find_map(|c| match c {
251 CapabilityDecl::Storage(s) if &s.name == storage_name => Some(s),
252 _ => None,
253 })
254 }
255
256 pub fn find_protocol_source<'a>(&'a self, protocol_name: &Name) -> Option<&'a ProtocolDecl> {
258 self.capabilities.iter().find_map(|c| match c {
259 CapabilityDecl::Protocol(r) if &r.name == protocol_name => Some(r),
260 _ => None,
261 })
262 }
263
264 pub fn find_directory_source<'a>(&'a self, directory_name: &Name) -> Option<&'a DirectoryDecl> {
266 self.capabilities.iter().find_map(|c| match c {
267 CapabilityDecl::Directory(r) if &r.name == directory_name => Some(r),
268 _ => None,
269 })
270 }
271
272 pub fn find_runner_source<'a>(&'a self, runner_name: &Name) -> Option<&'a RunnerDecl> {
274 self.capabilities.iter().find_map(|c| match c {
275 CapabilityDecl::Runner(r) if &r.name == runner_name => Some(r),
276 _ => None,
277 })
278 }
279
280 pub fn find_resolver_source<'a>(&'a self, resolver_name: &Name) -> Option<&'a ResolverDecl> {
282 self.capabilities.iter().find_map(|c| match c {
283 CapabilityDecl::Resolver(r) if &r.name == resolver_name => Some(r),
284 _ => None,
285 })
286 }
287
288 pub fn find_collection<'a>(&'a self, collection_name: &str) -> Option<&'a CollectionDecl> {
290 self.collections.iter().find(|c| c.name == collection_name)
291 }
292
293 pub fn is_protocol_exposed_to_framework(&self, in_target_name: &Name) -> bool {
295 self.exposes.iter().any(|expose| match expose {
296 ExposeDecl::Protocol(ExposeProtocolDecl { target, target_name, .. })
297 if target == &ExposeTarget::Framework =>
298 {
299 target_name == in_target_name
300 }
301 _ => false,
302 })
303 }
304
305 pub fn uses_protocol(&self, source_name: &Name) -> bool {
307 self.uses.iter().any(|use_decl| match use_decl {
308 UseDecl::Protocol(ls) => &ls.source_name == source_name,
309 _ => false,
310 })
311 }
312}
313
314pub use cm_types::Availability;
315
316fidl_translations_symmetrical_enums!(
317 fdecl::Availability,
318 Availability,
319 Required,
320 Optional,
321 SameAsTarget,
322 Transitional
323);
324
325pub use cm_types::DeliveryType;
326
327#[cfg(fuchsia_api_level_at_least = "HEAD")]
328impl FidlIntoNative<DeliveryType> for fdecl::DeliveryType {
329 fn fidl_into_native(self) -> DeliveryType {
330 self.try_into().unwrap()
331 }
332}
333
334#[cfg(fuchsia_api_level_at_least = "HEAD")]
335impl NativeIntoFidl<fdecl::DeliveryType> for DeliveryType {
336 fn native_into_fidl(self) -> fdecl::DeliveryType {
337 self.into()
338 }
339}
340
341pub trait SourcePath {
342 fn source_path(&self) -> BorrowedSeparatedPath<'_>;
343 fn is_from_dictionary(&self) -> bool {
344 !self.source_path().dirname.is_dot()
345 }
346}
347
348#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
349#[derive(Debug, Clone, PartialEq, Eq)]
350pub struct NameMapping {
351 pub source_name: Name,
352 pub target_name: Name,
353}
354
355impl NativeIntoFidl<fdecl::NameMapping> for NameMapping {
356 fn native_into_fidl(self) -> fdecl::NameMapping {
357 fdecl::NameMapping {
358 source_name: self.source_name.native_into_fidl(),
359 target_name: self.target_name.native_into_fidl(),
360 }
361 }
362}
363
364impl FidlIntoNative<NameMapping> for fdecl::NameMapping {
365 fn fidl_into_native(self) -> NameMapping {
366 NameMapping {
367 source_name: self.source_name.fidl_into_native(),
368 target_name: self.target_name.fidl_into_native(),
369 }
370 }
371}
372
373#[cfg_attr(
374 feature = "serde",
375 derive(Deserialize, Serialize),
376 serde(tag = "type", rename_all = "snake_case")
377)]
378#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
379#[fidl_decl(fidl_union = "fdecl::Expose")]
380pub enum ExposeDecl {
381 Service(ExposeServiceDecl),
382 Protocol(ExposeProtocolDecl),
383 Directory(ExposeDirectoryDecl),
384 Runner(ExposeRunnerDecl),
385 Resolver(ExposeResolverDecl),
386 Dictionary(ExposeDictionaryDecl),
387 Config(ExposeConfigurationDecl),
388}
389
390impl SourceName for ExposeDecl {
391 fn source_name(&self) -> &Name {
392 match self {
393 Self::Service(e) => e.source_name(),
394 Self::Protocol(e) => e.source_name(),
395 Self::Directory(e) => e.source_name(),
396 Self::Runner(e) => e.source_name(),
397 Self::Resolver(e) => e.source_name(),
398 Self::Dictionary(e) => e.source_name(),
399 Self::Config(e) => e.source_name(),
400 }
401 }
402}
403
404impl SourcePath for ExposeDecl {
405 fn source_path(&self) -> BorrowedSeparatedPath<'_> {
406 match self {
407 Self::Service(e) => e.source_path(),
408 Self::Protocol(e) => e.source_path(),
409 Self::Directory(e) => e.source_path(),
410 Self::Runner(e) => e.source_path(),
411 Self::Resolver(e) => e.source_path(),
412 Self::Dictionary(e) => e.source_path(),
413 Self::Config(e) => e.source_path(),
414 }
415 }
416}
417
418impl ExposeDeclCommon for ExposeDecl {
419 fn source(&self) -> &ExposeSource {
420 match self {
421 Self::Service(e) => e.source(),
422 Self::Protocol(e) => e.source(),
423 Self::Directory(e) => e.source(),
424 Self::Runner(e) => e.source(),
425 Self::Resolver(e) => e.source(),
426 Self::Dictionary(e) => e.source(),
427 Self::Config(e) => e.source(),
428 }
429 }
430
431 fn target(&self) -> &ExposeTarget {
432 match self {
433 Self::Service(e) => e.target(),
434 Self::Protocol(e) => e.target(),
435 Self::Directory(e) => e.target(),
436 Self::Runner(e) => e.target(),
437 Self::Resolver(e) => e.target(),
438 Self::Dictionary(e) => e.target(),
439 Self::Config(e) => e.target(),
440 }
441 }
442
443 fn target_name(&self) -> &Name {
444 match self {
445 Self::Service(e) => e.target_name(),
446 Self::Protocol(e) => e.target_name(),
447 Self::Directory(e) => e.target_name(),
448 Self::Runner(e) => e.target_name(),
449 Self::Resolver(e) => e.target_name(),
450 Self::Dictionary(e) => e.target_name(),
451 Self::Config(e) => e.target_name(),
452 }
453 }
454
455 fn availability(&self) -> &Availability {
456 match self {
457 Self::Service(e) => e.availability(),
458 Self::Protocol(e) => e.availability(),
459 Self::Directory(e) => e.availability(),
460 Self::Runner(e) => e.availability(),
461 Self::Resolver(e) => e.availability(),
462 Self::Dictionary(e) => e.availability(),
463 Self::Config(e) => e.availability(),
464 }
465 }
466}
467
468#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
469#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
470#[fidl_decl(fidl_table = "fdecl::ExposeService", source_path = "dictionary")]
471pub struct ExposeServiceDecl {
472 pub source: ExposeSource,
473 pub source_name: Name,
474 #[fidl_decl(default_preserve_none)]
475 pub source_dictionary: RelativePath,
476 pub target: ExposeTarget,
477 pub target_name: Name,
478 #[fidl_decl(default)]
479 pub availability: Availability,
480}
481
482#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
483#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
484#[fidl_decl(fidl_table = "fdecl::ExposeProtocol", source_path = "dictionary")]
485pub struct ExposeProtocolDecl {
486 pub source: ExposeSource,
487 pub source_name: Name,
488 #[fidl_decl(default_preserve_none)]
489 pub source_dictionary: RelativePath,
490 pub target: ExposeTarget,
491 pub target_name: Name,
492 #[fidl_decl(default)]
493 pub availability: Availability,
494}
495
496#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
497#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
498#[fidl_decl(fidl_table = "fdecl::ExposeDirectory", source_path = "dictionary")]
499pub struct ExposeDirectoryDecl {
500 pub source: ExposeSource,
501 pub source_name: Name,
502 #[fidl_decl(default_preserve_none)]
503 pub source_dictionary: RelativePath,
504 pub target: ExposeTarget,
505 pub target_name: Name,
506
507 #[cfg_attr(
508 feature = "serde",
509 serde(
510 deserialize_with = "serde_ext::deserialize_opt_fio_operations",
511 serialize_with = "serde_ext::serialize_opt_fio_operations"
512 )
513 )]
514 pub rights: Option<fio::Operations>,
515
516 #[fidl_decl(default_preserve_none)]
517 pub subdir: RelativePath,
518
519 #[fidl_decl(default)]
520 pub availability: Availability,
521}
522
523#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
524#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
525#[fidl_decl(fidl_table = "fdecl::ExposeRunner", source_path = "dictionary")]
526pub struct ExposeRunnerDecl {
527 pub source: ExposeSource,
528 pub source_name: Name,
529 #[fidl_decl(default_preserve_none)]
530 pub source_dictionary: RelativePath,
531 pub target: ExposeTarget,
532 pub target_name: Name,
533}
534
535#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
536#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
537#[fidl_decl(fidl_table = "fdecl::ExposeResolver", source_path = "dictionary")]
538pub struct ExposeResolverDecl {
539 pub source: ExposeSource,
540 pub source_name: Name,
541 #[fidl_decl(default_preserve_none)]
542 pub source_dictionary: RelativePath,
543 pub target: ExposeTarget,
544 pub target_name: Name,
545}
546
547#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
548#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
549#[fidl_decl(fidl_table = "fdecl::ExposeDictionary", source_path = "dictionary")]
550pub struct ExposeDictionaryDecl {
551 pub source: ExposeSource,
552 pub source_name: Name,
553 #[fidl_decl(default_preserve_none)]
554 pub source_dictionary: RelativePath,
555 pub target: ExposeTarget,
556 pub target_name: Name,
557 #[fidl_decl(default)]
558 pub availability: Availability,
559}
560
561#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
562#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
563#[fidl_decl(fidl_table = "fdecl::ExposeConfiguration", source_path = "name_only")]
564pub struct ExposeConfigurationDecl {
565 pub source: ExposeSource,
566 pub source_name: Name,
567 pub target: ExposeTarget,
568 pub target_name: Name,
569 #[fidl_decl(default_preserve_none)]
570 pub source_dictionary: RelativePath,
571 #[fidl_decl(default)]
572 pub availability: Availability,
573}
574
575#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
576#[fidl_decl(fidl_table = "fdecl::Child")]
577pub struct ChildDecl {
578 pub name: LongName,
579 pub url: Url,
580 pub startup: fdecl::StartupMode,
581 pub on_terminate: Option<fdecl::OnTerminate>,
582 pub environment: Option<Name>,
583 pub config_overrides: Option<Box<[ConfigOverride]>>,
584}
585
586#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
588pub struct ChildRef {
589 pub name: LongName,
590 pub collection: Option<Name>,
591}
592
593impl std::fmt::Display for ChildRef {
594 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
595 if let Some(collection) = &self.collection {
596 write!(f, "{}:{}", collection, self.name)
597 } else {
598 write!(f, "{}", self.name)
599 }
600 }
601}
602
603impl FidlIntoNative<ChildRef> for fdecl::ChildRef {
604 fn fidl_into_native(self) -> ChildRef {
605 ChildRef {
607 name: self.name.parse().unwrap(),
608 collection: self.collection.map(|c| c.parse().unwrap()),
609 }
610 }
611}
612
613impl NativeIntoFidl<fdecl::ChildRef> for ChildRef {
614 fn native_into_fidl(self) -> fdecl::ChildRef {
615 fdecl::ChildRef {
616 name: self.name.to_string(),
617 collection: self.collection.map(|c| c.to_string()),
618 }
619 }
620}
621
622#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
623#[fidl_decl(fidl_table = "fdecl::Collection")]
624pub struct CollectionDecl {
625 pub name: Name,
626 pub durability: fdecl::Durability,
627 pub environment: Option<Name>,
628
629 #[fidl_decl(default)]
630 pub allowed_offers: AllowedOffers,
631 #[fidl_decl(default)]
632 pub allow_long_names: bool,
633
634 pub persistent_storage: Option<bool>,
635}
636
637#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
638#[fidl_decl(fidl_table = "fdecl::Environment")]
639pub struct EnvironmentDecl {
640 pub name: Name,
641 pub extends: fdecl::EnvironmentExtends,
642 pub runners: Box<[RunnerRegistration]>,
643 pub resolvers: Box<[ResolverRegistration]>,
644 pub debug_capabilities: Box<[DebugRegistration]>,
645 pub stop_timeout_ms: Option<u32>,
646}
647
648#[cfg(fuchsia_api_level_at_least = "31")]
649#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
650#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
651#[fidl_decl(fidl_table = "fdecl::DebugInfo")]
652pub struct DebugInfo {
653 pub manifest_sources: Option<Box<[String]>>,
654}
655
656#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
657#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
658#[fidl_decl(fidl_table = "fdecl::RunnerRegistration")]
659pub struct RunnerRegistration {
660 pub source_name: Name,
661 pub target_name: Name,
662 pub source: RegistrationSource,
663}
664
665impl SourceName for RunnerRegistration {
666 fn source_name(&self) -> &Name {
667 &self.source_name
668 }
669}
670
671impl RegistrationDeclCommon for RunnerRegistration {
672 const TYPE: &'static str = "runner";
673
674 fn source(&self) -> &RegistrationSource {
675 &self.source
676 }
677}
678
679#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
680#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
681#[fidl_decl(fidl_table = "fdecl::ResolverRegistration")]
682pub struct ResolverRegistration {
683 pub resolver: Name,
684 pub source: RegistrationSource,
685 pub scheme: String,
686}
687
688impl SourceName for ResolverRegistration {
689 fn source_name(&self) -> &Name {
690 &self.resolver
691 }
692}
693
694impl RegistrationDeclCommon for ResolverRegistration {
695 const TYPE: &'static str = "resolver";
696
697 fn source(&self) -> &RegistrationSource {
698 &self.source
699 }
700}
701
702#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
703#[fidl_decl(fidl_union = "fdecl::DebugRegistration")]
704pub enum DebugRegistration {
705 Protocol(DebugProtocolRegistration),
706}
707
708impl RegistrationDeclCommon for DebugRegistration {
709 const TYPE: &'static str = "debug_protocol";
710
711 fn source(&self) -> &RegistrationSource {
712 match self {
713 DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source,
714 }
715 }
716}
717
718impl SourceName for DebugRegistration {
719 fn source_name(&self) -> &Name {
720 match self {
721 DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source_name,
722 }
723 }
724}
725
726#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
727#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
728#[fidl_decl(fidl_table = "fdecl::DebugProtocolRegistration")]
729pub struct DebugProtocolRegistration {
730 pub source_name: Name,
731 pub source: RegistrationSource,
732 pub target_name: Name,
733}
734
735#[derive(FidlDecl, Debug, Clone, PartialEq)]
736#[fidl_decl(fidl_table = "fdecl::Program")]
737pub struct ProgramDecl {
738 pub runner: Option<Name>,
739 pub info: fdata::Dictionary,
740}
741
742impl Default for ProgramDecl {
743 fn default() -> Self {
744 Self { runner: None, info: fdata::Dictionary::default() }
745 }
746}
747
748fidl_translations_identical!([u8; 32]);
749fidl_translations_identical!(u8);
750fidl_translations_identical!(u16);
751fidl_translations_identical!(u32);
752fidl_translations_identical!(u64);
753fidl_translations_identical!(i8);
754fidl_translations_identical!(i16);
755fidl_translations_identical!(i32);
756fidl_translations_identical!(i64);
757fidl_translations_identical!(bool);
758fidl_translations_identical!(String);
759fidl_translations_identical!(Vec<Name>);
760fidl_translations_identical!(fdecl::StartupMode);
761fidl_translations_identical!(fdecl::OnTerminate);
762fidl_translations_identical!(fdecl::Durability);
763fidl_translations_identical!(fdata::Dictionary);
764fidl_translations_identical!(fio::Operations);
765fidl_translations_identical!(fdecl::EnvironmentExtends);
766fidl_translations_identical!(fdecl::StorageId);
767fidl_translations_identical!(Vec<fprocess::HandleInfo>);
768fidl_translations_identical!(fsys::ServiceInstance);
769fidl_translations_from_into!(cm_types::AllowedOffers, fdecl::AllowedOffers);
770
771#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
772#[derive(Debug, Clone, PartialEq, Eq)]
773pub enum DependencyType {
774 Strong,
775 Weak,
776}
777
778impl Default for DependencyType {
779 fn default() -> Self {
780 Self::Strong
781 }
782}
783
784fidl_translations_symmetrical_enums!(fdecl::DependencyType, DependencyType, Strong, Weak);
785
786impl UseDecl {
787 pub fn path(&self) -> Option<&Path> {
788 match self {
789 UseDecl::Service(d) => Some(&d.target_path),
790 UseDecl::Protocol(d) => d.target_path.as_ref(),
791 UseDecl::Directory(d) => Some(&d.target_path),
792 UseDecl::Storage(d) => Some(&d.target_path),
793 UseDecl::EventStream(d) => Some(&d.target_path),
794 #[cfg(fuchsia_api_level_at_least = "HEAD")]
795 UseDecl::Runner(_) => None,
796 UseDecl::Config(_) => None,
797 #[cfg(fuchsia_api_level_at_least = "29")]
798 UseDecl::Dictionary(d) => Some(&d.target_path),
799 }
800 }
801
802 pub fn name(&self) -> Option<&Name> {
803 match self {
804 UseDecl::Storage(storage_decl) => Some(&storage_decl.source_name),
805 UseDecl::EventStream(_) => None,
806 UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Directory(_) => None,
807 #[cfg(fuchsia_api_level_at_least = "HEAD")]
808 UseDecl::Runner(_) => None,
809 UseDecl::Config(_) => None,
810 #[cfg(fuchsia_api_level_at_least = "29")]
811 UseDecl::Dictionary(_) => None,
812 }
813 }
814}
815
816impl SourceName for UseDecl {
817 fn source_name(&self) -> &Name {
818 match self {
819 UseDecl::Storage(storage_decl) => &storage_decl.source_name,
820 UseDecl::Service(service_decl) => &service_decl.source_name,
821 UseDecl::Protocol(protocol_decl) => &protocol_decl.source_name,
822 UseDecl::Directory(directory_decl) => &directory_decl.source_name,
823 UseDecl::EventStream(event_stream_decl) => &event_stream_decl.source_name,
824 #[cfg(fuchsia_api_level_at_least = "HEAD")]
825 UseDecl::Runner(runner_decl) => &runner_decl.source_name,
826 UseDecl::Config(u) => &u.source_name,
827 #[cfg(fuchsia_api_level_at_least = "29")]
828 UseDecl::Dictionary(dictionary_decl) => &dictionary_decl.source_name,
829 }
830 }
831}
832
833impl SourcePath for UseDecl {
834 fn source_path(&self) -> BorrowedSeparatedPath<'_> {
835 match self {
836 UseDecl::Service(u) => u.source_path(),
837 UseDecl::Protocol(u) => u.source_path(),
838 UseDecl::Directory(u) => u.source_path(),
839 UseDecl::Storage(u) => u.source_path(),
840 UseDecl::EventStream(u) => u.source_path(),
841 #[cfg(fuchsia_api_level_at_least = "HEAD")]
842 UseDecl::Runner(u) => u.source_path(),
843 UseDecl::Config(u) => u.source_path(),
844 #[cfg(fuchsia_api_level_at_least = "29")]
845 UseDecl::Dictionary(u) => u.source_path(),
846 }
847 }
848}
849
850pub trait SourceName {
852 fn source_name(&self) -> &Name;
853}
854
855pub trait RegistrationDeclCommon: SourceName + Send + Sync {
857 const TYPE: &'static str;
859 fn source(&self) -> &RegistrationSource;
860}
861
862pub trait ExposeDeclCommon: SourceName + SourcePath + fmt::Debug + Send + Sync {
864 fn target_name(&self) -> &Name;
865 fn target(&self) -> &ExposeTarget;
866 fn source(&self) -> &ExposeSource;
867 fn availability(&self) -> &Availability;
868}
869
870#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
874#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
875pub enum CapabilityTypeName {
876 Directory,
877 EventStream,
878 Protocol,
879 Resolver,
880 Runner,
881 Service,
882 Storage,
883 Dictionary,
884 Config,
885}
886
887impl std::str::FromStr for CapabilityTypeName {
888 type Err = Error;
889
890 fn from_str(s: &str) -> Result<Self, Self::Err> {
891 match s {
892 "directory" => Ok(CapabilityTypeName::Directory),
893 "event_stream" => Ok(CapabilityTypeName::EventStream),
894 "protocol" => Ok(CapabilityTypeName::Protocol),
895 "resolver" => Ok(CapabilityTypeName::Resolver),
896 "runner" => Ok(CapabilityTypeName::Runner),
897 "service" => Ok(CapabilityTypeName::Service),
898 "storage" => Ok(CapabilityTypeName::Storage),
899 "dictionary" => Ok(CapabilityTypeName::Dictionary),
900 "configuration" => Ok(CapabilityTypeName::Config),
901 _ => Err(Error::ParseCapabilityTypeName { raw: s.to_string() }),
902 }
903 }
904}
905
906impl FidlIntoNative<CapabilityTypeName> for String {
907 fn fidl_into_native(self) -> CapabilityTypeName {
908 self.parse().unwrap()
909 }
910}
911
912impl NativeIntoFidl<String> for CapabilityTypeName {
913 fn native_into_fidl(self) -> String {
914 self.to_string()
915 }
916}
917
918impl AsRef<str> for CapabilityTypeName {
919 fn as_ref(&self) -> &str {
920 match self {
921 CapabilityTypeName::Directory => "directory",
922 CapabilityTypeName::EventStream => "event_stream",
923 CapabilityTypeName::Protocol => "protocol",
924 CapabilityTypeName::Resolver => "resolver",
925 CapabilityTypeName::Runner => "runner",
926 CapabilityTypeName::Service => "service",
927 CapabilityTypeName::Storage => "storage",
928 CapabilityTypeName::Dictionary => "dictionary",
929 CapabilityTypeName::Config => "configuration",
930 }
931 }
932}
933
934impl fmt::Display for CapabilityTypeName {
935 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
936 write!(f, "{}", self.as_ref())
937 }
938}
939
940impl From<&UseDecl> for CapabilityTypeName {
941 fn from(use_decl: &UseDecl) -> Self {
942 match use_decl {
943 UseDecl::Service(_) => Self::Service,
944 UseDecl::Protocol(_) => Self::Protocol,
945 UseDecl::Directory(_) => Self::Directory,
946 UseDecl::Storage(_) => Self::Storage,
947 UseDecl::EventStream(_) => Self::EventStream,
948 #[cfg(fuchsia_api_level_at_least = "HEAD")]
949 UseDecl::Runner(_) => Self::Runner,
950 UseDecl::Config(_) => Self::Config,
951 #[cfg(fuchsia_api_level_at_least = "29")]
952 UseDecl::Dictionary(_) => Self::Dictionary,
953 }
954 }
955}
956
957impl From<&ExposeDecl> for CapabilityTypeName {
958 fn from(expose_decl: &ExposeDecl) -> Self {
959 match expose_decl {
960 ExposeDecl::Service(_) => Self::Service,
961 ExposeDecl::Protocol(_) => Self::Protocol,
962 ExposeDecl::Directory(_) => Self::Directory,
963 ExposeDecl::Runner(_) => Self::Runner,
964 ExposeDecl::Resolver(_) => Self::Resolver,
965 ExposeDecl::Dictionary(_) => Self::Dictionary,
966 ExposeDecl::Config(_) => Self::Config,
967 }
968 }
969}
970
971impl From<CapabilityTypeName> for fio::DirentType {
972 fn from(value: CapabilityTypeName) -> Self {
973 match value {
974 CapabilityTypeName::Directory => fio::DirentType::Directory,
975 CapabilityTypeName::EventStream => fio::DirentType::Service,
976 CapabilityTypeName::Protocol => fio::DirentType::Service,
977 CapabilityTypeName::Service => fio::DirentType::Directory,
978 CapabilityTypeName::Storage => fio::DirentType::Directory,
979 CapabilityTypeName::Dictionary => fio::DirentType::Directory,
980 CapabilityTypeName::Resolver => fio::DirentType::Service,
981 CapabilityTypeName::Runner => fio::DirentType::Service,
982 CapabilityTypeName::Config => fio::DirentType::Unknown,
984 }
985 }
986}
987
988impl FidlIntoNative<HashMap<String, DictionaryValue>> for fdata::Dictionary {
990 fn fidl_into_native(self) -> HashMap<String, DictionaryValue> {
991 from_fidl_dict(self)
992 }
993}
994
995impl NativeIntoFidl<fdata::Dictionary> for HashMap<String, DictionaryValue> {
996 fn native_into_fidl(self) -> fdata::Dictionary {
997 to_fidl_dict(self)
998 }
999}
1000
1001impl FidlIntoNative<BTreeMap<String, DictionaryValue>> for fdata::Dictionary {
1002 fn fidl_into_native(self) -> BTreeMap<String, DictionaryValue> {
1003 from_fidl_dict_btree(self)
1004 }
1005}
1006
1007impl NativeIntoFidl<fdata::Dictionary> for BTreeMap<String, DictionaryValue> {
1008 fn native_into_fidl(self) -> fdata::Dictionary {
1009 to_fidl_dict_btree(self)
1010 }
1011}
1012
1013#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1014pub enum DictionaryValue {
1015 Str(String),
1016 StrVec(Vec<String>),
1017 Null,
1018}
1019
1020impl FidlIntoNative<DictionaryValue> for Option<Box<fdata::DictionaryValue>> {
1021 fn fidl_into_native(self) -> DictionaryValue {
1022 match self {
1023 Some(v) => match *v {
1024 fdata::DictionaryValue::Str(s) => DictionaryValue::Str(s),
1025 fdata::DictionaryValue::StrVec(ss) => DictionaryValue::StrVec(ss),
1026 _ => DictionaryValue::Null,
1027 },
1028 None => DictionaryValue::Null,
1029 }
1030 }
1031}
1032
1033impl NativeIntoFidl<Option<Box<fdata::DictionaryValue>>> for DictionaryValue {
1034 fn native_into_fidl(self) -> Option<Box<fdata::DictionaryValue>> {
1035 match self {
1036 DictionaryValue::Str(s) => Some(Box::new(fdata::DictionaryValue::Str(s))),
1037 DictionaryValue::StrVec(ss) => Some(Box::new(fdata::DictionaryValue::StrVec(ss))),
1038 DictionaryValue::Null => None,
1039 }
1040 }
1041}
1042
1043fn from_fidl_dict(dict: fdata::Dictionary) -> HashMap<String, DictionaryValue> {
1044 match dict.entries {
1045 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
1046 _ => HashMap::new(),
1047 }
1048}
1049
1050fn to_fidl_dict(dict: HashMap<String, DictionaryValue>) -> fdata::Dictionary {
1051 fdata::Dictionary {
1052 entries: Some(
1053 dict.into_iter()
1054 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
1055 .collect(),
1056 ),
1057 ..Default::default()
1058 }
1059}
1060
1061fn from_fidl_dict_btree(dict: fdata::Dictionary) -> BTreeMap<String, DictionaryValue> {
1062 match dict.entries {
1063 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
1064 _ => BTreeMap::new(),
1065 }
1066}
1067
1068fn to_fidl_dict_btree(dict: BTreeMap<String, DictionaryValue>) -> fdata::Dictionary {
1069 fdata::Dictionary {
1070 entries: Some(
1071 dict.into_iter()
1072 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
1073 .collect(),
1074 ),
1075 ..Default::default()
1076 }
1077}
1078
1079#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1080#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1081pub enum EventScope {
1082 Child(ChildRef),
1083 Collection(Name),
1084}
1085
1086impl FidlIntoNative<EventScope> for fdecl::Ref {
1087 fn fidl_into_native(self) -> EventScope {
1088 match self {
1089 fdecl::Ref::Child(c) => {
1090 if let Some(_) = c.collection {
1091 panic!("Dynamic children scopes are not supported for EventStreams");
1092 } else {
1093 EventScope::Child(ChildRef { name: c.name.parse().unwrap(), collection: None })
1094 }
1095 }
1096 fdecl::Ref::Collection(collection) => {
1097 EventScope::Collection(collection.name.parse().unwrap())
1099 }
1100 _ => panic!("invalid EventScope variant"),
1101 }
1102 }
1103}
1104
1105impl NativeIntoFidl<fdecl::Ref> for EventScope {
1106 fn native_into_fidl(self) -> fdecl::Ref {
1107 match self {
1108 EventScope::Child(child) => fdecl::Ref::Child(child.native_into_fidl()),
1109 EventScope::Collection(name) => {
1110 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
1111 }
1112 }
1113 }
1114}
1115
1116#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1117#[derive(Debug, Clone, PartialEq, Eq)]
1118pub enum ExposeSource {
1119 Self_,
1120 Child(Name),
1121 Collection(Name),
1122 Framework,
1123 Capability(Name),
1124 Void,
1125}
1126
1127impl std::fmt::Display for ExposeSource {
1128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1129 match self {
1130 Self::Framework => write!(f, "framework"),
1131 Self::Child(c) => write!(f, "child `#{}`", c),
1132 Self::Collection(c) => write!(f, "collection `#{}`", c),
1133 Self::Self_ => write!(f, "self"),
1134 Self::Capability(c) => write!(f, "capability `{}`", c),
1135 Self::Void => write!(f, "void"),
1136 }
1137 }
1138}
1139
1140impl FidlIntoNative<ExposeSource> for fdecl::Ref {
1141 fn fidl_into_native(self) -> ExposeSource {
1142 match self {
1143 fdecl::Ref::Self_(_) => ExposeSource::Self_,
1144 fdecl::Ref::Child(c) => ExposeSource::Child(c.name.parse().unwrap()),
1146 fdecl::Ref::Collection(c) => ExposeSource::Collection(c.name.parse().unwrap()),
1148 fdecl::Ref::Framework(_) => ExposeSource::Framework,
1149 fdecl::Ref::Capability(c) => ExposeSource::Capability(c.name.parse().unwrap()),
1151 fdecl::Ref::VoidType(_) => ExposeSource::Void,
1152 _ => panic!("invalid ExposeSource variant"),
1153 }
1154 }
1155}
1156
1157impl NativeIntoFidl<fdecl::Ref> for ExposeSource {
1158 fn native_into_fidl(self) -> fdecl::Ref {
1159 match self {
1160 ExposeSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1161 ExposeSource::Child(name) => fdecl::Ref::Child(fdecl::ChildRef {
1162 name: name.native_into_fidl(),
1163 collection: None,
1164 }),
1165 ExposeSource::Collection(name) => {
1166 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
1167 }
1168 ExposeSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
1169 ExposeSource::Capability(name) => {
1170 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
1171 }
1172 ExposeSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
1173 }
1174 }
1175}
1176
1177#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1178#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1179pub enum ExposeTarget {
1180 Parent,
1181 Framework,
1182}
1183
1184impl std::fmt::Display for ExposeTarget {
1185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1186 match self {
1187 Self::Framework => write!(f, "framework"),
1188 Self::Parent => write!(f, "parent"),
1189 }
1190 }
1191}
1192
1193impl FidlIntoNative<ExposeTarget> for fdecl::Ref {
1194 fn fidl_into_native(self) -> ExposeTarget {
1195 match self {
1196 fdecl::Ref::Parent(_) => ExposeTarget::Parent,
1197 fdecl::Ref::Framework(_) => ExposeTarget::Framework,
1198 _ => panic!("invalid ExposeTarget variant"),
1199 }
1200 }
1201}
1202
1203impl NativeIntoFidl<fdecl::Ref> for ExposeTarget {
1204 fn native_into_fidl(self) -> fdecl::Ref {
1205 match self {
1206 ExposeTarget::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1207 ExposeTarget::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
1208 }
1209 }
1210}
1211
1212#[derive(Debug, Clone, PartialEq, Eq)]
1214pub struct ServiceSource<T> {
1215 pub source: T,
1217 pub source_name: Name,
1219}
1220
1221#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1222#[derive(Debug, Clone, PartialEq, Eq)]
1223pub enum StorageDirectorySource {
1224 Parent,
1225 Self_,
1226 Child(String),
1227}
1228
1229impl FidlIntoNative<StorageDirectorySource> for fdecl::Ref {
1230 fn fidl_into_native(self) -> StorageDirectorySource {
1231 match self {
1232 fdecl::Ref::Parent(_) => StorageDirectorySource::Parent,
1233 fdecl::Ref::Self_(_) => StorageDirectorySource::Self_,
1234 fdecl::Ref::Child(c) => StorageDirectorySource::Child(c.name),
1235 _ => panic!("invalid StorageDirectorySource variant"),
1236 }
1237 }
1238}
1239
1240impl NativeIntoFidl<fdecl::Ref> for StorageDirectorySource {
1241 fn native_into_fidl(self) -> fdecl::Ref {
1242 match self {
1243 StorageDirectorySource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1244 StorageDirectorySource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1245 StorageDirectorySource::Child(child_name) => {
1246 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
1247 }
1248 }
1249 }
1250}
1251
1252#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1253#[derive(Debug, Clone, PartialEq, Eq)]
1254pub enum DictionarySource {
1255 Parent,
1256 Self_,
1257 Child(ChildRef),
1258}
1259
1260impl FidlIntoNative<DictionarySource> for fdecl::Ref {
1261 fn fidl_into_native(self) -> DictionarySource {
1262 match self {
1263 Self::Parent(_) => DictionarySource::Parent,
1264 Self::Self_(_) => DictionarySource::Self_,
1265 Self::Child(c) => DictionarySource::Child(c.fidl_into_native()),
1266 _ => panic!("invalid DictionarySource variant"),
1267 }
1268 }
1269}
1270
1271impl NativeIntoFidl<fdecl::Ref> for DictionarySource {
1272 fn native_into_fidl(self) -> fdecl::Ref {
1273 match self {
1274 Self::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1275 Self::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1276 Self::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
1277 }
1278 }
1279}
1280
1281#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1282#[derive(Debug, Clone, PartialEq, Eq)]
1283pub enum RegistrationSource {
1284 Parent,
1285 Self_,
1286 Child(String),
1287}
1288
1289impl FidlIntoNative<RegistrationSource> for fdecl::Ref {
1290 fn fidl_into_native(self) -> RegistrationSource {
1291 match self {
1292 fdecl::Ref::Parent(_) => RegistrationSource::Parent,
1293 fdecl::Ref::Self_(_) => RegistrationSource::Self_,
1294 fdecl::Ref::Child(c) => RegistrationSource::Child(c.name),
1295 _ => panic!("invalid RegistrationSource variant"),
1296 }
1297 }
1298}
1299
1300impl NativeIntoFidl<fdecl::Ref> for RegistrationSource {
1301 fn native_into_fidl(self) -> fdecl::Ref {
1302 match self {
1303 RegistrationSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1304 RegistrationSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1305 RegistrationSource::Child(child_name) => {
1306 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
1307 }
1308 }
1309 }
1310}
1311
1312impl TryFrom<fdecl::Component> for ComponentDecl {
1316 type Error = Error;
1317
1318 fn try_from(decl: fdecl::Component) -> Result<Self, Self::Error> {
1319 cm_fidl_validator::validate(&decl, &mut DirectedGraph::new())
1320 .map_err(|err| Error::Validate { err })?;
1321 Ok(decl.fidl_into_native())
1322 }
1323}
1324
1325impl From<ComponentDecl> for fdecl::Component {
1327 fn from(decl: ComponentDecl) -> Self {
1328 decl.native_into_fidl()
1329 }
1330}
1331
1332#[derive(Debug, Error, Clone)]
1334pub enum Error {
1335 #[error("Fidl validation failed: {}", err)]
1336 Validate {
1337 #[source]
1338 err: cm_fidl_validator::error::ErrorList,
1339 },
1340 #[error("Invalid capability path: {}", raw)]
1341 InvalidCapabilityPath { raw: String },
1342 #[error("Invalid capability type name: {}", raw)]
1343 ParseCapabilityTypeName { raw: String },
1344}
1345
1346pub fn push_box<T>(container: &mut Box<[T]>, value: T) {
1349 let boxed = mem::replace(container, Box::from([]));
1350 let mut new_container: Vec<_> = boxed.into();
1351 new_container.push(value);
1352 *container = new_container.into();
1353}
1354
1355pub fn append_box<T>(container: &mut Box<[T]>, other: &mut Vec<T>) {
1358 let boxed = mem::replace(container, Box::from([]));
1359 let mut new_container: Vec<_> = boxed.into();
1360 new_container.append(other);
1361 *container = new_container.into();
1362}
1363
1364#[cfg(test)]
1365mod tests {
1366 use super::*;
1367 use difference::Changeset;
1368 use fidl_fuchsia_component_decl as fdecl;
1369
1370 fn offer_source_static_child(name: &str) -> OfferSource {
1371 OfferSource::Child(ChildRef { name: name.parse().unwrap(), collection: None })
1372 }
1373
1374 fn offer_target_static_child(name: &str) -> OfferTarget {
1375 OfferTarget::Child(ChildRef { name: name.parse().unwrap(), collection: None })
1376 }
1377
1378 macro_rules! test_try_from_decl {
1379 (
1380 $(
1381 $test_name:ident => {
1382 input = $input:expr,
1383 result = $result:expr,
1384 },
1385 )+
1386 ) => {
1387 $(
1388 #[test]
1389 fn $test_name() {
1390 {
1391 let res = ComponentDecl::try_from($input).expect("try_from failed");
1392 if res != $result {
1393 let a = format!("{:#?}", res);
1394 let e = format!("{:#?}", $result);
1395 panic!("Conversion from fidl to cm_rust did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
1396 }
1397 }
1398 {
1399 let res = fdecl::Component::try_from($result).expect("try_from failed");
1400 if res != $input {
1401 let a = format!("{:#?}", res);
1402 let e = format!("{:#?}", $input);
1403 panic!("Conversion from cm_rust to fidl did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
1404 }
1405 }
1406 }
1407 )+
1408 }
1409 }
1410
1411 macro_rules! test_fidl_into_and_from {
1412 (
1413 $(
1414 $test_name:ident => {
1415 input = $input:expr,
1416 input_type = $input_type:ty,
1417 result = $result:expr,
1418 result_type = $result_type:ty,
1419 },
1420 )+
1421 ) => {
1422 $(
1423 #[test]
1424 fn $test_name() {
1425 {
1426 let res: Vec<$result_type> =
1427 $input.into_iter().map(|e| e.fidl_into_native()).collect();
1428 assert_eq!(res, $result);
1429 }
1430 {
1431 let res: Vec<$input_type> =
1432 $result.into_iter().map(|e| e.native_into_fidl()).collect();
1433 assert_eq!(res, $input);
1434 }
1435 }
1436 )+
1437 }
1438 }
1439
1440 macro_rules! test_fidl_into {
1441 (
1442 $(
1443 $test_name:ident => {
1444 input = $input:expr,
1445 result = $result:expr,
1446 },
1447 )+
1448 ) => {
1449 $(
1450 #[test]
1451 fn $test_name() {
1452 test_fidl_into_helper($input, $result);
1453 }
1454 )+
1455 }
1456 }
1457
1458 fn test_fidl_into_helper<T, U>(input: T, expected_res: U)
1459 where
1460 T: FidlIntoNative<U>,
1461 U: std::cmp::PartialEq + std::fmt::Debug,
1462 {
1463 let res: U = input.fidl_into_native();
1464 assert_eq!(res, expected_res);
1465 }
1466
1467 test_try_from_decl! {
1468 try_from_empty => {
1469 input = fdecl::Component {
1470 program: None,
1471 uses: None,
1472 exposes: None,
1473 offers: None,
1474 capabilities: None,
1475 children: None,
1476 collections: None,
1477 facets: None,
1478 environments: None,
1479 ..Default::default()
1480 },
1481 result = ComponentDecl {
1482 program: None,
1483 uses: Box::from([]),
1484 exposes: Box::from([]),
1485 offers: Box::from([]),
1486 capabilities: Box::from([]),
1487 children: Box::from([]),
1488 collections: Box::from([]),
1489 facets: None,
1490 environments: Box::from([]),
1491 config: None,
1492 debug_info: None,
1493 },
1494 },
1495 try_from_all => {
1496 input = fdecl::Component {
1497 program: Some(fdecl::Program {
1498 runner: Some("elf".to_string()),
1499 info: Some(fdata::Dictionary {
1500 entries: Some(vec![
1501 fdata::DictionaryEntry {
1502 key: "args".to_string(),
1503 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
1504 },
1505 fdata::DictionaryEntry {
1506 key: "binary".to_string(),
1507 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
1508 },
1509 ]),
1510 ..Default::default()
1511 }),
1512 ..Default::default()
1513 }),
1514 uses: Some(vec![
1515 fdecl::Use::Service(fdecl::UseService {
1516 dependency_type: Some(fdecl::DependencyType::Strong),
1517 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1518 source_name: Some("netstack".to_string()),
1519 source_dictionary: Some("in/dict".to_string()),
1520 target_path: Some("/svc/mynetstack".to_string()),
1521 availability: Some(fdecl::Availability::Required),
1522 ..Default::default()
1523 }),
1524 fdecl::Use::Protocol(fdecl::UseProtocol {
1525 dependency_type: Some(fdecl::DependencyType::Strong),
1526 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1527 source_name: Some("legacy_netstack".to_string()),
1528 source_dictionary: Some("in/dict".to_string()),
1529 target_path: None,
1530 numbered_handle: Some(0xab),
1531 availability: Some(fdecl::Availability::Optional),
1532 ..Default::default()
1533 }),
1534 fdecl::Use::Protocol(fdecl::UseProtocol {
1535 dependency_type: Some(fdecl::DependencyType::Strong),
1536 source: Some(fdecl::Ref::Child(fdecl::ChildRef { name: "echo".to_string(), collection: None})),
1537 source_name: Some("echo_service".to_string()),
1538 source_dictionary: Some("in/dict".to_string()),
1539 target_path: Some("/svc/echo_service".to_string()),
1540 availability: Some(fdecl::Availability::Required),
1541 ..Default::default()
1542 }),
1543 fdecl::Use::Directory(fdecl::UseDirectory {
1544 dependency_type: Some(fdecl::DependencyType::Strong),
1545 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
1546 source_name: Some("dir".to_string()),
1547 source_dictionary: Some("dict1/me".to_string()),
1548 target_path: Some("/data".to_string()),
1549 rights: Some(fio::Operations::CONNECT),
1550 subdir: Some("foo/bar".to_string()),
1551 availability: Some(fdecl::Availability::Required),
1552 ..Default::default()
1553 }),
1554 fdecl::Use::Storage(fdecl::UseStorage {
1555 source_name: Some("cache".to_string()),
1556 target_path: Some("/cache".to_string()),
1557 availability: Some(fdecl::Availability::Required),
1558 ..Default::default()
1559 }),
1560 fdecl::Use::Storage(fdecl::UseStorage {
1561 source_name: Some("temp".to_string()),
1562 target_path: Some("/temp".to_string()),
1563 availability: Some(fdecl::Availability::Optional),
1564 ..Default::default()
1565 }),
1566 fdecl::Use::EventStream(fdecl::UseEventStream {
1567 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1568 collection: None,
1569 name: "netstack".to_string(),
1570 })),
1571 source_name: Some("stopped".to_string()),
1572 scope: Some(vec![
1573 fdecl::Ref::Child(fdecl::ChildRef {
1574 collection: None,
1575 name:"a".to_string(),
1576 }), fdecl::Ref::Collection(fdecl::CollectionRef {
1577 name:"b".to_string(),
1578 })]),
1579 target_path: Some("/svc/test".to_string()),
1580 availability: Some(fdecl::Availability::Optional),
1581 ..Default::default()
1582 }),
1583 fdecl::Use::Runner(fdecl::UseRunner {
1584 source: Some(fdecl::Ref::Environment(fdecl::EnvironmentRef {})),
1585 source_name: Some("elf".to_string()),
1586 source_dictionary: None,
1587 ..Default::default()
1588 }),
1589 fdecl::Use::Config(fdecl::UseConfiguration {
1590 source: Some(fdecl::Ref::Parent(fdecl::ParentRef)),
1591 source_name: Some("fuchsia.config.MyConfig".to_string()),
1592 target_name: Some("my_config".to_string()),
1593 availability: Some(fdecl::Availability::Required),
1594 type_: Some(fdecl::ConfigType{
1595 layout: fdecl::ConfigTypeLayout::Bool,
1596 parameters: Some(Vec::new()),
1597 constraints: Vec::new(),
1598 }),
1599 ..Default::default()
1600 }),
1601 #[cfg(fuchsia_api_level_at_least = "29")]
1602 fdecl::Use::Dictionary(fdecl::UseDictionary {
1603 dependency_type: Some(fdecl::DependencyType::Strong),
1604 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1605 source_name: Some("dictionary".to_string()),
1606 source_dictionary: Some("other_dictionary".to_string()),
1607 target_path: Some("/svc".to_string()),
1608 availability: Some(fdecl::Availability::Optional),
1609 ..Default::default()
1610 }),
1611 ]),
1612 exposes: Some(vec![
1613 fdecl::Expose::Protocol(fdecl::ExposeProtocol {
1614 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1615 name: "netstack".to_string(),
1616 collection: None,
1617 })),
1618 source_name: Some("legacy_netstack".to_string()),
1619 source_dictionary: Some("in/dict".to_string()),
1620 target_name: Some("legacy_mynetstack".to_string()),
1621 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1622 availability: Some(fdecl::Availability::Required),
1623 ..Default::default()
1624 }),
1625 fdecl::Expose::Directory(fdecl::ExposeDirectory {
1626 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1627 name: "netstack".to_string(),
1628 collection: None,
1629 })),
1630 source_name: Some("dir".to_string()),
1631 source_dictionary: Some("in/dict".to_string()),
1632 target_name: Some("data".to_string()),
1633 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1634 rights: Some(fio::Operations::CONNECT),
1635 subdir: Some("foo/bar".to_string()),
1636 availability: Some(fdecl::Availability::Optional),
1637 ..Default::default()
1638 }),
1639 fdecl::Expose::Runner(fdecl::ExposeRunner {
1640 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1641 name: "netstack".to_string(),
1642 collection: None,
1643 })),
1644 source_name: Some("elf".to_string()),
1645 source_dictionary: Some("in/dict".to_string()),
1646 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1647 target_name: Some("elf".to_string()),
1648 ..Default::default()
1649 }),
1650 fdecl::Expose::Resolver(fdecl::ExposeResolver{
1651 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1652 name: "netstack".to_string(),
1653 collection: None,
1654 })),
1655 source_name: Some("pkg".to_string()),
1656 source_dictionary: Some("in/dict".to_string()),
1657 target: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1658 target_name: Some("pkg".to_string()),
1659 ..Default::default()
1660 }),
1661 fdecl::Expose::Service(fdecl::ExposeService {
1662 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1663 name: "netstack".to_string(),
1664 collection: None,
1665 })),
1666 source_name: Some("netstack1".to_string()),
1667 source_dictionary: Some("in/dict".to_string()),
1668 target_name: Some("mynetstack".to_string()),
1669 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1670 availability: Some(fdecl::Availability::Required),
1671 ..Default::default()
1672 }),
1673 fdecl::Expose::Service(fdecl::ExposeService {
1674 source: Some(fdecl::Ref::Collection(fdecl::CollectionRef {
1675 name: "modular".to_string(),
1676 })),
1677 source_name: Some("netstack2".to_string()),
1678 source_dictionary: None,
1679 target_name: Some("mynetstack".to_string()),
1680 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1681 availability: Some(fdecl::Availability::Required),
1682 ..Default::default()
1683 }),
1684 fdecl::Expose::Dictionary(fdecl::ExposeDictionary {
1685 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1686 name: "netstack".to_string(),
1687 collection: None,
1688 })),
1689 source_name: Some("bundle".to_string()),
1690 source_dictionary: Some("in/dict".to_string()),
1691 target_name: Some("mybundle".to_string()),
1692 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1693 availability: Some(fdecl::Availability::Required),
1694 ..Default::default()
1695 }),
1696 ]),
1697 offers: Some(vec![
1698 fdecl::Offer::Protocol(fdecl::OfferProtocol {
1699 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1700 source_name: Some("legacy_netstack".to_string()),
1701 source_dictionary: Some("in/dict".to_string()),
1702 target: Some(fdecl::Ref::Child(
1703 fdecl::ChildRef {
1704 name: "echo".to_string(),
1705 collection: None,
1706 }
1707 )),
1708 target_name: Some("legacy_mynetstack".to_string()),
1709 dependency_type: Some(fdecl::DependencyType::Weak),
1710 availability: Some(fdecl::Availability::Required),
1711 ..Default::default()
1712 }),
1713 fdecl::Offer::Directory(fdecl::OfferDirectory {
1714 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1715 source_name: Some("dir".to_string()),
1716 source_dictionary: Some("in/dict".to_string()),
1717 target: Some(fdecl::Ref::Collection(
1718 fdecl::CollectionRef { name: "modular".to_string() }
1719 )),
1720 target_name: Some("data".to_string()),
1721 rights: Some(fio::Operations::CONNECT),
1722 subdir: None,
1723 dependency_type: Some(fdecl::DependencyType::Strong),
1724 availability: Some(fdecl::Availability::Optional),
1725 ..Default::default()
1726 }),
1727 fdecl::Offer::Storage(fdecl::OfferStorage {
1728 source_name: Some("cache".to_string()),
1729 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
1730 target: Some(fdecl::Ref::Collection(
1731 fdecl::CollectionRef { name: "modular".to_string() }
1732 )),
1733 target_name: Some("cache".to_string()),
1734 availability: Some(fdecl::Availability::Required),
1735 ..Default::default()
1736 }),
1737 fdecl::Offer::Runner(fdecl::OfferRunner {
1738 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1739 source_name: Some("elf".to_string()),
1740 source_dictionary: Some("in/dict".to_string()),
1741 target: Some(fdecl::Ref::Child(
1742 fdecl::ChildRef {
1743 name: "echo".to_string(),
1744 collection: None,
1745 }
1746 )),
1747 target_name: Some("elf2".to_string()),
1748 ..Default::default()
1749 }),
1750 fdecl::Offer::Resolver(fdecl::OfferResolver{
1751 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1752 source_name: Some("pkg".to_string()),
1753 source_dictionary: Some("in/dict".to_string()),
1754 target: Some(fdecl::Ref::Child(
1755 fdecl::ChildRef {
1756 name: "echo".to_string(),
1757 collection: None,
1758 }
1759 )),
1760 target_name: Some("pkg".to_string()),
1761 ..Default::default()
1762 }),
1763 fdecl::Offer::Service(fdecl::OfferService {
1764 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1765 source_name: Some("netstack1".to_string()),
1766 source_dictionary: Some("in/dict".to_string()),
1767 target: Some(fdecl::Ref::Child(
1768 fdecl::ChildRef {
1769 name: "echo".to_string(),
1770 collection: None,
1771 }
1772 )),
1773 target_name: Some("mynetstack1".to_string()),
1774 availability: Some(fdecl::Availability::Required),
1775 dependency_type: Some(fdecl::DependencyType::Strong),
1776 ..Default::default()
1777 }),
1778 fdecl::Offer::Service(fdecl::OfferService {
1779 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1780 source_name: Some("netstack2".to_string()),
1781 source_dictionary: None,
1782 target: Some(fdecl::Ref::Child(
1783 fdecl::ChildRef {
1784 name: "echo".to_string(),
1785 collection: None,
1786 }
1787 )),
1788 target_name: Some("mynetstack2".to_string()),
1789 availability: Some(fdecl::Availability::Optional),
1790 dependency_type: Some(fdecl::DependencyType::Strong),
1791 ..Default::default()
1792 }),
1793 fdecl::Offer::Service(fdecl::OfferService {
1794 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1795 source_name: Some("netstack3".to_string()),
1796 source_dictionary: None,
1797 target: Some(fdecl::Ref::Child(
1798 fdecl::ChildRef {
1799 name: "echo".to_string(),
1800 collection: None,
1801 }
1802 )),
1803 target_name: Some("mynetstack3".to_string()),
1804 source_instance_filter: Some(vec!["allowedinstance".to_string()]),
1805 renamed_instances: Some(vec![fdecl::NameMapping{source_name: "default".to_string(), target_name: "allowedinstance".to_string()}]),
1806 availability: Some(fdecl::Availability::Required),
1807 dependency_type: Some(fdecl::DependencyType::Strong),
1808 ..Default::default()
1809 }),
1810 fdecl::Offer::Dictionary(fdecl::OfferDictionary {
1811 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1812 source_name: Some("bundle".to_string()),
1813 source_dictionary: Some("in/dict".to_string()),
1814 target: Some(fdecl::Ref::Child(
1815 fdecl::ChildRef {
1816 name: "echo".to_string(),
1817 collection: None,
1818 }
1819 )),
1820 target_name: Some("mybundle".to_string()),
1821 dependency_type: Some(fdecl::DependencyType::Weak),
1822 availability: Some(fdecl::Availability::Required),
1823 ..Default::default()
1824 }),
1825 ]),
1826 capabilities: Some(vec![
1827 fdecl::Capability::Service(fdecl::Service {
1828 name: Some("netstack".to_string()),
1829 source_path: Some("/netstack".to_string()),
1830 ..Default::default()
1831 }),
1832 fdecl::Capability::Protocol(fdecl::Protocol {
1833 name: Some("netstack2".to_string()),
1834 source_path: Some("/netstack2".to_string()),
1835 delivery: Some(fdecl::DeliveryType::Immediate),
1836 ..Default::default()
1837 }),
1838 fdecl::Capability::Directory(fdecl::Directory {
1839 name: Some("data".to_string()),
1840 source_path: Some("/data".to_string()),
1841 rights: Some(fio::Operations::CONNECT),
1842 ..Default::default()
1843 }),
1844 fdecl::Capability::Storage(fdecl::Storage {
1845 name: Some("cache".to_string()),
1846 backing_dir: Some("data".to_string()),
1847 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1848 subdir: Some("cache".to_string()),
1849 storage_id: Some(fdecl::StorageId::StaticInstanceId),
1850 ..Default::default()
1851 }),
1852 fdecl::Capability::Runner(fdecl::Runner {
1853 name: Some("elf".to_string()),
1854 source_path: Some("/elf".to_string()),
1855 ..Default::default()
1856 }),
1857 fdecl::Capability::Resolver(fdecl::Resolver {
1858 name: Some("pkg".to_string()),
1859 source_path: Some("/pkg_resolver".to_string()),
1860 ..Default::default()
1861 }),
1862 fdecl::Capability::Dictionary(fdecl::Dictionary {
1863 name: Some("dict1".to_string()),
1864 ..Default::default()
1865 }),
1866 fdecl::Capability::Dictionary(fdecl::Dictionary {
1867 name: Some("dict2".to_string()),
1868 source_path: Some("/in/other".to_string()),
1869 ..Default::default()
1870 }),
1871 ]),
1872 children: Some(vec![
1873 fdecl::Child {
1874 name: Some("netstack".to_string()),
1875 url: Some("fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm"
1876 .to_string()),
1877 startup: Some(fdecl::StartupMode::Lazy),
1878 on_terminate: None,
1879 environment: None,
1880 ..Default::default()
1881 },
1882 fdecl::Child {
1883 name: Some("gtest".to_string()),
1884 url: Some("fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string()),
1885 startup: Some(fdecl::StartupMode::Lazy),
1886 on_terminate: Some(fdecl::OnTerminate::None),
1887 environment: None,
1888 ..Default::default()
1889 },
1890 fdecl::Child {
1891 name: Some("echo".to_string()),
1892 url: Some("fuchsia-pkg://fuchsia.com/echo#meta/echo.cm"
1893 .to_string()),
1894 startup: Some(fdecl::StartupMode::Eager),
1895 on_terminate: Some(fdecl::OnTerminate::Reboot),
1896 environment: Some("test_env".to_string()),
1897 ..Default::default()
1898 },
1899 ]),
1900 collections: Some(vec![
1901 fdecl::Collection {
1902 name: Some("modular".to_string()),
1903 durability: Some(fdecl::Durability::Transient),
1904 environment: None,
1905 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
1906 allow_long_names: Some(true),
1907 persistent_storage: None,
1908 ..Default::default()
1909 },
1910 fdecl::Collection {
1911 name: Some("tests".to_string()),
1912 durability: Some(fdecl::Durability::Transient),
1913 environment: Some("test_env".to_string()),
1914 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
1915 allow_long_names: Some(true),
1916 persistent_storage: Some(true),
1917 ..Default::default()
1918 },
1919 ]),
1920 facets: Some(fdata::Dictionary {
1921 entries: Some(vec![
1922 fdata::DictionaryEntry {
1923 key: "author".to_string(),
1924 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
1925 },
1926 ]),
1927 ..Default::default()
1928 }),
1929 environments: Some(vec![
1930 fdecl::Environment {
1931 name: Some("test_env".to_string()),
1932 extends: Some(fdecl::EnvironmentExtends::Realm),
1933 runners: Some(vec![
1934 fdecl::RunnerRegistration {
1935 source_name: Some("runner".to_string()),
1936 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1937 name: "gtest".to_string(),
1938 collection: None,
1939 })),
1940 target_name: Some("gtest-runner".to_string()),
1941 ..Default::default()
1942 }
1943 ]),
1944 resolvers: Some(vec![
1945 fdecl::ResolverRegistration {
1946 resolver: Some("pkg_resolver".to_string()),
1947 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1948 scheme: Some("fuchsia-pkg".to_string()),
1949 ..Default::default()
1950 }
1951 ]),
1952 debug_capabilities: Some(vec![
1953 fdecl::DebugRegistration::Protocol(fdecl::DebugProtocolRegistration {
1954 source_name: Some("some_protocol".to_string()),
1955 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1956 name: "gtest".to_string(),
1957 collection: None,
1958 })),
1959 target_name: Some("some_protocol".to_string()),
1960 ..Default::default()
1961 })
1962 ]),
1963 stop_timeout_ms: Some(4567),
1964 ..Default::default()
1965 }
1966 ]),
1967 config: Some(fdecl::ConfigSchema{
1968 fields: Some(vec![
1969 fdecl::ConfigField {
1970 key: Some("enable_logging".to_string()),
1971 type_: Some(fdecl::ConfigType {
1972 layout: fdecl::ConfigTypeLayout::Bool,
1973 parameters: Some(vec![]),
1974 constraints: vec![],
1975 }),
1976 mutability: Some(Default::default()),
1977 ..Default::default()
1978 }
1979 ]),
1980 checksum: Some(fdecl::ConfigChecksum::Sha256([
1981 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
1982 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
1983 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
1984 ])),
1985 value_source: Some(
1986 fdecl::ConfigValueSource::PackagePath("fake.cvf".to_string())
1987 ),
1988 ..Default::default()
1989 }),
1990 ..Default::default()
1991 },
1992 result = {
1993 ComponentDecl {
1994 program: Some(ProgramDecl {
1995 runner: Some("elf".parse().unwrap()),
1996 info: fdata::Dictionary {
1997 entries: Some(vec![
1998 fdata::DictionaryEntry {
1999 key: "args".to_string(),
2000 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
2001 },
2002 fdata::DictionaryEntry{
2003 key: "binary".to_string(),
2004 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
2005 },
2006 ]),
2007 ..Default::default()
2008 },
2009 }),
2010 uses: Box::from([
2011 UseDecl::Service(UseServiceDecl {
2012 dependency_type: DependencyType::Strong,
2013 source: UseSource::Parent,
2014 source_name: "netstack".parse().unwrap(),
2015 source_dictionary: "in/dict".parse().unwrap(),
2016 target_path: "/svc/mynetstack".parse().unwrap(),
2017 availability: Availability::Required,
2018 }),
2019 UseDecl::Protocol(UseProtocolDecl {
2020 dependency_type: DependencyType::Strong,
2021 source: UseSource::Parent,
2022 source_name: "legacy_netstack".parse().unwrap(),
2023 source_dictionary: "in/dict".parse().unwrap(),
2024 target_path: None,
2025 numbered_handle: Some(HandleType::from(0xab)),
2026 availability: Availability::Optional,
2027 }),
2028 UseDecl::Protocol(UseProtocolDecl {
2029 dependency_type: DependencyType::Strong,
2030 source: UseSource::Child("echo".parse().unwrap()),
2031 source_name: "echo_service".parse().unwrap(),
2032 source_dictionary: "in/dict".parse().unwrap(),
2033 target_path: Some("/svc/echo_service".parse().unwrap()),
2034 numbered_handle: None,
2035 availability: Availability::Required,
2036 }),
2037 UseDecl::Directory(UseDirectoryDecl {
2038 dependency_type: DependencyType::Strong,
2039 source: UseSource::Self_,
2040 source_name: "dir".parse().unwrap(),
2041 source_dictionary: "dict1/me".parse().unwrap(),
2042 target_path: "/data".parse().unwrap(),
2043 rights: fio::Operations::CONNECT,
2044 subdir: "foo/bar".parse().unwrap(),
2045 availability: Availability::Required,
2046 }),
2047 UseDecl::Storage(UseStorageDecl {
2048 source_name: "cache".parse().unwrap(),
2049 target_path: "/cache".parse().unwrap(),
2050 availability: Availability::Required,
2051 }),
2052 UseDecl::Storage(UseStorageDecl {
2053 source_name: "temp".parse().unwrap(),
2054 target_path: "/temp".parse().unwrap(),
2055 availability: Availability::Optional,
2056 }),
2057 UseDecl::EventStream(Box::new(UseEventStreamDecl {
2058 source: UseSource::Child("netstack".parse().unwrap()),
2059 scope: Some(Box::from([EventScope::Child(ChildRef{ name: "a".parse().unwrap(), collection: None}), EventScope::Collection("b".parse().unwrap())])),
2060 source_name: "stopped".parse().unwrap(),
2061 target_path: "/svc/test".parse().unwrap(),
2062 filter: None,
2063 availability: Availability::Optional,
2064 })),
2065 UseDecl::Runner(UseRunnerDecl {
2066 source: UseSource::Environment,
2067 source_name: "elf".parse().unwrap(),
2068 source_dictionary: ".".parse().unwrap(),
2069 }),
2070 UseDecl::Config(Box::new(UseConfigurationDecl {
2071 source: UseSource::Parent,
2072 source_name: "fuchsia.config.MyConfig".parse().unwrap(),
2073 target_name: "my_config".parse().unwrap(),
2074 availability: Availability::Required,
2075 type_: ConfigValueType::Bool,
2076 default: None,
2077 source_dictionary: ".".parse().unwrap(),
2078 })),
2079 #[cfg(fuchsia_api_level_at_least = "29")]
2080 UseDecl::Dictionary(UseDictionaryDecl {
2081 dependency_type: DependencyType::Strong,
2082 source: UseSource::Parent,
2083 source_name: "dictionary".parse().unwrap(),
2084 source_dictionary: "other_dictionary".parse().unwrap(),
2085 target_path: "/svc".parse().unwrap(),
2086 availability: Availability::Optional,
2087 }),
2088 ]),
2089 exposes: Box::from([
2090 ExposeDecl::Protocol(ExposeProtocolDecl {
2091 source: ExposeSource::Child("netstack".parse().unwrap()),
2092 source_name: "legacy_netstack".parse().unwrap(),
2093 source_dictionary: "in/dict".parse().unwrap(),
2094 target_name: "legacy_mynetstack".parse().unwrap(),
2095 target: ExposeTarget::Parent,
2096 availability: Availability::Required,
2097 }),
2098 ExposeDecl::Directory(ExposeDirectoryDecl {
2099 source: ExposeSource::Child("netstack".parse().unwrap()),
2100 source_name: "dir".parse().unwrap(),
2101 source_dictionary: "in/dict".parse().unwrap(),
2102 target_name: "data".parse().unwrap(),
2103 target: ExposeTarget::Parent,
2104 rights: Some(fio::Operations::CONNECT),
2105 subdir: "foo/bar".parse().unwrap(),
2106 availability: Availability::Optional,
2107 }),
2108 ExposeDecl::Runner(ExposeRunnerDecl {
2109 source: ExposeSource::Child("netstack".parse().unwrap()),
2110 source_name: "elf".parse().unwrap(),
2111 source_dictionary: "in/dict".parse().unwrap(),
2112 target: ExposeTarget::Parent,
2113 target_name: "elf".parse().unwrap(),
2114 }),
2115 ExposeDecl::Resolver(ExposeResolverDecl {
2116 source: ExposeSource::Child("netstack".parse().unwrap()),
2117 source_name: "pkg".parse().unwrap(),
2118 source_dictionary: "in/dict".parse().unwrap(),
2119 target: ExposeTarget::Parent,
2120 target_name: "pkg".parse().unwrap(),
2121 }),
2122 ExposeDecl::Service(ExposeServiceDecl {
2123 source: ExposeSource::Child("netstack".parse().unwrap()),
2124 source_name: "netstack1".parse().unwrap(),
2125 source_dictionary: "in/dict".parse().unwrap(),
2126 target_name: "mynetstack".parse().unwrap(),
2127 target: ExposeTarget::Parent,
2128 availability: Availability::Required,
2129 }),
2130 ExposeDecl::Service(ExposeServiceDecl {
2131 source: ExposeSource::Collection("modular".parse().unwrap()),
2132 source_name: "netstack2".parse().unwrap(),
2133 source_dictionary: ".".parse().unwrap(),
2134 target_name: "mynetstack".parse().unwrap(),
2135 target: ExposeTarget::Parent,
2136 availability: Availability::Required,
2137 }),
2138 ExposeDecl::Dictionary(ExposeDictionaryDecl {
2139 source: ExposeSource::Child("netstack".parse().unwrap()),
2140 source_name: "bundle".parse().unwrap(),
2141 source_dictionary: "in/dict".parse().unwrap(),
2142 target_name: "mybundle".parse().unwrap(),
2143 target: ExposeTarget::Parent,
2144 availability: Availability::Required,
2145 }),
2146 ]),
2147 offers: Box::from([
2148 OfferDecl::Protocol(OfferProtocolDecl {
2149 source: OfferSource::Parent,
2150 source_name: "legacy_netstack".parse().unwrap(),
2151 source_dictionary: "in/dict".parse().unwrap(),
2152 target: offer_target_static_child("echo"),
2153 target_name: "legacy_mynetstack".parse().unwrap(),
2154 dependency_type: DependencyType::Weak,
2155 availability: Availability::Required,
2156 }),
2157 OfferDecl::Directory(Box::new(OfferDirectoryDecl {
2158 source: OfferSource::Parent,
2159 source_name: "dir".parse().unwrap(),
2160 source_dictionary: "in/dict".parse().unwrap(),
2161 target: OfferTarget::Collection("modular".parse().unwrap()),
2162 target_name: "data".parse().unwrap(),
2163 rights: Some(fio::Operations::CONNECT),
2164 subdir: ".".parse().unwrap(),
2165 dependency_type: DependencyType::Strong,
2166 availability: Availability::Optional,
2167 })),
2168 OfferDecl::Storage(OfferStorageDecl {
2169 source_name: "cache".parse().unwrap(),
2170 source: OfferSource::Self_,
2171 target: OfferTarget::Collection("modular".parse().unwrap()),
2172 target_name: "cache".parse().unwrap(),
2173 availability: Availability::Required,
2174 }),
2175 OfferDecl::Runner(OfferRunnerDecl {
2176 source: OfferSource::Parent,
2177 source_name: "elf".parse().unwrap(),
2178 source_dictionary: "in/dict".parse().unwrap(),
2179 target: offer_target_static_child("echo"),
2180 target_name: "elf2".parse().unwrap(),
2181 }),
2182 OfferDecl::Resolver(OfferResolverDecl {
2183 source: OfferSource::Parent,
2184 source_name: "pkg".parse().unwrap(),
2185 source_dictionary: "in/dict".parse().unwrap(),
2186 target: offer_target_static_child("echo"),
2187 target_name: "pkg".parse().unwrap(),
2188 }),
2189 OfferDecl::Service(Box::new(OfferServiceDecl {
2190 source: OfferSource::Parent,
2191 source_name: "netstack1".parse().unwrap(),
2192 source_dictionary: "in/dict".parse().unwrap(),
2193 source_instance_filter: None,
2194 renamed_instances: None,
2195 target: offer_target_static_child("echo"),
2196 target_name: "mynetstack1".parse().unwrap(),
2197 availability: Availability::Required,
2198 dependency_type: Default::default(),
2199 })),
2200 OfferDecl::Service(Box::new(OfferServiceDecl {
2201 source: OfferSource::Parent,
2202 source_name: "netstack2".parse().unwrap(),
2203 source_dictionary: ".".parse().unwrap(),
2204 source_instance_filter: None,
2205 renamed_instances: None,
2206 target: offer_target_static_child("echo"),
2207 target_name: "mynetstack2".parse().unwrap(),
2208 availability: Availability::Optional,
2209 dependency_type: Default::default(),
2210 })),
2211 OfferDecl::Service(Box::new(OfferServiceDecl {
2212 source: OfferSource::Parent,
2213 source_name: "netstack3".parse().unwrap(),
2214 source_dictionary: ".".parse().unwrap(),
2215 source_instance_filter: Some(Box::from(["allowedinstance".parse().unwrap()])),
2216 renamed_instances: Some(Box::from([NameMapping{source_name: "default".parse().unwrap(), target_name: "allowedinstance".parse().unwrap()}])),
2217 target: offer_target_static_child("echo"),
2218 target_name: "mynetstack3".parse().unwrap(),
2219 availability: Availability::Required,
2220 dependency_type: Default::default(),
2221 })),
2222 OfferDecl::Dictionary(OfferDictionaryDecl {
2223 source: OfferSource::Parent,
2224 source_name: "bundle".parse().unwrap(),
2225 source_dictionary: "in/dict".parse().unwrap(),
2226 target: offer_target_static_child("echo"),
2227 target_name: "mybundle".parse().unwrap(),
2228 dependency_type: DependencyType::Weak,
2229 availability: Availability::Required,
2230 }),
2231 ]),
2232 capabilities: Box::from([
2233 CapabilityDecl::Service(ServiceDecl {
2234 name: "netstack".parse().unwrap(),
2235 source_path: Some("/netstack".parse().unwrap()),
2236 }),
2237 CapabilityDecl::Protocol(ProtocolDecl {
2238 name: "netstack2".parse().unwrap(),
2239 source_path: Some("/netstack2".parse().unwrap()),
2240 delivery: DeliveryType::Immediate,
2241 }),
2242 CapabilityDecl::Directory(DirectoryDecl {
2243 name: "data".parse().unwrap(),
2244 source_path: Some("/data".parse().unwrap()),
2245 rights: fio::Operations::CONNECT,
2246 }),
2247 CapabilityDecl::Storage(StorageDecl {
2248 name: "cache".parse().unwrap(),
2249 backing_dir: "data".parse().unwrap(),
2250 source: StorageDirectorySource::Parent,
2251 subdir: "cache".parse().unwrap(),
2252 storage_id: fdecl::StorageId::StaticInstanceId,
2253 }),
2254 CapabilityDecl::Runner(RunnerDecl {
2255 name: "elf".parse().unwrap(),
2256 source_path: Some("/elf".parse().unwrap()),
2257 }),
2258 CapabilityDecl::Resolver(ResolverDecl {
2259 name: "pkg".parse().unwrap(),
2260 source_path: Some("/pkg_resolver".parse().unwrap()),
2261 }),
2262 CapabilityDecl::Dictionary(DictionaryDecl {
2263 name: "dict1".parse().unwrap(),
2264 source_path: None,
2265 }),
2266 CapabilityDecl::Dictionary(DictionaryDecl {
2267 name: "dict2".parse().unwrap(),
2268 source_path: Some("/in/other".parse().unwrap()),
2269 }),
2270 ]),
2271 children: Box::from([
2272 ChildDecl {
2273 name: "netstack".parse().unwrap(),
2274 url: "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm".parse().unwrap(),
2275 startup: fdecl::StartupMode::Lazy,
2276 on_terminate: None,
2277 environment: None,
2278 config_overrides: None,
2279 },
2280 ChildDecl {
2281 name: "gtest".parse().unwrap(),
2282 url: "fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".parse().unwrap(),
2283 startup: fdecl::StartupMode::Lazy,
2284 on_terminate: Some(fdecl::OnTerminate::None),
2285 environment: None,
2286 config_overrides: None,
2287 },
2288 ChildDecl {
2289 name: "echo".parse().unwrap(),
2290 url: "fuchsia-pkg://fuchsia.com/echo#meta/echo.cm".parse().unwrap(),
2291 startup: fdecl::StartupMode::Eager,
2292 on_terminate: Some(fdecl::OnTerminate::Reboot),
2293 environment: Some("test_env".parse().unwrap()),
2294 config_overrides: None,
2295 },
2296 ]),
2297 collections: Box::from([
2298 CollectionDecl {
2299 name: "modular".parse().unwrap(),
2300 durability: fdecl::Durability::Transient,
2301 environment: None,
2302 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2303 allow_long_names: true,
2304 persistent_storage: None,
2305 },
2306 CollectionDecl {
2307 name: "tests".parse().unwrap(),
2308 durability: fdecl::Durability::Transient,
2309 environment: Some("test_env".parse().unwrap()),
2310 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
2311 allow_long_names: true,
2312 persistent_storage: Some(true),
2313 },
2314 ]),
2315 facets: Some(fdata::Dictionary {
2316 entries: Some(vec![
2317 fdata::DictionaryEntry {
2318 key: "author".to_string(),
2319 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
2320 },
2321 ]),
2322 ..Default::default()
2323 }),
2324 environments: Box::from([
2325 EnvironmentDecl {
2326 name: "test_env".parse().unwrap(),
2327 extends: fdecl::EnvironmentExtends::Realm,
2328 runners: Box::from([
2329 RunnerRegistration {
2330 source_name: "runner".parse().unwrap(),
2331 source: RegistrationSource::Child("gtest".to_string()),
2332 target_name: "gtest-runner".parse().unwrap(),
2333 }
2334 ]),
2335 resolvers: Box::from([
2336 ResolverRegistration {
2337 resolver: "pkg_resolver".parse().unwrap(),
2338 source: RegistrationSource::Parent,
2339 scheme: "fuchsia-pkg".to_string(),
2340 }
2341 ]),
2342 debug_capabilities: Box::from([
2343 DebugRegistration::Protocol(DebugProtocolRegistration {
2344 source_name: "some_protocol".parse().unwrap(),
2345 source: RegistrationSource::Child("gtest".to_string()),
2346 target_name: "some_protocol".parse().unwrap(),
2347 })
2348 ]),
2349 stop_timeout_ms: Some(4567),
2350 }
2351 ]),
2352 config: Some(ConfigDecl {
2353 fields: Box::from([
2354 ConfigField {
2355 key: "enable_logging".into(),
2356 type_: ConfigValueType::Bool,
2357 mutability: ConfigMutability::default(),
2358 }
2359 ]),
2360 checksum: ConfigChecksum::Sha256([
2361 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
2362 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
2363 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
2364 ]),
2365 value_source: ConfigValueSource::PackagePath("fake.cvf".into())
2366 }),
2367 debug_info: None,
2368 }
2369 },
2370 },
2371 }
2372
2373 test_fidl_into_and_from! {
2374 fidl_into_and_from_use_source => {
2375 input = vec![
2376 fdecl::Ref::Parent(fdecl::ParentRef{}),
2377 fdecl::Ref::Framework(fdecl::FrameworkRef{}),
2378 fdecl::Ref::Debug(fdecl::DebugRef{}),
2379 fdecl::Ref::Capability(fdecl::CapabilityRef {name: "capability".to_string()}),
2380 fdecl::Ref::Child(fdecl::ChildRef {
2381 name: "foo".into(),
2382 collection: None,
2383 }),
2384 fdecl::Ref::Environment(fdecl::EnvironmentRef{}),
2385 ],
2386 input_type = fdecl::Ref,
2387 result = vec![
2388 UseSource::Parent,
2389 UseSource::Framework,
2390 UseSource::Debug,
2391 UseSource::Capability("capability".parse().unwrap()),
2392 UseSource::Child("foo".parse().unwrap()),
2393 UseSource::Environment,
2394 ],
2395 result_type = UseSource,
2396 },
2397 fidl_into_and_from_expose_source => {
2398 input = vec![
2399 fdecl::Ref::Self_(fdecl::SelfRef {}),
2400 fdecl::Ref::Child(fdecl::ChildRef {
2401 name: "foo".into(),
2402 collection: None,
2403 }),
2404 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2405 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
2406 ],
2407 input_type = fdecl::Ref,
2408 result = vec![
2409 ExposeSource::Self_,
2410 ExposeSource::Child("foo".parse().unwrap()),
2411 ExposeSource::Framework,
2412 ExposeSource::Collection("foo".parse().unwrap()),
2413 ],
2414 result_type = ExposeSource,
2415 },
2416 fidl_into_and_from_offer_source => {
2417 input = vec![
2418 fdecl::Ref::Self_(fdecl::SelfRef {}),
2419 fdecl::Ref::Child(fdecl::ChildRef {
2420 name: "foo".into(),
2421 collection: None,
2422 }),
2423 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2424 fdecl::Ref::Capability(fdecl::CapabilityRef { name: "foo".to_string() }),
2425 fdecl::Ref::Parent(fdecl::ParentRef {}),
2426 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
2427 fdecl::Ref::VoidType(fdecl::VoidRef {}),
2428 ],
2429 input_type = fdecl::Ref,
2430 result = vec![
2431 OfferSource::Self_,
2432 offer_source_static_child("foo"),
2433 OfferSource::Framework,
2434 OfferSource::Capability("foo".parse().unwrap()),
2435 OfferSource::Parent,
2436 OfferSource::Collection("foo".parse().unwrap()),
2437 OfferSource::Void,
2438 ],
2439 result_type = OfferSource,
2440 },
2441 fidl_into_and_from_dictionary_source => {
2442 input = vec![
2443 fdecl::Ref::Self_(fdecl::SelfRef {}),
2444 fdecl::Ref::Child(fdecl::ChildRef {
2445 name: "foo".into(),
2446 collection: None,
2447 }),
2448 fdecl::Ref::Parent(fdecl::ParentRef {}),
2449 ],
2450 input_type = fdecl::Ref,
2451 result = vec![
2452 DictionarySource::Self_,
2453 DictionarySource::Child(ChildRef {
2454 name: "foo".parse().unwrap(),
2455 collection: None,
2456 }),
2457 DictionarySource::Parent,
2458 ],
2459 result_type = DictionarySource,
2460 },
2461
2462 fidl_into_and_from_capability_without_path => {
2463 input = vec![
2464 fdecl::Protocol {
2465 name: Some("foo_protocol".to_string()),
2466 source_path: None,
2467 delivery: Some(fdecl::DeliveryType::Immediate),
2468 ..Default::default()
2469 },
2470 ],
2471 input_type = fdecl::Protocol,
2472 result = vec![
2473 ProtocolDecl {
2474 name: "foo_protocol".parse().unwrap(),
2475 source_path: None,
2476 delivery: DeliveryType::Immediate,
2477 }
2478 ],
2479 result_type = ProtocolDecl,
2480 },
2481 fidl_into_and_from_storage_capability => {
2482 input = vec![
2483 fdecl::Storage {
2484 name: Some("minfs".to_string()),
2485 backing_dir: Some("minfs".into()),
2486 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2487 name: "foo".into(),
2488 collection: None,
2489 })),
2490 subdir: None,
2491 storage_id: Some(fdecl::StorageId::StaticInstanceIdOrMoniker),
2492 ..Default::default()
2493 },
2494 ],
2495 input_type = fdecl::Storage,
2496 result = vec![
2497 StorageDecl {
2498 name: "minfs".parse().unwrap(),
2499 backing_dir: "minfs".parse().unwrap(),
2500 source: StorageDirectorySource::Child("foo".to_string()),
2501 subdir: ".".parse().unwrap(),
2502 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
2503 },
2504 ],
2505 result_type = StorageDecl,
2506 },
2507 fidl_into_and_from_storage_capability_restricted => {
2508 input = vec![
2509 fdecl::Storage {
2510 name: Some("minfs".to_string()),
2511 backing_dir: Some("minfs".into()),
2512 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2513 name: "foo".into(),
2514 collection: None,
2515 })),
2516 subdir: None,
2517 storage_id: Some(fdecl::StorageId::StaticInstanceId),
2518 ..Default::default()
2519 },
2520 ],
2521 input_type = fdecl::Storage,
2522 result = vec![
2523 StorageDecl {
2524 name: "minfs".parse().unwrap(),
2525 backing_dir: "minfs".parse().unwrap(),
2526 source: StorageDirectorySource::Child("foo".to_string()),
2527 subdir: ".".parse().unwrap(),
2528 storage_id: fdecl::StorageId::StaticInstanceId,
2529 },
2530 ],
2531 result_type = StorageDecl,
2532 },
2533 }
2534
2535 test_fidl_into! {
2536 all_with_omitted_defaults => {
2537 input = fdecl::Component {
2538 program: Some(fdecl::Program {
2539 runner: Some("elf".to_string()),
2540 info: Some(fdata::Dictionary {
2541 entries: Some(vec![]),
2542 ..Default::default()
2543 }),
2544 ..Default::default()
2545 }),
2546 uses: Some(vec![]),
2547 exposes: Some(vec![]),
2548 offers: Some(vec![]),
2549 capabilities: Some(vec![]),
2550 children: Some(vec![]),
2551 collections: Some(vec![
2552 fdecl::Collection {
2553 name: Some("modular".to_string()),
2554 durability: Some(fdecl::Durability::Transient),
2555 environment: None,
2556 allowed_offers: None,
2557 allow_long_names: None,
2558 persistent_storage: None,
2559 ..Default::default()
2560 },
2561 fdecl::Collection {
2562 name: Some("tests".to_string()),
2563 durability: Some(fdecl::Durability::Transient),
2564 environment: Some("test_env".to_string()),
2565 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
2566 allow_long_names: None,
2567 persistent_storage: Some(false),
2568 ..Default::default()
2569 },
2570 fdecl::Collection {
2571 name: Some("dyn_offers".to_string()),
2572 durability: Some(fdecl::Durability::Transient),
2573 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
2574 allow_long_names: None,
2575 persistent_storage: Some(true),
2576 ..Default::default()
2577 },
2578 fdecl::Collection {
2579 name: Some("long_child_names".to_string()),
2580 durability: Some(fdecl::Durability::Transient),
2581 allowed_offers: None,
2582 allow_long_names: Some(true),
2583 persistent_storage: None,
2584 ..Default::default()
2585 },
2586 ]),
2587 facets: Some(fdata::Dictionary{
2588 entries: Some(vec![]),
2589 ..Default::default()
2590 }),
2591 environments: Some(vec![]),
2592 ..Default::default()
2593 },
2594 result = {
2595 ComponentDecl {
2596 program: Some(ProgramDecl {
2597 runner: Some("elf".parse().unwrap()),
2598 info: fdata::Dictionary {
2599 entries: Some(vec![]),
2600 ..Default::default()
2601 },
2602 }),
2603 uses: Box::from([]),
2604 exposes: Box::from([]),
2605 offers: Box::from([]),
2606 capabilities: Box::from([]),
2607 children: Box::from([]),
2608 collections: Box::from([
2609 CollectionDecl {
2610 name: "modular".parse().unwrap(),
2611 durability: fdecl::Durability::Transient,
2612 environment: None,
2613 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2614 allow_long_names: false,
2615 persistent_storage: None,
2616 },
2617 CollectionDecl {
2618 name: "tests".parse().unwrap(),
2619 durability: fdecl::Durability::Transient,
2620 environment: Some("test_env".parse().unwrap()),
2621 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2622 allow_long_names: false,
2623 persistent_storage: Some(false),
2624 },
2625 CollectionDecl {
2626 name: "dyn_offers".parse().unwrap(),
2627 durability: fdecl::Durability::Transient,
2628 environment: None,
2629 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
2630 allow_long_names: false,
2631 persistent_storage: Some(true),
2632 },
2633 CollectionDecl {
2634 name: "long_child_names".parse().unwrap(),
2635 durability: fdecl::Durability::Transient,
2636 environment: None,
2637 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2638 allow_long_names: true,
2639 persistent_storage: None,
2640 },
2641 ]),
2642 facets: Some(fdata::Dictionary{
2643 entries: Some(vec![]),
2644 ..Default::default()
2645 }),
2646 environments: Box::from([]),
2647 config: None,
2648 debug_info: None,
2649 }
2650 },
2651 },
2652 }
2653
2654 #[test]
2655 fn default_expose_availability() {
2656 let source = fdecl::Ref::Self_(fdecl::SelfRef {});
2657 let source_name = "source";
2658 let target = fdecl::Ref::Parent(fdecl::ParentRef {});
2659 let target_name = "target";
2660 let expose_service: ExposeServiceDecl = fdecl::ExposeService {
2661 source: Some(source.clone()),
2662 source_name: Some(source_name.into()),
2663 target: Some(target.clone()),
2664 target_name: Some(target_name.into()),
2665 availability: None,
2666 ..Default::default()
2667 }
2668 .fidl_into_native();
2669 assert_eq!(*expose_service.availability(), Availability::Required);
2670
2671 let expose_protocol: ExposeProtocolDecl = fdecl::ExposeProtocol {
2672 source: Some(source.clone()),
2673 source_name: Some(source_name.into()),
2674 target: Some(target.clone()),
2675 target_name: Some(target_name.into()),
2676 ..Default::default()
2677 }
2678 .fidl_into_native();
2679 assert_eq!(*expose_protocol.availability(), Availability::Required);
2680
2681 let expose_directory: ExposeDirectoryDecl = fdecl::ExposeDirectory {
2682 source: Some(source.clone()),
2683 source_name: Some(source_name.into()),
2684 target: Some(target.clone()),
2685 target_name: Some(target_name.into()),
2686 ..Default::default()
2687 }
2688 .fidl_into_native();
2689 assert_eq!(*expose_directory.availability(), Availability::Required);
2690
2691 let expose_runner: ExposeRunnerDecl = fdecl::ExposeRunner {
2692 source: Some(source.clone()),
2693 source_name: Some(source_name.into()),
2694 target: Some(target.clone()),
2695 target_name: Some(target_name.into()),
2696 ..Default::default()
2697 }
2698 .fidl_into_native();
2699 assert_eq!(*expose_runner.availability(), Availability::Required);
2700
2701 let expose_resolver: ExposeResolverDecl = fdecl::ExposeResolver {
2702 source: Some(source.clone()),
2703 source_name: Some(source_name.into()),
2704 target: Some(target.clone()),
2705 target_name: Some(target_name.into()),
2706 ..Default::default()
2707 }
2708 .fidl_into_native();
2709 assert_eq!(*expose_resolver.availability(), Availability::Required);
2710
2711 let expose_dictionary: ExposeDictionaryDecl = fdecl::ExposeDictionary {
2712 source: Some(source.clone()),
2713 source_name: Some(source_name.into()),
2714 target: Some(target.clone()),
2715 target_name: Some(target_name.into()),
2716 ..Default::default()
2717 }
2718 .fidl_into_native();
2719 assert_eq!(*expose_dictionary.availability(), Availability::Required);
2720 }
2721
2722 #[test]
2723 fn default_delivery_type() {
2724 let protocol: ProtocolDecl = fdecl::Protocol {
2725 name: Some("foo".to_string()),
2726 source_path: Some("/foo".to_string()),
2727 delivery: None,
2728 ..Default::default()
2729 }
2730 .fidl_into_native();
2731 assert_eq!(protocol.delivery, DeliveryType::Immediate)
2732 }
2733
2734 #[test]
2735 fn on_readable_delivery_type() {
2736 let protocol: ProtocolDecl = fdecl::Protocol {
2737 name: Some("foo".to_string()),
2738 source_path: Some("/foo".to_string()),
2739 delivery: Some(fdecl::DeliveryType::OnReadable),
2740 ..Default::default()
2741 }
2742 .fidl_into_native();
2743 assert_eq!(protocol.delivery, DeliveryType::OnReadable)
2744 }
2745
2746 #[test]
2747 fn config_value_matches_type() {
2748 let bool_true = ConfigValue::Single(ConfigSingleValue::Bool(true));
2749 let bool_false = ConfigValue::Single(ConfigSingleValue::Bool(false));
2750 let uint8_zero = ConfigValue::Single(ConfigSingleValue::Uint8(0));
2751 let vec_bool_true = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([true])));
2752 let vec_bool_false = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([false])));
2753
2754 assert!(bool_true.matches_type(&bool_false));
2755 assert!(vec_bool_true.matches_type(&vec_bool_false));
2756
2757 assert!(!bool_true.matches_type(&uint8_zero));
2758 assert!(!bool_true.matches_type(&vec_bool_true));
2759 }
2760}