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