1use crate::types::right::{Rights, RightsClause};
6use crate::{
7 AnyRef, AsClause, Canonicalize, CapabilityClause, DictionaryRef, EventScope, FilterClause,
8 FromClause, PathClause, SourceAvailability, SpannedCapabilityClause, one_or_many_from_impl,
9 option_one_or_many_as_ref, option_spanned_one_or_many_as_ref,
10};
11
12use crate::one_or_many::OneOrMany;
13pub use cm_types::{
14 Availability, BorrowedName, BoundedName, DependencyType, HandleType, Name, OnTerminate,
15 ParseError, Path, RelativePath, StartupMode, Url,
16};
17use cml_macro::{OneOrMany, Reference};
18use json_spanned_value::Spanned;
19use reference_doc::ReferenceDoc;
20use serde::{Deserialize, Serialize};
21use serde_json::{Map, Value};
22
23use std::fmt;
24
25#[derive(Deserialize, Debug, PartialEq, Clone, ReferenceDoc, Serialize)]
57#[serde(deny_unknown_fields)]
58#[reference_doc(fields_as = "list", top_level_doc_after_fields)]
59pub struct Expose {
60 #[serde(skip_serializing_if = "Option::is_none")]
62 #[reference_doc(skip = true)]
63 pub service: Option<OneOrMany<Name>>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 #[reference_doc(skip = true)]
68 pub protocol: Option<OneOrMany<Name>>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 #[reference_doc(skip = true)]
73 pub directory: Option<OneOrMany<Name>>,
74
75 #[serde(skip_serializing_if = "Option::is_none")]
77 #[reference_doc(skip = true)]
78 pub runner: Option<OneOrMany<Name>>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
82 #[reference_doc(skip = true)]
83 pub resolver: Option<OneOrMany<Name>>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 #[reference_doc(skip = true)]
88 pub dictionary: Option<OneOrMany<Name>>,
89
90 #[serde(skip_serializing_if = "Option::is_none")]
92 #[reference_doc(skip = true)]
93 pub config: Option<OneOrMany<Name>>,
94
95 pub from: OneOrMany<ExposeFromRef>,
102
103 #[serde(skip_serializing_if = "Option::is_none")]
107 pub r#as: Option<Name>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub to: Option<ExposeToRef>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
116 #[reference_doc(json_type = "array of string")]
117 pub rights: Option<Rights>,
118
119 #[serde(skip_serializing_if = "Option::is_none")]
122 pub subdir: Option<RelativePath>,
123
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub event_stream: Option<OneOrMany<Name>>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
132 pub scope: Option<OneOrMany<EventScope>>,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
151 pub availability: Option<Availability>,
152
153 #[serde(skip_serializing_if = "Option::is_none")]
158 pub source_availability: Option<SourceAvailability>,
159}
160
161impl Expose {
162 pub fn new_from(from: OneOrMany<ExposeFromRef>) -> Self {
163 Self {
164 from,
165 service: None,
166 protocol: None,
167 directory: None,
168 config: None,
169 runner: None,
170 resolver: None,
171 dictionary: None,
172 r#as: None,
173 to: None,
174 rights: None,
175 subdir: None,
176 event_stream: None,
177 scope: None,
178 availability: None,
179 source_availability: None,
180 }
181 }
182}
183
184impl FromClause for Expose {
185 fn from_(&self) -> OneOrMany<AnyRef<'_>> {
186 one_or_many_from_impl(&self.from)
187 }
188}
189
190impl AsClause for Expose {
191 fn r#as(&self) -> Option<&BorrowedName> {
192 self.r#as.as_ref().map(Name::as_ref)
193 }
194}
195
196impl PathClause for Expose {
197 fn path(&self) -> Option<&Path> {
198 None
199 }
200}
201
202impl FilterClause for Expose {
203 fn filter(&self) -> Option<&Map<String, Value>> {
204 None
205 }
206}
207
208impl RightsClause for Expose {
209 fn rights(&self) -> Option<&Rights> {
210 self.rights.as_ref()
211 }
212}
213
214impl Canonicalize for Expose {
215 fn canonicalize(&mut self) {
216 if let Some(service) = &mut self.service {
218 service.canonicalize();
219 } else if let Some(protocol) = &mut self.protocol {
220 protocol.canonicalize();
221 } else if let Some(directory) = &mut self.directory {
222 directory.canonicalize();
223 } else if let Some(runner) = &mut self.runner {
224 runner.canonicalize();
225 } else if let Some(resolver) = &mut self.resolver {
226 resolver.canonicalize();
227 } else if let Some(event_stream) = &mut self.event_stream {
228 event_stream.canonicalize();
229 if let Some(scope) = &mut self.scope {
230 scope.canonicalize();
231 }
232 }
233 }
235}
236
237impl CapabilityClause for Expose {
238 fn service(&self) -> Option<OneOrMany<&BorrowedName>> {
239 option_one_or_many_as_ref(&self.service)
240 }
241 fn protocol(&self) -> Option<OneOrMany<&BorrowedName>> {
242 option_one_or_many_as_ref(&self.protocol)
243 }
244 fn directory(&self) -> Option<OneOrMany<&BorrowedName>> {
245 option_one_or_many_as_ref(&self.directory)
246 }
247 fn storage(&self) -> Option<OneOrMany<&BorrowedName>> {
248 None
249 }
250 fn runner(&self) -> Option<OneOrMany<&BorrowedName>> {
251 option_one_or_many_as_ref(&self.runner)
252 }
253 fn resolver(&self) -> Option<OneOrMany<&BorrowedName>> {
254 option_one_or_many_as_ref(&self.resolver)
255 }
256 fn event_stream(&self) -> Option<OneOrMany<&BorrowedName>> {
257 option_one_or_many_as_ref(&self.event_stream)
258 }
259 fn dictionary(&self) -> Option<OneOrMany<&BorrowedName>> {
260 option_one_or_many_as_ref(&self.dictionary)
261 }
262 fn config(&self) -> Option<OneOrMany<&BorrowedName>> {
263 option_one_or_many_as_ref(&self.config)
264 }
265
266 fn set_service(&mut self, o: Option<OneOrMany<Name>>) {
267 self.service = o;
268 }
269 fn set_protocol(&mut self, o: Option<OneOrMany<Name>>) {
270 self.protocol = o;
271 }
272 fn set_directory(&mut self, o: Option<OneOrMany<Name>>) {
273 self.directory = o;
274 }
275 fn set_storage(&mut self, _o: Option<OneOrMany<Name>>) {}
276 fn set_runner(&mut self, o: Option<OneOrMany<Name>>) {
277 self.runner = o;
278 }
279 fn set_resolver(&mut self, o: Option<OneOrMany<Name>>) {
280 self.resolver = o;
281 }
282 fn set_event_stream(&mut self, o: Option<OneOrMany<Name>>) {
283 self.event_stream = o;
284 }
285 fn set_dictionary(&mut self, o: Option<OneOrMany<Name>>) {
286 self.dictionary = o;
287 }
288 fn set_config(&mut self, o: Option<OneOrMany<Name>>) {
289 self.config = o;
290 }
291
292 fn availability(&self) -> Option<Availability> {
293 None
294 }
295 fn set_availability(&mut self, _a: Option<Availability>) {}
296
297 fn decl_type(&self) -> &'static str {
298 "expose"
299 }
300 fn supported(&self) -> &[&'static str] {
301 &[
302 "service",
303 "protocol",
304 "directory",
305 "runner",
306 "resolver",
307 "event_stream",
308 "dictionary",
309 "config",
310 ]
311 }
312 fn are_many_names_allowed(&self) -> bool {
313 [
314 "service",
315 "protocol",
316 "directory",
317 "runner",
318 "resolver",
319 "event_stream",
320 "dictionary",
321 "config",
322 ]
323 .contains(&self.capability_type().unwrap())
324 }
325}
326
327#[derive(Deserialize, Debug, PartialEq, Clone)]
328#[serde(deny_unknown_fields)]
329pub struct SpannedExpose {
330 pub service: Option<OneOrMany<Name>>,
332
333 pub protocol: Option<OneOrMany<Name>>,
335
336 pub directory: Option<OneOrMany<Name>>,
338
339 pub runner: Option<OneOrMany<Name>>,
341
342 pub resolver: Option<OneOrMany<Name>>,
344
345 pub dictionary: Option<OneOrMany<Name>>,
347
348 pub config: Option<OneOrMany<Name>>,
350
351 pub from: Spanned<OneOrMany<ExposeFromRef>>,
358
359 pub r#as: Option<Spanned<Name>>,
363
364 pub to: Option<Spanned<ExposeToRef>>,
366
367 pub rights: Option<Spanned<Rights>>,
370
371 pub subdir: Option<Spanned<RelativePath>>,
374
375 pub event_stream: Option<Spanned<OneOrMany<Name>>>,
377
378 pub scope: Option<OneOrMany<EventScope>>,
382
383 pub availability: Option<Availability>,
400
401 pub source_availability: Option<SourceAvailability>,
406}
407
408impl AsClause for SpannedExpose {
409 fn r#as(&self) -> Option<&BorrowedName> {
410 self.r#as.as_ref().map(|spanned_value| {
411 let bounded_name: &BoundedName<255> = spanned_value.as_ref();
412 let borrowed_name: &BorrowedName = bounded_name.as_ref();
413 borrowed_name
414 })
415 }
416}
417
418impl SpannedCapabilityClause for SpannedExpose {
419 fn service(&self) -> Option<OneOrMany<&BorrowedName>> {
420 option_one_or_many_as_ref(&self.service)
421 }
422 fn protocol(&self) -> Option<OneOrMany<&BorrowedName>> {
423 option_one_or_many_as_ref(&self.protocol)
424 }
425 fn directory(&self) -> Option<OneOrMany<&BorrowedName>> {
426 option_one_or_many_as_ref(&self.directory)
427 }
428 fn storage(&self) -> Option<OneOrMany<&BorrowedName>> {
429 None
430 }
431 fn runner(&self) -> Option<OneOrMany<&BorrowedName>> {
432 option_one_or_many_as_ref(&self.runner)
433 }
434 fn resolver(&self) -> Option<OneOrMany<&BorrowedName>> {
435 option_one_or_many_as_ref(&self.resolver)
436 }
437 fn event_stream(&self) -> Option<OneOrMany<&BorrowedName>> {
438 option_spanned_one_or_many_as_ref(&self.event_stream)
439 }
440 fn dictionary(&self) -> Option<OneOrMany<&BorrowedName>> {
441 option_one_or_many_as_ref(&self.dictionary)
442 }
443 fn config(&self) -> Option<OneOrMany<&BorrowedName>> {
444 option_one_or_many_as_ref(&self.config)
445 }
446
447 fn decl_type(&self) -> &'static str {
448 "expose"
449 }
450 fn supported(&self) -> &[&'static str] {
451 &[
452 "service",
453 "protocol",
454 "directory",
455 "runner",
456 "resolver",
457 "event_stream",
458 "dictionary",
459 "config",
460 ]
461 }
462}
463
464#[derive(OneOrMany, Debug, Clone)]
466#[one_or_many(
467 expected = "one or an array of \"framework\", \"self\", \"#<child-name>\", or a dictionary path",
468 inner_type = "ExposeFromRef",
469 min_length = 1,
470 unique_items = true
471)]
472pub struct OneOrManyExposeFromRefs;
473
474#[derive(Debug, PartialEq, Eq, Hash, Clone, Reference)]
476#[reference(expected = "\"framework\", \"self\", \"void\", or \"#<child-name>\"")]
477pub enum ExposeFromRef {
478 Named(Name),
480 Framework,
482 Self_,
484 Void,
486 Dictionary(DictionaryRef),
488}
489
490#[derive(Debug, PartialEq, Eq, Hash, Clone, Reference)]
492#[reference(expected = "\"parent\", \"framework\", or none")]
493pub enum ExposeToRef {
494 Parent,
496 Framework,
498}