1use cm_rust_derive::{FidlDecl, UseDeclCommon};
6use cm_types::{BorrowedSeparatedPath, Name, Path, RelativePath};
7use fidl_fuchsia_component_decl as fdecl;
8use fidl_fuchsia_io as fio;
9use from_enum::FromEnum;
10use std::collections::BTreeMap;
11use std::fmt;
12use std::hash::Hash;
13use std::sync::LazyLock;
14
15use crate::{
16 Availability, ConfigValue, ConfigValueType, DependencyType, DictionaryValue, EventScope,
17 FidlIntoNative, NativeIntoFidl, SourceName, SourcePath,
18};
19
20#[cfg(fuchsia_api_level_at_least = "29")]
21pub use cm_types::HandleType;
22
23#[cfg(feature = "serde")]
24use crate::serde_ext;
25
26#[cfg(feature = "serde")]
27use serde::{Deserialize, Serialize};
28
29#[cfg_attr(
30 feature = "serde",
31 derive(Deserialize, Serialize),
32 serde(tag = "type", rename_all = "snake_case")
33)]
34#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
35#[fidl_decl(fidl_union = "fdecl::Use")]
36pub enum UseDecl {
37 Service(UseServiceDecl),
38 Protocol(UseProtocolDecl),
39 Directory(UseDirectoryDecl),
40 Storage(UseStorageDecl),
41 EventStream(Box<UseEventStreamDecl>),
42 #[cfg(fuchsia_api_level_at_least = "HEAD")]
43 Runner(UseRunnerDecl),
44 Config(Box<UseConfigurationDecl>),
45 #[cfg(fuchsia_api_level_at_least = "29")]
46 Dictionary(UseDictionaryDecl),
47}
48
49#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
51#[fidl_decl(fidl_table = "fdecl::UseService", source_path = "dictionary")]
52pub struct UseServiceDecl {
53 pub source: UseSource,
54 pub source_name: Name,
55 #[fidl_decl(default_preserve_none)]
56 pub source_dictionary: RelativePath,
57 pub target_path: Path,
58 pub dependency_type: DependencyType,
59 #[fidl_decl(default)]
60 pub availability: Availability,
61}
62
63#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
64#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
65#[fidl_decl(fidl_table = "fdecl::UseProtocol", source_path = "dictionary")]
66pub struct UseProtocolDecl {
67 pub source: UseSource,
68 pub source_name: Name,
69 #[fidl_decl(default_preserve_none)]
70 pub source_dictionary: RelativePath,
71 pub target_path: Option<Path>,
72 #[cfg(fuchsia_api_level_at_least = "29")]
73 pub numbered_handle: Option<HandleType>,
74 pub dependency_type: DependencyType,
75 #[fidl_decl(default)]
76 pub availability: Availability,
77}
78
79#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
80#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
81#[fidl_decl(fidl_table = "fdecl::UseDirectory", source_path = "dictionary")]
82pub struct UseDirectoryDecl {
83 pub source: UseSource,
84 pub source_name: Name,
85 #[fidl_decl(default_preserve_none)]
86 pub source_dictionary: RelativePath,
87 pub target_path: Path,
88
89 #[cfg_attr(
90 feature = "serde",
91 serde(
92 deserialize_with = "serde_ext::deserialize_fio_operations",
93 serialize_with = "serde_ext::serialize_fio_operations"
94 )
95 )]
96 pub rights: fio::Operations,
97
98 #[fidl_decl(default_preserve_none)]
99 pub subdir: RelativePath,
100 pub dependency_type: DependencyType,
101 #[fidl_decl(default)]
102 pub availability: Availability,
103}
104
105#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
106#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
107#[fidl_decl(fidl_table = "fdecl::UseStorage", source_path = "name_only")]
108pub struct UseStorageDecl {
109 pub source_name: Name,
110 pub target_path: Path,
111 #[fidl_decl(default)]
112 pub availability: Availability,
113}
114
115impl SourceName for UseStorageDecl {
116 fn source_name(&self) -> &Name {
117 &self.source_name
118 }
119}
120
121impl UseDeclCommon for UseStorageDecl {
122 fn source(&self) -> &UseSource {
123 &UseSource::Parent
124 }
125
126 fn availability(&self) -> &Availability {
127 &self.availability
128 }
129}
130
131#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
132#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq, Hash)]
133#[fidl_decl(fidl_table = "fdecl::UseEventStream", source_path = "name_only")]
134pub struct UseEventStreamDecl {
135 pub source_name: Name,
136 pub source: UseSource,
137 pub scope: Option<Box<[EventScope]>>,
138 pub target_path: Path,
139 pub filter: Option<BTreeMap<String, DictionaryValue>>,
140 #[fidl_decl(default)]
141 pub availability: Availability,
142}
143
144#[cfg(fuchsia_api_level_at_least = "HEAD")]
145#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
146#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
147#[fidl_decl(fidl_table = "fdecl::UseRunner", source_path = "dictionary")]
148pub struct UseRunnerDecl {
149 pub source: UseSource,
150 pub source_name: Name,
151 #[fidl_decl(default_preserve_none)]
152 pub source_dictionary: RelativePath,
153}
154
155#[cfg(fuchsia_api_level_at_least = "29")]
156#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
157#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
158#[fidl_decl(fidl_table = "fdecl::UseDictionary", source_path = "dictionary")]
159pub struct UseDictionaryDecl {
160 pub source: UseSource,
161 pub source_name: Name,
162 #[fidl_decl(default_preserve_none)]
163 pub source_dictionary: RelativePath,
164 pub target_path: Path,
165 pub dependency_type: DependencyType,
166 #[fidl_decl(default)]
167 pub availability: Availability,
168}
169
170#[cfg(fuchsia_api_level_at_least = "HEAD")]
171impl SourceName for UseRunnerDecl {
172 fn source_name(&self) -> &Name {
173 &self.source_name
174 }
175}
176
177#[cfg(fuchsia_api_level_at_least = "HEAD")]
178impl UseDeclCommon for UseRunnerDecl {
179 fn source(&self) -> &UseSource {
180 &self.source
181 }
182
183 fn availability(&self) -> &Availability {
184 &Availability::Required
185 }
186}
187
188#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
189#[derive(FidlDecl, UseDeclCommon, Debug, Clone, PartialEq, Eq)]
190#[fidl_decl(fidl_table = "fdecl::UseConfiguration", source_path = "dictionary")]
191pub struct UseConfigurationDecl {
192 pub source: UseSource,
193 pub source_name: Name,
194 #[fidl_decl(default_preserve_none)]
195 pub source_dictionary: RelativePath,
196 pub target_name: Name,
197 #[fidl_decl(default)]
198 pub availability: Availability,
199 pub type_: ConfigValueType,
200 pub default: Option<ConfigValue>,
201}
202
203impl UseDeclCommon for UseDecl {
204 fn source(&self) -> &UseSource {
205 match &self {
206 UseDecl::Service(u) => u.source(),
207 UseDecl::Protocol(u) => u.source(),
208 UseDecl::Directory(u) => u.source(),
209 UseDecl::Storage(u) => u.source(),
210 UseDecl::EventStream(u) => u.source(),
211 #[cfg(fuchsia_api_level_at_least = "HEAD")]
212 UseDecl::Runner(u) => u.source(),
213 UseDecl::Config(u) => u.source(),
214 #[cfg(fuchsia_api_level_at_least = "29")]
215 UseDecl::Dictionary(u) => u.source(),
216 }
217 }
218
219 fn availability(&self) -> &Availability {
220 match &self {
221 UseDecl::Service(u) => u.availability(),
222 UseDecl::Protocol(u) => u.availability(),
223 UseDecl::Directory(u) => u.availability(),
224 UseDecl::Storage(u) => u.availability(),
225 UseDecl::EventStream(u) => u.availability(),
226 #[cfg(fuchsia_api_level_at_least = "HEAD")]
227 UseDecl::Runner(u) => u.availability(),
228 UseDecl::Config(u) => u.availability(),
229 #[cfg(fuchsia_api_level_at_least = "29")]
230 UseDecl::Dictionary(u) => u.availability(),
231 }
232 }
233}
234
235pub trait UseDeclCommon: SourceName + SourcePath + Send + Sync {
237 fn source(&self) -> &UseSource;
238 fn availability(&self) -> &Availability;
239}
240
241#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub enum UseSource {
244 Parent,
245 Framework,
246 Debug,
247 Self_,
248 Capability(Name),
249 Child(Name),
250 Collection(Name),
251 #[cfg(fuchsia_api_level_at_least = "HEAD")]
252 Environment,
253}
254
255impl std::fmt::Display for UseSource {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 match self {
258 Self::Framework => write!(f, "framework"),
259 Self::Parent => write!(f, "parent"),
260 Self::Debug => write!(f, "debug environment"),
261 Self::Self_ => write!(f, "self"),
262 Self::Capability(c) => write!(f, "capability `{}`", c),
263 Self::Child(c) => write!(f, "child `#{}`", c),
264 Self::Collection(c) => write!(f, "collection `#{}`", c),
265 #[cfg(fuchsia_api_level_at_least = "HEAD")]
266 Self::Environment => write!(f, "environment"),
267 }
268 }
269}
270
271impl FidlIntoNative<UseSource> for fdecl::Ref {
272 fn fidl_into_native(self) -> UseSource {
273 match self {
274 fdecl::Ref::Parent(_) => UseSource::Parent,
275 fdecl::Ref::Framework(_) => UseSource::Framework,
276 fdecl::Ref::Debug(_) => UseSource::Debug,
277 fdecl::Ref::Self_(_) => UseSource::Self_,
278 fdecl::Ref::Capability(c) => UseSource::Capability(c.name.parse().unwrap()),
280 fdecl::Ref::Child(c) => UseSource::Child(c.name.parse().unwrap()),
281 fdecl::Ref::Collection(c) => UseSource::Collection(c.name.parse().unwrap()),
282 #[cfg(fuchsia_api_level_at_least = "HEAD")]
283 fdecl::Ref::Environment(_) => UseSource::Environment,
284 _ => panic!("invalid UseSource variant"),
285 }
286 }
287}
288
289impl NativeIntoFidl<fdecl::Ref> for UseSource {
290 fn native_into_fidl(self) -> fdecl::Ref {
291 match self {
292 UseSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
293 UseSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
294 UseSource::Debug => fdecl::Ref::Debug(fdecl::DebugRef {}),
295 UseSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
296 UseSource::Capability(name) => {
297 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
298 }
299 UseSource::Child(name) => {
300 fdecl::Ref::Child(fdecl::ChildRef { name: name.to_string(), collection: None })
301 }
302 UseSource::Collection(name) => {
303 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.to_string() })
304 }
305 #[cfg(fuchsia_api_level_at_least = "HEAD")]
306 UseSource::Environment => fdecl::Ref::Environment(fdecl::EnvironmentRef {}),
307 }
308 }
309}
310
311#[cfg(fuchsia_api_level_at_least = "29")]
312impl FidlIntoNative<HandleType> for u8 {
313 fn fidl_into_native(self) -> HandleType {
314 self.into()
315 }
316}
317
318#[cfg(fuchsia_api_level_at_least = "29")]
319impl NativeIntoFidl<u8> for HandleType {
320 fn native_into_fidl(self) -> u8 {
321 self.into()
322 }
323}