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 fmt::Display for CapabilityTypeName {
919 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
920 let display_name = 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 write!(f, "{}", display_name)
932 }
933}
934
935impl From<&UseDecl> for CapabilityTypeName {
936 fn from(use_decl: &UseDecl) -> Self {
937 match use_decl {
938 UseDecl::Service(_) => Self::Service,
939 UseDecl::Protocol(_) => Self::Protocol,
940 UseDecl::Directory(_) => Self::Directory,
941 UseDecl::Storage(_) => Self::Storage,
942 UseDecl::EventStream(_) => Self::EventStream,
943 #[cfg(fuchsia_api_level_at_least = "HEAD")]
944 UseDecl::Runner(_) => Self::Runner,
945 UseDecl::Config(_) => Self::Config,
946 #[cfg(fuchsia_api_level_at_least = "29")]
947 UseDecl::Dictionary(_) => Self::Dictionary,
948 }
949 }
950}
951
952impl From<&ExposeDecl> for CapabilityTypeName {
953 fn from(expose_decl: &ExposeDecl) -> Self {
954 match expose_decl {
955 ExposeDecl::Service(_) => Self::Service,
956 ExposeDecl::Protocol(_) => Self::Protocol,
957 ExposeDecl::Directory(_) => Self::Directory,
958 ExposeDecl::Runner(_) => Self::Runner,
959 ExposeDecl::Resolver(_) => Self::Resolver,
960 ExposeDecl::Dictionary(_) => Self::Dictionary,
961 ExposeDecl::Config(_) => Self::Config,
962 }
963 }
964}
965
966impl From<CapabilityTypeName> for fio::DirentType {
967 fn from(value: CapabilityTypeName) -> Self {
968 match value {
969 CapabilityTypeName::Directory => fio::DirentType::Directory,
970 CapabilityTypeName::EventStream => fio::DirentType::Service,
971 CapabilityTypeName::Protocol => fio::DirentType::Service,
972 CapabilityTypeName::Service => fio::DirentType::Directory,
973 CapabilityTypeName::Storage => fio::DirentType::Directory,
974 CapabilityTypeName::Dictionary => fio::DirentType::Directory,
975 CapabilityTypeName::Resolver => fio::DirentType::Service,
976 CapabilityTypeName::Runner => fio::DirentType::Service,
977 CapabilityTypeName::Config => fio::DirentType::Unknown,
979 }
980 }
981}
982
983impl FidlIntoNative<HashMap<String, DictionaryValue>> for fdata::Dictionary {
985 fn fidl_into_native(self) -> HashMap<String, DictionaryValue> {
986 from_fidl_dict(self)
987 }
988}
989
990impl NativeIntoFidl<fdata::Dictionary> for HashMap<String, DictionaryValue> {
991 fn native_into_fidl(self) -> fdata::Dictionary {
992 to_fidl_dict(self)
993 }
994}
995
996impl FidlIntoNative<BTreeMap<String, DictionaryValue>> for fdata::Dictionary {
997 fn fidl_into_native(self) -> BTreeMap<String, DictionaryValue> {
998 from_fidl_dict_btree(self)
999 }
1000}
1001
1002impl NativeIntoFidl<fdata::Dictionary> for BTreeMap<String, DictionaryValue> {
1003 fn native_into_fidl(self) -> fdata::Dictionary {
1004 to_fidl_dict_btree(self)
1005 }
1006}
1007
1008#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1009pub enum DictionaryValue {
1010 Str(String),
1011 StrVec(Vec<String>),
1012 Null,
1013}
1014
1015impl FidlIntoNative<DictionaryValue> for Option<Box<fdata::DictionaryValue>> {
1016 fn fidl_into_native(self) -> DictionaryValue {
1017 match self {
1018 Some(v) => match *v {
1019 fdata::DictionaryValue::Str(s) => DictionaryValue::Str(s),
1020 fdata::DictionaryValue::StrVec(ss) => DictionaryValue::StrVec(ss),
1021 _ => DictionaryValue::Null,
1022 },
1023 None => DictionaryValue::Null,
1024 }
1025 }
1026}
1027
1028impl NativeIntoFidl<Option<Box<fdata::DictionaryValue>>> for DictionaryValue {
1029 fn native_into_fidl(self) -> Option<Box<fdata::DictionaryValue>> {
1030 match self {
1031 DictionaryValue::Str(s) => Some(Box::new(fdata::DictionaryValue::Str(s))),
1032 DictionaryValue::StrVec(ss) => Some(Box::new(fdata::DictionaryValue::StrVec(ss))),
1033 DictionaryValue::Null => None,
1034 }
1035 }
1036}
1037
1038fn from_fidl_dict(dict: fdata::Dictionary) -> HashMap<String, DictionaryValue> {
1039 match dict.entries {
1040 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
1041 _ => HashMap::new(),
1042 }
1043}
1044
1045fn to_fidl_dict(dict: HashMap<String, DictionaryValue>) -> fdata::Dictionary {
1046 fdata::Dictionary {
1047 entries: Some(
1048 dict.into_iter()
1049 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
1050 .collect(),
1051 ),
1052 ..Default::default()
1053 }
1054}
1055
1056fn from_fidl_dict_btree(dict: fdata::Dictionary) -> BTreeMap<String, DictionaryValue> {
1057 match dict.entries {
1058 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
1059 _ => BTreeMap::new(),
1060 }
1061}
1062
1063fn to_fidl_dict_btree(dict: BTreeMap<String, DictionaryValue>) -> fdata::Dictionary {
1064 fdata::Dictionary {
1065 entries: Some(
1066 dict.into_iter()
1067 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
1068 .collect(),
1069 ),
1070 ..Default::default()
1071 }
1072}
1073
1074#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1075#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1076pub enum EventScope {
1077 Child(ChildRef),
1078 Collection(Name),
1079}
1080
1081impl FidlIntoNative<EventScope> for fdecl::Ref {
1082 fn fidl_into_native(self) -> EventScope {
1083 match self {
1084 fdecl::Ref::Child(c) => {
1085 if let Some(_) = c.collection {
1086 panic!("Dynamic children scopes are not supported for EventStreams");
1087 } else {
1088 EventScope::Child(ChildRef { name: c.name.parse().unwrap(), collection: None })
1089 }
1090 }
1091 fdecl::Ref::Collection(collection) => {
1092 EventScope::Collection(collection.name.parse().unwrap())
1094 }
1095 _ => panic!("invalid EventScope variant"),
1096 }
1097 }
1098}
1099
1100impl NativeIntoFidl<fdecl::Ref> for EventScope {
1101 fn native_into_fidl(self) -> fdecl::Ref {
1102 match self {
1103 EventScope::Child(child) => fdecl::Ref::Child(child.native_into_fidl()),
1104 EventScope::Collection(name) => {
1105 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
1106 }
1107 }
1108 }
1109}
1110
1111#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1112#[derive(Debug, Clone, PartialEq, Eq)]
1113pub enum ExposeSource {
1114 Self_,
1115 Child(Name),
1116 Collection(Name),
1117 Framework,
1118 Capability(Name),
1119 Void,
1120}
1121
1122impl std::fmt::Display for ExposeSource {
1123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1124 match self {
1125 Self::Framework => write!(f, "framework"),
1126 Self::Child(c) => write!(f, "child `#{}`", c),
1127 Self::Collection(c) => write!(f, "collection `#{}`", c),
1128 Self::Self_ => write!(f, "self"),
1129 Self::Capability(c) => write!(f, "capability `{}`", c),
1130 Self::Void => write!(f, "void"),
1131 }
1132 }
1133}
1134
1135impl FidlIntoNative<ExposeSource> for fdecl::Ref {
1136 fn fidl_into_native(self) -> ExposeSource {
1137 match self {
1138 fdecl::Ref::Self_(_) => ExposeSource::Self_,
1139 fdecl::Ref::Child(c) => ExposeSource::Child(c.name.parse().unwrap()),
1141 fdecl::Ref::Collection(c) => ExposeSource::Collection(c.name.parse().unwrap()),
1143 fdecl::Ref::Framework(_) => ExposeSource::Framework,
1144 fdecl::Ref::Capability(c) => ExposeSource::Capability(c.name.parse().unwrap()),
1146 fdecl::Ref::VoidType(_) => ExposeSource::Void,
1147 _ => panic!("invalid ExposeSource variant"),
1148 }
1149 }
1150}
1151
1152impl NativeIntoFidl<fdecl::Ref> for ExposeSource {
1153 fn native_into_fidl(self) -> fdecl::Ref {
1154 match self {
1155 ExposeSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1156 ExposeSource::Child(name) => fdecl::Ref::Child(fdecl::ChildRef {
1157 name: name.native_into_fidl(),
1158 collection: None,
1159 }),
1160 ExposeSource::Collection(name) => {
1161 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
1162 }
1163 ExposeSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
1164 ExposeSource::Capability(name) => {
1165 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
1166 }
1167 ExposeSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
1168 }
1169 }
1170}
1171
1172#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1173#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1174pub enum ExposeTarget {
1175 Parent,
1176 Framework,
1177}
1178
1179impl std::fmt::Display for ExposeTarget {
1180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1181 match self {
1182 Self::Framework => write!(f, "framework"),
1183 Self::Parent => write!(f, "parent"),
1184 }
1185 }
1186}
1187
1188impl FidlIntoNative<ExposeTarget> for fdecl::Ref {
1189 fn fidl_into_native(self) -> ExposeTarget {
1190 match self {
1191 fdecl::Ref::Parent(_) => ExposeTarget::Parent,
1192 fdecl::Ref::Framework(_) => ExposeTarget::Framework,
1193 _ => panic!("invalid ExposeTarget variant"),
1194 }
1195 }
1196}
1197
1198impl NativeIntoFidl<fdecl::Ref> for ExposeTarget {
1199 fn native_into_fidl(self) -> fdecl::Ref {
1200 match self {
1201 ExposeTarget::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1202 ExposeTarget::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
1203 }
1204 }
1205}
1206
1207#[derive(Debug, Clone, PartialEq, Eq)]
1209pub struct ServiceSource<T> {
1210 pub source: T,
1212 pub source_name: Name,
1214}
1215
1216#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1217#[derive(Debug, Clone, PartialEq, Eq)]
1218pub enum StorageDirectorySource {
1219 Parent,
1220 Self_,
1221 Child(String),
1222}
1223
1224impl FidlIntoNative<StorageDirectorySource> for fdecl::Ref {
1225 fn fidl_into_native(self) -> StorageDirectorySource {
1226 match self {
1227 fdecl::Ref::Parent(_) => StorageDirectorySource::Parent,
1228 fdecl::Ref::Self_(_) => StorageDirectorySource::Self_,
1229 fdecl::Ref::Child(c) => StorageDirectorySource::Child(c.name),
1230 _ => panic!("invalid StorageDirectorySource variant"),
1231 }
1232 }
1233}
1234
1235impl NativeIntoFidl<fdecl::Ref> for StorageDirectorySource {
1236 fn native_into_fidl(self) -> fdecl::Ref {
1237 match self {
1238 StorageDirectorySource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1239 StorageDirectorySource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1240 StorageDirectorySource::Child(child_name) => {
1241 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
1242 }
1243 }
1244 }
1245}
1246
1247#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1248#[derive(Debug, Clone, PartialEq, Eq)]
1249pub enum DictionarySource {
1250 Parent,
1251 Self_,
1252 Child(ChildRef),
1253}
1254
1255impl FidlIntoNative<DictionarySource> for fdecl::Ref {
1256 fn fidl_into_native(self) -> DictionarySource {
1257 match self {
1258 Self::Parent(_) => DictionarySource::Parent,
1259 Self::Self_(_) => DictionarySource::Self_,
1260 Self::Child(c) => DictionarySource::Child(c.fidl_into_native()),
1261 _ => panic!("invalid DictionarySource variant"),
1262 }
1263 }
1264}
1265
1266impl NativeIntoFidl<fdecl::Ref> for DictionarySource {
1267 fn native_into_fidl(self) -> fdecl::Ref {
1268 match self {
1269 Self::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1270 Self::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1271 Self::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
1272 }
1273 }
1274}
1275
1276#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1277#[derive(Debug, Clone, PartialEq, Eq)]
1278pub enum RegistrationSource {
1279 Parent,
1280 Self_,
1281 Child(String),
1282}
1283
1284impl FidlIntoNative<RegistrationSource> for fdecl::Ref {
1285 fn fidl_into_native(self) -> RegistrationSource {
1286 match self {
1287 fdecl::Ref::Parent(_) => RegistrationSource::Parent,
1288 fdecl::Ref::Self_(_) => RegistrationSource::Self_,
1289 fdecl::Ref::Child(c) => RegistrationSource::Child(c.name),
1290 _ => panic!("invalid RegistrationSource variant"),
1291 }
1292 }
1293}
1294
1295impl NativeIntoFidl<fdecl::Ref> for RegistrationSource {
1296 fn native_into_fidl(self) -> fdecl::Ref {
1297 match self {
1298 RegistrationSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
1299 RegistrationSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
1300 RegistrationSource::Child(child_name) => {
1301 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
1302 }
1303 }
1304 }
1305}
1306
1307impl TryFrom<fdecl::Component> for ComponentDecl {
1311 type Error = Error;
1312
1313 fn try_from(decl: fdecl::Component) -> Result<Self, Self::Error> {
1314 cm_fidl_validator::validate(&decl, &mut DirectedGraph::new())
1315 .map_err(|err| Error::Validate { err })?;
1316 Ok(decl.fidl_into_native())
1317 }
1318}
1319
1320impl From<ComponentDecl> for fdecl::Component {
1322 fn from(decl: ComponentDecl) -> Self {
1323 decl.native_into_fidl()
1324 }
1325}
1326
1327#[derive(Debug, Error, Clone)]
1329pub enum Error {
1330 #[error("Fidl validation failed: {}", err)]
1331 Validate {
1332 #[source]
1333 err: cm_fidl_validator::error::ErrorList,
1334 },
1335 #[error("Invalid capability path: {}", raw)]
1336 InvalidCapabilityPath { raw: String },
1337 #[error("Invalid capability type name: {}", raw)]
1338 ParseCapabilityTypeName { raw: String },
1339}
1340
1341pub fn push_box<T>(container: &mut Box<[T]>, value: T) {
1344 let boxed = mem::replace(container, Box::from([]));
1345 let mut new_container: Vec<_> = boxed.into();
1346 new_container.push(value);
1347 *container = new_container.into();
1348}
1349
1350pub fn append_box<T>(container: &mut Box<[T]>, other: &mut Vec<T>) {
1353 let boxed = mem::replace(container, Box::from([]));
1354 let mut new_container: Vec<_> = boxed.into();
1355 new_container.append(other);
1356 *container = new_container.into();
1357}
1358
1359#[cfg(test)]
1360mod tests {
1361 use super::*;
1362 use difference::Changeset;
1363 use fidl_fuchsia_component_decl as fdecl;
1364
1365 fn offer_source_static_child(name: &str) -> OfferSource {
1366 OfferSource::Child(ChildRef { name: name.parse().unwrap(), collection: None })
1367 }
1368
1369 fn offer_target_static_child(name: &str) -> OfferTarget {
1370 OfferTarget::Child(ChildRef { name: name.parse().unwrap(), collection: None })
1371 }
1372
1373 macro_rules! test_try_from_decl {
1374 (
1375 $(
1376 $test_name:ident => {
1377 input = $input:expr,
1378 result = $result:expr,
1379 },
1380 )+
1381 ) => {
1382 $(
1383 #[test]
1384 fn $test_name() {
1385 {
1386 let res = ComponentDecl::try_from($input).expect("try_from failed");
1387 if res != $result {
1388 let a = format!("{:#?}", res);
1389 let e = format!("{:#?}", $result);
1390 panic!("Conversion from fidl to cm_rust did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
1391 }
1392 }
1393 {
1394 let res = fdecl::Component::try_from($result).expect("try_from failed");
1395 if res != $input {
1396 let a = format!("{:#?}", res);
1397 let e = format!("{:#?}", $input);
1398 panic!("Conversion from cm_rust to fidl did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
1399 }
1400 }
1401 }
1402 )+
1403 }
1404 }
1405
1406 macro_rules! test_fidl_into_and_from {
1407 (
1408 $(
1409 $test_name:ident => {
1410 input = $input:expr,
1411 input_type = $input_type:ty,
1412 result = $result:expr,
1413 result_type = $result_type:ty,
1414 },
1415 )+
1416 ) => {
1417 $(
1418 #[test]
1419 fn $test_name() {
1420 {
1421 let res: Vec<$result_type> =
1422 $input.into_iter().map(|e| e.fidl_into_native()).collect();
1423 assert_eq!(res, $result);
1424 }
1425 {
1426 let res: Vec<$input_type> =
1427 $result.into_iter().map(|e| e.native_into_fidl()).collect();
1428 assert_eq!(res, $input);
1429 }
1430 }
1431 )+
1432 }
1433 }
1434
1435 macro_rules! test_fidl_into {
1436 (
1437 $(
1438 $test_name:ident => {
1439 input = $input:expr,
1440 result = $result:expr,
1441 },
1442 )+
1443 ) => {
1444 $(
1445 #[test]
1446 fn $test_name() {
1447 test_fidl_into_helper($input, $result);
1448 }
1449 )+
1450 }
1451 }
1452
1453 fn test_fidl_into_helper<T, U>(input: T, expected_res: U)
1454 where
1455 T: FidlIntoNative<U>,
1456 U: std::cmp::PartialEq + std::fmt::Debug,
1457 {
1458 let res: U = input.fidl_into_native();
1459 assert_eq!(res, expected_res);
1460 }
1461
1462 test_try_from_decl! {
1463 try_from_empty => {
1464 input = fdecl::Component {
1465 program: None,
1466 uses: None,
1467 exposes: None,
1468 offers: None,
1469 capabilities: None,
1470 children: None,
1471 collections: None,
1472 facets: None,
1473 environments: None,
1474 ..Default::default()
1475 },
1476 result = ComponentDecl {
1477 program: None,
1478 uses: Box::from([]),
1479 exposes: Box::from([]),
1480 offers: Box::from([]),
1481 capabilities: Box::from([]),
1482 children: Box::from([]),
1483 collections: Box::from([]),
1484 facets: None,
1485 environments: Box::from([]),
1486 config: None,
1487 debug_info: None,
1488 },
1489 },
1490 try_from_all => {
1491 input = fdecl::Component {
1492 program: Some(fdecl::Program {
1493 runner: Some("elf".to_string()),
1494 info: Some(fdata::Dictionary {
1495 entries: Some(vec![
1496 fdata::DictionaryEntry {
1497 key: "args".to_string(),
1498 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
1499 },
1500 fdata::DictionaryEntry {
1501 key: "binary".to_string(),
1502 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
1503 },
1504 ]),
1505 ..Default::default()
1506 }),
1507 ..Default::default()
1508 }),
1509 uses: Some(vec![
1510 fdecl::Use::Service(fdecl::UseService {
1511 dependency_type: Some(fdecl::DependencyType::Strong),
1512 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1513 source_name: Some("netstack".to_string()),
1514 source_dictionary: Some("in/dict".to_string()),
1515 target_path: Some("/svc/mynetstack".to_string()),
1516 availability: Some(fdecl::Availability::Required),
1517 ..Default::default()
1518 }),
1519 fdecl::Use::Protocol(fdecl::UseProtocol {
1520 dependency_type: Some(fdecl::DependencyType::Strong),
1521 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1522 source_name: Some("legacy_netstack".to_string()),
1523 source_dictionary: Some("in/dict".to_string()),
1524 target_path: None,
1525 numbered_handle: Some(0xab),
1526 availability: Some(fdecl::Availability::Optional),
1527 ..Default::default()
1528 }),
1529 fdecl::Use::Protocol(fdecl::UseProtocol {
1530 dependency_type: Some(fdecl::DependencyType::Strong),
1531 source: Some(fdecl::Ref::Child(fdecl::ChildRef { name: "echo".to_string(), collection: None})),
1532 source_name: Some("echo_service".to_string()),
1533 source_dictionary: Some("in/dict".to_string()),
1534 target_path: Some("/svc/echo_service".to_string()),
1535 availability: Some(fdecl::Availability::Required),
1536 ..Default::default()
1537 }),
1538 fdecl::Use::Directory(fdecl::UseDirectory {
1539 dependency_type: Some(fdecl::DependencyType::Strong),
1540 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
1541 source_name: Some("dir".to_string()),
1542 source_dictionary: Some("dict1/me".to_string()),
1543 target_path: Some("/data".to_string()),
1544 rights: Some(fio::Operations::CONNECT),
1545 subdir: Some("foo/bar".to_string()),
1546 availability: Some(fdecl::Availability::Required),
1547 ..Default::default()
1548 }),
1549 fdecl::Use::Storage(fdecl::UseStorage {
1550 source_name: Some("cache".to_string()),
1551 target_path: Some("/cache".to_string()),
1552 availability: Some(fdecl::Availability::Required),
1553 ..Default::default()
1554 }),
1555 fdecl::Use::Storage(fdecl::UseStorage {
1556 source_name: Some("temp".to_string()),
1557 target_path: Some("/temp".to_string()),
1558 availability: Some(fdecl::Availability::Optional),
1559 ..Default::default()
1560 }),
1561 fdecl::Use::EventStream(fdecl::UseEventStream {
1562 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1563 collection: None,
1564 name: "netstack".to_string(),
1565 })),
1566 source_name: Some("stopped".to_string()),
1567 scope: Some(vec![
1568 fdecl::Ref::Child(fdecl::ChildRef {
1569 collection: None,
1570 name:"a".to_string(),
1571 }), fdecl::Ref::Collection(fdecl::CollectionRef {
1572 name:"b".to_string(),
1573 })]),
1574 target_path: Some("/svc/test".to_string()),
1575 availability: Some(fdecl::Availability::Optional),
1576 ..Default::default()
1577 }),
1578 fdecl::Use::Runner(fdecl::UseRunner {
1579 source: Some(fdecl::Ref::Environment(fdecl::EnvironmentRef {})),
1580 source_name: Some("elf".to_string()),
1581 source_dictionary: None,
1582 ..Default::default()
1583 }),
1584 fdecl::Use::Config(fdecl::UseConfiguration {
1585 source: Some(fdecl::Ref::Parent(fdecl::ParentRef)),
1586 source_name: Some("fuchsia.config.MyConfig".to_string()),
1587 target_name: Some("my_config".to_string()),
1588 availability: Some(fdecl::Availability::Required),
1589 type_: Some(fdecl::ConfigType{
1590 layout: fdecl::ConfigTypeLayout::Bool,
1591 parameters: Some(Vec::new()),
1592 constraints: Vec::new(),
1593 }),
1594 ..Default::default()
1595 }),
1596 #[cfg(fuchsia_api_level_at_least = "29")]
1597 fdecl::Use::Dictionary(fdecl::UseDictionary {
1598 dependency_type: Some(fdecl::DependencyType::Strong),
1599 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1600 source_name: Some("dictionary".to_string()),
1601 source_dictionary: Some("other_dictionary".to_string()),
1602 target_path: Some("/svc".to_string()),
1603 availability: Some(fdecl::Availability::Optional),
1604 ..Default::default()
1605 }),
1606 ]),
1607 exposes: Some(vec![
1608 fdecl::Expose::Protocol(fdecl::ExposeProtocol {
1609 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1610 name: "netstack".to_string(),
1611 collection: None,
1612 })),
1613 source_name: Some("legacy_netstack".to_string()),
1614 source_dictionary: Some("in/dict".to_string()),
1615 target_name: Some("legacy_mynetstack".to_string()),
1616 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1617 availability: Some(fdecl::Availability::Required),
1618 ..Default::default()
1619 }),
1620 fdecl::Expose::Directory(fdecl::ExposeDirectory {
1621 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1622 name: "netstack".to_string(),
1623 collection: None,
1624 })),
1625 source_name: Some("dir".to_string()),
1626 source_dictionary: Some("in/dict".to_string()),
1627 target_name: Some("data".to_string()),
1628 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1629 rights: Some(fio::Operations::CONNECT),
1630 subdir: Some("foo/bar".to_string()),
1631 availability: Some(fdecl::Availability::Optional),
1632 ..Default::default()
1633 }),
1634 fdecl::Expose::Runner(fdecl::ExposeRunner {
1635 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1636 name: "netstack".to_string(),
1637 collection: None,
1638 })),
1639 source_name: Some("elf".to_string()),
1640 source_dictionary: Some("in/dict".to_string()),
1641 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1642 target_name: Some("elf".to_string()),
1643 ..Default::default()
1644 }),
1645 fdecl::Expose::Resolver(fdecl::ExposeResolver{
1646 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1647 name: "netstack".to_string(),
1648 collection: None,
1649 })),
1650 source_name: Some("pkg".to_string()),
1651 source_dictionary: Some("in/dict".to_string()),
1652 target: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1653 target_name: Some("pkg".to_string()),
1654 ..Default::default()
1655 }),
1656 fdecl::Expose::Service(fdecl::ExposeService {
1657 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1658 name: "netstack".to_string(),
1659 collection: None,
1660 })),
1661 source_name: Some("netstack1".to_string()),
1662 source_dictionary: Some("in/dict".to_string()),
1663 target_name: Some("mynetstack".to_string()),
1664 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1665 availability: Some(fdecl::Availability::Required),
1666 ..Default::default()
1667 }),
1668 fdecl::Expose::Service(fdecl::ExposeService {
1669 source: Some(fdecl::Ref::Collection(fdecl::CollectionRef {
1670 name: "modular".to_string(),
1671 })),
1672 source_name: Some("netstack2".to_string()),
1673 source_dictionary: None,
1674 target_name: Some("mynetstack".to_string()),
1675 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1676 availability: Some(fdecl::Availability::Required),
1677 ..Default::default()
1678 }),
1679 fdecl::Expose::Dictionary(fdecl::ExposeDictionary {
1680 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1681 name: "netstack".to_string(),
1682 collection: None,
1683 })),
1684 source_name: Some("bundle".to_string()),
1685 source_dictionary: Some("in/dict".to_string()),
1686 target_name: Some("mybundle".to_string()),
1687 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1688 availability: Some(fdecl::Availability::Required),
1689 ..Default::default()
1690 }),
1691 ]),
1692 offers: Some(vec![
1693 fdecl::Offer::Protocol(fdecl::OfferProtocol {
1694 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1695 source_name: Some("legacy_netstack".to_string()),
1696 source_dictionary: Some("in/dict".to_string()),
1697 target: Some(fdecl::Ref::Child(
1698 fdecl::ChildRef {
1699 name: "echo".to_string(),
1700 collection: None,
1701 }
1702 )),
1703 target_name: Some("legacy_mynetstack".to_string()),
1704 dependency_type: Some(fdecl::DependencyType::Weak),
1705 availability: Some(fdecl::Availability::Required),
1706 ..Default::default()
1707 }),
1708 fdecl::Offer::Directory(fdecl::OfferDirectory {
1709 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1710 source_name: Some("dir".to_string()),
1711 source_dictionary: Some("in/dict".to_string()),
1712 target: Some(fdecl::Ref::Collection(
1713 fdecl::CollectionRef { name: "modular".to_string() }
1714 )),
1715 target_name: Some("data".to_string()),
1716 rights: Some(fio::Operations::CONNECT),
1717 subdir: None,
1718 dependency_type: Some(fdecl::DependencyType::Strong),
1719 availability: Some(fdecl::Availability::Optional),
1720 ..Default::default()
1721 }),
1722 fdecl::Offer::Storage(fdecl::OfferStorage {
1723 source_name: Some("cache".to_string()),
1724 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
1725 target: Some(fdecl::Ref::Collection(
1726 fdecl::CollectionRef { name: "modular".to_string() }
1727 )),
1728 target_name: Some("cache".to_string()),
1729 availability: Some(fdecl::Availability::Required),
1730 ..Default::default()
1731 }),
1732 fdecl::Offer::Runner(fdecl::OfferRunner {
1733 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1734 source_name: Some("elf".to_string()),
1735 source_dictionary: Some("in/dict".to_string()),
1736 target: Some(fdecl::Ref::Child(
1737 fdecl::ChildRef {
1738 name: "echo".to_string(),
1739 collection: None,
1740 }
1741 )),
1742 target_name: Some("elf2".to_string()),
1743 ..Default::default()
1744 }),
1745 fdecl::Offer::Resolver(fdecl::OfferResolver{
1746 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1747 source_name: Some("pkg".to_string()),
1748 source_dictionary: Some("in/dict".to_string()),
1749 target: Some(fdecl::Ref::Child(
1750 fdecl::ChildRef {
1751 name: "echo".to_string(),
1752 collection: None,
1753 }
1754 )),
1755 target_name: Some("pkg".to_string()),
1756 ..Default::default()
1757 }),
1758 fdecl::Offer::Service(fdecl::OfferService {
1759 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1760 source_name: Some("netstack1".to_string()),
1761 source_dictionary: Some("in/dict".to_string()),
1762 target: Some(fdecl::Ref::Child(
1763 fdecl::ChildRef {
1764 name: "echo".to_string(),
1765 collection: None,
1766 }
1767 )),
1768 target_name: Some("mynetstack1".to_string()),
1769 availability: Some(fdecl::Availability::Required),
1770 dependency_type: Some(fdecl::DependencyType::Strong),
1771 ..Default::default()
1772 }),
1773 fdecl::Offer::Service(fdecl::OfferService {
1774 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1775 source_name: Some("netstack2".to_string()),
1776 source_dictionary: None,
1777 target: Some(fdecl::Ref::Child(
1778 fdecl::ChildRef {
1779 name: "echo".to_string(),
1780 collection: None,
1781 }
1782 )),
1783 target_name: Some("mynetstack2".to_string()),
1784 availability: Some(fdecl::Availability::Optional),
1785 dependency_type: Some(fdecl::DependencyType::Strong),
1786 ..Default::default()
1787 }),
1788 fdecl::Offer::Service(fdecl::OfferService {
1789 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1790 source_name: Some("netstack3".to_string()),
1791 source_dictionary: None,
1792 target: Some(fdecl::Ref::Child(
1793 fdecl::ChildRef {
1794 name: "echo".to_string(),
1795 collection: None,
1796 }
1797 )),
1798 target_name: Some("mynetstack3".to_string()),
1799 source_instance_filter: Some(vec!["allowedinstance".to_string()]),
1800 renamed_instances: Some(vec![fdecl::NameMapping{source_name: "default".to_string(), target_name: "allowedinstance".to_string()}]),
1801 availability: Some(fdecl::Availability::Required),
1802 dependency_type: Some(fdecl::DependencyType::Strong),
1803 ..Default::default()
1804 }),
1805 fdecl::Offer::Dictionary(fdecl::OfferDictionary {
1806 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1807 source_name: Some("bundle".to_string()),
1808 source_dictionary: Some("in/dict".to_string()),
1809 target: Some(fdecl::Ref::Child(
1810 fdecl::ChildRef {
1811 name: "echo".to_string(),
1812 collection: None,
1813 }
1814 )),
1815 target_name: Some("mybundle".to_string()),
1816 dependency_type: Some(fdecl::DependencyType::Weak),
1817 availability: Some(fdecl::Availability::Required),
1818 ..Default::default()
1819 }),
1820 ]),
1821 capabilities: Some(vec![
1822 fdecl::Capability::Service(fdecl::Service {
1823 name: Some("netstack".to_string()),
1824 source_path: Some("/netstack".to_string()),
1825 ..Default::default()
1826 }),
1827 fdecl::Capability::Protocol(fdecl::Protocol {
1828 name: Some("netstack2".to_string()),
1829 source_path: Some("/netstack2".to_string()),
1830 delivery: Some(fdecl::DeliveryType::Immediate),
1831 ..Default::default()
1832 }),
1833 fdecl::Capability::Directory(fdecl::Directory {
1834 name: Some("data".to_string()),
1835 source_path: Some("/data".to_string()),
1836 rights: Some(fio::Operations::CONNECT),
1837 ..Default::default()
1838 }),
1839 fdecl::Capability::Storage(fdecl::Storage {
1840 name: Some("cache".to_string()),
1841 backing_dir: Some("data".to_string()),
1842 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
1843 subdir: Some("cache".to_string()),
1844 storage_id: Some(fdecl::StorageId::StaticInstanceId),
1845 ..Default::default()
1846 }),
1847 fdecl::Capability::Runner(fdecl::Runner {
1848 name: Some("elf".to_string()),
1849 source_path: Some("/elf".to_string()),
1850 ..Default::default()
1851 }),
1852 fdecl::Capability::Resolver(fdecl::Resolver {
1853 name: Some("pkg".to_string()),
1854 source_path: Some("/pkg_resolver".to_string()),
1855 ..Default::default()
1856 }),
1857 fdecl::Capability::Dictionary(fdecl::Dictionary {
1858 name: Some("dict1".to_string()),
1859 ..Default::default()
1860 }),
1861 fdecl::Capability::Dictionary(fdecl::Dictionary {
1862 name: Some("dict2".to_string()),
1863 source_path: Some("/in/other".to_string()),
1864 ..Default::default()
1865 }),
1866 ]),
1867 children: Some(vec![
1868 fdecl::Child {
1869 name: Some("netstack".to_string()),
1870 url: Some("fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm"
1871 .to_string()),
1872 startup: Some(fdecl::StartupMode::Lazy),
1873 on_terminate: None,
1874 environment: None,
1875 ..Default::default()
1876 },
1877 fdecl::Child {
1878 name: Some("gtest".to_string()),
1879 url: Some("fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string()),
1880 startup: Some(fdecl::StartupMode::Lazy),
1881 on_terminate: Some(fdecl::OnTerminate::None),
1882 environment: None,
1883 ..Default::default()
1884 },
1885 fdecl::Child {
1886 name: Some("echo".to_string()),
1887 url: Some("fuchsia-pkg://fuchsia.com/echo#meta/echo.cm"
1888 .to_string()),
1889 startup: Some(fdecl::StartupMode::Eager),
1890 on_terminate: Some(fdecl::OnTerminate::Reboot),
1891 environment: Some("test_env".to_string()),
1892 ..Default::default()
1893 },
1894 ]),
1895 collections: Some(vec![
1896 fdecl::Collection {
1897 name: Some("modular".to_string()),
1898 durability: Some(fdecl::Durability::Transient),
1899 environment: None,
1900 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
1901 allow_long_names: Some(true),
1902 persistent_storage: None,
1903 ..Default::default()
1904 },
1905 fdecl::Collection {
1906 name: Some("tests".to_string()),
1907 durability: Some(fdecl::Durability::Transient),
1908 environment: Some("test_env".to_string()),
1909 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
1910 allow_long_names: Some(true),
1911 persistent_storage: Some(true),
1912 ..Default::default()
1913 },
1914 ]),
1915 facets: Some(fdata::Dictionary {
1916 entries: Some(vec![
1917 fdata::DictionaryEntry {
1918 key: "author".to_string(),
1919 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
1920 },
1921 ]),
1922 ..Default::default()
1923 }),
1924 environments: Some(vec![
1925 fdecl::Environment {
1926 name: Some("test_env".to_string()),
1927 extends: Some(fdecl::EnvironmentExtends::Realm),
1928 runners: Some(vec![
1929 fdecl::RunnerRegistration {
1930 source_name: Some("runner".to_string()),
1931 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1932 name: "gtest".to_string(),
1933 collection: None,
1934 })),
1935 target_name: Some("gtest-runner".to_string()),
1936 ..Default::default()
1937 }
1938 ]),
1939 resolvers: Some(vec![
1940 fdecl::ResolverRegistration {
1941 resolver: Some("pkg_resolver".to_string()),
1942 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
1943 scheme: Some("fuchsia-pkg".to_string()),
1944 ..Default::default()
1945 }
1946 ]),
1947 debug_capabilities: Some(vec![
1948 fdecl::DebugRegistration::Protocol(fdecl::DebugProtocolRegistration {
1949 source_name: Some("some_protocol".to_string()),
1950 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
1951 name: "gtest".to_string(),
1952 collection: None,
1953 })),
1954 target_name: Some("some_protocol".to_string()),
1955 ..Default::default()
1956 })
1957 ]),
1958 stop_timeout_ms: Some(4567),
1959 ..Default::default()
1960 }
1961 ]),
1962 config: Some(fdecl::ConfigSchema{
1963 fields: Some(vec![
1964 fdecl::ConfigField {
1965 key: Some("enable_logging".to_string()),
1966 type_: Some(fdecl::ConfigType {
1967 layout: fdecl::ConfigTypeLayout::Bool,
1968 parameters: Some(vec![]),
1969 constraints: vec![],
1970 }),
1971 mutability: Some(Default::default()),
1972 ..Default::default()
1973 }
1974 ]),
1975 checksum: Some(fdecl::ConfigChecksum::Sha256([
1976 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
1977 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
1978 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
1979 ])),
1980 value_source: Some(
1981 fdecl::ConfigValueSource::PackagePath("fake.cvf".to_string())
1982 ),
1983 ..Default::default()
1984 }),
1985 ..Default::default()
1986 },
1987 result = {
1988 ComponentDecl {
1989 program: Some(ProgramDecl {
1990 runner: Some("elf".parse().unwrap()),
1991 info: fdata::Dictionary {
1992 entries: Some(vec![
1993 fdata::DictionaryEntry {
1994 key: "args".to_string(),
1995 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
1996 },
1997 fdata::DictionaryEntry{
1998 key: "binary".to_string(),
1999 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
2000 },
2001 ]),
2002 ..Default::default()
2003 },
2004 }),
2005 uses: Box::from([
2006 UseDecl::Service(UseServiceDecl {
2007 dependency_type: DependencyType::Strong,
2008 source: UseSource::Parent,
2009 source_name: "netstack".parse().unwrap(),
2010 source_dictionary: "in/dict".parse().unwrap(),
2011 target_path: "/svc/mynetstack".parse().unwrap(),
2012 availability: Availability::Required,
2013 }),
2014 UseDecl::Protocol(UseProtocolDecl {
2015 dependency_type: DependencyType::Strong,
2016 source: UseSource::Parent,
2017 source_name: "legacy_netstack".parse().unwrap(),
2018 source_dictionary: "in/dict".parse().unwrap(),
2019 target_path: None,
2020 numbered_handle: Some(HandleType::from(0xab)),
2021 availability: Availability::Optional,
2022 }),
2023 UseDecl::Protocol(UseProtocolDecl {
2024 dependency_type: DependencyType::Strong,
2025 source: UseSource::Child("echo".parse().unwrap()),
2026 source_name: "echo_service".parse().unwrap(),
2027 source_dictionary: "in/dict".parse().unwrap(),
2028 target_path: Some("/svc/echo_service".parse().unwrap()),
2029 numbered_handle: None,
2030 availability: Availability::Required,
2031 }),
2032 UseDecl::Directory(UseDirectoryDecl {
2033 dependency_type: DependencyType::Strong,
2034 source: UseSource::Self_,
2035 source_name: "dir".parse().unwrap(),
2036 source_dictionary: "dict1/me".parse().unwrap(),
2037 target_path: "/data".parse().unwrap(),
2038 rights: fio::Operations::CONNECT,
2039 subdir: "foo/bar".parse().unwrap(),
2040 availability: Availability::Required,
2041 }),
2042 UseDecl::Storage(UseStorageDecl {
2043 source_name: "cache".parse().unwrap(),
2044 target_path: "/cache".parse().unwrap(),
2045 availability: Availability::Required,
2046 }),
2047 UseDecl::Storage(UseStorageDecl {
2048 source_name: "temp".parse().unwrap(),
2049 target_path: "/temp".parse().unwrap(),
2050 availability: Availability::Optional,
2051 }),
2052 UseDecl::EventStream(Box::new(UseEventStreamDecl {
2053 source: UseSource::Child("netstack".parse().unwrap()),
2054 scope: Some(Box::from([EventScope::Child(ChildRef{ name: "a".parse().unwrap(), collection: None}), EventScope::Collection("b".parse().unwrap())])),
2055 source_name: "stopped".parse().unwrap(),
2056 target_path: "/svc/test".parse().unwrap(),
2057 filter: None,
2058 availability: Availability::Optional,
2059 })),
2060 UseDecl::Runner(UseRunnerDecl {
2061 source: UseSource::Environment,
2062 source_name: "elf".parse().unwrap(),
2063 source_dictionary: ".".parse().unwrap(),
2064 }),
2065 UseDecl::Config(Box::new(UseConfigurationDecl {
2066 source: UseSource::Parent,
2067 source_name: "fuchsia.config.MyConfig".parse().unwrap(),
2068 target_name: "my_config".parse().unwrap(),
2069 availability: Availability::Required,
2070 type_: ConfigValueType::Bool,
2071 default: None,
2072 source_dictionary: ".".parse().unwrap(),
2073 })),
2074 #[cfg(fuchsia_api_level_at_least = "29")]
2075 UseDecl::Dictionary(UseDictionaryDecl {
2076 dependency_type: DependencyType::Strong,
2077 source: UseSource::Parent,
2078 source_name: "dictionary".parse().unwrap(),
2079 source_dictionary: "other_dictionary".parse().unwrap(),
2080 target_path: "/svc".parse().unwrap(),
2081 availability: Availability::Optional,
2082 }),
2083 ]),
2084 exposes: Box::from([
2085 ExposeDecl::Protocol(ExposeProtocolDecl {
2086 source: ExposeSource::Child("netstack".parse().unwrap()),
2087 source_name: "legacy_netstack".parse().unwrap(),
2088 source_dictionary: "in/dict".parse().unwrap(),
2089 target_name: "legacy_mynetstack".parse().unwrap(),
2090 target: ExposeTarget::Parent,
2091 availability: Availability::Required,
2092 }),
2093 ExposeDecl::Directory(ExposeDirectoryDecl {
2094 source: ExposeSource::Child("netstack".parse().unwrap()),
2095 source_name: "dir".parse().unwrap(),
2096 source_dictionary: "in/dict".parse().unwrap(),
2097 target_name: "data".parse().unwrap(),
2098 target: ExposeTarget::Parent,
2099 rights: Some(fio::Operations::CONNECT),
2100 subdir: "foo/bar".parse().unwrap(),
2101 availability: Availability::Optional,
2102 }),
2103 ExposeDecl::Runner(ExposeRunnerDecl {
2104 source: ExposeSource::Child("netstack".parse().unwrap()),
2105 source_name: "elf".parse().unwrap(),
2106 source_dictionary: "in/dict".parse().unwrap(),
2107 target: ExposeTarget::Parent,
2108 target_name: "elf".parse().unwrap(),
2109 }),
2110 ExposeDecl::Resolver(ExposeResolverDecl {
2111 source: ExposeSource::Child("netstack".parse().unwrap()),
2112 source_name: "pkg".parse().unwrap(),
2113 source_dictionary: "in/dict".parse().unwrap(),
2114 target: ExposeTarget::Parent,
2115 target_name: "pkg".parse().unwrap(),
2116 }),
2117 ExposeDecl::Service(ExposeServiceDecl {
2118 source: ExposeSource::Child("netstack".parse().unwrap()),
2119 source_name: "netstack1".parse().unwrap(),
2120 source_dictionary: "in/dict".parse().unwrap(),
2121 target_name: "mynetstack".parse().unwrap(),
2122 target: ExposeTarget::Parent,
2123 availability: Availability::Required,
2124 }),
2125 ExposeDecl::Service(ExposeServiceDecl {
2126 source: ExposeSource::Collection("modular".parse().unwrap()),
2127 source_name: "netstack2".parse().unwrap(),
2128 source_dictionary: ".".parse().unwrap(),
2129 target_name: "mynetstack".parse().unwrap(),
2130 target: ExposeTarget::Parent,
2131 availability: Availability::Required,
2132 }),
2133 ExposeDecl::Dictionary(ExposeDictionaryDecl {
2134 source: ExposeSource::Child("netstack".parse().unwrap()),
2135 source_name: "bundle".parse().unwrap(),
2136 source_dictionary: "in/dict".parse().unwrap(),
2137 target_name: "mybundle".parse().unwrap(),
2138 target: ExposeTarget::Parent,
2139 availability: Availability::Required,
2140 }),
2141 ]),
2142 offers: Box::from([
2143 OfferDecl::Protocol(OfferProtocolDecl {
2144 source: OfferSource::Parent,
2145 source_name: "legacy_netstack".parse().unwrap(),
2146 source_dictionary: "in/dict".parse().unwrap(),
2147 target: offer_target_static_child("echo"),
2148 target_name: "legacy_mynetstack".parse().unwrap(),
2149 dependency_type: DependencyType::Weak,
2150 availability: Availability::Required,
2151 }),
2152 OfferDecl::Directory(Box::new(OfferDirectoryDecl {
2153 source: OfferSource::Parent,
2154 source_name: "dir".parse().unwrap(),
2155 source_dictionary: "in/dict".parse().unwrap(),
2156 target: OfferTarget::Collection("modular".parse().unwrap()),
2157 target_name: "data".parse().unwrap(),
2158 rights: Some(fio::Operations::CONNECT),
2159 subdir: ".".parse().unwrap(),
2160 dependency_type: DependencyType::Strong,
2161 availability: Availability::Optional,
2162 })),
2163 OfferDecl::Storage(OfferStorageDecl {
2164 source_name: "cache".parse().unwrap(),
2165 source: OfferSource::Self_,
2166 target: OfferTarget::Collection("modular".parse().unwrap()),
2167 target_name: "cache".parse().unwrap(),
2168 availability: Availability::Required,
2169 }),
2170 OfferDecl::Runner(OfferRunnerDecl {
2171 source: OfferSource::Parent,
2172 source_name: "elf".parse().unwrap(),
2173 source_dictionary: "in/dict".parse().unwrap(),
2174 target: offer_target_static_child("echo"),
2175 target_name: "elf2".parse().unwrap(),
2176 }),
2177 OfferDecl::Resolver(OfferResolverDecl {
2178 source: OfferSource::Parent,
2179 source_name: "pkg".parse().unwrap(),
2180 source_dictionary: "in/dict".parse().unwrap(),
2181 target: offer_target_static_child("echo"),
2182 target_name: "pkg".parse().unwrap(),
2183 }),
2184 OfferDecl::Service(Box::new(OfferServiceDecl {
2185 source: OfferSource::Parent,
2186 source_name: "netstack1".parse().unwrap(),
2187 source_dictionary: "in/dict".parse().unwrap(),
2188 source_instance_filter: None,
2189 renamed_instances: None,
2190 target: offer_target_static_child("echo"),
2191 target_name: "mynetstack1".parse().unwrap(),
2192 availability: Availability::Required,
2193 dependency_type: Default::default(),
2194 })),
2195 OfferDecl::Service(Box::new(OfferServiceDecl {
2196 source: OfferSource::Parent,
2197 source_name: "netstack2".parse().unwrap(),
2198 source_dictionary: ".".parse().unwrap(),
2199 source_instance_filter: None,
2200 renamed_instances: None,
2201 target: offer_target_static_child("echo"),
2202 target_name: "mynetstack2".parse().unwrap(),
2203 availability: Availability::Optional,
2204 dependency_type: Default::default(),
2205 })),
2206 OfferDecl::Service(Box::new(OfferServiceDecl {
2207 source: OfferSource::Parent,
2208 source_name: "netstack3".parse().unwrap(),
2209 source_dictionary: ".".parse().unwrap(),
2210 source_instance_filter: Some(Box::from(["allowedinstance".parse().unwrap()])),
2211 renamed_instances: Some(Box::from([NameMapping{source_name: "default".parse().unwrap(), target_name: "allowedinstance".parse().unwrap()}])),
2212 target: offer_target_static_child("echo"),
2213 target_name: "mynetstack3".parse().unwrap(),
2214 availability: Availability::Required,
2215 dependency_type: Default::default(),
2216 })),
2217 OfferDecl::Dictionary(OfferDictionaryDecl {
2218 source: OfferSource::Parent,
2219 source_name: "bundle".parse().unwrap(),
2220 source_dictionary: "in/dict".parse().unwrap(),
2221 target: offer_target_static_child("echo"),
2222 target_name: "mybundle".parse().unwrap(),
2223 dependency_type: DependencyType::Weak,
2224 availability: Availability::Required,
2225 }),
2226 ]),
2227 capabilities: Box::from([
2228 CapabilityDecl::Service(ServiceDecl {
2229 name: "netstack".parse().unwrap(),
2230 source_path: Some("/netstack".parse().unwrap()),
2231 }),
2232 CapabilityDecl::Protocol(ProtocolDecl {
2233 name: "netstack2".parse().unwrap(),
2234 source_path: Some("/netstack2".parse().unwrap()),
2235 delivery: DeliveryType::Immediate,
2236 }),
2237 CapabilityDecl::Directory(DirectoryDecl {
2238 name: "data".parse().unwrap(),
2239 source_path: Some("/data".parse().unwrap()),
2240 rights: fio::Operations::CONNECT,
2241 }),
2242 CapabilityDecl::Storage(StorageDecl {
2243 name: "cache".parse().unwrap(),
2244 backing_dir: "data".parse().unwrap(),
2245 source: StorageDirectorySource::Parent,
2246 subdir: "cache".parse().unwrap(),
2247 storage_id: fdecl::StorageId::StaticInstanceId,
2248 }),
2249 CapabilityDecl::Runner(RunnerDecl {
2250 name: "elf".parse().unwrap(),
2251 source_path: Some("/elf".parse().unwrap()),
2252 }),
2253 CapabilityDecl::Resolver(ResolverDecl {
2254 name: "pkg".parse().unwrap(),
2255 source_path: Some("/pkg_resolver".parse().unwrap()),
2256 }),
2257 CapabilityDecl::Dictionary(DictionaryDecl {
2258 name: "dict1".parse().unwrap(),
2259 source_path: None,
2260 }),
2261 CapabilityDecl::Dictionary(DictionaryDecl {
2262 name: "dict2".parse().unwrap(),
2263 source_path: Some("/in/other".parse().unwrap()),
2264 }),
2265 ]),
2266 children: Box::from([
2267 ChildDecl {
2268 name: "netstack".parse().unwrap(),
2269 url: "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm".parse().unwrap(),
2270 startup: fdecl::StartupMode::Lazy,
2271 on_terminate: None,
2272 environment: None,
2273 config_overrides: None,
2274 },
2275 ChildDecl {
2276 name: "gtest".parse().unwrap(),
2277 url: "fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".parse().unwrap(),
2278 startup: fdecl::StartupMode::Lazy,
2279 on_terminate: Some(fdecl::OnTerminate::None),
2280 environment: None,
2281 config_overrides: None,
2282 },
2283 ChildDecl {
2284 name: "echo".parse().unwrap(),
2285 url: "fuchsia-pkg://fuchsia.com/echo#meta/echo.cm".parse().unwrap(),
2286 startup: fdecl::StartupMode::Eager,
2287 on_terminate: Some(fdecl::OnTerminate::Reboot),
2288 environment: Some("test_env".parse().unwrap()),
2289 config_overrides: None,
2290 },
2291 ]),
2292 collections: Box::from([
2293 CollectionDecl {
2294 name: "modular".parse().unwrap(),
2295 durability: fdecl::Durability::Transient,
2296 environment: None,
2297 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2298 allow_long_names: true,
2299 persistent_storage: None,
2300 },
2301 CollectionDecl {
2302 name: "tests".parse().unwrap(),
2303 durability: fdecl::Durability::Transient,
2304 environment: Some("test_env".parse().unwrap()),
2305 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
2306 allow_long_names: true,
2307 persistent_storage: Some(true),
2308 },
2309 ]),
2310 facets: Some(fdata::Dictionary {
2311 entries: Some(vec![
2312 fdata::DictionaryEntry {
2313 key: "author".to_string(),
2314 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
2315 },
2316 ]),
2317 ..Default::default()
2318 }),
2319 environments: Box::from([
2320 EnvironmentDecl {
2321 name: "test_env".parse().unwrap(),
2322 extends: fdecl::EnvironmentExtends::Realm,
2323 runners: Box::from([
2324 RunnerRegistration {
2325 source_name: "runner".parse().unwrap(),
2326 source: RegistrationSource::Child("gtest".to_string()),
2327 target_name: "gtest-runner".parse().unwrap(),
2328 }
2329 ]),
2330 resolvers: Box::from([
2331 ResolverRegistration {
2332 resolver: "pkg_resolver".parse().unwrap(),
2333 source: RegistrationSource::Parent,
2334 scheme: "fuchsia-pkg".to_string(),
2335 }
2336 ]),
2337 debug_capabilities: Box::from([
2338 DebugRegistration::Protocol(DebugProtocolRegistration {
2339 source_name: "some_protocol".parse().unwrap(),
2340 source: RegistrationSource::Child("gtest".to_string()),
2341 target_name: "some_protocol".parse().unwrap(),
2342 })
2343 ]),
2344 stop_timeout_ms: Some(4567),
2345 }
2346 ]),
2347 config: Some(ConfigDecl {
2348 fields: Box::from([
2349 ConfigField {
2350 key: "enable_logging".to_string(),
2351 type_: ConfigValueType::Bool,
2352 mutability: ConfigMutability::default(),
2353 }
2354 ]),
2355 checksum: ConfigChecksum::Sha256([
2356 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
2357 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
2358 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
2359 ]),
2360 value_source: ConfigValueSource::PackagePath("fake.cvf".to_string())
2361 }),
2362 debug_info: None,
2363 }
2364 },
2365 },
2366 }
2367
2368 test_fidl_into_and_from! {
2369 fidl_into_and_from_use_source => {
2370 input = vec![
2371 fdecl::Ref::Parent(fdecl::ParentRef{}),
2372 fdecl::Ref::Framework(fdecl::FrameworkRef{}),
2373 fdecl::Ref::Debug(fdecl::DebugRef{}),
2374 fdecl::Ref::Capability(fdecl::CapabilityRef {name: "capability".to_string()}),
2375 fdecl::Ref::Child(fdecl::ChildRef {
2376 name: "foo".into(),
2377 collection: None,
2378 }),
2379 fdecl::Ref::Environment(fdecl::EnvironmentRef{}),
2380 ],
2381 input_type = fdecl::Ref,
2382 result = vec![
2383 UseSource::Parent,
2384 UseSource::Framework,
2385 UseSource::Debug,
2386 UseSource::Capability("capability".parse().unwrap()),
2387 UseSource::Child("foo".parse().unwrap()),
2388 UseSource::Environment,
2389 ],
2390 result_type = UseSource,
2391 },
2392 fidl_into_and_from_expose_source => {
2393 input = vec![
2394 fdecl::Ref::Self_(fdecl::SelfRef {}),
2395 fdecl::Ref::Child(fdecl::ChildRef {
2396 name: "foo".into(),
2397 collection: None,
2398 }),
2399 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2400 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
2401 ],
2402 input_type = fdecl::Ref,
2403 result = vec![
2404 ExposeSource::Self_,
2405 ExposeSource::Child("foo".parse().unwrap()),
2406 ExposeSource::Framework,
2407 ExposeSource::Collection("foo".parse().unwrap()),
2408 ],
2409 result_type = ExposeSource,
2410 },
2411 fidl_into_and_from_offer_source => {
2412 input = vec![
2413 fdecl::Ref::Self_(fdecl::SelfRef {}),
2414 fdecl::Ref::Child(fdecl::ChildRef {
2415 name: "foo".into(),
2416 collection: None,
2417 }),
2418 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2419 fdecl::Ref::Capability(fdecl::CapabilityRef { name: "foo".to_string() }),
2420 fdecl::Ref::Parent(fdecl::ParentRef {}),
2421 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
2422 fdecl::Ref::VoidType(fdecl::VoidRef {}),
2423 ],
2424 input_type = fdecl::Ref,
2425 result = vec![
2426 OfferSource::Self_,
2427 offer_source_static_child("foo"),
2428 OfferSource::Framework,
2429 OfferSource::Capability("foo".parse().unwrap()),
2430 OfferSource::Parent,
2431 OfferSource::Collection("foo".parse().unwrap()),
2432 OfferSource::Void,
2433 ],
2434 result_type = OfferSource,
2435 },
2436 fidl_into_and_from_dictionary_source => {
2437 input = vec![
2438 fdecl::Ref::Self_(fdecl::SelfRef {}),
2439 fdecl::Ref::Child(fdecl::ChildRef {
2440 name: "foo".into(),
2441 collection: None,
2442 }),
2443 fdecl::Ref::Parent(fdecl::ParentRef {}),
2444 ],
2445 input_type = fdecl::Ref,
2446 result = vec![
2447 DictionarySource::Self_,
2448 DictionarySource::Child(ChildRef {
2449 name: "foo".parse().unwrap(),
2450 collection: None,
2451 }),
2452 DictionarySource::Parent,
2453 ],
2454 result_type = DictionarySource,
2455 },
2456
2457 fidl_into_and_from_capability_without_path => {
2458 input = vec![
2459 fdecl::Protocol {
2460 name: Some("foo_protocol".to_string()),
2461 source_path: None,
2462 delivery: Some(fdecl::DeliveryType::Immediate),
2463 ..Default::default()
2464 },
2465 ],
2466 input_type = fdecl::Protocol,
2467 result = vec![
2468 ProtocolDecl {
2469 name: "foo_protocol".parse().unwrap(),
2470 source_path: None,
2471 delivery: DeliveryType::Immediate,
2472 }
2473 ],
2474 result_type = ProtocolDecl,
2475 },
2476 fidl_into_and_from_storage_capability => {
2477 input = vec![
2478 fdecl::Storage {
2479 name: Some("minfs".to_string()),
2480 backing_dir: Some("minfs".into()),
2481 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2482 name: "foo".into(),
2483 collection: None,
2484 })),
2485 subdir: None,
2486 storage_id: Some(fdecl::StorageId::StaticInstanceIdOrMoniker),
2487 ..Default::default()
2488 },
2489 ],
2490 input_type = fdecl::Storage,
2491 result = vec![
2492 StorageDecl {
2493 name: "minfs".parse().unwrap(),
2494 backing_dir: "minfs".parse().unwrap(),
2495 source: StorageDirectorySource::Child("foo".to_string()),
2496 subdir: ".".parse().unwrap(),
2497 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
2498 },
2499 ],
2500 result_type = StorageDecl,
2501 },
2502 fidl_into_and_from_storage_capability_restricted => {
2503 input = vec![
2504 fdecl::Storage {
2505 name: Some("minfs".to_string()),
2506 backing_dir: Some("minfs".into()),
2507 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2508 name: "foo".into(),
2509 collection: None,
2510 })),
2511 subdir: None,
2512 storage_id: Some(fdecl::StorageId::StaticInstanceId),
2513 ..Default::default()
2514 },
2515 ],
2516 input_type = fdecl::Storage,
2517 result = vec![
2518 StorageDecl {
2519 name: "minfs".parse().unwrap(),
2520 backing_dir: "minfs".parse().unwrap(),
2521 source: StorageDirectorySource::Child("foo".to_string()),
2522 subdir: ".".parse().unwrap(),
2523 storage_id: fdecl::StorageId::StaticInstanceId,
2524 },
2525 ],
2526 result_type = StorageDecl,
2527 },
2528 }
2529
2530 test_fidl_into! {
2531 all_with_omitted_defaults => {
2532 input = fdecl::Component {
2533 program: Some(fdecl::Program {
2534 runner: Some("elf".to_string()),
2535 info: Some(fdata::Dictionary {
2536 entries: Some(vec![]),
2537 ..Default::default()
2538 }),
2539 ..Default::default()
2540 }),
2541 uses: Some(vec![]),
2542 exposes: Some(vec![]),
2543 offers: Some(vec![]),
2544 capabilities: Some(vec![]),
2545 children: Some(vec![]),
2546 collections: Some(vec![
2547 fdecl::Collection {
2548 name: Some("modular".to_string()),
2549 durability: Some(fdecl::Durability::Transient),
2550 environment: None,
2551 allowed_offers: None,
2552 allow_long_names: None,
2553 persistent_storage: None,
2554 ..Default::default()
2555 },
2556 fdecl::Collection {
2557 name: Some("tests".to_string()),
2558 durability: Some(fdecl::Durability::Transient),
2559 environment: Some("test_env".to_string()),
2560 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
2561 allow_long_names: None,
2562 persistent_storage: Some(false),
2563 ..Default::default()
2564 },
2565 fdecl::Collection {
2566 name: Some("dyn_offers".to_string()),
2567 durability: Some(fdecl::Durability::Transient),
2568 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
2569 allow_long_names: None,
2570 persistent_storage: Some(true),
2571 ..Default::default()
2572 },
2573 fdecl::Collection {
2574 name: Some("long_child_names".to_string()),
2575 durability: Some(fdecl::Durability::Transient),
2576 allowed_offers: None,
2577 allow_long_names: Some(true),
2578 persistent_storage: None,
2579 ..Default::default()
2580 },
2581 ]),
2582 facets: Some(fdata::Dictionary{
2583 entries: Some(vec![]),
2584 ..Default::default()
2585 }),
2586 environments: Some(vec![]),
2587 ..Default::default()
2588 },
2589 result = {
2590 ComponentDecl {
2591 program: Some(ProgramDecl {
2592 runner: Some("elf".parse().unwrap()),
2593 info: fdata::Dictionary {
2594 entries: Some(vec![]),
2595 ..Default::default()
2596 },
2597 }),
2598 uses: Box::from([]),
2599 exposes: Box::from([]),
2600 offers: Box::from([]),
2601 capabilities: Box::from([]),
2602 children: Box::from([]),
2603 collections: Box::from([
2604 CollectionDecl {
2605 name: "modular".parse().unwrap(),
2606 durability: fdecl::Durability::Transient,
2607 environment: None,
2608 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2609 allow_long_names: false,
2610 persistent_storage: None,
2611 },
2612 CollectionDecl {
2613 name: "tests".parse().unwrap(),
2614 durability: fdecl::Durability::Transient,
2615 environment: Some("test_env".parse().unwrap()),
2616 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2617 allow_long_names: false,
2618 persistent_storage: Some(false),
2619 },
2620 CollectionDecl {
2621 name: "dyn_offers".parse().unwrap(),
2622 durability: fdecl::Durability::Transient,
2623 environment: None,
2624 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
2625 allow_long_names: false,
2626 persistent_storage: Some(true),
2627 },
2628 CollectionDecl {
2629 name: "long_child_names".parse().unwrap(),
2630 durability: fdecl::Durability::Transient,
2631 environment: None,
2632 allowed_offers: cm_types::AllowedOffers::StaticOnly,
2633 allow_long_names: true,
2634 persistent_storage: None,
2635 },
2636 ]),
2637 facets: Some(fdata::Dictionary{
2638 entries: Some(vec![]),
2639 ..Default::default()
2640 }),
2641 environments: Box::from([]),
2642 config: None,
2643 debug_info: None,
2644 }
2645 },
2646 },
2647 }
2648
2649 #[test]
2650 fn default_expose_availability() {
2651 let source = fdecl::Ref::Self_(fdecl::SelfRef {});
2652 let source_name = "source";
2653 let target = fdecl::Ref::Parent(fdecl::ParentRef {});
2654 let target_name = "target";
2655 let expose_service: ExposeServiceDecl = fdecl::ExposeService {
2656 source: Some(source.clone()),
2657 source_name: Some(source_name.into()),
2658 target: Some(target.clone()),
2659 target_name: Some(target_name.into()),
2660 availability: None,
2661 ..Default::default()
2662 }
2663 .fidl_into_native();
2664 assert_eq!(*expose_service.availability(), Availability::Required);
2665
2666 let expose_protocol: ExposeProtocolDecl = fdecl::ExposeProtocol {
2667 source: Some(source.clone()),
2668 source_name: Some(source_name.into()),
2669 target: Some(target.clone()),
2670 target_name: Some(target_name.into()),
2671 ..Default::default()
2672 }
2673 .fidl_into_native();
2674 assert_eq!(*expose_protocol.availability(), Availability::Required);
2675
2676 let expose_directory: ExposeDirectoryDecl = fdecl::ExposeDirectory {
2677 source: Some(source.clone()),
2678 source_name: Some(source_name.into()),
2679 target: Some(target.clone()),
2680 target_name: Some(target_name.into()),
2681 ..Default::default()
2682 }
2683 .fidl_into_native();
2684 assert_eq!(*expose_directory.availability(), Availability::Required);
2685
2686 let expose_runner: ExposeRunnerDecl = fdecl::ExposeRunner {
2687 source: Some(source.clone()),
2688 source_name: Some(source_name.into()),
2689 target: Some(target.clone()),
2690 target_name: Some(target_name.into()),
2691 ..Default::default()
2692 }
2693 .fidl_into_native();
2694 assert_eq!(*expose_runner.availability(), Availability::Required);
2695
2696 let expose_resolver: ExposeResolverDecl = fdecl::ExposeResolver {
2697 source: Some(source.clone()),
2698 source_name: Some(source_name.into()),
2699 target: Some(target.clone()),
2700 target_name: Some(target_name.into()),
2701 ..Default::default()
2702 }
2703 .fidl_into_native();
2704 assert_eq!(*expose_resolver.availability(), Availability::Required);
2705
2706 let expose_dictionary: ExposeDictionaryDecl = fdecl::ExposeDictionary {
2707 source: Some(source.clone()),
2708 source_name: Some(source_name.into()),
2709 target: Some(target.clone()),
2710 target_name: Some(target_name.into()),
2711 ..Default::default()
2712 }
2713 .fidl_into_native();
2714 assert_eq!(*expose_dictionary.availability(), Availability::Required);
2715 }
2716
2717 #[test]
2718 fn default_delivery_type() {
2719 let protocol: ProtocolDecl = fdecl::Protocol {
2720 name: Some("foo".to_string()),
2721 source_path: Some("/foo".to_string()),
2722 delivery: None,
2723 ..Default::default()
2724 }
2725 .fidl_into_native();
2726 assert_eq!(protocol.delivery, DeliveryType::Immediate)
2727 }
2728
2729 #[test]
2730 fn on_readable_delivery_type() {
2731 let protocol: ProtocolDecl = fdecl::Protocol {
2732 name: Some("foo".to_string()),
2733 source_path: Some("/foo".to_string()),
2734 delivery: Some(fdecl::DeliveryType::OnReadable),
2735 ..Default::default()
2736 }
2737 .fidl_into_native();
2738 assert_eq!(protocol.delivery, DeliveryType::OnReadable)
2739 }
2740
2741 #[test]
2742 fn config_value_matches_type() {
2743 let bool_true = ConfigValue::Single(ConfigSingleValue::Bool(true));
2744 let bool_false = ConfigValue::Single(ConfigSingleValue::Bool(false));
2745 let uint8_zero = ConfigValue::Single(ConfigSingleValue::Uint8(0));
2746 let vec_bool_true = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([true])));
2747 let vec_bool_false = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([false])));
2748
2749 assert!(bool_true.matches_type(&bool_false));
2750 assert!(vec_bool_true.matches_type(&vec_bool_false));
2751
2752 assert!(!bool_true.matches_type(&uint8_zero));
2753 assert!(!bool_true.matches_type(&vec_bool_true));
2754 }
2755}