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