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