1use cm_rust_derive::{ExposeDeclCommon, ExposeDeclCommonAlwaysRequired, FidlDecl, UseDeclCommon};
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 offer;
28
29#[allow(unused_imports)]
30pub use crate::offer::*; pub trait FidlIntoNative<T> {
34 fn fidl_into_native(self) -> T;
35}
36
37impl<Native, Fidl> FidlIntoNative<Box<[Native]>> for Vec<Fidl>
38where
39 Fidl: FidlIntoNative<Native>,
40{
41 fn fidl_into_native(self) -> Box<[Native]> {
42 IntoIterator::into_iter(self).map(|s| s.fidl_into_native()).collect()
43 }
44}
45
46pub trait NativeIntoFidl<T> {
47 fn native_into_fidl(self) -> T;
48}
49
50impl<Native, Fidl> NativeIntoFidl<Vec<Fidl>> for Box<[Native]>
51where
52 Native: NativeIntoFidl<Fidl>,
53{
54 fn native_into_fidl(self) -> Vec<Fidl> {
55 IntoIterator::into_iter(self).map(|s| s.native_into_fidl()).collect()
56 }
57}
58
59impl FidlIntoNative<Name> for String {
60 fn fidl_into_native(self) -> Name {
61 self.parse().unwrap()
63 }
64}
65
66impl NativeIntoFidl<String> for Name {
67 fn native_into_fidl(self) -> String {
68 self.to_string()
69 }
70}
71
72impl FidlIntoNative<LongName> for String {
73 fn fidl_into_native(self) -> LongName {
74 self.parse().unwrap()
76 }
77}
78
79impl NativeIntoFidl<String> for LongName {
80 fn native_into_fidl(self) -> String {
81 self.to_string()
82 }
83}
84
85impl FidlIntoNative<Path> for String {
86 fn fidl_into_native(self) -> Path {
87 self.parse().unwrap()
89 }
90}
91
92impl NativeIntoFidl<String> for Path {
93 fn native_into_fidl(self) -> String {
94 self.to_string()
95 }
96}
97
98impl FidlIntoNative<RelativePath> for String {
99 fn fidl_into_native(self) -> RelativePath {
100 self.parse().unwrap()
102 }
103}
104
105impl NativeIntoFidl<String> for RelativePath {
106 fn native_into_fidl(self) -> String {
107 self.to_string()
108 }
109}
110
111impl NativeIntoFidl<Option<String>> for RelativePath {
112 fn native_into_fidl(self) -> Option<String> {
113 if self.is_dot() { None } else { Some(self.to_string()) }
114 }
115}
116
117impl FidlIntoNative<Url> for String {
118 fn fidl_into_native(self) -> Url {
119 self.parse().unwrap()
121 }
122}
123
124impl NativeIntoFidl<String> for Url {
125 fn native_into_fidl(self) -> String {
126 self.to_string()
127 }
128}
129
130macro_rules! fidl_translations_identical {
132 ($into_type:ty) => {
133 impl FidlIntoNative<$into_type> for $into_type {
134 fn fidl_into_native(self) -> $into_type {
135 self
136 }
137 }
138 impl NativeIntoFidl<$into_type> for $into_type {
139 fn native_into_fidl(self) -> Self {
140 self
141 }
142 }
143 };
144}
145
146macro_rules! fidl_translations_from_into {
149 ($native_type:ty, $fidl_type:ty) => {
150 impl FidlIntoNative<$native_type> for $fidl_type {
151 fn fidl_into_native(self) -> $native_type {
152 self.into()
153 }
154 }
155 impl NativeIntoFidl<$fidl_type> for $native_type {
156 fn native_into_fidl(self) -> $fidl_type {
157 self.into()
158 }
159 }
160 };
161}
162
163macro_rules! fidl_translations_symmetrical_enums {
169($fidl_type:ty , $native_type:ty, $($variant: ident),*) => {
170 impl FidlIntoNative<$native_type> for $fidl_type {
171 fn fidl_into_native(self) -> $native_type {
172 match self {
173 $( <$fidl_type>::$variant => <$native_type>::$variant, )*
174 }
175 }
176 }
177 impl NativeIntoFidl<$fidl_type> for $native_type {
178 fn native_into_fidl(self) -> $fidl_type {
179 match self {
180 $( <$native_type>::$variant => <$fidl_type>::$variant, )*
181 }
182 }
183 }
184 };
185}
186
187#[derive(FidlDecl, Debug, Clone, PartialEq, Default)]
188#[fidl_decl(fidl_table = "fdecl::Component")]
189pub struct ComponentDecl {
190 pub program: Option<ProgramDecl>,
191 pub uses: Box<[UseDecl]>,
192 pub exposes: Box<[ExposeDecl]>,
193 pub offers: Box<[OfferDecl]>,
194 pub capabilities: Box<[CapabilityDecl]>,
195 pub children: Box<[ChildDecl]>,
196 pub collections: Box<[CollectionDecl]>,
197 pub facets: Option<fdata::Dictionary>,
198 pub environments: Box<[EnvironmentDecl]>,
199 pub config: Option<ConfigDecl>,
200 #[cfg(fuchsia_api_level_at_least = "NEXT")]
201 pub debug_info: Option<DebugInfo>,
202}
203
204impl ComponentDecl {
205 #[cfg(fuchsia_api_level_at_least = "HEAD")]
207 pub fn get_runner(&self) -> Option<UseRunnerDecl> {
208 self.program
209 .as_ref()
210 .and_then(|p| p.runner.as_ref())
211 .map(|r| UseRunnerDecl {
212 source: UseSource::Environment,
213 source_name: r.clone(),
214 source_dictionary: Default::default(),
215 })
216 .or_else(|| {
217 self.uses.iter().find_map(|u| match u {
218 UseDecl::Runner(r) => Some(r.clone()),
219 _ => None,
220 })
221 })
222 }
223
224 pub fn find_storage_source<'a>(&'a self, storage_name: &Name) -> Option<&'a StorageDecl> {
226 self.capabilities.iter().find_map(|c| match c {
227 CapabilityDecl::Storage(s) if &s.name == storage_name => Some(s),
228 _ => None,
229 })
230 }
231
232 pub fn find_protocol_source<'a>(&'a self, protocol_name: &Name) -> Option<&'a ProtocolDecl> {
234 self.capabilities.iter().find_map(|c| match c {
235 CapabilityDecl::Protocol(r) if &r.name == protocol_name => Some(r),
236 _ => None,
237 })
238 }
239
240 pub fn find_directory_source<'a>(&'a self, directory_name: &Name) -> Option<&'a DirectoryDecl> {
242 self.capabilities.iter().find_map(|c| match c {
243 CapabilityDecl::Directory(r) if &r.name == directory_name => Some(r),
244 _ => None,
245 })
246 }
247
248 pub fn find_runner_source<'a>(&'a self, runner_name: &Name) -> Option<&'a RunnerDecl> {
250 self.capabilities.iter().find_map(|c| match c {
251 CapabilityDecl::Runner(r) if &r.name == runner_name => Some(r),
252 _ => None,
253 })
254 }
255
256 pub fn find_resolver_source<'a>(&'a self, resolver_name: &Name) -> Option<&'a ResolverDecl> {
258 self.capabilities.iter().find_map(|c| match c {
259 CapabilityDecl::Resolver(r) if &r.name == resolver_name => Some(r),
260 _ => None,
261 })
262 }
263
264 pub fn find_collection<'a>(&'a self, collection_name: &str) -> Option<&'a CollectionDecl> {
266 self.collections.iter().find(|c| c.name == collection_name)
267 }
268
269 pub fn is_protocol_exposed_to_framework(&self, in_target_name: &Name) -> bool {
271 self.exposes.iter().any(|expose| match expose {
272 ExposeDecl::Protocol(ExposeProtocolDecl { target, target_name, .. })
273 if target == &ExposeTarget::Framework =>
274 {
275 target_name == in_target_name
276 }
277 _ => false,
278 })
279 }
280
281 pub fn uses_protocol(&self, source_name: &Name) -> bool {
283 self.uses.iter().any(|use_decl| match use_decl {
284 UseDecl::Protocol(ls) => &ls.source_name == source_name,
285 _ => false,
286 })
287 }
288}
289
290pub use cm_types::Availability;
291
292fidl_translations_symmetrical_enums!(
293 fdecl::Availability,
294 Availability,
295 Required,
296 Optional,
297 SameAsTarget,
298 Transitional
299);
300
301pub use cm_types::DeliveryType;
302
303#[cfg(fuchsia_api_level_at_least = "HEAD")]
304impl FidlIntoNative<DeliveryType> for fdecl::DeliveryType {
305 fn fidl_into_native(self) -> DeliveryType {
306 self.try_into().unwrap()
307 }
308}
309
310#[cfg(fuchsia_api_level_at_least = "HEAD")]
311impl NativeIntoFidl<fdecl::DeliveryType> for DeliveryType {
312 fn native_into_fidl(self) -> fdecl::DeliveryType {
313 self.into()
314 }
315}
316
317#[cfg(fuchsia_api_level_at_least = "29")]
318pub use cm_types::HandleType;
319
320#[cfg(fuchsia_api_level_at_least = "29")]
321impl FidlIntoNative<HandleType> for u8 {
322 fn fidl_into_native(self) -> HandleType {
323 self.into()
324 }
325}
326
327#[cfg(fuchsia_api_level_at_least = "29")]
328impl NativeIntoFidl<u8> for HandleType {
329 fn native_into_fidl(self) -> u8 {
330 self.into()
331 }
332}
333
334pub trait SourcePath {
335 fn source_path(&self) -> BorrowedSeparatedPath<'_>;
336 fn is_from_dictionary(&self) -> bool {
337 !self.source_path().dirname.is_dot()
338 }
339}
340
341#[cfg_attr(
342 feature = "serde",
343 derive(Deserialize, Serialize),
344 serde(tag = "type", rename_all = "snake_case")
345)]
346#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
347#[fidl_decl(fidl_union = "fdecl::Use")]
348pub enum UseDecl {
349 Service(UseServiceDecl),
350 Protocol(UseProtocolDecl),
351 Directory(UseDirectoryDecl),
352 Storage(UseStorageDecl),
353 EventStream(UseEventStreamDecl),
354 #[cfg(fuchsia_api_level_at_least = "HEAD")]
355 Runner(UseRunnerDecl),
356 Config(UseConfigurationDecl),
357 #[cfg(fuchsia_api_level_at_least = "29")]
358 Dictionary(UseDictionaryDecl),
359}
360
361#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
362#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
363#[fidl_decl(fidl_table = "fdecl::UseService", source_path = "dictionary")]
364pub struct UseServiceDecl {
365 pub source: UseSource,
366 pub source_name: Name,
367 #[fidl_decl(default_preserve_none)]
368 pub source_dictionary: RelativePath,
369 pub target_path: Path,
370 pub dependency_type: DependencyType,
371 #[fidl_decl(default)]
372 pub availability: Availability,
373}
374
375#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
376#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
377#[fidl_decl(fidl_table = "fdecl::UseProtocol", source_path = "dictionary")]
378pub struct UseProtocolDecl {
379 pub source: UseSource,
380 pub source_name: Name,
381 #[fidl_decl(default_preserve_none)]
382 pub source_dictionary: RelativePath,
383 pub target_path: Option<Path>,
384 #[cfg(fuchsia_api_level_at_least = "29")]
385 pub numbered_handle: Option<HandleType>,
386 pub dependency_type: DependencyType,
387 #[fidl_decl(default)]
388 pub availability: Availability,
389}
390
391#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
392#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
393#[fidl_decl(fidl_table = "fdecl::UseDirectory", source_path = "dictionary")]
394pub struct UseDirectoryDecl {
395 pub source: UseSource,
396 pub source_name: Name,
397 #[fidl_decl(default_preserve_none)]
398 pub source_dictionary: RelativePath,
399 pub target_path: Path,
400
401 #[cfg_attr(
402 feature = "serde",
403 serde(
404 deserialize_with = "serde_ext::deserialize_fio_operations",
405 serialize_with = "serde_ext::serialize_fio_operations"
406 )
407 )]
408 pub rights: fio::Operations,
409
410 #[fidl_decl(default_preserve_none)]
411 pub subdir: RelativePath,
412 pub dependency_type: DependencyType,
413 #[fidl_decl(default)]
414 pub availability: Availability,
415}
416
417#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
418#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
419#[fidl_decl(fidl_table = "fdecl::UseStorage", source_path = "name_only")]
420pub struct UseStorageDecl {
421 pub source_name: Name,
422 pub target_path: Path,
423 #[fidl_decl(default)]
424 pub availability: Availability,
425}
426
427impl SourceName for UseStorageDecl {
428 fn source_name(&self) -> &Name {
429 &self.source_name
430 }
431}
432
433impl UseDeclCommon for UseStorageDecl {
434 fn source(&self) -> &UseSource {
435 &UseSource::Parent
436 }
437
438 fn availability(&self) -> &Availability {
439 &self.availability
440 }
441}
442
443#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
444#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq, Hash)]
445#[fidl_decl(fidl_table = "fdecl::UseEventStream", source_path = "name_only")]
446pub struct UseEventStreamDecl {
447 pub source_name: Name,
448 pub source: UseSource,
449 pub scope: Option<Box<[EventScope]>>,
450 pub target_path: Path,
451 pub filter: Option<BTreeMap<String, DictionaryValue>>,
452 #[fidl_decl(default)]
453 pub availability: Availability,
454}
455
456#[cfg(fuchsia_api_level_at_least = "HEAD")]
457#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
458#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
459#[fidl_decl(fidl_table = "fdecl::UseRunner", source_path = "dictionary")]
460pub struct UseRunnerDecl {
461 pub source: UseSource,
462 pub source_name: Name,
463 #[fidl_decl(default_preserve_none)]
464 pub source_dictionary: RelativePath,
465}
466
467#[cfg(fuchsia_api_level_at_least = "29")]
468#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
469#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
470#[fidl_decl(fidl_table = "fdecl::UseDictionary", source_path = "dictionary")]
471pub struct UseDictionaryDecl {
472 pub source: UseSource,
473 pub source_name: Name,
474 #[fidl_decl(default_preserve_none)]
475 pub source_dictionary: RelativePath,
476 pub target_path: Path,
477 pub dependency_type: DependencyType,
478 #[fidl_decl(default)]
479 pub availability: Availability,
480}
481
482#[cfg(fuchsia_api_level_at_least = "HEAD")]
483impl SourceName for UseRunnerDecl {
484 fn source_name(&self) -> &Name {
485 &self.source_name
486 }
487}
488
489#[cfg(fuchsia_api_level_at_least = "HEAD")]
490impl UseDeclCommon for UseRunnerDecl {
491 fn source(&self) -> &UseSource {
492 &self.source
493 }
494
495 fn availability(&self) -> &Availability {
496 &Availability::Required
497 }
498}
499
500#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
501#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
502#[fidl_decl(fidl_table = "fdecl::UseConfiguration", source_path = "dictionary")]
503pub struct UseConfigurationDecl {
504 pub source: UseSource,
505 pub source_name: Name,
506 #[fidl_decl(default_preserve_none)]
507 pub source_dictionary: RelativePath,
508 pub target_name: Name,
509 #[fidl_decl(default)]
510 pub availability: Availability,
511 pub type_: ConfigValueType,
512 pub default: Option<ConfigValue>,
513}
514
515#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
516#[derive(Debug, Clone, PartialEq, Eq)]
517pub struct NameMapping {
518 pub source_name: Name,
519 pub target_name: Name,
520}
521
522impl NativeIntoFidl<fdecl::NameMapping> for NameMapping {
523 fn native_into_fidl(self) -> fdecl::NameMapping {
524 fdecl::NameMapping {
525 source_name: self.source_name.native_into_fidl(),
526 target_name: self.target_name.native_into_fidl(),
527 }
528 }
529}
530
531impl FidlIntoNative<NameMapping> for fdecl::NameMapping {
532 fn fidl_into_native(self) -> NameMapping {
533 NameMapping {
534 source_name: self.source_name.fidl_into_native(),
535 target_name: self.target_name.fidl_into_native(),
536 }
537 }
538}
539
540impl UseDeclCommon for UseDecl {
541 fn source(&self) -> &UseSource {
542 match &self {
543 UseDecl::Service(u) => u.source(),
544 UseDecl::Protocol(u) => u.source(),
545 UseDecl::Directory(u) => u.source(),
546 UseDecl::Storage(u) => u.source(),
547 UseDecl::EventStream(u) => u.source(),
548 #[cfg(fuchsia_api_level_at_least = "HEAD")]
549 UseDecl::Runner(u) => u.source(),
550 UseDecl::Config(u) => u.source(),
551 #[cfg(fuchsia_api_level_at_least = "29")]
552 UseDecl::Dictionary(u) => u.source(),
553 }
554 }
555
556 fn availability(&self) -> &Availability {
557 match &self {
558 UseDecl::Service(u) => u.availability(),
559 UseDecl::Protocol(u) => u.availability(),
560 UseDecl::Directory(u) => u.availability(),
561 UseDecl::Storage(u) => u.availability(),
562 UseDecl::EventStream(u) => u.availability(),
563 #[cfg(fuchsia_api_level_at_least = "HEAD")]
564 UseDecl::Runner(u) => u.availability(),
565 UseDecl::Config(u) => u.availability(),
566 #[cfg(fuchsia_api_level_at_least = "29")]
567 UseDecl::Dictionary(u) => u.availability(),
568 }
569 }
570}
571
572#[cfg_attr(
573 feature = "serde",
574 derive(Deserialize, Serialize),
575 serde(tag = "type", rename_all = "snake_case")
576)]
577#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
578#[fidl_decl(fidl_union = "fdecl::Expose")]
579pub enum ExposeDecl {
580 Service(ExposeServiceDecl),
581 Protocol(ExposeProtocolDecl),
582 Directory(ExposeDirectoryDecl),
583 Runner(ExposeRunnerDecl),
584 Resolver(ExposeResolverDecl),
585 Dictionary(ExposeDictionaryDecl),
586 Config(ExposeConfigurationDecl),
587}
588
589impl SourceName for ExposeDecl {
590 fn source_name(&self) -> &Name {
591 match self {
592 Self::Service(e) => e.source_name(),
593 Self::Protocol(e) => e.source_name(),
594 Self::Directory(e) => e.source_name(),
595 Self::Runner(e) => e.source_name(),
596 Self::Resolver(e) => e.source_name(),
597 Self::Dictionary(e) => e.source_name(),
598 Self::Config(e) => e.source_name(),
599 }
600 }
601}
602
603impl SourcePath for ExposeDecl {
604 fn source_path(&self) -> BorrowedSeparatedPath<'_> {
605 match self {
606 Self::Service(e) => e.source_path(),
607 Self::Protocol(e) => e.source_path(),
608 Self::Directory(e) => e.source_path(),
609 Self::Runner(e) => e.source_path(),
610 Self::Resolver(e) => e.source_path(),
611 Self::Dictionary(e) => e.source_path(),
612 Self::Config(e) => e.source_path(),
613 }
614 }
615}
616
617impl ExposeDeclCommon for ExposeDecl {
618 fn source(&self) -> &ExposeSource {
619 match self {
620 Self::Service(e) => e.source(),
621 Self::Protocol(e) => e.source(),
622 Self::Directory(e) => e.source(),
623 Self::Runner(e) => e.source(),
624 Self::Resolver(e) => e.source(),
625 Self::Dictionary(e) => e.source(),
626 Self::Config(e) => e.source(),
627 }
628 }
629
630 fn target(&self) -> &ExposeTarget {
631 match self {
632 Self::Service(e) => e.target(),
633 Self::Protocol(e) => e.target(),
634 Self::Directory(e) => e.target(),
635 Self::Runner(e) => e.target(),
636 Self::Resolver(e) => e.target(),
637 Self::Dictionary(e) => e.target(),
638 Self::Config(e) => e.target(),
639 }
640 }
641
642 fn target_name(&self) -> &Name {
643 match self {
644 Self::Service(e) => e.target_name(),
645 Self::Protocol(e) => e.target_name(),
646 Self::Directory(e) => e.target_name(),
647 Self::Runner(e) => e.target_name(),
648 Self::Resolver(e) => e.target_name(),
649 Self::Dictionary(e) => e.target_name(),
650 Self::Config(e) => e.target_name(),
651 }
652 }
653
654 fn availability(&self) -> &Availability {
655 match self {
656 Self::Service(e) => e.availability(),
657 Self::Protocol(e) => e.availability(),
658 Self::Directory(e) => e.availability(),
659 Self::Runner(e) => e.availability(),
660 Self::Resolver(e) => e.availability(),
661 Self::Dictionary(e) => e.availability(),
662 Self::Config(e) => e.availability(),
663 }
664 }
665}
666
667#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
668#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
669#[fidl_decl(fidl_table = "fdecl::ExposeService", source_path = "dictionary")]
670pub struct ExposeServiceDecl {
671 pub source: ExposeSource,
672 pub source_name: Name,
673 #[fidl_decl(default_preserve_none)]
674 pub source_dictionary: RelativePath,
675 pub target: ExposeTarget,
676 pub target_name: Name,
677 #[fidl_decl(default)]
678 pub availability: Availability,
679}
680
681#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
682#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
683#[fidl_decl(fidl_table = "fdecl::ExposeProtocol", source_path = "dictionary")]
684pub struct ExposeProtocolDecl {
685 pub source: ExposeSource,
686 pub source_name: Name,
687 #[fidl_decl(default_preserve_none)]
688 pub source_dictionary: RelativePath,
689 pub target: ExposeTarget,
690 pub target_name: Name,
691 #[fidl_decl(default)]
692 pub availability: Availability,
693}
694
695#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
696#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
697#[fidl_decl(fidl_table = "fdecl::ExposeDirectory", source_path = "dictionary")]
698pub struct ExposeDirectoryDecl {
699 pub source: ExposeSource,
700 pub source_name: Name,
701 #[fidl_decl(default_preserve_none)]
702 pub source_dictionary: RelativePath,
703 pub target: ExposeTarget,
704 pub target_name: Name,
705
706 #[cfg_attr(
707 feature = "serde",
708 serde(
709 deserialize_with = "serde_ext::deserialize_opt_fio_operations",
710 serialize_with = "serde_ext::serialize_opt_fio_operations"
711 )
712 )]
713 pub rights: Option<fio::Operations>,
714
715 #[fidl_decl(default_preserve_none)]
716 pub subdir: RelativePath,
717
718 #[fidl_decl(default)]
719 pub availability: Availability,
720}
721
722#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
723#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
724#[fidl_decl(fidl_table = "fdecl::ExposeRunner", source_path = "dictionary")]
725pub struct ExposeRunnerDecl {
726 pub source: ExposeSource,
727 pub source_name: Name,
728 #[fidl_decl(default_preserve_none)]
729 pub source_dictionary: RelativePath,
730 pub target: ExposeTarget,
731 pub target_name: Name,
732}
733
734#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
735#[derive(FidlDecl, ExposeDeclCommonAlwaysRequired, Debug, Clone, PartialEq, Eq)]
736#[fidl_decl(fidl_table = "fdecl::ExposeResolver", source_path = "dictionary")]
737pub struct ExposeResolverDecl {
738 pub source: ExposeSource,
739 pub source_name: Name,
740 #[fidl_decl(default_preserve_none)]
741 pub source_dictionary: RelativePath,
742 pub target: ExposeTarget,
743 pub target_name: Name,
744}
745
746#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
747#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
748#[fidl_decl(fidl_table = "fdecl::ExposeDictionary", source_path = "dictionary")]
749pub struct ExposeDictionaryDecl {
750 pub source: ExposeSource,
751 pub source_name: Name,
752 #[fidl_decl(default_preserve_none)]
753 pub source_dictionary: RelativePath,
754 pub target: ExposeTarget,
755 pub target_name: Name,
756 #[fidl_decl(default)]
757 pub availability: Availability,
758}
759
760#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
761#[derive(FidlDecl, ExposeDeclCommon, Debug, Clone, PartialEq, Eq)]
762#[fidl_decl(fidl_table = "fdecl::ExposeConfiguration", source_path = "name_only")]
763pub struct ExposeConfigurationDecl {
764 pub source: ExposeSource,
765 pub source_name: Name,
766 pub target: ExposeTarget,
767 pub target_name: Name,
768 #[fidl_decl(default_preserve_none)]
769 pub source_dictionary: RelativePath,
770 #[fidl_decl(default)]
771 pub availability: Availability,
772}
773
774#[cfg_attr(
775 feature = "serde",
776 derive(Deserialize, Serialize),
777 serde(tag = "type", rename_all = "snake_case")
778)]
779#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
780#[fidl_decl(fidl_union = "fdecl::Capability")]
781pub enum CapabilityDecl {
782 Service(ServiceDecl),
783 Protocol(ProtocolDecl),
784 Directory(DirectoryDecl),
785 Storage(StorageDecl),
786 Runner(RunnerDecl),
787 Resolver(ResolverDecl),
788 EventStream(EventStreamDecl),
789 Dictionary(DictionaryDecl),
790 Config(ConfigurationDecl),
791}
792
793#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
794#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
795#[fidl_decl(fidl_table = "fdecl::Service")]
796pub struct ServiceDecl {
797 pub name: Name,
798 pub source_path: Option<Path>,
799}
800
801#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
802#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
803#[fidl_decl(fidl_table = "fdecl::Protocol")]
804pub struct ProtocolDecl {
805 pub name: Name,
806 pub source_path: Option<Path>,
807 #[fidl_decl(default)]
808 #[cfg(fuchsia_api_level_at_least = "HEAD")]
809 pub delivery: DeliveryType,
810}
811
812#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
813#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
814#[fidl_decl(fidl_table = "fdecl::Directory")]
815pub struct DirectoryDecl {
816 pub name: Name,
817 pub source_path: Option<Path>,
818
819 #[cfg_attr(
820 feature = "serde",
821 serde(
822 deserialize_with = "serde_ext::deserialize_fio_operations",
823 serialize_with = "serde_ext::serialize_fio_operations"
824 )
825 )]
826 pub rights: fio::Operations,
827}
828
829#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
830#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
831#[fidl_decl(fidl_table = "fdecl::Storage")]
832pub struct StorageDecl {
833 pub name: Name,
834 pub source: StorageDirectorySource,
835 pub backing_dir: Name,
836 #[fidl_decl(default_preserve_none)]
837 pub subdir: RelativePath,
838 #[cfg_attr(feature = "serde", serde(with = "serde_ext::StorageId"))]
839 pub storage_id: fdecl::StorageId,
840}
841
842#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
843#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
844#[fidl_decl(fidl_table = "fdecl::Runner")]
845pub struct RunnerDecl {
846 pub name: Name,
847 pub source_path: Option<Path>,
848}
849
850#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
851#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
852#[fidl_decl(fidl_table = "fdecl::Resolver")]
853pub struct ResolverDecl {
854 pub name: Name,
855 pub source_path: Option<Path>,
856}
857
858#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
859#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
860#[fidl_decl(fidl_table = "fdecl::EventStream")]
861pub struct EventStreamDecl {
862 pub name: Name,
863}
864
865#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
866#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
867#[fidl_decl(fidl_table = "fdecl::Dictionary")]
868pub struct DictionaryDecl {
869 pub name: Name,
870 pub source_path: Option<Path>,
871}
872
873#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
874#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
875#[fidl_decl(fidl_table = "fdecl::Configuration")]
876pub struct ConfigurationDecl {
877 pub name: Name,
878 pub value: ConfigValue,
879}
880
881impl CapabilityDecl {
882 pub fn name(&self) -> &Name {
883 match self {
884 CapabilityDecl::Directory(decl) => &decl.name,
885 CapabilityDecl::Protocol(decl) => &decl.name,
886 CapabilityDecl::Resolver(decl) => &decl.name,
887 CapabilityDecl::Runner(decl) => &decl.name,
888 CapabilityDecl::Service(decl) => &decl.name,
889 CapabilityDecl::Storage(decl) => &decl.name,
890 CapabilityDecl::EventStream(decl) => &decl.name,
891 CapabilityDecl::Dictionary(decl) => &decl.name,
892 CapabilityDecl::Config(decl) => &decl.name,
893 }
894 }
895
896 pub fn path(&self) -> Option<&Path> {
897 match self {
898 CapabilityDecl::Directory(decl) => decl.source_path.as_ref(),
899 CapabilityDecl::Protocol(decl) => decl.source_path.as_ref(),
900 CapabilityDecl::Resolver(decl) => decl.source_path.as_ref(),
901 CapabilityDecl::Runner(decl) => decl.source_path.as_ref(),
902 CapabilityDecl::Service(decl) => decl.source_path.as_ref(),
903 CapabilityDecl::Storage(_) => None,
904 CapabilityDecl::EventStream(_) => None,
905 CapabilityDecl::Dictionary(_) => None,
906 CapabilityDecl::Config(_) => None,
907 }
908 }
909}
910
911#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
912#[fidl_decl(fidl_table = "fdecl::Child")]
913pub struct ChildDecl {
914 pub name: LongName,
915 pub url: Url,
916 pub startup: fdecl::StartupMode,
917 pub on_terminate: Option<fdecl::OnTerminate>,
918 pub environment: Option<Name>,
919 pub config_overrides: Option<Box<[ConfigOverride]>>,
920}
921
922#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
923#[derive(Debug, Clone, PartialEq, Eq, Hash)]
924pub struct ChildRef {
925 pub name: LongName,
926 pub collection: Option<Name>,
927}
928
929impl std::fmt::Display for ChildRef {
930 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
931 if let Some(collection) = &self.collection {
932 write!(f, "{}:{}", collection, self.name)
933 } else {
934 write!(f, "{}", self.name)
935 }
936 }
937}
938
939impl FidlIntoNative<ChildRef> for fdecl::ChildRef {
940 fn fidl_into_native(self) -> ChildRef {
941 ChildRef {
943 name: self.name.parse().unwrap(),
944 collection: self.collection.map(|c| c.parse().unwrap()),
945 }
946 }
947}
948
949impl NativeIntoFidl<fdecl::ChildRef> for ChildRef {
950 fn native_into_fidl(self) -> fdecl::ChildRef {
951 fdecl::ChildRef {
952 name: self.name.to_string(),
953 collection: self.collection.map(|c| c.to_string()),
954 }
955 }
956}
957
958#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
959#[fidl_decl(fidl_table = "fdecl::Collection")]
960pub struct CollectionDecl {
961 pub name: Name,
962 pub durability: fdecl::Durability,
963 pub environment: Option<Name>,
964
965 #[fidl_decl(default)]
966 pub allowed_offers: AllowedOffers,
967 #[fidl_decl(default)]
968 pub allow_long_names: bool,
969
970 pub persistent_storage: Option<bool>,
971}
972
973#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
974#[fidl_decl(fidl_table = "fdecl::Environment")]
975pub struct EnvironmentDecl {
976 pub name: Name,
977 pub extends: fdecl::EnvironmentExtends,
978 pub runners: Box<[RunnerRegistration]>,
979 pub resolvers: Box<[ResolverRegistration]>,
980 pub debug_capabilities: Box<[DebugRegistration]>,
981 pub stop_timeout_ms: Option<u32>,
982}
983
984#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
985#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
986#[fidl_decl(fidl_table = "fdecl::ConfigOverride")]
987pub struct ConfigOverride {
988 pub key: String,
989 pub value: ConfigValue,
990}
991
992#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
993#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
994#[fidl_decl(fidl_table = "fdecl::ConfigSchema")]
995pub struct ConfigDecl {
996 pub fields: Box<[ConfigField]>,
997 pub checksum: ConfigChecksum,
998 pub value_source: ConfigValueSource,
999}
1000
1001#[cfg(fuchsia_api_level_at_least = "NEXT")]
1002#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1003#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1004#[fidl_decl(fidl_table = "fdecl::DebugInfo")]
1005pub struct DebugInfo {
1006 pub manifest_sources: Option<Box<[String]>>,
1007}
1008
1009#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1010#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1011#[fidl_decl(fidl_union = "fdecl::ConfigChecksum")]
1012pub enum ConfigChecksum {
1013 Sha256([u8; 32]),
1014}
1015
1016#[cfg(fuchsia_api_level_at_least = "HEAD")]
1017#[derive(FidlDecl, Debug, Default, Clone, PartialEq, Eq)]
1018#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1019#[fidl_decl(fidl_table = "fdecl::ConfigSourceCapabilities")]
1020pub struct ConfigSourceCapabilities {}
1021
1022#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1023#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1024#[fidl_decl(fidl_union = "fdecl::ConfigValueSource")]
1025pub enum ConfigValueSource {
1026 PackagePath(String),
1027 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1028 Capabilities(ConfigSourceCapabilities),
1029}
1030
1031#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1032#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1033#[fidl_decl(fidl_table = "fdecl::ConfigField")]
1034pub struct ConfigField {
1035 pub key: String,
1036 pub type_: ConfigValueType,
1037
1038 #[fidl_decl(default)]
1040 pub mutability: ConfigMutability,
1041}
1042
1043#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1044#[derive(Debug, Clone, PartialEq, Eq)]
1045pub enum ConfigNestedValueType {
1046 Bool,
1047 Uint8,
1048 Int8,
1049 Uint16,
1050 Int16,
1051 Uint32,
1052 Int32,
1053 Uint64,
1054 Int64,
1055 String { max_size: u32 },
1056}
1057
1058#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1059#[derive(Debug, Clone, PartialEq, Eq)]
1060pub enum ConfigValueType {
1061 Bool,
1062 Uint8,
1063 Int8,
1064 Uint16,
1065 Int16,
1066 Uint32,
1067 Int32,
1068 Uint64,
1069 Int64,
1070 String { max_size: u32 },
1071 Vector { nested_type: ConfigNestedValueType, max_count: u32 },
1072}
1073
1074impl ConfigValueType {
1075 pub fn get_max_size(&self) -> Option<u32> {
1076 match self {
1077 ConfigValueType::String { max_size } => Some(*max_size),
1078 ConfigValueType::Bool
1079 | ConfigValueType::Uint8
1080 | ConfigValueType::Int8
1081 | ConfigValueType::Uint16
1082 | ConfigValueType::Int16
1083 | ConfigValueType::Uint32
1084 | ConfigValueType::Int32
1085 | ConfigValueType::Uint64
1086 | ConfigValueType::Int64
1087 | ConfigValueType::Vector { .. } => None,
1088 }
1089 }
1090
1091 pub fn get_nested_type(&self) -> Option<ConfigNestedValueType> {
1092 match self {
1093 ConfigValueType::Vector { nested_type, .. } => Some(nested_type.clone()),
1094 ConfigValueType::Bool
1095 | ConfigValueType::Uint8
1096 | ConfigValueType::Int8
1097 | ConfigValueType::Uint16
1098 | ConfigValueType::Int16
1099 | ConfigValueType::Uint32
1100 | ConfigValueType::Int32
1101 | ConfigValueType::Uint64
1102 | ConfigValueType::Int64
1103 | ConfigValueType::String { .. } => None,
1104 }
1105 }
1106
1107 pub fn get_max_count(&self) -> Option<u32> {
1108 match self {
1109 ConfigValueType::Vector { max_count, .. } => Some(*max_count),
1110 ConfigValueType::Bool
1111 | ConfigValueType::Uint8
1112 | ConfigValueType::Int8
1113 | ConfigValueType::Uint16
1114 | ConfigValueType::Int16
1115 | ConfigValueType::Uint32
1116 | ConfigValueType::Int32
1117 | ConfigValueType::Uint64
1118 | ConfigValueType::Int64
1119 | ConfigValueType::String { .. } => None,
1120 }
1121 }
1122}
1123
1124impl FidlIntoNative<ConfigNestedValueType> for fdecl::ConfigType {
1125 fn fidl_into_native(mut self) -> ConfigNestedValueType {
1126 match self.layout {
1127 fdecl::ConfigTypeLayout::Bool => ConfigNestedValueType::Bool,
1128 fdecl::ConfigTypeLayout::Uint8 => ConfigNestedValueType::Uint8,
1129 fdecl::ConfigTypeLayout::Uint16 => ConfigNestedValueType::Uint16,
1130 fdecl::ConfigTypeLayout::Uint32 => ConfigNestedValueType::Uint32,
1131 fdecl::ConfigTypeLayout::Uint64 => ConfigNestedValueType::Uint64,
1132 fdecl::ConfigTypeLayout::Int8 => ConfigNestedValueType::Int8,
1133 fdecl::ConfigTypeLayout::Int16 => ConfigNestedValueType::Int16,
1134 fdecl::ConfigTypeLayout::Int32 => ConfigNestedValueType::Int32,
1135 fdecl::ConfigTypeLayout::Int64 => ConfigNestedValueType::Int64,
1136 fdecl::ConfigTypeLayout::String => {
1137 let max_size =
1138 if let fdecl::LayoutConstraint::MaxSize(s) = self.constraints.remove(0) {
1139 s
1140 } else {
1141 panic!("Unexpected constraint on String layout type for config field");
1142 };
1143 ConfigNestedValueType::String { max_size }
1144 }
1145 fdecl::ConfigTypeLayout::Vector => {
1146 panic!("Nested vectors are not supported in structured config")
1147 }
1148 fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
1149 }
1150 }
1151}
1152
1153impl NativeIntoFidl<fdecl::ConfigType> for ConfigNestedValueType {
1154 fn native_into_fidl(self) -> fdecl::ConfigType {
1155 let layout = match self {
1156 ConfigNestedValueType::Bool => fdecl::ConfigTypeLayout::Bool,
1157 ConfigNestedValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
1158 ConfigNestedValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
1159 ConfigNestedValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
1160 ConfigNestedValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
1161 ConfigNestedValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
1162 ConfigNestedValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
1163 ConfigNestedValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
1164 ConfigNestedValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
1165 ConfigNestedValueType::String { .. } => fdecl::ConfigTypeLayout::String,
1166 };
1167 let constraints = match self {
1168 ConfigNestedValueType::String { max_size } => {
1169 vec![fdecl::LayoutConstraint::MaxSize(max_size)]
1170 }
1171 _ => vec![],
1172 };
1173 fdecl::ConfigType { layout, constraints, parameters: Some(vec![]) }
1174 }
1175}
1176
1177impl FidlIntoNative<ConfigValueType> for fdecl::ConfigType {
1178 fn fidl_into_native(mut self) -> ConfigValueType {
1179 match self.layout {
1180 fdecl::ConfigTypeLayout::Bool => ConfigValueType::Bool,
1181 fdecl::ConfigTypeLayout::Uint8 => ConfigValueType::Uint8,
1182 fdecl::ConfigTypeLayout::Uint16 => ConfigValueType::Uint16,
1183 fdecl::ConfigTypeLayout::Uint32 => ConfigValueType::Uint32,
1184 fdecl::ConfigTypeLayout::Uint64 => ConfigValueType::Uint64,
1185 fdecl::ConfigTypeLayout::Int8 => ConfigValueType::Int8,
1186 fdecl::ConfigTypeLayout::Int16 => ConfigValueType::Int16,
1187 fdecl::ConfigTypeLayout::Int32 => ConfigValueType::Int32,
1188 fdecl::ConfigTypeLayout::Int64 => ConfigValueType::Int64,
1189 fdecl::ConfigTypeLayout::String => {
1190 let max_size = if let fdecl::LayoutConstraint::MaxSize(s) =
1191 self.constraints.remove(0)
1192 {
1193 s
1194 } else {
1195 panic!(
1196 "Unexpected constraint on String layout type for config field. Expected MaxSize."
1197 );
1198 };
1199 ConfigValueType::String { max_size }
1200 }
1201 fdecl::ConfigTypeLayout::Vector => {
1202 let max_count = if let fdecl::LayoutConstraint::MaxSize(c) =
1203 self.constraints.remove(0)
1204 {
1205 c
1206 } else {
1207 panic!(
1208 "Unexpected constraint on Vector layout type for config field. Expected MaxSize."
1209 );
1210 };
1211 let mut parameters =
1212 self.parameters.expect("Config field must have parameters set");
1213 let nested_type = if let fdecl::LayoutParameter::NestedType(nested_type) =
1214 parameters.remove(0)
1215 {
1216 nested_type.fidl_into_native()
1217 } else {
1218 panic!(
1219 "Unexpected parameter on Vector layout type for config field. Expected NestedType."
1220 );
1221 };
1222 ConfigValueType::Vector { max_count, nested_type }
1223 }
1224 fdecl::ConfigTypeLayoutUnknown!() => panic!("Unknown layout type for config field"),
1225 }
1226 }
1227}
1228
1229impl NativeIntoFidl<fdecl::ConfigType> for ConfigValueType {
1230 fn native_into_fidl(self) -> fdecl::ConfigType {
1231 let layout = match self {
1232 ConfigValueType::Bool => fdecl::ConfigTypeLayout::Bool,
1233 ConfigValueType::Uint8 => fdecl::ConfigTypeLayout::Uint8,
1234 ConfigValueType::Uint16 => fdecl::ConfigTypeLayout::Uint16,
1235 ConfigValueType::Uint32 => fdecl::ConfigTypeLayout::Uint32,
1236 ConfigValueType::Uint64 => fdecl::ConfigTypeLayout::Uint64,
1237 ConfigValueType::Int8 => fdecl::ConfigTypeLayout::Int8,
1238 ConfigValueType::Int16 => fdecl::ConfigTypeLayout::Int16,
1239 ConfigValueType::Int32 => fdecl::ConfigTypeLayout::Int32,
1240 ConfigValueType::Int64 => fdecl::ConfigTypeLayout::Int64,
1241 ConfigValueType::String { .. } => fdecl::ConfigTypeLayout::String,
1242 ConfigValueType::Vector { .. } => fdecl::ConfigTypeLayout::Vector,
1243 };
1244 let (constraints, parameters) = match self {
1245 ConfigValueType::String { max_size } => {
1246 (vec![fdecl::LayoutConstraint::MaxSize(max_size)], vec![])
1247 }
1248 ConfigValueType::Vector { max_count, nested_type } => {
1249 let nested_type = nested_type.native_into_fidl();
1250 (
1251 vec![fdecl::LayoutConstraint::MaxSize(max_count)],
1252 vec![fdecl::LayoutParameter::NestedType(nested_type)],
1253 )
1254 }
1255 _ => (vec![], vec![]),
1256 };
1257 fdecl::ConfigType { layout, constraints, parameters: Some(parameters) }
1258 }
1259}
1260
1261bitflags::bitflags! {
1262 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1263 pub struct ConfigMutability: u32 {
1266 const PARENT = fdecl::ConfigMutability::PARENT.bits();
1267 }
1268}
1269
1270#[cfg(feature = "serde")]
1271bitflags_serde_legacy::impl_traits!(ConfigMutability);
1272
1273impl NativeIntoFidl<fdecl::ConfigMutability> for ConfigMutability {
1274 fn native_into_fidl(self) -> fdecl::ConfigMutability {
1275 fdecl::ConfigMutability::from_bits_allow_unknown(self.bits())
1276 }
1277}
1278
1279impl FidlIntoNative<ConfigMutability> for fdecl::ConfigMutability {
1280 fn fidl_into_native(self) -> ConfigMutability {
1281 ConfigMutability::from_bits_retain(self.bits())
1282 }
1283}
1284
1285#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1286#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1287#[fidl_decl(fidl_table = "fdecl::ConfigValuesData")]
1288pub struct ConfigValuesData {
1289 pub values: Box<[ConfigValueSpec]>,
1290 pub checksum: ConfigChecksum,
1291}
1292
1293#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1294#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1295#[fidl_decl(fidl_table = "fdecl::ConfigValueSpec")]
1296pub struct ConfigValueSpec {
1297 pub value: ConfigValue,
1298}
1299
1300#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
1301#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1302#[fidl_decl(fidl_union = "fdecl::ConfigValue")]
1303pub enum ConfigValue {
1304 Single(ConfigSingleValue),
1305 Vector(ConfigVectorValue),
1306}
1307
1308impl ConfigValue {
1309 pub fn ty(&self) -> ConfigValueType {
1311 match self {
1312 Self::Single(sv) => sv.ty(),
1313 Self::Vector(vv) => vv.ty(),
1314 }
1315 }
1316
1317 pub fn matches_type(&self, other: &ConfigValue) -> bool {
1319 match (self, other) {
1320 (ConfigValue::Single(a), ConfigValue::Single(b)) => {
1321 std::mem::discriminant(a) == std::mem::discriminant(b)
1322 }
1323 (ConfigValue::Vector(a), ConfigValue::Vector(b)) => {
1324 std::mem::discriminant(a) == std::mem::discriminant(b)
1325 }
1326 _ => false,
1327 }
1328 }
1329}
1330
1331impl From<&str> for ConfigValue {
1332 fn from(value: &str) -> Self {
1333 ConfigValue::Single(value.to_string().into())
1334 }
1335}
1336
1337impl From<Vec<&str>> for ConfigValue {
1338 fn from(value: Vec<&str>) -> Self {
1339 let value: Box<[_]> = value.into_iter().map(|s| s.to_string()).collect();
1340 ConfigValue::Vector(value.into())
1341 }
1342}
1343
1344macro_rules! generate_configvalue_from {
1345 ($name:expr, $type:ty) => {
1346 impl From<$type> for ConfigValue {
1347 fn from(value: $type) -> Self {
1348 $name(value.into())
1349 }
1350 }
1351 };
1352}
1353
1354generate_configvalue_from!(ConfigValue::Single, bool);
1355generate_configvalue_from!(ConfigValue::Single, u8);
1356generate_configvalue_from!(ConfigValue::Single, u16);
1357generate_configvalue_from!(ConfigValue::Single, u32);
1358generate_configvalue_from!(ConfigValue::Single, u64);
1359generate_configvalue_from!(ConfigValue::Single, i8);
1360generate_configvalue_from!(ConfigValue::Single, i16);
1361generate_configvalue_from!(ConfigValue::Single, i32);
1362generate_configvalue_from!(ConfigValue::Single, i64);
1363generate_configvalue_from!(ConfigValue::Single, String);
1364generate_configvalue_from!(ConfigValue::Vector, Box<[bool]>);
1365generate_configvalue_from!(ConfigValue::Vector, Box<[u8]>);
1366generate_configvalue_from!(ConfigValue::Vector, Box<[u16]>);
1367generate_configvalue_from!(ConfigValue::Vector, Box<[u32]>);
1368generate_configvalue_from!(ConfigValue::Vector, Box<[u64]>);
1369generate_configvalue_from!(ConfigValue::Vector, Box<[i8]>);
1370generate_configvalue_from!(ConfigValue::Vector, Box<[i16]>);
1371generate_configvalue_from!(ConfigValue::Vector, Box<[i32]>);
1372generate_configvalue_from!(ConfigValue::Vector, Box<[i64]>);
1373generate_configvalue_from!(ConfigValue::Vector, Box<[String]>);
1374generate_configvalue_from!(ConfigValue::Vector, Vec<bool>);
1375generate_configvalue_from!(ConfigValue::Vector, Vec<u8>);
1376generate_configvalue_from!(ConfigValue::Vector, Vec<u16>);
1377generate_configvalue_from!(ConfigValue::Vector, Vec<u32>);
1378generate_configvalue_from!(ConfigValue::Vector, Vec<u64>);
1379generate_configvalue_from!(ConfigValue::Vector, Vec<i8>);
1380generate_configvalue_from!(ConfigValue::Vector, Vec<i16>);
1381generate_configvalue_from!(ConfigValue::Vector, Vec<i32>);
1382generate_configvalue_from!(ConfigValue::Vector, Vec<i64>);
1383generate_configvalue_from!(ConfigValue::Vector, Vec<String>);
1384
1385impl fmt::Display for ConfigValue {
1386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1387 match self {
1388 ConfigValue::Single(sv) => sv.fmt(f),
1389 ConfigValue::Vector(lv) => lv.fmt(f),
1390 }
1391 }
1392}
1393
1394#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
1395#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1396#[fidl_decl(fidl_union = "fdecl::ConfigSingleValue")]
1397pub enum ConfigSingleValue {
1398 Bool(bool),
1399 Uint8(u8),
1400 Uint16(u16),
1401 Uint32(u32),
1402 Uint64(u64),
1403 Int8(i8),
1404 Int16(i16),
1405 Int32(i32),
1406 Int64(i64),
1407 String(String),
1408}
1409
1410impl ConfigSingleValue {
1411 fn ty(&self) -> ConfigValueType {
1412 match self {
1413 ConfigSingleValue::Bool(_) => ConfigValueType::Bool,
1414 ConfigSingleValue::Uint8(_) => ConfigValueType::Uint8,
1415 ConfigSingleValue::Uint16(_) => ConfigValueType::Uint16,
1416 ConfigSingleValue::Uint32(_) => ConfigValueType::Uint32,
1417 ConfigSingleValue::Uint64(_) => ConfigValueType::Uint64,
1418 ConfigSingleValue::Int8(_) => ConfigValueType::Int8,
1419 ConfigSingleValue::Int16(_) => ConfigValueType::Int16,
1420 ConfigSingleValue::Int32(_) => ConfigValueType::Int32,
1421 ConfigSingleValue::Int64(_) => ConfigValueType::Int64,
1422 ConfigSingleValue::String(_) => ConfigValueType::String { max_size: std::u32::MAX },
1424 }
1425 }
1426}
1427
1428impl fmt::Display for ConfigSingleValue {
1429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1430 use ConfigSingleValue::*;
1431 match self {
1432 Bool(v) => write!(f, "{}", v),
1433 Uint8(v) => write!(f, "{}", v),
1434 Uint16(v) => write!(f, "{}", v),
1435 Uint32(v) => write!(f, "{}", v),
1436 Uint64(v) => write!(f, "{}", v),
1437 Int8(v) => write!(f, "{}", v),
1438 Int16(v) => write!(f, "{}", v),
1439 Int32(v) => write!(f, "{}", v),
1440 Int64(v) => write!(f, "{}", v),
1441 String(v) => write!(f, "\"{}\"", v),
1442 }
1443 }
1444}
1445
1446#[derive(FromEnum, FidlDecl, Debug, Clone, PartialEq, Eq)]
1447#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1448#[fidl_decl(fidl_union = "fdecl::ConfigVectorValue")]
1449pub enum ConfigVectorValue {
1450 BoolVector(Box<[bool]>),
1451 Uint8Vector(Box<[u8]>),
1452 Uint16Vector(Box<[u16]>),
1453 Uint32Vector(Box<[u32]>),
1454 Uint64Vector(Box<[u64]>),
1455 Int8Vector(Box<[i8]>),
1456 Int16Vector(Box<[i16]>),
1457 Int32Vector(Box<[i32]>),
1458 Int64Vector(Box<[i64]>),
1459 StringVector(Box<[String]>),
1460}
1461
1462impl From<Vec<bool>> for ConfigVectorValue {
1463 fn from(v: Vec<bool>) -> Self {
1464 Self::BoolVector(v.into())
1465 }
1466}
1467
1468impl From<Vec<u8>> for ConfigVectorValue {
1469 fn from(v: Vec<u8>) -> Self {
1470 Self::Uint8Vector(v.into())
1471 }
1472}
1473
1474impl From<Vec<u16>> for ConfigVectorValue {
1475 fn from(v: Vec<u16>) -> Self {
1476 Self::Uint16Vector(v.into())
1477 }
1478}
1479
1480impl From<Vec<u32>> for ConfigVectorValue {
1481 fn from(v: Vec<u32>) -> Self {
1482 Self::Uint32Vector(v.into())
1483 }
1484}
1485
1486impl From<Vec<u64>> for ConfigVectorValue {
1487 fn from(v: Vec<u64>) -> Self {
1488 Self::Uint64Vector(v.into())
1489 }
1490}
1491
1492impl From<Vec<i8>> for ConfigVectorValue {
1493 fn from(v: Vec<i8>) -> Self {
1494 Self::Int8Vector(v.into())
1495 }
1496}
1497
1498impl From<Vec<i16>> for ConfigVectorValue {
1499 fn from(v: Vec<i16>) -> Self {
1500 Self::Int16Vector(v.into())
1501 }
1502}
1503
1504impl From<Vec<i32>> for ConfigVectorValue {
1505 fn from(v: Vec<i32>) -> Self {
1506 Self::Int32Vector(v.into())
1507 }
1508}
1509
1510impl From<Vec<i64>> for ConfigVectorValue {
1511 fn from(v: Vec<i64>) -> Self {
1512 Self::Int64Vector(v.into())
1513 }
1514}
1515
1516impl From<Vec<String>> for ConfigVectorValue {
1517 fn from(v: Vec<String>) -> Self {
1518 Self::StringVector(v.into())
1519 }
1520}
1521
1522impl ConfigVectorValue {
1523 fn ty(&self) -> ConfigValueType {
1524 match self {
1526 ConfigVectorValue::BoolVector(_) => ConfigValueType::Vector {
1527 nested_type: ConfigNestedValueType::Bool,
1528 max_count: std::u32::MAX,
1529 },
1530 ConfigVectorValue::Uint8Vector(_) => ConfigValueType::Vector {
1531 nested_type: ConfigNestedValueType::Uint8,
1532 max_count: std::u32::MAX,
1533 },
1534 ConfigVectorValue::Uint16Vector(_) => ConfigValueType::Vector {
1535 nested_type: ConfigNestedValueType::Uint16,
1536 max_count: std::u32::MAX,
1537 },
1538 ConfigVectorValue::Uint32Vector(_) => ConfigValueType::Vector {
1539 nested_type: ConfigNestedValueType::Uint32,
1540 max_count: std::u32::MAX,
1541 },
1542 ConfigVectorValue::Uint64Vector(_) => ConfigValueType::Vector {
1543 nested_type: ConfigNestedValueType::Uint64,
1544 max_count: std::u32::MAX,
1545 },
1546 ConfigVectorValue::Int8Vector(_) => ConfigValueType::Vector {
1547 nested_type: ConfigNestedValueType::Int8,
1548 max_count: std::u32::MAX,
1549 },
1550 ConfigVectorValue::Int16Vector(_) => ConfigValueType::Vector {
1551 nested_type: ConfigNestedValueType::Int16,
1552 max_count: std::u32::MAX,
1553 },
1554 ConfigVectorValue::Int32Vector(_) => ConfigValueType::Vector {
1555 nested_type: ConfigNestedValueType::Int32,
1556 max_count: std::u32::MAX,
1557 },
1558 ConfigVectorValue::Int64Vector(_) => ConfigValueType::Vector {
1559 nested_type: ConfigNestedValueType::Int64,
1560 max_count: std::u32::MAX,
1561 },
1562 ConfigVectorValue::StringVector(_) => ConfigValueType::Vector {
1563 nested_type: ConfigNestedValueType::String { max_size: std::u32::MAX },
1564 max_count: std::u32::MAX,
1565 },
1566 }
1567 }
1568}
1569
1570impl fmt::Display for ConfigVectorValue {
1571 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1572 use ConfigVectorValue::*;
1573 macro_rules! print_list {
1574 ($f:ident, $list:ident) => {{
1575 $f.write_str("[")?;
1576
1577 for (i, item) in $list.iter().enumerate() {
1578 if i > 0 {
1579 $f.write_str(", ")?;
1580 }
1581 write!($f, "{}", item)?;
1582 }
1583
1584 $f.write_str("]")
1585 }};
1586 }
1587 match self {
1588 BoolVector(l) => print_list!(f, l),
1589 Uint8Vector(l) => print_list!(f, l),
1590 Uint16Vector(l) => print_list!(f, l),
1591 Uint32Vector(l) => print_list!(f, l),
1592 Uint64Vector(l) => print_list!(f, l),
1593 Int8Vector(l) => print_list!(f, l),
1594 Int16Vector(l) => print_list!(f, l),
1595 Int32Vector(l) => print_list!(f, l),
1596 Int64Vector(l) => print_list!(f, l),
1597 StringVector(l) => {
1598 f.write_str("[")?;
1599 for (i, item) in l.iter().enumerate() {
1600 if i > 0 {
1601 f.write_str(", ")?;
1602 }
1603 write!(f, "\"{}\"", item)?;
1604 }
1605 f.write_str("]")
1606 }
1607 }
1608 }
1609}
1610
1611#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1612#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1613#[fidl_decl(fidl_table = "fdecl::RunnerRegistration")]
1614pub struct RunnerRegistration {
1615 pub source_name: Name,
1616 pub target_name: Name,
1617 pub source: RegistrationSource,
1618}
1619
1620impl SourceName for RunnerRegistration {
1621 fn source_name(&self) -> &Name {
1622 &self.source_name
1623 }
1624}
1625
1626impl RegistrationDeclCommon for RunnerRegistration {
1627 const TYPE: &'static str = "runner";
1628
1629 fn source(&self) -> &RegistrationSource {
1630 &self.source
1631 }
1632}
1633
1634#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1635#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1636#[fidl_decl(fidl_table = "fdecl::ResolverRegistration")]
1637pub struct ResolverRegistration {
1638 pub resolver: Name,
1639 pub source: RegistrationSource,
1640 pub scheme: String,
1641}
1642
1643impl SourceName for ResolverRegistration {
1644 fn source_name(&self) -> &Name {
1645 &self.resolver
1646 }
1647}
1648
1649impl RegistrationDeclCommon for ResolverRegistration {
1650 const TYPE: &'static str = "resolver";
1651
1652 fn source(&self) -> &RegistrationSource {
1653 &self.source
1654 }
1655}
1656
1657#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1658#[fidl_decl(fidl_union = "fdecl::DebugRegistration")]
1659pub enum DebugRegistration {
1660 Protocol(DebugProtocolRegistration),
1661}
1662
1663impl RegistrationDeclCommon for DebugRegistration {
1664 const TYPE: &'static str = "debug_protocol";
1665
1666 fn source(&self) -> &RegistrationSource {
1667 match self {
1668 DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source,
1669 }
1670 }
1671}
1672
1673impl SourceName for DebugRegistration {
1674 fn source_name(&self) -> &Name {
1675 match self {
1676 DebugRegistration::Protocol(protocol_reg) => &protocol_reg.source_name,
1677 }
1678 }
1679}
1680
1681#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1682#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
1683#[fidl_decl(fidl_table = "fdecl::DebugProtocolRegistration")]
1684pub struct DebugProtocolRegistration {
1685 pub source_name: Name,
1686 pub source: RegistrationSource,
1687 pub target_name: Name,
1688}
1689
1690#[derive(FidlDecl, Debug, Clone, PartialEq)]
1691#[fidl_decl(fidl_table = "fdecl::Program")]
1692pub struct ProgramDecl {
1693 pub runner: Option<Name>,
1694 pub info: fdata::Dictionary,
1695}
1696
1697impl Default for ProgramDecl {
1698 fn default() -> Self {
1699 Self { runner: None, info: fdata::Dictionary::default() }
1700 }
1701}
1702
1703fidl_translations_identical!([u8; 32]);
1704fidl_translations_identical!(u8);
1705fidl_translations_identical!(u16);
1706fidl_translations_identical!(u32);
1707fidl_translations_identical!(u64);
1708fidl_translations_identical!(i8);
1709fidl_translations_identical!(i16);
1710fidl_translations_identical!(i32);
1711fidl_translations_identical!(i64);
1712fidl_translations_identical!(bool);
1713fidl_translations_identical!(String);
1714fidl_translations_identical!(Vec<Name>);
1715fidl_translations_identical!(fdecl::StartupMode);
1716fidl_translations_identical!(fdecl::OnTerminate);
1717fidl_translations_identical!(fdecl::Durability);
1718fidl_translations_identical!(fdata::Dictionary);
1719fidl_translations_identical!(fio::Operations);
1720fidl_translations_identical!(fdecl::EnvironmentExtends);
1721fidl_translations_identical!(fdecl::StorageId);
1722fidl_translations_identical!(Vec<fprocess::HandleInfo>);
1723fidl_translations_identical!(fsys::ServiceInstance);
1724fidl_translations_from_into!(cm_types::AllowedOffers, fdecl::AllowedOffers);
1725
1726#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1727#[derive(Debug, Clone, PartialEq, Eq)]
1728pub enum DependencyType {
1729 Strong,
1730 Weak,
1731}
1732
1733impl Default for DependencyType {
1734 fn default() -> Self {
1735 Self::Strong
1736 }
1737}
1738
1739fidl_translations_symmetrical_enums!(fdecl::DependencyType, DependencyType, Strong, Weak);
1740
1741impl UseDecl {
1742 pub fn path(&self) -> Option<&Path> {
1743 match self {
1744 UseDecl::Service(d) => Some(&d.target_path),
1745 UseDecl::Protocol(d) => d.target_path.as_ref(),
1746 UseDecl::Directory(d) => Some(&d.target_path),
1747 UseDecl::Storage(d) => Some(&d.target_path),
1748 UseDecl::EventStream(d) => Some(&d.target_path),
1749 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1750 UseDecl::Runner(_) => None,
1751 UseDecl::Config(_) => None,
1752 #[cfg(fuchsia_api_level_at_least = "29")]
1753 UseDecl::Dictionary(d) => Some(&d.target_path),
1754 }
1755 }
1756
1757 pub fn name(&self) -> Option<&Name> {
1758 match self {
1759 UseDecl::Storage(storage_decl) => Some(&storage_decl.source_name),
1760 UseDecl::EventStream(_) => None,
1761 UseDecl::Service(_) | UseDecl::Protocol(_) | UseDecl::Directory(_) => None,
1762 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1763 UseDecl::Runner(_) => None,
1764 UseDecl::Config(_) => None,
1765 #[cfg(fuchsia_api_level_at_least = "29")]
1766 UseDecl::Dictionary(_) => None,
1767 }
1768 }
1769}
1770
1771impl SourceName for UseDecl {
1772 fn source_name(&self) -> &Name {
1773 match self {
1774 UseDecl::Storage(storage_decl) => &storage_decl.source_name,
1775 UseDecl::Service(service_decl) => &service_decl.source_name,
1776 UseDecl::Protocol(protocol_decl) => &protocol_decl.source_name,
1777 UseDecl::Directory(directory_decl) => &directory_decl.source_name,
1778 UseDecl::EventStream(event_stream_decl) => &event_stream_decl.source_name,
1779 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1780 UseDecl::Runner(runner_decl) => &runner_decl.source_name,
1781 UseDecl::Config(u) => &u.source_name,
1782 #[cfg(fuchsia_api_level_at_least = "29")]
1783 UseDecl::Dictionary(dictionary_decl) => &dictionary_decl.source_name,
1784 }
1785 }
1786}
1787
1788impl SourcePath for UseDecl {
1789 fn source_path(&self) -> BorrowedSeparatedPath<'_> {
1790 match self {
1791 UseDecl::Service(u) => u.source_path(),
1792 UseDecl::Protocol(u) => u.source_path(),
1793 UseDecl::Directory(u) => u.source_path(),
1794 UseDecl::Storage(u) => u.source_path(),
1795 UseDecl::EventStream(u) => u.source_path(),
1796 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1797 UseDecl::Runner(u) => u.source_path(),
1798 UseDecl::Config(u) => u.source_path(),
1799 #[cfg(fuchsia_api_level_at_least = "29")]
1800 UseDecl::Dictionary(u) => u.source_path(),
1801 }
1802 }
1803}
1804
1805pub trait SourceName {
1807 fn source_name(&self) -> &Name;
1808}
1809
1810pub trait UseDeclCommon: SourceName + SourcePath + Send + Sync {
1812 fn source(&self) -> &UseSource;
1813 fn availability(&self) -> &Availability;
1814}
1815
1816pub trait RegistrationDeclCommon: SourceName + Send + Sync {
1818 const TYPE: &'static str;
1820 fn source(&self) -> &RegistrationSource;
1821}
1822
1823pub trait ExposeDeclCommon: SourceName + SourcePath + fmt::Debug + Send + Sync {
1825 fn target_name(&self) -> &Name;
1826 fn target(&self) -> &ExposeTarget;
1827 fn source(&self) -> &ExposeSource;
1828 fn availability(&self) -> &Availability;
1829}
1830
1831#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
1835#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
1836pub enum CapabilityTypeName {
1837 Directory,
1838 EventStream,
1839 Protocol,
1840 Resolver,
1841 Runner,
1842 Service,
1843 Storage,
1844 Dictionary,
1845 Config,
1846}
1847
1848impl std::str::FromStr for CapabilityTypeName {
1849 type Err = Error;
1850
1851 fn from_str(s: &str) -> Result<Self, Self::Err> {
1852 match s {
1853 "directory" => Ok(CapabilityTypeName::Directory),
1854 "event_stream" => Ok(CapabilityTypeName::EventStream),
1855 "protocol" => Ok(CapabilityTypeName::Protocol),
1856 "resolver" => Ok(CapabilityTypeName::Resolver),
1857 "runner" => Ok(CapabilityTypeName::Runner),
1858 "service" => Ok(CapabilityTypeName::Service),
1859 "storage" => Ok(CapabilityTypeName::Storage),
1860 "dictionary" => Ok(CapabilityTypeName::Dictionary),
1861 "configuration" => Ok(CapabilityTypeName::Config),
1862 _ => Err(Error::ParseCapabilityTypeName { raw: s.to_string() }),
1863 }
1864 }
1865}
1866
1867impl FidlIntoNative<CapabilityTypeName> for String {
1868 fn fidl_into_native(self) -> CapabilityTypeName {
1869 self.parse().unwrap()
1870 }
1871}
1872
1873impl NativeIntoFidl<String> for CapabilityTypeName {
1874 fn native_into_fidl(self) -> String {
1875 self.to_string()
1876 }
1877}
1878
1879impl fmt::Display for CapabilityTypeName {
1880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1881 let display_name = match &self {
1882 CapabilityTypeName::Directory => "directory",
1883 CapabilityTypeName::EventStream => "event_stream",
1884 CapabilityTypeName::Protocol => "protocol",
1885 CapabilityTypeName::Resolver => "resolver",
1886 CapabilityTypeName::Runner => "runner",
1887 CapabilityTypeName::Service => "service",
1888 CapabilityTypeName::Storage => "storage",
1889 CapabilityTypeName::Dictionary => "dictionary",
1890 CapabilityTypeName::Config => "configuration",
1891 };
1892 write!(f, "{}", display_name)
1893 }
1894}
1895
1896impl From<&UseDecl> for CapabilityTypeName {
1897 fn from(use_decl: &UseDecl) -> Self {
1898 match use_decl {
1899 UseDecl::Service(_) => Self::Service,
1900 UseDecl::Protocol(_) => Self::Protocol,
1901 UseDecl::Directory(_) => Self::Directory,
1902 UseDecl::Storage(_) => Self::Storage,
1903 UseDecl::EventStream(_) => Self::EventStream,
1904 #[cfg(fuchsia_api_level_at_least = "HEAD")]
1905 UseDecl::Runner(_) => Self::Runner,
1906 UseDecl::Config(_) => Self::Config,
1907 #[cfg(fuchsia_api_level_at_least = "29")]
1908 UseDecl::Dictionary(_) => Self::Dictionary,
1909 }
1910 }
1911}
1912
1913impl From<&ExposeDecl> for CapabilityTypeName {
1914 fn from(expose_decl: &ExposeDecl) -> Self {
1915 match expose_decl {
1916 ExposeDecl::Service(_) => Self::Service,
1917 ExposeDecl::Protocol(_) => Self::Protocol,
1918 ExposeDecl::Directory(_) => Self::Directory,
1919 ExposeDecl::Runner(_) => Self::Runner,
1920 ExposeDecl::Resolver(_) => Self::Resolver,
1921 ExposeDecl::Dictionary(_) => Self::Dictionary,
1922 ExposeDecl::Config(_) => Self::Config,
1923 }
1924 }
1925}
1926
1927impl From<&CapabilityDecl> for CapabilityTypeName {
1928 fn from(capability: &CapabilityDecl) -> Self {
1929 match capability {
1930 CapabilityDecl::Service(_) => Self::Service,
1931 CapabilityDecl::Protocol(_) => Self::Protocol,
1932 CapabilityDecl::Directory(_) => Self::Directory,
1933 CapabilityDecl::Storage(_) => Self::Storage,
1934 CapabilityDecl::Runner(_) => Self::Runner,
1935 CapabilityDecl::Resolver(_) => Self::Resolver,
1936 CapabilityDecl::EventStream(_) => Self::EventStream,
1937 CapabilityDecl::Dictionary(_) => Self::Dictionary,
1938 CapabilityDecl::Config(_) => Self::Config,
1939 }
1940 }
1941}
1942
1943impl From<CapabilityTypeName> for fio::DirentType {
1944 fn from(value: CapabilityTypeName) -> Self {
1945 match value {
1946 CapabilityTypeName::Directory => fio::DirentType::Directory,
1947 CapabilityTypeName::EventStream => fio::DirentType::Service,
1948 CapabilityTypeName::Protocol => fio::DirentType::Service,
1949 CapabilityTypeName::Service => fio::DirentType::Directory,
1950 CapabilityTypeName::Storage => fio::DirentType::Directory,
1951 CapabilityTypeName::Dictionary => fio::DirentType::Directory,
1952 CapabilityTypeName::Resolver => fio::DirentType::Service,
1953 CapabilityTypeName::Runner => fio::DirentType::Service,
1954 CapabilityTypeName::Config => fio::DirentType::Unknown,
1956 }
1957 }
1958}
1959
1960impl FidlIntoNative<HashMap<String, DictionaryValue>> for fdata::Dictionary {
1962 fn fidl_into_native(self) -> HashMap<String, DictionaryValue> {
1963 from_fidl_dict(self)
1964 }
1965}
1966
1967impl NativeIntoFidl<fdata::Dictionary> for HashMap<String, DictionaryValue> {
1968 fn native_into_fidl(self) -> fdata::Dictionary {
1969 to_fidl_dict(self)
1970 }
1971}
1972
1973impl FidlIntoNative<BTreeMap<String, DictionaryValue>> for fdata::Dictionary {
1974 fn fidl_into_native(self) -> BTreeMap<String, DictionaryValue> {
1975 from_fidl_dict_btree(self)
1976 }
1977}
1978
1979impl NativeIntoFidl<fdata::Dictionary> for BTreeMap<String, DictionaryValue> {
1980 fn native_into_fidl(self) -> fdata::Dictionary {
1981 to_fidl_dict_btree(self)
1982 }
1983}
1984
1985#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1986pub enum DictionaryValue {
1987 Str(String),
1988 StrVec(Vec<String>),
1989 Null,
1990}
1991
1992impl FidlIntoNative<DictionaryValue> for Option<Box<fdata::DictionaryValue>> {
1993 fn fidl_into_native(self) -> DictionaryValue {
1994 match self {
1995 Some(v) => match *v {
1996 fdata::DictionaryValue::Str(s) => DictionaryValue::Str(s),
1997 fdata::DictionaryValue::StrVec(ss) => DictionaryValue::StrVec(ss),
1998 _ => DictionaryValue::Null,
1999 },
2000 None => DictionaryValue::Null,
2001 }
2002 }
2003}
2004
2005impl NativeIntoFidl<Option<Box<fdata::DictionaryValue>>> for DictionaryValue {
2006 fn native_into_fidl(self) -> Option<Box<fdata::DictionaryValue>> {
2007 match self {
2008 DictionaryValue::Str(s) => Some(Box::new(fdata::DictionaryValue::Str(s))),
2009 DictionaryValue::StrVec(ss) => Some(Box::new(fdata::DictionaryValue::StrVec(ss))),
2010 DictionaryValue::Null => None,
2011 }
2012 }
2013}
2014
2015fn from_fidl_dict(dict: fdata::Dictionary) -> HashMap<String, DictionaryValue> {
2016 match dict.entries {
2017 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
2018 _ => HashMap::new(),
2019 }
2020}
2021
2022fn to_fidl_dict(dict: HashMap<String, DictionaryValue>) -> fdata::Dictionary {
2023 fdata::Dictionary {
2024 entries: Some(
2025 dict.into_iter()
2026 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
2027 .collect(),
2028 ),
2029 ..Default::default()
2030 }
2031}
2032
2033fn from_fidl_dict_btree(dict: fdata::Dictionary) -> BTreeMap<String, DictionaryValue> {
2034 match dict.entries {
2035 Some(entries) => entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect(),
2036 _ => BTreeMap::new(),
2037 }
2038}
2039
2040fn to_fidl_dict_btree(dict: BTreeMap<String, DictionaryValue>) -> fdata::Dictionary {
2041 fdata::Dictionary {
2042 entries: Some(
2043 dict.into_iter()
2044 .map(|(key, value)| fdata::DictionaryEntry { key, value: value.native_into_fidl() })
2045 .collect(),
2046 ),
2047 ..Default::default()
2048 }
2049}
2050
2051#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2052#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2053pub enum UseSource {
2054 Parent,
2055 Framework,
2056 Debug,
2057 Self_,
2058 Capability(Name),
2059 Child(Name),
2060 Collection(Name),
2061 #[cfg(fuchsia_api_level_at_least = "HEAD")]
2062 Environment,
2063}
2064
2065impl std::fmt::Display for UseSource {
2066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2067 match self {
2068 Self::Framework => write!(f, "framework"),
2069 Self::Parent => write!(f, "parent"),
2070 Self::Debug => write!(f, "debug environment"),
2071 Self::Self_ => write!(f, "self"),
2072 Self::Capability(c) => write!(f, "capability `{}`", c),
2073 Self::Child(c) => write!(f, "child `#{}`", c),
2074 Self::Collection(c) => write!(f, "collection `#{}`", c),
2075 #[cfg(fuchsia_api_level_at_least = "HEAD")]
2076 Self::Environment => write!(f, "environment"),
2077 }
2078 }
2079}
2080
2081impl FidlIntoNative<UseSource> for fdecl::Ref {
2082 fn fidl_into_native(self) -> UseSource {
2083 match self {
2084 fdecl::Ref::Parent(_) => UseSource::Parent,
2085 fdecl::Ref::Framework(_) => UseSource::Framework,
2086 fdecl::Ref::Debug(_) => UseSource::Debug,
2087 fdecl::Ref::Self_(_) => UseSource::Self_,
2088 fdecl::Ref::Capability(c) => UseSource::Capability(c.name.parse().unwrap()),
2090 fdecl::Ref::Child(c) => UseSource::Child(c.name.parse().unwrap()),
2091 fdecl::Ref::Collection(c) => UseSource::Collection(c.name.parse().unwrap()),
2092 #[cfg(fuchsia_api_level_at_least = "HEAD")]
2093 fdecl::Ref::Environment(_) => UseSource::Environment,
2094 _ => panic!("invalid UseSource variant"),
2095 }
2096 }
2097}
2098
2099impl NativeIntoFidl<fdecl::Ref> for UseSource {
2100 fn native_into_fidl(self) -> fdecl::Ref {
2101 match self {
2102 UseSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
2103 UseSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2104 UseSource::Debug => fdecl::Ref::Debug(fdecl::DebugRef {}),
2105 UseSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
2106 UseSource::Capability(name) => {
2107 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
2108 }
2109 UseSource::Child(name) => {
2110 fdecl::Ref::Child(fdecl::ChildRef { name: name.to_string(), collection: None })
2111 }
2112 UseSource::Collection(name) => {
2113 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.to_string() })
2114 }
2115 #[cfg(fuchsia_api_level_at_least = "HEAD")]
2116 UseSource::Environment => fdecl::Ref::Environment(fdecl::EnvironmentRef {}),
2117 }
2118 }
2119}
2120
2121#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2122#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2123pub enum EventScope {
2124 Child(ChildRef),
2125 Collection(Name),
2126}
2127
2128impl FidlIntoNative<EventScope> for fdecl::Ref {
2129 fn fidl_into_native(self) -> EventScope {
2130 match self {
2131 fdecl::Ref::Child(c) => {
2132 if let Some(_) = c.collection {
2133 panic!("Dynamic children scopes are not supported for EventStreams");
2134 } else {
2135 EventScope::Child(ChildRef { name: c.name.parse().unwrap(), collection: None })
2136 }
2137 }
2138 fdecl::Ref::Collection(collection) => {
2139 EventScope::Collection(collection.name.parse().unwrap())
2141 }
2142 _ => panic!("invalid EventScope variant"),
2143 }
2144 }
2145}
2146
2147impl NativeIntoFidl<fdecl::Ref> for EventScope {
2148 fn native_into_fidl(self) -> fdecl::Ref {
2149 match self {
2150 EventScope::Child(child) => fdecl::Ref::Child(child.native_into_fidl()),
2151 EventScope::Collection(name) => {
2152 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
2153 }
2154 }
2155 }
2156}
2157
2158#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2159#[derive(Debug, Clone, PartialEq, Eq)]
2160pub enum ExposeSource {
2161 Self_,
2162 Child(Name),
2163 Collection(Name),
2164 Framework,
2165 Capability(Name),
2166 Void,
2167}
2168
2169impl std::fmt::Display for ExposeSource {
2170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2171 match self {
2172 Self::Framework => write!(f, "framework"),
2173 Self::Child(c) => write!(f, "child `#{}`", c),
2174 Self::Collection(c) => write!(f, "collection `#{}`", c),
2175 Self::Self_ => write!(f, "self"),
2176 Self::Capability(c) => write!(f, "capability `{}`", c),
2177 Self::Void => write!(f, "void"),
2178 }
2179 }
2180}
2181
2182impl FidlIntoNative<ExposeSource> for fdecl::Ref {
2183 fn fidl_into_native(self) -> ExposeSource {
2184 match self {
2185 fdecl::Ref::Self_(_) => ExposeSource::Self_,
2186 fdecl::Ref::Child(c) => ExposeSource::Child(c.name.parse().unwrap()),
2188 fdecl::Ref::Collection(c) => ExposeSource::Collection(c.name.parse().unwrap()),
2190 fdecl::Ref::Framework(_) => ExposeSource::Framework,
2191 fdecl::Ref::Capability(c) => ExposeSource::Capability(c.name.parse().unwrap()),
2193 fdecl::Ref::VoidType(_) => ExposeSource::Void,
2194 _ => panic!("invalid ExposeSource variant"),
2195 }
2196 }
2197}
2198
2199impl NativeIntoFidl<fdecl::Ref> for ExposeSource {
2200 fn native_into_fidl(self) -> fdecl::Ref {
2201 match self {
2202 ExposeSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
2203 ExposeSource::Child(name) => fdecl::Ref::Child(fdecl::ChildRef {
2204 name: name.native_into_fidl(),
2205 collection: None,
2206 }),
2207 ExposeSource::Collection(name) => {
2208 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
2209 }
2210 ExposeSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2211 ExposeSource::Capability(name) => {
2212 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
2213 }
2214 ExposeSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
2215 }
2216 }
2217}
2218
2219#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2220#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2221pub enum ExposeTarget {
2222 Parent,
2223 Framework,
2224}
2225
2226impl std::fmt::Display for ExposeTarget {
2227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2228 match self {
2229 Self::Framework => write!(f, "framework"),
2230 Self::Parent => write!(f, "parent"),
2231 }
2232 }
2233}
2234
2235impl FidlIntoNative<ExposeTarget> for fdecl::Ref {
2236 fn fidl_into_native(self) -> ExposeTarget {
2237 match self {
2238 fdecl::Ref::Parent(_) => ExposeTarget::Parent,
2239 fdecl::Ref::Framework(_) => ExposeTarget::Framework,
2240 _ => panic!("invalid ExposeTarget variant"),
2241 }
2242 }
2243}
2244
2245impl NativeIntoFidl<fdecl::Ref> for ExposeTarget {
2246 fn native_into_fidl(self) -> fdecl::Ref {
2247 match self {
2248 ExposeTarget::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
2249 ExposeTarget::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
2250 }
2251 }
2252}
2253
2254#[derive(Debug, Clone, PartialEq, Eq)]
2256pub struct ServiceSource<T> {
2257 pub source: T,
2259 pub source_name: Name,
2261}
2262
2263#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2264#[derive(Debug, Clone, PartialEq, Eq)]
2265pub enum StorageDirectorySource {
2266 Parent,
2267 Self_,
2268 Child(String),
2269}
2270
2271impl FidlIntoNative<StorageDirectorySource> for fdecl::Ref {
2272 fn fidl_into_native(self) -> StorageDirectorySource {
2273 match self {
2274 fdecl::Ref::Parent(_) => StorageDirectorySource::Parent,
2275 fdecl::Ref::Self_(_) => StorageDirectorySource::Self_,
2276 fdecl::Ref::Child(c) => StorageDirectorySource::Child(c.name),
2277 _ => panic!("invalid StorageDirectorySource variant"),
2278 }
2279 }
2280}
2281
2282impl NativeIntoFidl<fdecl::Ref> for StorageDirectorySource {
2283 fn native_into_fidl(self) -> fdecl::Ref {
2284 match self {
2285 StorageDirectorySource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
2286 StorageDirectorySource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
2287 StorageDirectorySource::Child(child_name) => {
2288 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
2289 }
2290 }
2291 }
2292}
2293
2294#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2295#[derive(Debug, Clone, PartialEq, Eq)]
2296pub enum DictionarySource {
2297 Parent,
2298 Self_,
2299 Child(ChildRef),
2300}
2301
2302impl FidlIntoNative<DictionarySource> for fdecl::Ref {
2303 fn fidl_into_native(self) -> DictionarySource {
2304 match self {
2305 Self::Parent(_) => DictionarySource::Parent,
2306 Self::Self_(_) => DictionarySource::Self_,
2307 Self::Child(c) => DictionarySource::Child(c.fidl_into_native()),
2308 _ => panic!("invalid DictionarySource variant"),
2309 }
2310 }
2311}
2312
2313impl NativeIntoFidl<fdecl::Ref> for DictionarySource {
2314 fn native_into_fidl(self) -> fdecl::Ref {
2315 match self {
2316 Self::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
2317 Self::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
2318 Self::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
2319 }
2320 }
2321}
2322
2323#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
2324#[derive(Debug, Clone, PartialEq, Eq)]
2325pub enum RegistrationSource {
2326 Parent,
2327 Self_,
2328 Child(String),
2329}
2330
2331impl FidlIntoNative<RegistrationSource> for fdecl::Ref {
2332 fn fidl_into_native(self) -> RegistrationSource {
2333 match self {
2334 fdecl::Ref::Parent(_) => RegistrationSource::Parent,
2335 fdecl::Ref::Self_(_) => RegistrationSource::Self_,
2336 fdecl::Ref::Child(c) => RegistrationSource::Child(c.name),
2337 _ => panic!("invalid RegistrationSource variant"),
2338 }
2339 }
2340}
2341
2342impl NativeIntoFidl<fdecl::Ref> for RegistrationSource {
2343 fn native_into_fidl(self) -> fdecl::Ref {
2344 match self {
2345 RegistrationSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
2346 RegistrationSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
2347 RegistrationSource::Child(child_name) => {
2348 fdecl::Ref::Child(fdecl::ChildRef { name: child_name, collection: None })
2349 }
2350 }
2351 }
2352}
2353
2354impl TryFrom<fdecl::Component> for ComponentDecl {
2358 type Error = Error;
2359
2360 fn try_from(decl: fdecl::Component) -> Result<Self, Self::Error> {
2361 cm_fidl_validator::validate(&decl, &mut DirectedGraph::new())
2362 .map_err(|err| Error::Validate { err })?;
2363 Ok(decl.fidl_into_native())
2364 }
2365}
2366
2367impl From<ComponentDecl> for fdecl::Component {
2369 fn from(decl: ComponentDecl) -> Self {
2370 decl.native_into_fidl()
2371 }
2372}
2373
2374#[derive(Debug, Error, Clone)]
2376pub enum Error {
2377 #[error("Fidl validation failed: {}", err)]
2378 Validate {
2379 #[source]
2380 err: cm_fidl_validator::error::ErrorList,
2381 },
2382 #[error("Invalid capability path: {}", raw)]
2383 InvalidCapabilityPath { raw: String },
2384 #[error("Invalid capability type name: {}", raw)]
2385 ParseCapabilityTypeName { raw: String },
2386}
2387
2388pub fn push_box<T>(container: &mut Box<[T]>, value: T) {
2391 let boxed = mem::replace(container, Box::from([]));
2392 let mut new_container: Vec<_> = boxed.into();
2393 new_container.push(value);
2394 *container = new_container.into();
2395}
2396
2397pub fn append_box<T>(container: &mut Box<[T]>, other: &mut Vec<T>) {
2400 let boxed = mem::replace(container, Box::from([]));
2401 let mut new_container: Vec<_> = boxed.into();
2402 new_container.append(other);
2403 *container = new_container.into();
2404}
2405
2406#[cfg(test)]
2407mod tests {
2408 use super::*;
2409 use difference::Changeset;
2410 use fidl_fuchsia_component_decl as fdecl;
2411
2412 fn offer_source_static_child(name: &str) -> OfferSource {
2413 OfferSource::Child(ChildRef { name: name.parse().unwrap(), collection: None })
2414 }
2415
2416 fn offer_target_static_child(name: &str) -> OfferTarget {
2417 OfferTarget::Child(ChildRef { name: name.parse().unwrap(), collection: None })
2418 }
2419
2420 macro_rules! test_try_from_decl {
2421 (
2422 $(
2423 $test_name:ident => {
2424 input = $input:expr,
2425 result = $result:expr,
2426 },
2427 )+
2428 ) => {
2429 $(
2430 #[test]
2431 fn $test_name() {
2432 {
2433 let res = ComponentDecl::try_from($input).expect("try_from failed");
2434 if res != $result {
2435 let a = format!("{:#?}", res);
2436 let e = format!("{:#?}", $result);
2437 panic!("Conversion from fidl to cm_rust did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
2438 }
2439 }
2440 {
2441 let res = fdecl::Component::try_from($result).expect("try_from failed");
2442 if res != $input {
2443 let a = format!("{:#?}", res);
2444 let e = format!("{:#?}", $input);
2445 panic!("Conversion from cm_rust to fidl did not yield expected result:\n{}", Changeset::new(&a, &e, "\n"));
2446 }
2447 }
2448 }
2449 )+
2450 }
2451 }
2452
2453 macro_rules! test_fidl_into_and_from {
2454 (
2455 $(
2456 $test_name:ident => {
2457 input = $input:expr,
2458 input_type = $input_type:ty,
2459 result = $result:expr,
2460 result_type = $result_type:ty,
2461 },
2462 )+
2463 ) => {
2464 $(
2465 #[test]
2466 fn $test_name() {
2467 {
2468 let res: Vec<$result_type> =
2469 $input.into_iter().map(|e| e.fidl_into_native()).collect();
2470 assert_eq!(res, $result);
2471 }
2472 {
2473 let res: Vec<$input_type> =
2474 $result.into_iter().map(|e| e.native_into_fidl()).collect();
2475 assert_eq!(res, $input);
2476 }
2477 }
2478 )+
2479 }
2480 }
2481
2482 macro_rules! test_fidl_into {
2483 (
2484 $(
2485 $test_name:ident => {
2486 input = $input:expr,
2487 result = $result:expr,
2488 },
2489 )+
2490 ) => {
2491 $(
2492 #[test]
2493 fn $test_name() {
2494 test_fidl_into_helper($input, $result);
2495 }
2496 )+
2497 }
2498 }
2499
2500 fn test_fidl_into_helper<T, U>(input: T, expected_res: U)
2501 where
2502 T: FidlIntoNative<U>,
2503 U: std::cmp::PartialEq + std::fmt::Debug,
2504 {
2505 let res: U = input.fidl_into_native();
2506 assert_eq!(res, expected_res);
2507 }
2508
2509 test_try_from_decl! {
2510 try_from_empty => {
2511 input = fdecl::Component {
2512 program: None,
2513 uses: None,
2514 exposes: None,
2515 offers: None,
2516 capabilities: None,
2517 children: None,
2518 collections: None,
2519 facets: None,
2520 environments: None,
2521 ..Default::default()
2522 },
2523 result = ComponentDecl {
2524 program: None,
2525 uses: Box::from([]),
2526 exposes: Box::from([]),
2527 offers: Box::from([]),
2528 capabilities: Box::from([]),
2529 children: Box::from([]),
2530 collections: Box::from([]),
2531 facets: None,
2532 environments: Box::from([]),
2533 config: None,
2534 debug_info: None,
2535 },
2536 },
2537 try_from_all => {
2538 input = fdecl::Component {
2539 program: Some(fdecl::Program {
2540 runner: Some("elf".to_string()),
2541 info: Some(fdata::Dictionary {
2542 entries: Some(vec![
2543 fdata::DictionaryEntry {
2544 key: "args".to_string(),
2545 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
2546 },
2547 fdata::DictionaryEntry {
2548 key: "binary".to_string(),
2549 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
2550 },
2551 ]),
2552 ..Default::default()
2553 }),
2554 ..Default::default()
2555 }),
2556 uses: Some(vec![
2557 fdecl::Use::Service(fdecl::UseService {
2558 dependency_type: Some(fdecl::DependencyType::Strong),
2559 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2560 source_name: Some("netstack".to_string()),
2561 source_dictionary: Some("in/dict".to_string()),
2562 target_path: Some("/svc/mynetstack".to_string()),
2563 availability: Some(fdecl::Availability::Required),
2564 ..Default::default()
2565 }),
2566 fdecl::Use::Protocol(fdecl::UseProtocol {
2567 dependency_type: Some(fdecl::DependencyType::Strong),
2568 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2569 source_name: Some("legacy_netstack".to_string()),
2570 source_dictionary: Some("in/dict".to_string()),
2571 target_path: None,
2572 numbered_handle: Some(0xab),
2573 availability: Some(fdecl::Availability::Optional),
2574 ..Default::default()
2575 }),
2576 fdecl::Use::Protocol(fdecl::UseProtocol {
2577 dependency_type: Some(fdecl::DependencyType::Strong),
2578 source: Some(fdecl::Ref::Child(fdecl::ChildRef { name: "echo".to_string(), collection: None})),
2579 source_name: Some("echo_service".to_string()),
2580 source_dictionary: Some("in/dict".to_string()),
2581 target_path: Some("/svc/echo_service".to_string()),
2582 availability: Some(fdecl::Availability::Required),
2583 ..Default::default()
2584 }),
2585 fdecl::Use::Directory(fdecl::UseDirectory {
2586 dependency_type: Some(fdecl::DependencyType::Strong),
2587 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
2588 source_name: Some("dir".to_string()),
2589 source_dictionary: Some("dict1/me".to_string()),
2590 target_path: Some("/data".to_string()),
2591 rights: Some(fio::Operations::CONNECT),
2592 subdir: Some("foo/bar".to_string()),
2593 availability: Some(fdecl::Availability::Required),
2594 ..Default::default()
2595 }),
2596 fdecl::Use::Storage(fdecl::UseStorage {
2597 source_name: Some("cache".to_string()),
2598 target_path: Some("/cache".to_string()),
2599 availability: Some(fdecl::Availability::Required),
2600 ..Default::default()
2601 }),
2602 fdecl::Use::Storage(fdecl::UseStorage {
2603 source_name: Some("temp".to_string()),
2604 target_path: Some("/temp".to_string()),
2605 availability: Some(fdecl::Availability::Optional),
2606 ..Default::default()
2607 }),
2608 fdecl::Use::EventStream(fdecl::UseEventStream {
2609 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2610 collection: None,
2611 name: "netstack".to_string(),
2612 })),
2613 source_name: Some("stopped".to_string()),
2614 scope: Some(vec![
2615 fdecl::Ref::Child(fdecl::ChildRef {
2616 collection: None,
2617 name:"a".to_string(),
2618 }), fdecl::Ref::Collection(fdecl::CollectionRef {
2619 name:"b".to_string(),
2620 })]),
2621 target_path: Some("/svc/test".to_string()),
2622 availability: Some(fdecl::Availability::Optional),
2623 ..Default::default()
2624 }),
2625 fdecl::Use::Runner(fdecl::UseRunner {
2626 source: Some(fdecl::Ref::Environment(fdecl::EnvironmentRef {})),
2627 source_name: Some("elf".to_string()),
2628 source_dictionary: None,
2629 ..Default::default()
2630 }),
2631 fdecl::Use::Config(fdecl::UseConfiguration {
2632 source: Some(fdecl::Ref::Parent(fdecl::ParentRef)),
2633 source_name: Some("fuchsia.config.MyConfig".to_string()),
2634 target_name: Some("my_config".to_string()),
2635 availability: Some(fdecl::Availability::Required),
2636 type_: Some(fdecl::ConfigType{
2637 layout: fdecl::ConfigTypeLayout::Bool,
2638 parameters: Some(Vec::new()),
2639 constraints: Vec::new(),
2640 }),
2641 ..Default::default()
2642 }),
2643 #[cfg(fuchsia_api_level_at_least = "29")]
2644 fdecl::Use::Dictionary(fdecl::UseDictionary {
2645 dependency_type: Some(fdecl::DependencyType::Strong),
2646 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2647 source_name: Some("dictionary".to_string()),
2648 source_dictionary: Some("other_dictionary".to_string()),
2649 target_path: Some("/svc".to_string()),
2650 availability: Some(fdecl::Availability::Optional),
2651 ..Default::default()
2652 }),
2653 ]),
2654 exposes: Some(vec![
2655 fdecl::Expose::Protocol(fdecl::ExposeProtocol {
2656 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2657 name: "netstack".to_string(),
2658 collection: None,
2659 })),
2660 source_name: Some("legacy_netstack".to_string()),
2661 source_dictionary: Some("in/dict".to_string()),
2662 target_name: Some("legacy_mynetstack".to_string()),
2663 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2664 availability: Some(fdecl::Availability::Required),
2665 ..Default::default()
2666 }),
2667 fdecl::Expose::Directory(fdecl::ExposeDirectory {
2668 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2669 name: "netstack".to_string(),
2670 collection: None,
2671 })),
2672 source_name: Some("dir".to_string()),
2673 source_dictionary: Some("in/dict".to_string()),
2674 target_name: Some("data".to_string()),
2675 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2676 rights: Some(fio::Operations::CONNECT),
2677 subdir: Some("foo/bar".to_string()),
2678 availability: Some(fdecl::Availability::Optional),
2679 ..Default::default()
2680 }),
2681 fdecl::Expose::Runner(fdecl::ExposeRunner {
2682 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2683 name: "netstack".to_string(),
2684 collection: None,
2685 })),
2686 source_name: Some("elf".to_string()),
2687 source_dictionary: Some("in/dict".to_string()),
2688 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2689 target_name: Some("elf".to_string()),
2690 ..Default::default()
2691 }),
2692 fdecl::Expose::Resolver(fdecl::ExposeResolver{
2693 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2694 name: "netstack".to_string(),
2695 collection: None,
2696 })),
2697 source_name: Some("pkg".to_string()),
2698 source_dictionary: Some("in/dict".to_string()),
2699 target: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
2700 target_name: Some("pkg".to_string()),
2701 ..Default::default()
2702 }),
2703 fdecl::Expose::Service(fdecl::ExposeService {
2704 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2705 name: "netstack".to_string(),
2706 collection: None,
2707 })),
2708 source_name: Some("netstack1".to_string()),
2709 source_dictionary: Some("in/dict".to_string()),
2710 target_name: Some("mynetstack".to_string()),
2711 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2712 availability: Some(fdecl::Availability::Required),
2713 ..Default::default()
2714 }),
2715 fdecl::Expose::Service(fdecl::ExposeService {
2716 source: Some(fdecl::Ref::Collection(fdecl::CollectionRef {
2717 name: "modular".to_string(),
2718 })),
2719 source_name: Some("netstack2".to_string()),
2720 source_dictionary: None,
2721 target_name: Some("mynetstack".to_string()),
2722 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2723 availability: Some(fdecl::Availability::Required),
2724 ..Default::default()
2725 }),
2726 fdecl::Expose::Dictionary(fdecl::ExposeDictionary {
2727 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2728 name: "netstack".to_string(),
2729 collection: None,
2730 })),
2731 source_name: Some("bundle".to_string()),
2732 source_dictionary: Some("in/dict".to_string()),
2733 target_name: Some("mybundle".to_string()),
2734 target: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2735 availability: Some(fdecl::Availability::Required),
2736 ..Default::default()
2737 }),
2738 ]),
2739 offers: Some(vec![
2740 fdecl::Offer::Protocol(fdecl::OfferProtocol {
2741 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2742 source_name: Some("legacy_netstack".to_string()),
2743 source_dictionary: Some("in/dict".to_string()),
2744 target: Some(fdecl::Ref::Child(
2745 fdecl::ChildRef {
2746 name: "echo".to_string(),
2747 collection: None,
2748 }
2749 )),
2750 target_name: Some("legacy_mynetstack".to_string()),
2751 dependency_type: Some(fdecl::DependencyType::Weak),
2752 availability: Some(fdecl::Availability::Required),
2753 ..Default::default()
2754 }),
2755 fdecl::Offer::Directory(fdecl::OfferDirectory {
2756 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2757 source_name: Some("dir".to_string()),
2758 source_dictionary: Some("in/dict".to_string()),
2759 target: Some(fdecl::Ref::Collection(
2760 fdecl::CollectionRef { name: "modular".to_string() }
2761 )),
2762 target_name: Some("data".to_string()),
2763 rights: Some(fio::Operations::CONNECT),
2764 subdir: None,
2765 dependency_type: Some(fdecl::DependencyType::Strong),
2766 availability: Some(fdecl::Availability::Optional),
2767 ..Default::default()
2768 }),
2769 fdecl::Offer::Storage(fdecl::OfferStorage {
2770 source_name: Some("cache".to_string()),
2771 source: Some(fdecl::Ref::Self_(fdecl::SelfRef {})),
2772 target: Some(fdecl::Ref::Collection(
2773 fdecl::CollectionRef { name: "modular".to_string() }
2774 )),
2775 target_name: Some("cache".to_string()),
2776 availability: Some(fdecl::Availability::Required),
2777 ..Default::default()
2778 }),
2779 fdecl::Offer::Runner(fdecl::OfferRunner {
2780 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2781 source_name: Some("elf".to_string()),
2782 source_dictionary: Some("in/dict".to_string()),
2783 target: Some(fdecl::Ref::Child(
2784 fdecl::ChildRef {
2785 name: "echo".to_string(),
2786 collection: None,
2787 }
2788 )),
2789 target_name: Some("elf2".to_string()),
2790 ..Default::default()
2791 }),
2792 fdecl::Offer::Resolver(fdecl::OfferResolver{
2793 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
2794 source_name: Some("pkg".to_string()),
2795 source_dictionary: Some("in/dict".to_string()),
2796 target: Some(fdecl::Ref::Child(
2797 fdecl::ChildRef {
2798 name: "echo".to_string(),
2799 collection: None,
2800 }
2801 )),
2802 target_name: Some("pkg".to_string()),
2803 ..Default::default()
2804 }),
2805 fdecl::Offer::Service(fdecl::OfferService {
2806 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2807 source_name: Some("netstack1".to_string()),
2808 source_dictionary: Some("in/dict".to_string()),
2809 target: Some(fdecl::Ref::Child(
2810 fdecl::ChildRef {
2811 name: "echo".to_string(),
2812 collection: None,
2813 }
2814 )),
2815 target_name: Some("mynetstack1".to_string()),
2816 availability: Some(fdecl::Availability::Required),
2817 dependency_type: Some(fdecl::DependencyType::Strong),
2818 ..Default::default()
2819 }),
2820 fdecl::Offer::Service(fdecl::OfferService {
2821 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2822 source_name: Some("netstack2".to_string()),
2823 source_dictionary: None,
2824 target: Some(fdecl::Ref::Child(
2825 fdecl::ChildRef {
2826 name: "echo".to_string(),
2827 collection: None,
2828 }
2829 )),
2830 target_name: Some("mynetstack2".to_string()),
2831 availability: Some(fdecl::Availability::Optional),
2832 dependency_type: Some(fdecl::DependencyType::Strong),
2833 ..Default::default()
2834 }),
2835 fdecl::Offer::Service(fdecl::OfferService {
2836 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2837 source_name: Some("netstack3".to_string()),
2838 source_dictionary: None,
2839 target: Some(fdecl::Ref::Child(
2840 fdecl::ChildRef {
2841 name: "echo".to_string(),
2842 collection: None,
2843 }
2844 )),
2845 target_name: Some("mynetstack3".to_string()),
2846 source_instance_filter: Some(vec!["allowedinstance".to_string()]),
2847 renamed_instances: Some(vec![fdecl::NameMapping{source_name: "default".to_string(), target_name: "allowedinstance".to_string()}]),
2848 availability: Some(fdecl::Availability::Required),
2849 dependency_type: Some(fdecl::DependencyType::Strong),
2850 ..Default::default()
2851 }),
2852 fdecl::Offer::Dictionary(fdecl::OfferDictionary {
2853 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2854 source_name: Some("bundle".to_string()),
2855 source_dictionary: Some("in/dict".to_string()),
2856 target: Some(fdecl::Ref::Child(
2857 fdecl::ChildRef {
2858 name: "echo".to_string(),
2859 collection: None,
2860 }
2861 )),
2862 target_name: Some("mybundle".to_string()),
2863 dependency_type: Some(fdecl::DependencyType::Weak),
2864 availability: Some(fdecl::Availability::Required),
2865 ..Default::default()
2866 }),
2867 ]),
2868 capabilities: Some(vec![
2869 fdecl::Capability::Service(fdecl::Service {
2870 name: Some("netstack".to_string()),
2871 source_path: Some("/netstack".to_string()),
2872 ..Default::default()
2873 }),
2874 fdecl::Capability::Protocol(fdecl::Protocol {
2875 name: Some("netstack2".to_string()),
2876 source_path: Some("/netstack2".to_string()),
2877 delivery: Some(fdecl::DeliveryType::Immediate),
2878 ..Default::default()
2879 }),
2880 fdecl::Capability::Directory(fdecl::Directory {
2881 name: Some("data".to_string()),
2882 source_path: Some("/data".to_string()),
2883 rights: Some(fio::Operations::CONNECT),
2884 ..Default::default()
2885 }),
2886 fdecl::Capability::Storage(fdecl::Storage {
2887 name: Some("cache".to_string()),
2888 backing_dir: Some("data".to_string()),
2889 source: Some(fdecl::Ref::Parent(fdecl::ParentRef {})),
2890 subdir: Some("cache".to_string()),
2891 storage_id: Some(fdecl::StorageId::StaticInstanceId),
2892 ..Default::default()
2893 }),
2894 fdecl::Capability::Runner(fdecl::Runner {
2895 name: Some("elf".to_string()),
2896 source_path: Some("/elf".to_string()),
2897 ..Default::default()
2898 }),
2899 fdecl::Capability::Resolver(fdecl::Resolver {
2900 name: Some("pkg".to_string()),
2901 source_path: Some("/pkg_resolver".to_string()),
2902 ..Default::default()
2903 }),
2904 fdecl::Capability::Dictionary(fdecl::Dictionary {
2905 name: Some("dict1".to_string()),
2906 ..Default::default()
2907 }),
2908 fdecl::Capability::Dictionary(fdecl::Dictionary {
2909 name: Some("dict2".to_string()),
2910 source_path: Some("/in/other".to_string()),
2911 ..Default::default()
2912 }),
2913 ]),
2914 children: Some(vec![
2915 fdecl::Child {
2916 name: Some("netstack".to_string()),
2917 url: Some("fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm"
2918 .to_string()),
2919 startup: Some(fdecl::StartupMode::Lazy),
2920 on_terminate: None,
2921 environment: None,
2922 ..Default::default()
2923 },
2924 fdecl::Child {
2925 name: Some("gtest".to_string()),
2926 url: Some("fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".to_string()),
2927 startup: Some(fdecl::StartupMode::Lazy),
2928 on_terminate: Some(fdecl::OnTerminate::None),
2929 environment: None,
2930 ..Default::default()
2931 },
2932 fdecl::Child {
2933 name: Some("echo".to_string()),
2934 url: Some("fuchsia-pkg://fuchsia.com/echo#meta/echo.cm"
2935 .to_string()),
2936 startup: Some(fdecl::StartupMode::Eager),
2937 on_terminate: Some(fdecl::OnTerminate::Reboot),
2938 environment: Some("test_env".to_string()),
2939 ..Default::default()
2940 },
2941 ]),
2942 collections: Some(vec![
2943 fdecl::Collection {
2944 name: Some("modular".to_string()),
2945 durability: Some(fdecl::Durability::Transient),
2946 environment: None,
2947 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
2948 allow_long_names: Some(true),
2949 persistent_storage: None,
2950 ..Default::default()
2951 },
2952 fdecl::Collection {
2953 name: Some("tests".to_string()),
2954 durability: Some(fdecl::Durability::Transient),
2955 environment: Some("test_env".to_string()),
2956 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
2957 allow_long_names: Some(true),
2958 persistent_storage: Some(true),
2959 ..Default::default()
2960 },
2961 ]),
2962 facets: Some(fdata::Dictionary {
2963 entries: Some(vec![
2964 fdata::DictionaryEntry {
2965 key: "author".to_string(),
2966 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
2967 },
2968 ]),
2969 ..Default::default()
2970 }),
2971 environments: Some(vec![
2972 fdecl::Environment {
2973 name: Some("test_env".to_string()),
2974 extends: Some(fdecl::EnvironmentExtends::Realm),
2975 runners: Some(vec![
2976 fdecl::RunnerRegistration {
2977 source_name: Some("runner".to_string()),
2978 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2979 name: "gtest".to_string(),
2980 collection: None,
2981 })),
2982 target_name: Some("gtest-runner".to_string()),
2983 ..Default::default()
2984 }
2985 ]),
2986 resolvers: Some(vec![
2987 fdecl::ResolverRegistration {
2988 resolver: Some("pkg_resolver".to_string()),
2989 source: Some(fdecl::Ref::Parent(fdecl::ParentRef{})),
2990 scheme: Some("fuchsia-pkg".to_string()),
2991 ..Default::default()
2992 }
2993 ]),
2994 debug_capabilities: Some(vec![
2995 fdecl::DebugRegistration::Protocol(fdecl::DebugProtocolRegistration {
2996 source_name: Some("some_protocol".to_string()),
2997 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
2998 name: "gtest".to_string(),
2999 collection: None,
3000 })),
3001 target_name: Some("some_protocol".to_string()),
3002 ..Default::default()
3003 })
3004 ]),
3005 stop_timeout_ms: Some(4567),
3006 ..Default::default()
3007 }
3008 ]),
3009 config: Some(fdecl::ConfigSchema{
3010 fields: Some(vec![
3011 fdecl::ConfigField {
3012 key: Some("enable_logging".to_string()),
3013 type_: Some(fdecl::ConfigType {
3014 layout: fdecl::ConfigTypeLayout::Bool,
3015 parameters: Some(vec![]),
3016 constraints: vec![],
3017 }),
3018 mutability: Some(Default::default()),
3019 ..Default::default()
3020 }
3021 ]),
3022 checksum: Some(fdecl::ConfigChecksum::Sha256([
3023 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
3024 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
3025 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
3026 ])),
3027 value_source: Some(
3028 fdecl::ConfigValueSource::PackagePath("fake.cvf".to_string())
3029 ),
3030 ..Default::default()
3031 }),
3032 ..Default::default()
3033 },
3034 result = {
3035 ComponentDecl {
3036 program: Some(ProgramDecl {
3037 runner: Some("elf".parse().unwrap()),
3038 info: fdata::Dictionary {
3039 entries: Some(vec![
3040 fdata::DictionaryEntry {
3041 key: "args".to_string(),
3042 value: Some(Box::new(fdata::DictionaryValue::StrVec(vec!["foo".to_string(), "bar".to_string()]))),
3043 },
3044 fdata::DictionaryEntry{
3045 key: "binary".to_string(),
3046 value: Some(Box::new(fdata::DictionaryValue::Str("bin/app".to_string()))),
3047 },
3048 ]),
3049 ..Default::default()
3050 },
3051 }),
3052 uses: Box::from([
3053 UseDecl::Service(UseServiceDecl {
3054 dependency_type: DependencyType::Strong,
3055 source: UseSource::Parent,
3056 source_name: "netstack".parse().unwrap(),
3057 source_dictionary: "in/dict".parse().unwrap(),
3058 target_path: "/svc/mynetstack".parse().unwrap(),
3059 availability: Availability::Required,
3060 }),
3061 UseDecl::Protocol(UseProtocolDecl {
3062 dependency_type: DependencyType::Strong,
3063 source: UseSource::Parent,
3064 source_name: "legacy_netstack".parse().unwrap(),
3065 source_dictionary: "in/dict".parse().unwrap(),
3066 target_path: None,
3067 numbered_handle: Some(HandleType::from(0xab)),
3068 availability: Availability::Optional,
3069 }),
3070 UseDecl::Protocol(UseProtocolDecl {
3071 dependency_type: DependencyType::Strong,
3072 source: UseSource::Child("echo".parse().unwrap()),
3073 source_name: "echo_service".parse().unwrap(),
3074 source_dictionary: "in/dict".parse().unwrap(),
3075 target_path: Some("/svc/echo_service".parse().unwrap()),
3076 numbered_handle: None,
3077 availability: Availability::Required,
3078 }),
3079 UseDecl::Directory(UseDirectoryDecl {
3080 dependency_type: DependencyType::Strong,
3081 source: UseSource::Self_,
3082 source_name: "dir".parse().unwrap(),
3083 source_dictionary: "dict1/me".parse().unwrap(),
3084 target_path: "/data".parse().unwrap(),
3085 rights: fio::Operations::CONNECT,
3086 subdir: "foo/bar".parse().unwrap(),
3087 availability: Availability::Required,
3088 }),
3089 UseDecl::Storage(UseStorageDecl {
3090 source_name: "cache".parse().unwrap(),
3091 target_path: "/cache".parse().unwrap(),
3092 availability: Availability::Required,
3093 }),
3094 UseDecl::Storage(UseStorageDecl {
3095 source_name: "temp".parse().unwrap(),
3096 target_path: "/temp".parse().unwrap(),
3097 availability: Availability::Optional,
3098 }),
3099 UseDecl::EventStream(UseEventStreamDecl {
3100 source: UseSource::Child("netstack".parse().unwrap()),
3101 scope: Some(Box::from([EventScope::Child(ChildRef{ name: "a".parse().unwrap(), collection: None}), EventScope::Collection("b".parse().unwrap())])),
3102 source_name: "stopped".parse().unwrap(),
3103 target_path: "/svc/test".parse().unwrap(),
3104 filter: None,
3105 availability: Availability::Optional,
3106 }),
3107 UseDecl::Runner(UseRunnerDecl {
3108 source: UseSource::Environment,
3109 source_name: "elf".parse().unwrap(),
3110 source_dictionary: ".".parse().unwrap(),
3111 }),
3112 UseDecl::Config(UseConfigurationDecl {
3113 source: UseSource::Parent,
3114 source_name: "fuchsia.config.MyConfig".parse().unwrap(),
3115 target_name: "my_config".parse().unwrap(),
3116 availability: Availability::Required,
3117 type_: ConfigValueType::Bool,
3118 default: None,
3119 source_dictionary: ".".parse().unwrap(),
3120 }),
3121 #[cfg(fuchsia_api_level_at_least = "29")]
3122 UseDecl::Dictionary(UseDictionaryDecl {
3123 dependency_type: DependencyType::Strong,
3124 source: UseSource::Parent,
3125 source_name: "dictionary".parse().unwrap(),
3126 source_dictionary: "other_dictionary".parse().unwrap(),
3127 target_path: "/svc".parse().unwrap(),
3128 availability: Availability::Optional,
3129 }),
3130 ]),
3131 exposes: Box::from([
3132 ExposeDecl::Protocol(ExposeProtocolDecl {
3133 source: ExposeSource::Child("netstack".parse().unwrap()),
3134 source_name: "legacy_netstack".parse().unwrap(),
3135 source_dictionary: "in/dict".parse().unwrap(),
3136 target_name: "legacy_mynetstack".parse().unwrap(),
3137 target: ExposeTarget::Parent,
3138 availability: Availability::Required,
3139 }),
3140 ExposeDecl::Directory(ExposeDirectoryDecl {
3141 source: ExposeSource::Child("netstack".parse().unwrap()),
3142 source_name: "dir".parse().unwrap(),
3143 source_dictionary: "in/dict".parse().unwrap(),
3144 target_name: "data".parse().unwrap(),
3145 target: ExposeTarget::Parent,
3146 rights: Some(fio::Operations::CONNECT),
3147 subdir: "foo/bar".parse().unwrap(),
3148 availability: Availability::Optional,
3149 }),
3150 ExposeDecl::Runner(ExposeRunnerDecl {
3151 source: ExposeSource::Child("netstack".parse().unwrap()),
3152 source_name: "elf".parse().unwrap(),
3153 source_dictionary: "in/dict".parse().unwrap(),
3154 target: ExposeTarget::Parent,
3155 target_name: "elf".parse().unwrap(),
3156 }),
3157 ExposeDecl::Resolver(ExposeResolverDecl {
3158 source: ExposeSource::Child("netstack".parse().unwrap()),
3159 source_name: "pkg".parse().unwrap(),
3160 source_dictionary: "in/dict".parse().unwrap(),
3161 target: ExposeTarget::Parent,
3162 target_name: "pkg".parse().unwrap(),
3163 }),
3164 ExposeDecl::Service(ExposeServiceDecl {
3165 source: ExposeSource::Child("netstack".parse().unwrap()),
3166 source_name: "netstack1".parse().unwrap(),
3167 source_dictionary: "in/dict".parse().unwrap(),
3168 target_name: "mynetstack".parse().unwrap(),
3169 target: ExposeTarget::Parent,
3170 availability: Availability::Required,
3171 }),
3172 ExposeDecl::Service(ExposeServiceDecl {
3173 source: ExposeSource::Collection("modular".parse().unwrap()),
3174 source_name: "netstack2".parse().unwrap(),
3175 source_dictionary: ".".parse().unwrap(),
3176 target_name: "mynetstack".parse().unwrap(),
3177 target: ExposeTarget::Parent,
3178 availability: Availability::Required,
3179 }),
3180 ExposeDecl::Dictionary(ExposeDictionaryDecl {
3181 source: ExposeSource::Child("netstack".parse().unwrap()),
3182 source_name: "bundle".parse().unwrap(),
3183 source_dictionary: "in/dict".parse().unwrap(),
3184 target_name: "mybundle".parse().unwrap(),
3185 target: ExposeTarget::Parent,
3186 availability: Availability::Required,
3187 }),
3188 ]),
3189 offers: Box::from([
3190 OfferDecl::Protocol(OfferProtocolDecl {
3191 source: OfferSource::Parent,
3192 source_name: "legacy_netstack".parse().unwrap(),
3193 source_dictionary: "in/dict".parse().unwrap(),
3194 target: offer_target_static_child("echo"),
3195 target_name: "legacy_mynetstack".parse().unwrap(),
3196 dependency_type: DependencyType::Weak,
3197 availability: Availability::Required,
3198 }),
3199 OfferDecl::Directory(OfferDirectoryDecl {
3200 source: OfferSource::Parent,
3201 source_name: "dir".parse().unwrap(),
3202 source_dictionary: "in/dict".parse().unwrap(),
3203 target: OfferTarget::Collection("modular".parse().unwrap()),
3204 target_name: "data".parse().unwrap(),
3205 rights: Some(fio::Operations::CONNECT),
3206 subdir: ".".parse().unwrap(),
3207 dependency_type: DependencyType::Strong,
3208 availability: Availability::Optional,
3209 }),
3210 OfferDecl::Storage(OfferStorageDecl {
3211 source_name: "cache".parse().unwrap(),
3212 source: OfferSource::Self_,
3213 target: OfferTarget::Collection("modular".parse().unwrap()),
3214 target_name: "cache".parse().unwrap(),
3215 availability: Availability::Required,
3216 }),
3217 OfferDecl::Runner(OfferRunnerDecl {
3218 source: OfferSource::Parent,
3219 source_name: "elf".parse().unwrap(),
3220 source_dictionary: "in/dict".parse().unwrap(),
3221 target: offer_target_static_child("echo"),
3222 target_name: "elf2".parse().unwrap(),
3223 }),
3224 OfferDecl::Resolver(OfferResolverDecl {
3225 source: OfferSource::Parent,
3226 source_name: "pkg".parse().unwrap(),
3227 source_dictionary: "in/dict".parse().unwrap(),
3228 target: offer_target_static_child("echo"),
3229 target_name: "pkg".parse().unwrap(),
3230 }),
3231 OfferDecl::Service(OfferServiceDecl {
3232 source: OfferSource::Parent,
3233 source_name: "netstack1".parse().unwrap(),
3234 source_dictionary: "in/dict".parse().unwrap(),
3235 source_instance_filter: None,
3236 renamed_instances: None,
3237 target: offer_target_static_child("echo"),
3238 target_name: "mynetstack1".parse().unwrap(),
3239 availability: Availability::Required,
3240 dependency_type: Default::default(),
3241 }),
3242 OfferDecl::Service(OfferServiceDecl {
3243 source: OfferSource::Parent,
3244 source_name: "netstack2".parse().unwrap(),
3245 source_dictionary: ".".parse().unwrap(),
3246 source_instance_filter: None,
3247 renamed_instances: None,
3248 target: offer_target_static_child("echo"),
3249 target_name: "mynetstack2".parse().unwrap(),
3250 availability: Availability::Optional,
3251 dependency_type: Default::default(),
3252 }),
3253 OfferDecl::Service(OfferServiceDecl {
3254 source: OfferSource::Parent,
3255 source_name: "netstack3".parse().unwrap(),
3256 source_dictionary: ".".parse().unwrap(),
3257 source_instance_filter: Some(Box::from(["allowedinstance".parse().unwrap()])),
3258 renamed_instances: Some(Box::from([NameMapping{source_name: "default".parse().unwrap(), target_name: "allowedinstance".parse().unwrap()}])),
3259 target: offer_target_static_child("echo"),
3260 target_name: "mynetstack3".parse().unwrap(),
3261 availability: Availability::Required,
3262 dependency_type: Default::default(),
3263 }),
3264 OfferDecl::Dictionary(OfferDictionaryDecl {
3265 source: OfferSource::Parent,
3266 source_name: "bundle".parse().unwrap(),
3267 source_dictionary: "in/dict".parse().unwrap(),
3268 target: offer_target_static_child("echo"),
3269 target_name: "mybundle".parse().unwrap(),
3270 dependency_type: DependencyType::Weak,
3271 availability: Availability::Required,
3272 }),
3273 ]),
3274 capabilities: Box::from([
3275 CapabilityDecl::Service(ServiceDecl {
3276 name: "netstack".parse().unwrap(),
3277 source_path: Some("/netstack".parse().unwrap()),
3278 }),
3279 CapabilityDecl::Protocol(ProtocolDecl {
3280 name: "netstack2".parse().unwrap(),
3281 source_path: Some("/netstack2".parse().unwrap()),
3282 delivery: DeliveryType::Immediate,
3283 }),
3284 CapabilityDecl::Directory(DirectoryDecl {
3285 name: "data".parse().unwrap(),
3286 source_path: Some("/data".parse().unwrap()),
3287 rights: fio::Operations::CONNECT,
3288 }),
3289 CapabilityDecl::Storage(StorageDecl {
3290 name: "cache".parse().unwrap(),
3291 backing_dir: "data".parse().unwrap(),
3292 source: StorageDirectorySource::Parent,
3293 subdir: "cache".parse().unwrap(),
3294 storage_id: fdecl::StorageId::StaticInstanceId,
3295 }),
3296 CapabilityDecl::Runner(RunnerDecl {
3297 name: "elf".parse().unwrap(),
3298 source_path: Some("/elf".parse().unwrap()),
3299 }),
3300 CapabilityDecl::Resolver(ResolverDecl {
3301 name: "pkg".parse().unwrap(),
3302 source_path: Some("/pkg_resolver".parse().unwrap()),
3303 }),
3304 CapabilityDecl::Dictionary(DictionaryDecl {
3305 name: "dict1".parse().unwrap(),
3306 source_path: None,
3307 }),
3308 CapabilityDecl::Dictionary(DictionaryDecl {
3309 name: "dict2".parse().unwrap(),
3310 source_path: Some("/in/other".parse().unwrap()),
3311 }),
3312 ]),
3313 children: Box::from([
3314 ChildDecl {
3315 name: "netstack".parse().unwrap(),
3316 url: "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm".parse().unwrap(),
3317 startup: fdecl::StartupMode::Lazy,
3318 on_terminate: None,
3319 environment: None,
3320 config_overrides: None,
3321 },
3322 ChildDecl {
3323 name: "gtest".parse().unwrap(),
3324 url: "fuchsia-pkg://fuchsia.com/gtest#meta/gtest.cm".parse().unwrap(),
3325 startup: fdecl::StartupMode::Lazy,
3326 on_terminate: Some(fdecl::OnTerminate::None),
3327 environment: None,
3328 config_overrides: None,
3329 },
3330 ChildDecl {
3331 name: "echo".parse().unwrap(),
3332 url: "fuchsia-pkg://fuchsia.com/echo#meta/echo.cm".parse().unwrap(),
3333 startup: fdecl::StartupMode::Eager,
3334 on_terminate: Some(fdecl::OnTerminate::Reboot),
3335 environment: Some("test_env".parse().unwrap()),
3336 config_overrides: None,
3337 },
3338 ]),
3339 collections: Box::from([
3340 CollectionDecl {
3341 name: "modular".parse().unwrap(),
3342 durability: fdecl::Durability::Transient,
3343 environment: None,
3344 allowed_offers: cm_types::AllowedOffers::StaticOnly,
3345 allow_long_names: true,
3346 persistent_storage: None,
3347 },
3348 CollectionDecl {
3349 name: "tests".parse().unwrap(),
3350 durability: fdecl::Durability::Transient,
3351 environment: Some("test_env".parse().unwrap()),
3352 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
3353 allow_long_names: true,
3354 persistent_storage: Some(true),
3355 },
3356 ]),
3357 facets: Some(fdata::Dictionary {
3358 entries: Some(vec![
3359 fdata::DictionaryEntry {
3360 key: "author".to_string(),
3361 value: Some(Box::new(fdata::DictionaryValue::Str("Fuchsia".to_string()))),
3362 },
3363 ]),
3364 ..Default::default()
3365 }),
3366 environments: Box::from([
3367 EnvironmentDecl {
3368 name: "test_env".parse().unwrap(),
3369 extends: fdecl::EnvironmentExtends::Realm,
3370 runners: Box::from([
3371 RunnerRegistration {
3372 source_name: "runner".parse().unwrap(),
3373 source: RegistrationSource::Child("gtest".to_string()),
3374 target_name: "gtest-runner".parse().unwrap(),
3375 }
3376 ]),
3377 resolvers: Box::from([
3378 ResolverRegistration {
3379 resolver: "pkg_resolver".parse().unwrap(),
3380 source: RegistrationSource::Parent,
3381 scheme: "fuchsia-pkg".to_string(),
3382 }
3383 ]),
3384 debug_capabilities: Box::from([
3385 DebugRegistration::Protocol(DebugProtocolRegistration {
3386 source_name: "some_protocol".parse().unwrap(),
3387 source: RegistrationSource::Child("gtest".to_string()),
3388 target_name: "some_protocol".parse().unwrap(),
3389 })
3390 ]),
3391 stop_timeout_ms: Some(4567),
3392 }
3393 ]),
3394 config: Some(ConfigDecl {
3395 fields: Box::from([
3396 ConfigField {
3397 key: "enable_logging".to_string(),
3398 type_: ConfigValueType::Bool,
3399 mutability: ConfigMutability::default(),
3400 }
3401 ]),
3402 checksum: ConfigChecksum::Sha256([
3403 0x64, 0x49, 0x9E, 0x75, 0xF3, 0x37, 0x69, 0x88, 0x74, 0x3B, 0x38, 0x16,
3404 0xCD, 0x14, 0x70, 0x9F, 0x3D, 0x4A, 0xD3, 0xE2, 0x24, 0x9A, 0x1A, 0x34,
3405 0x80, 0xB4, 0x9E, 0xB9, 0x63, 0x57, 0xD6, 0xED,
3406 ]),
3407 value_source: ConfigValueSource::PackagePath("fake.cvf".to_string())
3408 }),
3409 debug_info: None,
3410 }
3411 },
3412 },
3413 }
3414
3415 test_fidl_into_and_from! {
3416 fidl_into_and_from_use_source => {
3417 input = vec![
3418 fdecl::Ref::Parent(fdecl::ParentRef{}),
3419 fdecl::Ref::Framework(fdecl::FrameworkRef{}),
3420 fdecl::Ref::Debug(fdecl::DebugRef{}),
3421 fdecl::Ref::Capability(fdecl::CapabilityRef {name: "capability".to_string()}),
3422 fdecl::Ref::Child(fdecl::ChildRef {
3423 name: "foo".into(),
3424 collection: None,
3425 }),
3426 fdecl::Ref::Environment(fdecl::EnvironmentRef{}),
3427 ],
3428 input_type = fdecl::Ref,
3429 result = vec![
3430 UseSource::Parent,
3431 UseSource::Framework,
3432 UseSource::Debug,
3433 UseSource::Capability("capability".parse().unwrap()),
3434 UseSource::Child("foo".parse().unwrap()),
3435 UseSource::Environment,
3436 ],
3437 result_type = UseSource,
3438 },
3439 fidl_into_and_from_expose_source => {
3440 input = vec![
3441 fdecl::Ref::Self_(fdecl::SelfRef {}),
3442 fdecl::Ref::Child(fdecl::ChildRef {
3443 name: "foo".into(),
3444 collection: None,
3445 }),
3446 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
3447 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
3448 ],
3449 input_type = fdecl::Ref,
3450 result = vec![
3451 ExposeSource::Self_,
3452 ExposeSource::Child("foo".parse().unwrap()),
3453 ExposeSource::Framework,
3454 ExposeSource::Collection("foo".parse().unwrap()),
3455 ],
3456 result_type = ExposeSource,
3457 },
3458 fidl_into_and_from_offer_source => {
3459 input = vec![
3460 fdecl::Ref::Self_(fdecl::SelfRef {}),
3461 fdecl::Ref::Child(fdecl::ChildRef {
3462 name: "foo".into(),
3463 collection: None,
3464 }),
3465 fdecl::Ref::Framework(fdecl::FrameworkRef {}),
3466 fdecl::Ref::Capability(fdecl::CapabilityRef { name: "foo".to_string() }),
3467 fdecl::Ref::Parent(fdecl::ParentRef {}),
3468 fdecl::Ref::Collection(fdecl::CollectionRef { name: "foo".to_string() }),
3469 fdecl::Ref::VoidType(fdecl::VoidRef {}),
3470 ],
3471 input_type = fdecl::Ref,
3472 result = vec![
3473 OfferSource::Self_,
3474 offer_source_static_child("foo"),
3475 OfferSource::Framework,
3476 OfferSource::Capability("foo".parse().unwrap()),
3477 OfferSource::Parent,
3478 OfferSource::Collection("foo".parse().unwrap()),
3479 OfferSource::Void,
3480 ],
3481 result_type = OfferSource,
3482 },
3483 fidl_into_and_from_dictionary_source => {
3484 input = vec![
3485 fdecl::Ref::Self_(fdecl::SelfRef {}),
3486 fdecl::Ref::Child(fdecl::ChildRef {
3487 name: "foo".into(),
3488 collection: None,
3489 }),
3490 fdecl::Ref::Parent(fdecl::ParentRef {}),
3491 ],
3492 input_type = fdecl::Ref,
3493 result = vec![
3494 DictionarySource::Self_,
3495 DictionarySource::Child(ChildRef {
3496 name: "foo".parse().unwrap(),
3497 collection: None,
3498 }),
3499 DictionarySource::Parent,
3500 ],
3501 result_type = DictionarySource,
3502 },
3503
3504 fidl_into_and_from_capability_without_path => {
3505 input = vec![
3506 fdecl::Protocol {
3507 name: Some("foo_protocol".to_string()),
3508 source_path: None,
3509 delivery: Some(fdecl::DeliveryType::Immediate),
3510 ..Default::default()
3511 },
3512 ],
3513 input_type = fdecl::Protocol,
3514 result = vec![
3515 ProtocolDecl {
3516 name: "foo_protocol".parse().unwrap(),
3517 source_path: None,
3518 delivery: DeliveryType::Immediate,
3519 }
3520 ],
3521 result_type = ProtocolDecl,
3522 },
3523 fidl_into_and_from_storage_capability => {
3524 input = vec![
3525 fdecl::Storage {
3526 name: Some("minfs".to_string()),
3527 backing_dir: Some("minfs".into()),
3528 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
3529 name: "foo".into(),
3530 collection: None,
3531 })),
3532 subdir: None,
3533 storage_id: Some(fdecl::StorageId::StaticInstanceIdOrMoniker),
3534 ..Default::default()
3535 },
3536 ],
3537 input_type = fdecl::Storage,
3538 result = vec![
3539 StorageDecl {
3540 name: "minfs".parse().unwrap(),
3541 backing_dir: "minfs".parse().unwrap(),
3542 source: StorageDirectorySource::Child("foo".to_string()),
3543 subdir: ".".parse().unwrap(),
3544 storage_id: fdecl::StorageId::StaticInstanceIdOrMoniker,
3545 },
3546 ],
3547 result_type = StorageDecl,
3548 },
3549 fidl_into_and_from_storage_capability_restricted => {
3550 input = vec![
3551 fdecl::Storage {
3552 name: Some("minfs".to_string()),
3553 backing_dir: Some("minfs".into()),
3554 source: Some(fdecl::Ref::Child(fdecl::ChildRef {
3555 name: "foo".into(),
3556 collection: None,
3557 })),
3558 subdir: None,
3559 storage_id: Some(fdecl::StorageId::StaticInstanceId),
3560 ..Default::default()
3561 },
3562 ],
3563 input_type = fdecl::Storage,
3564 result = vec![
3565 StorageDecl {
3566 name: "minfs".parse().unwrap(),
3567 backing_dir: "minfs".parse().unwrap(),
3568 source: StorageDirectorySource::Child("foo".to_string()),
3569 subdir: ".".parse().unwrap(),
3570 storage_id: fdecl::StorageId::StaticInstanceId,
3571 },
3572 ],
3573 result_type = StorageDecl,
3574 },
3575 }
3576
3577 test_fidl_into! {
3578 all_with_omitted_defaults => {
3579 input = fdecl::Component {
3580 program: Some(fdecl::Program {
3581 runner: Some("elf".to_string()),
3582 info: Some(fdata::Dictionary {
3583 entries: Some(vec![]),
3584 ..Default::default()
3585 }),
3586 ..Default::default()
3587 }),
3588 uses: Some(vec![]),
3589 exposes: Some(vec![]),
3590 offers: Some(vec![]),
3591 capabilities: Some(vec![]),
3592 children: Some(vec![]),
3593 collections: Some(vec![
3594 fdecl::Collection {
3595 name: Some("modular".to_string()),
3596 durability: Some(fdecl::Durability::Transient),
3597 environment: None,
3598 allowed_offers: None,
3599 allow_long_names: None,
3600 persistent_storage: None,
3601 ..Default::default()
3602 },
3603 fdecl::Collection {
3604 name: Some("tests".to_string()),
3605 durability: Some(fdecl::Durability::Transient),
3606 environment: Some("test_env".to_string()),
3607 allowed_offers: Some(fdecl::AllowedOffers::StaticOnly),
3608 allow_long_names: None,
3609 persistent_storage: Some(false),
3610 ..Default::default()
3611 },
3612 fdecl::Collection {
3613 name: Some("dyn_offers".to_string()),
3614 durability: Some(fdecl::Durability::Transient),
3615 allowed_offers: Some(fdecl::AllowedOffers::StaticAndDynamic),
3616 allow_long_names: None,
3617 persistent_storage: Some(true),
3618 ..Default::default()
3619 },
3620 fdecl::Collection {
3621 name: Some("long_child_names".to_string()),
3622 durability: Some(fdecl::Durability::Transient),
3623 allowed_offers: None,
3624 allow_long_names: Some(true),
3625 persistent_storage: None,
3626 ..Default::default()
3627 },
3628 ]),
3629 facets: Some(fdata::Dictionary{
3630 entries: Some(vec![]),
3631 ..Default::default()
3632 }),
3633 environments: Some(vec![]),
3634 ..Default::default()
3635 },
3636 result = {
3637 ComponentDecl {
3638 program: Some(ProgramDecl {
3639 runner: Some("elf".parse().unwrap()),
3640 info: fdata::Dictionary {
3641 entries: Some(vec![]),
3642 ..Default::default()
3643 },
3644 }),
3645 uses: Box::from([]),
3646 exposes: Box::from([]),
3647 offers: Box::from([]),
3648 capabilities: Box::from([]),
3649 children: Box::from([]),
3650 collections: Box::from([
3651 CollectionDecl {
3652 name: "modular".parse().unwrap(),
3653 durability: fdecl::Durability::Transient,
3654 environment: None,
3655 allowed_offers: cm_types::AllowedOffers::StaticOnly,
3656 allow_long_names: false,
3657 persistent_storage: None,
3658 },
3659 CollectionDecl {
3660 name: "tests".parse().unwrap(),
3661 durability: fdecl::Durability::Transient,
3662 environment: Some("test_env".parse().unwrap()),
3663 allowed_offers: cm_types::AllowedOffers::StaticOnly,
3664 allow_long_names: false,
3665 persistent_storage: Some(false),
3666 },
3667 CollectionDecl {
3668 name: "dyn_offers".parse().unwrap(),
3669 durability: fdecl::Durability::Transient,
3670 environment: None,
3671 allowed_offers: cm_types::AllowedOffers::StaticAndDynamic,
3672 allow_long_names: false,
3673 persistent_storage: Some(true),
3674 },
3675 CollectionDecl {
3676 name: "long_child_names".parse().unwrap(),
3677 durability: fdecl::Durability::Transient,
3678 environment: None,
3679 allowed_offers: cm_types::AllowedOffers::StaticOnly,
3680 allow_long_names: true,
3681 persistent_storage: None,
3682 },
3683 ]),
3684 facets: Some(fdata::Dictionary{
3685 entries: Some(vec![]),
3686 ..Default::default()
3687 }),
3688 environments: Box::from([]),
3689 config: None,
3690 debug_info: None,
3691 }
3692 },
3693 },
3694 }
3695
3696 #[test]
3697 fn default_expose_availability() {
3698 let source = fdecl::Ref::Self_(fdecl::SelfRef {});
3699 let source_name = "source";
3700 let target = fdecl::Ref::Parent(fdecl::ParentRef {});
3701 let target_name = "target";
3702 assert_eq!(
3703 *fdecl::ExposeService {
3704 source: Some(source.clone()),
3705 source_name: Some(source_name.into()),
3706 target: Some(target.clone()),
3707 target_name: Some(target_name.into()),
3708 availability: None,
3709 ..Default::default()
3710 }
3711 .fidl_into_native()
3712 .availability(),
3713 Availability::Required
3714 );
3715 assert_eq!(
3716 *fdecl::ExposeProtocol {
3717 source: Some(source.clone()),
3718 source_name: Some(source_name.into()),
3719 target: Some(target.clone()),
3720 target_name: Some(target_name.into()),
3721 ..Default::default()
3722 }
3723 .fidl_into_native()
3724 .availability(),
3725 Availability::Required
3726 );
3727 assert_eq!(
3728 *fdecl::ExposeDirectory {
3729 source: Some(source.clone()),
3730 source_name: Some(source_name.into()),
3731 target: Some(target.clone()),
3732 target_name: Some(target_name.into()),
3733 ..Default::default()
3734 }
3735 .fidl_into_native()
3736 .availability(),
3737 Availability::Required
3738 );
3739 assert_eq!(
3740 *fdecl::ExposeRunner {
3741 source: Some(source.clone()),
3742 source_name: Some(source_name.into()),
3743 target: Some(target.clone()),
3744 target_name: Some(target_name.into()),
3745 ..Default::default()
3746 }
3747 .fidl_into_native()
3748 .availability(),
3749 Availability::Required
3750 );
3751 assert_eq!(
3752 *fdecl::ExposeResolver {
3753 source: Some(source.clone()),
3754 source_name: Some(source_name.into()),
3755 target: Some(target.clone()),
3756 target_name: Some(target_name.into()),
3757 ..Default::default()
3758 }
3759 .fidl_into_native()
3760 .availability(),
3761 Availability::Required
3762 );
3763 assert_eq!(
3764 *fdecl::ExposeDictionary {
3765 source: Some(source.clone()),
3766 source_name: Some(source_name.into()),
3767 target: Some(target.clone()),
3768 target_name: Some(target_name.into()),
3769 ..Default::default()
3770 }
3771 .fidl_into_native()
3772 .availability(),
3773 Availability::Required
3774 );
3775 }
3776
3777 #[test]
3778 fn default_delivery_type() {
3779 assert_eq!(
3780 fdecl::Protocol {
3781 name: Some("foo".to_string()),
3782 source_path: Some("/foo".to_string()),
3783 delivery: None,
3784 ..Default::default()
3785 }
3786 .fidl_into_native()
3787 .delivery,
3788 DeliveryType::Immediate
3789 )
3790 }
3791
3792 #[test]
3793 fn on_readable_delivery_type() {
3794 assert_eq!(
3795 fdecl::Protocol {
3796 name: Some("foo".to_string()),
3797 source_path: Some("/foo".to_string()),
3798 delivery: Some(fdecl::DeliveryType::OnReadable),
3799 ..Default::default()
3800 }
3801 .fidl_into_native()
3802 .delivery,
3803 DeliveryType::OnReadable
3804 )
3805 }
3806
3807 #[test]
3808 fn config_value_matches_type() {
3809 let bool_true = ConfigValue::Single(ConfigSingleValue::Bool(true));
3810 let bool_false = ConfigValue::Single(ConfigSingleValue::Bool(false));
3811 let uint8_zero = ConfigValue::Single(ConfigSingleValue::Uint8(0));
3812 let vec_bool_true = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([true])));
3813 let vec_bool_false = ConfigValue::Vector(ConfigVectorValue::BoolVector(Box::from([false])));
3814
3815 assert!(bool_true.matches_type(&bool_false));
3816 assert!(vec_bool_true.matches_type(&vec_bool_false));
3817
3818 assert!(!bool_true.matches_type(&uint8_zero));
3819 assert!(!bool_true.matches_type(&vec_bool_true));
3820 }
3821}