1use cm_rust_derive::{FidlDecl, OfferDeclCommon, OfferDeclCommonNoAvailability};
6use cm_types::{BorrowedSeparatedPath, Name, RelativePath};
7use fidl_fuchsia_component_decl as fdecl;
8use fidl_fuchsia_io as fio;
9use from_enum::FromEnum;
10use std::fmt;
11use std::hash::Hash;
12use std::sync::LazyLock;
13
14use crate::{
15 Availability, CapabilityTypeName, ChildRef, DependencyType, EventScope, FidlIntoNative,
16 NameMapping, NativeIntoFidl, SourceName, SourcePath,
17};
18
19#[cfg(feature = "serde")]
20use crate::serde_ext;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[cfg_attr(
26 feature = "serde",
27 derive(Deserialize, Serialize),
28 serde(tag = "type", rename_all = "snake_case")
29)]
30#[derive(FidlDecl, FromEnum, Debug, Clone, PartialEq, Eq)]
31#[fidl_decl(fidl_union = "fdecl::Offer")]
32pub enum OfferDecl {
33 Service(OfferServiceDecl),
34 Protocol(OfferProtocolDecl),
35 Directory(OfferDirectoryDecl),
36 Storage(OfferStorageDecl),
37 Runner(OfferRunnerDecl),
38 Resolver(OfferResolverDecl),
39 EventStream(OfferEventStreamDecl),
40 Dictionary(OfferDictionaryDecl),
41 Config(OfferConfigurationDecl),
42}
43
44#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
45#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
46#[fidl_decl(fidl_table = "fdecl::OfferEventStream", source_path = "name_only")]
47pub struct OfferEventStreamDecl {
48 pub source: OfferSource,
49 pub scope: Option<Box<[EventScope]>>,
50 pub source_name: Name,
51 pub target: OfferTarget,
52 pub target_name: Name,
53 #[fidl_decl(default)]
54 pub availability: Availability,
55}
56
57#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
58#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
59#[fidl_decl(fidl_table = "fdecl::OfferService", source_path = "dictionary")]
60pub struct OfferServiceDecl {
61 pub source: OfferSource,
62 pub source_name: Name,
63 #[fidl_decl(default_preserve_none)]
64 pub source_dictionary: RelativePath,
65 pub target: OfferTarget,
66 pub target_name: Name,
67 pub source_instance_filter: Option<Box<[Name]>>,
68 pub renamed_instances: Option<Box<[NameMapping]>>,
69 #[fidl_decl(default)]
70 pub availability: Availability,
71 #[cfg(fuchsia_api_level_at_least = "HEAD")]
72 #[fidl_decl(default)]
73 pub dependency_type: DependencyType,
74}
75
76#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
77#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
78#[fidl_decl(fidl_table = "fdecl::OfferProtocol", source_path = "dictionary")]
79pub struct OfferProtocolDecl {
80 pub source: OfferSource,
81 pub source_name: Name,
82 #[fidl_decl(default_preserve_none)]
83 pub source_dictionary: RelativePath,
84 pub target: OfferTarget,
85 pub target_name: Name,
86 pub dependency_type: DependencyType,
87 #[fidl_decl(default)]
88 pub availability: Availability,
89}
90
91#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
92#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
93#[fidl_decl(fidl_table = "fdecl::OfferDirectory", source_path = "dictionary")]
94pub struct OfferDirectoryDecl {
95 pub source: OfferSource,
96 pub source_name: Name,
97 #[fidl_decl(default_preserve_none)]
98 pub source_dictionary: RelativePath,
99 pub target: OfferTarget,
100 pub target_name: Name,
101 pub dependency_type: DependencyType,
102
103 #[cfg_attr(
104 feature = "serde",
105 serde(
106 deserialize_with = "serde_ext::deserialize_opt_fio_operations",
107 serialize_with = "serde_ext::serialize_opt_fio_operations"
108 )
109 )]
110 pub rights: Option<fio::Operations>,
111
112 #[fidl_decl(default_preserve_none)]
113 pub subdir: RelativePath,
114 #[fidl_decl(default)]
115 pub availability: Availability,
116}
117
118#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
119#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
120#[fidl_decl(fidl_table = "fdecl::OfferStorage", source_path = "name_only")]
121pub struct OfferStorageDecl {
122 pub source: OfferSource,
123 pub source_name: Name,
124 pub target: OfferTarget,
125 pub target_name: Name,
126 #[fidl_decl(default)]
127 pub availability: Availability,
128}
129
130#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
131#[derive(FidlDecl, Debug, Clone, PartialEq, Eq)]
132#[fidl_decl(fidl_table = "fdecl::OfferRunner", source_path = "dictionary")]
133pub struct OfferRunnerDecl {
134 pub source: OfferSource,
135 pub source_name: Name,
136 #[fidl_decl(default_preserve_none)]
137 pub source_dictionary: RelativePath,
138 pub target: OfferTarget,
139 pub target_name: Name,
140}
141
142#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
143#[derive(FidlDecl, OfferDeclCommonNoAvailability, Debug, Clone, PartialEq, Eq)]
144#[fidl_decl(fidl_table = "fdecl::OfferResolver", source_path = "dictionary")]
145pub struct OfferResolverDecl {
146 pub source: OfferSource,
147 pub source_name: Name,
148 #[fidl_decl(default_preserve_none)]
149 pub source_dictionary: RelativePath,
150 pub target: OfferTarget,
151 pub target_name: Name,
152}
153
154#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
155#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
156#[fidl_decl(fidl_table = "fdecl::OfferDictionary", source_path = "dictionary")]
157pub struct OfferDictionaryDecl {
158 pub source: OfferSource,
159 pub source_name: Name,
160 #[fidl_decl(default_preserve_none)]
161 pub source_dictionary: RelativePath,
162 pub target: OfferTarget,
163 pub target_name: Name,
164 pub dependency_type: DependencyType,
165 #[fidl_decl(default)]
166 pub availability: Availability,
167}
168
169#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
170#[derive(FidlDecl, OfferDeclCommon, Debug, Clone, PartialEq, Eq)]
171#[fidl_decl(fidl_table = "fdecl::OfferConfiguration", source_path = "dictionary")]
172pub struct OfferConfigurationDecl {
173 pub source: OfferSource,
174 pub source_name: Name,
175 #[fidl_decl(default_preserve_none)]
176 pub source_dictionary: RelativePath,
177 pub target: OfferTarget,
178 pub target_name: Name,
179 #[fidl_decl(default)]
180 pub availability: Availability,
181}
182
183impl SourceName for OfferDecl {
184 fn source_name(&self) -> &Name {
185 match &self {
186 OfferDecl::Service(o) => o.source_name(),
187 OfferDecl::Protocol(o) => o.source_name(),
188 OfferDecl::Directory(o) => o.source_name(),
189 OfferDecl::Storage(o) => o.source_name(),
190 OfferDecl::Runner(o) => o.source_name(),
191 OfferDecl::Resolver(o) => o.source_name(),
192 OfferDecl::EventStream(o) => o.source_name(),
193 OfferDecl::Dictionary(o) => o.source_name(),
194 OfferDecl::Config(o) => o.source_name(),
195 }
196 }
197}
198
199impl SourcePath for OfferDecl {
200 fn source_path(&self) -> BorrowedSeparatedPath<'_> {
201 match &self {
202 OfferDecl::Service(o) => o.source_path(),
203 OfferDecl::Protocol(o) => o.source_path(),
204 OfferDecl::Directory(o) => o.source_path(),
205 OfferDecl::Storage(o) => o.source_path(),
206 OfferDecl::Runner(o) => o.source_path(),
207 OfferDecl::Resolver(o) => o.source_path(),
208 OfferDecl::EventStream(o) => o.source_path(),
209 OfferDecl::Dictionary(o) => o.source_path(),
210 OfferDecl::Config(o) => o.source_path(),
211 }
212 }
213}
214
215impl OfferDeclCommon for OfferDecl {
216 fn target_name(&self) -> &Name {
217 match &self {
218 OfferDecl::Service(o) => o.target_name(),
219 OfferDecl::Protocol(o) => o.target_name(),
220 OfferDecl::Directory(o) => o.target_name(),
221 OfferDecl::Storage(o) => o.target_name(),
222 OfferDecl::Runner(o) => o.target_name(),
223 OfferDecl::Resolver(o) => o.target_name(),
224 OfferDecl::EventStream(o) => o.target_name(),
225 OfferDecl::Dictionary(o) => o.target_name(),
226 OfferDecl::Config(o) => o.target_name(),
227 }
228 }
229
230 fn target(&self) -> &OfferTarget {
231 match &self {
232 OfferDecl::Service(o) => o.target(),
233 OfferDecl::Protocol(o) => o.target(),
234 OfferDecl::Directory(o) => o.target(),
235 OfferDecl::Storage(o) => o.target(),
236 OfferDecl::Runner(o) => o.target(),
237 OfferDecl::Resolver(o) => o.target(),
238 OfferDecl::EventStream(o) => o.target(),
239 OfferDecl::Dictionary(o) => o.target(),
240 OfferDecl::Config(o) => o.target(),
241 }
242 }
243
244 fn source(&self) -> &OfferSource {
245 match &self {
246 OfferDecl::Service(o) => o.source(),
247 OfferDecl::Protocol(o) => o.source(),
248 OfferDecl::Directory(o) => o.source(),
249 OfferDecl::Storage(o) => o.source(),
250 OfferDecl::Runner(o) => o.source(),
251 OfferDecl::Resolver(o) => o.source(),
252 OfferDecl::EventStream(o) => o.source(),
253 OfferDecl::Dictionary(o) => o.source(),
254 OfferDecl::Config(o) => o.source(),
255 }
256 }
257
258 fn availability(&self) -> &Availability {
259 match &self {
260 OfferDecl::Service(o) => o.availability(),
261 OfferDecl::Protocol(o) => o.availability(),
262 OfferDecl::Directory(o) => o.availability(),
263 OfferDecl::Storage(o) => o.availability(),
264 OfferDecl::Runner(o) => o.availability(),
265 OfferDecl::Resolver(o) => o.availability(),
266 OfferDecl::EventStream(o) => o.availability(),
267 OfferDecl::Dictionary(o) => o.availability(),
268 OfferDecl::Config(o) => o.availability(),
269 }
270 }
271}
272
273impl SourceName for OfferRunnerDecl {
274 fn source_name(&self) -> &Name {
275 &self.source_name
276 }
277}
278
279impl OfferDeclCommon for OfferRunnerDecl {
280 fn target_name(&self) -> &Name {
281 &self.target_name
282 }
283
284 fn target(&self) -> &OfferTarget {
285 &self.target
286 }
287
288 fn source(&self) -> &OfferSource {
289 &self.source
290 }
291
292 fn availability(&self) -> &Availability {
293 &Availability::Required
294 }
295}
296
297pub trait OfferDeclCommon: SourceName + SourcePath + fmt::Debug + Send + Sync {
299 fn target_name(&self) -> &Name;
300 fn target(&self) -> &OfferTarget;
301 fn source(&self) -> &OfferSource;
302 fn availability(&self) -> &Availability;
303}
304
305impl From<&OfferDecl> for CapabilityTypeName {
306 fn from(offer_decl: &OfferDecl) -> Self {
307 match offer_decl {
308 OfferDecl::Service(_) => Self::Service,
309 OfferDecl::Protocol(_) => Self::Protocol,
310 OfferDecl::Directory(_) => Self::Directory,
311 OfferDecl::Storage(_) => Self::Storage,
312 OfferDecl::Runner(_) => Self::Runner,
313 OfferDecl::Resolver(_) => Self::Resolver,
314 OfferDecl::EventStream(_) => Self::EventStream,
315 OfferDecl::Dictionary(_) => Self::Dictionary,
316 OfferDecl::Config(_) => Self::Config,
317 }
318 }
319}
320
321#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
322#[derive(Debug, Clone, PartialEq, Eq)]
323pub enum OfferSource {
324 Framework,
325 Parent,
326 Child(ChildRef),
327 Collection(Name),
328 Self_,
329 Capability(Name),
330 Void,
331}
332
333impl std::fmt::Display for OfferSource {
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 match self {
336 Self::Framework => write!(f, "framework"),
337 Self::Parent => write!(f, "parent"),
338 Self::Child(c) => write!(f, "child `#{}`", c),
339 Self::Collection(c) => write!(f, "collection `#{}`", c),
340 Self::Self_ => write!(f, "self"),
341 Self::Capability(c) => write!(f, "capability `{}`", c),
342 Self::Void => write!(f, "void"),
343 }
344 }
345}
346
347impl FidlIntoNative<OfferSource> for fdecl::Ref {
348 fn fidl_into_native(self) -> OfferSource {
349 match self {
350 fdecl::Ref::Parent(_) => OfferSource::Parent,
351 fdecl::Ref::Self_(_) => OfferSource::Self_,
352 fdecl::Ref::Child(c) => OfferSource::Child(c.fidl_into_native()),
353 fdecl::Ref::Collection(c) => OfferSource::Collection(c.name.parse().unwrap()),
355 fdecl::Ref::Framework(_) => OfferSource::Framework,
356 fdecl::Ref::Capability(c) => OfferSource::Capability(c.name.parse().unwrap()),
358 fdecl::Ref::VoidType(_) => OfferSource::Void,
359 _ => panic!("invalid OfferSource variant"),
360 }
361 }
362}
363
364impl NativeIntoFidl<fdecl::Ref> for OfferSource {
365 fn native_into_fidl(self) -> fdecl::Ref {
366 match self {
367 OfferSource::Parent => fdecl::Ref::Parent(fdecl::ParentRef {}),
368 OfferSource::Self_ => fdecl::Ref::Self_(fdecl::SelfRef {}),
369 OfferSource::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
370 OfferSource::Collection(name) => {
371 fdecl::Ref::Collection(fdecl::CollectionRef { name: name.native_into_fidl() })
372 }
373 OfferSource::Framework => fdecl::Ref::Framework(fdecl::FrameworkRef {}),
374 OfferSource::Capability(name) => {
375 fdecl::Ref::Capability(fdecl::CapabilityRef { name: name.to_string() })
376 }
377 OfferSource::Void => fdecl::Ref::VoidType(fdecl::VoidRef {}),
378 }
379 }
380}
381
382#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub enum OfferTarget {
385 Child(ChildRef),
386 Collection(Name),
387 Capability(Name),
388}
389
390impl std::fmt::Display for OfferTarget {
391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 match self {
393 Self::Child(c) => write!(f, "child `#{}`", c),
394 Self::Collection(c) => write!(f, "collection `#{}`", c),
395 Self::Capability(c) => write!(f, "capability `#{}`", c),
396 }
397 }
398}
399
400impl FidlIntoNative<OfferTarget> for fdecl::Ref {
401 fn fidl_into_native(self) -> OfferTarget {
402 match self {
403 fdecl::Ref::Child(c) => OfferTarget::Child(c.fidl_into_native()),
404 fdecl::Ref::Collection(c) => OfferTarget::Collection(c.name.parse().unwrap()),
406 fdecl::Ref::Capability(c) => OfferTarget::Capability(c.name.parse().unwrap()),
407 _ => panic!("invalid OfferTarget variant"),
408 }
409 }
410}
411
412impl NativeIntoFidl<fdecl::Ref> for OfferTarget {
413 fn native_into_fidl(self) -> fdecl::Ref {
414 match self {
415 OfferTarget::Child(c) => fdecl::Ref::Child(c.native_into_fidl()),
416 OfferTarget::Collection(collection_name) => {
417 fdecl::Ref::Collection(fdecl::CollectionRef {
418 name: collection_name.native_into_fidl(),
419 })
420 }
421 OfferTarget::Capability(capability_name) => {
422 fdecl::Ref::Capability(fdecl::CapabilityRef {
423 name: capability_name.native_into_fidl(),
424 })
425 }
426 }
427 }
428}