1use crate::types::common::*;
6use crate::{
7 AnyRef, CanonicalizeContext, ConfigNestedValueType, ConfigType, DictionaryRef, Error,
8 EventScope, FromClauseContext,
9};
10
11use crate::one_or_many::{OneOrMany, always_one_context};
12use crate::types::right::{Rights, RightsClause};
13pub use cm_types::{
14 Availability, BorrowedName, DependencyType, HandleType, Name, OnTerminate, ParseError, Path,
15 RelativePath, StartupMode, Url,
16};
17use cml_macro::Reference;
18use reference_doc::ReferenceDoc;
19use serde::{Deserialize, Serialize};
20use serde_json::{Map, Value};
21use std::num::NonZeroU32;
22
23use std::fmt;
24use std::sync::Arc;
25
26#[derive(Debug, PartialEq, Eq, Hash, Clone, Reference)]
28#[reference(
29 expected = "\"parent\", \"framework\", \"debug\", \"self\", \"#<capability-name>\", \"#<child-name>\", \"#<collection-name>\", dictionary path, or none"
30)]
31pub enum UseFromRef {
32 Parent,
34 Framework,
36 Debug,
38 Named(Name),
50 Self_,
52 Dictionary(DictionaryRef),
54}
55
56#[derive(Deserialize, Debug, Default, PartialEq, Clone, ReferenceDoc, Serialize)]
89#[serde(deny_unknown_fields)]
90#[reference_doc(fields_as = "list", top_level_doc_after_fields)]
91pub struct Use {
92 #[serde(skip_serializing_if = "Option::is_none")]
94 #[reference_doc(skip = true)]
95 pub service: Option<OneOrMany<Name>>,
96
97 #[serde(skip_serializing_if = "Option::is_none")]
99 #[reference_doc(skip = true)]
100 pub protocol: Option<OneOrMany<Name>>,
101
102 #[serde(skip_serializing_if = "Option::is_none")]
104 #[reference_doc(skip = true)]
105 pub directory: Option<Name>,
106
107 #[serde(skip_serializing_if = "Option::is_none")]
109 #[reference_doc(skip = true)]
110 pub storage: Option<Name>,
111
112 #[serde(skip_serializing_if = "Option::is_none")]
114 #[reference_doc(skip = true)]
115 pub event_stream: Option<OneOrMany<Name>>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 #[reference_doc(skip = true)]
120 pub runner: Option<Name>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
124 #[reference_doc(skip = true)]
125 pub config: Option<Name>,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
129 #[reference_doc(skip = true)]
130 pub dictionary: Option<OneOrMany<Name>>,
131
132 #[serde(skip_serializing_if = "Option::is_none")]
145 pub from: Option<UseFromRef>,
146
147 #[serde(skip_serializing_if = "Option::is_none")]
151 pub path: Option<Path>,
152
153 #[serde(skip_serializing_if = "Option::is_none")]
159 pub numbered_handle: Option<HandleType>,
160
161 #[serde(skip_serializing_if = "Option::is_none")]
164 #[reference_doc(json_type = "array of string")]
165 pub rights: Option<Rights>,
166
167 #[serde(skip_serializing_if = "Option::is_none")]
170 pub subdir: Option<RelativePath>,
171
172 #[serde(skip_serializing_if = "Option::is_none")]
175 pub scope: Option<OneOrMany<EventScope>>,
176
177 #[serde(skip_serializing_if = "Option::is_none")]
181 pub filter: Option<Map<String, Value>>,
182
183 #[serde(skip_serializing_if = "Option::is_none")]
193 pub dependency: Option<DependencyType>,
194
195 #[serde(skip_serializing_if = "Option::is_none")]
209 pub availability: Option<Availability>,
210
211 #[serde(skip_serializing_if = "Option::is_none")]
214 pub key: Option<Name>,
215
216 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
229 #[reference_doc(rename = "type")]
230 pub config_type: Option<ConfigType>,
231
232 #[serde(rename = "max_size", skip_serializing_if = "Option::is_none")]
235 #[reference_doc(rename = "max_size")]
236 pub config_max_size: Option<NonZeroU32>,
237
238 #[serde(rename = "max_count", skip_serializing_if = "Option::is_none")]
241 #[reference_doc(rename = "max_count")]
242 pub config_max_count: Option<NonZeroU32>,
243
244 #[serde(rename = "element", skip_serializing_if = "Option::is_none")]
262 #[reference_doc(rename = "element", json_type = "object")]
263 pub config_element_type: Option<ConfigNestedValueType>,
264
265 #[serde(rename = "default", skip_serializing_if = "Option::is_none")]
269 #[reference_doc(rename = "default")]
270 pub config_default: Option<serde_json::Value>,
271}
272
273#[derive(Debug, Clone, Serialize)]
274pub struct ContextUse {
275 #[serde(skip)]
276 pub origin: Arc<std::path::Path>,
277
278 #[serde(skip_serializing_if = "Option::is_none")]
279 pub service: Option<ContextSpanned<OneOrMany<Name>>>,
280
281 #[serde(skip_serializing_if = "Option::is_none")]
282 pub protocol: Option<ContextSpanned<OneOrMany<Name>>>,
283
284 #[serde(skip_serializing_if = "Option::is_none")]
285 pub directory: Option<ContextSpanned<Name>>,
286
287 #[serde(skip_serializing_if = "Option::is_none")]
288 pub storage: Option<ContextSpanned<Name>>,
289
290 #[serde(skip_serializing_if = "Option::is_none")]
291 pub event_stream: Option<ContextSpanned<OneOrMany<Name>>>,
292
293 #[serde(skip_serializing_if = "Option::is_none")]
294 pub runner: Option<ContextSpanned<Name>>,
295
296 #[serde(skip_serializing_if = "Option::is_none")]
297 pub config: Option<ContextSpanned<Name>>,
298
299 #[serde(skip_serializing_if = "Option::is_none")]
300 pub dictionary: Option<ContextSpanned<OneOrMany<Name>>>,
301
302 #[serde(skip_serializing_if = "Option::is_none")]
303 pub from: Option<ContextSpanned<UseFromRef>>,
304
305 #[serde(skip_serializing_if = "Option::is_none")]
306 pub path: Option<ContextSpanned<Path>>,
307
308 #[serde(skip_serializing_if = "Option::is_none")]
309 pub numbered_handle: Option<ContextSpanned<HandleType>>,
310
311 #[serde(skip_serializing_if = "Option::is_none")]
312 pub rights: Option<ContextSpanned<Rights>>,
313
314 #[serde(skip_serializing_if = "Option::is_none")]
315 pub subdir: Option<ContextSpanned<RelativePath>>,
316
317 #[serde(skip_serializing_if = "Option::is_none")]
318 pub scope: Option<ContextSpanned<OneOrMany<EventScope>>>,
319
320 #[serde(skip_serializing_if = "Option::is_none")]
321 pub filter: Option<ContextSpanned<Map<String, Value>>>,
322
323 #[serde(skip_serializing_if = "Option::is_none")]
324 pub dependency: Option<ContextSpanned<DependencyType>>,
325
326 #[serde(skip_serializing_if = "Option::is_none")]
327 pub availability: Option<ContextSpanned<Availability>>,
328
329 #[serde(skip_serializing_if = "Option::is_none")]
330 pub key: Option<ContextSpanned<Name>>,
331
332 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
333 pub config_type: Option<ContextSpanned<ConfigType>>,
334
335 #[serde(rename = "max_size", skip_serializing_if = "Option::is_none")]
336 pub config_max_size: Option<ContextSpanned<NonZeroU32>>,
337
338 #[serde(rename = "max_count", skip_serializing_if = "Option::is_none")]
339 pub config_max_count: Option<ContextSpanned<NonZeroU32>>,
340
341 #[serde(rename = "element", skip_serializing_if = "Option::is_none")]
342 pub config_element_type: Option<ContextSpanned<ConfigNestedValueType>>,
343
344 #[serde(rename = "default", skip_serializing_if = "Option::is_none")]
345 pub config_default: Option<ContextSpanned<serde_json::Value>>,
346}
347
348impl ContextCapabilityClause for ContextUse {
349 fn service(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
350 option_one_or_many_as_ref_context(&self.service)
351 }
352 fn protocol(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
353 option_one_or_many_as_ref_context(&self.protocol)
354 }
355 fn directory(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
356 self.directory.as_ref().map(|s| ContextSpanned {
357 value: OneOrMany::One((s.value).as_ref()),
358 origin: s.origin.clone(),
359 })
360 }
361 fn storage(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
362 self.storage.as_ref().map(|s| ContextSpanned {
363 value: OneOrMany::One((s.value).as_ref()),
364 origin: s.origin.clone(),
365 })
366 }
367 fn runner(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
368 self.runner.as_ref().map(|s| ContextSpanned {
369 value: OneOrMany::One((s.value).as_ref()),
370 origin: s.origin.clone(),
371 })
372 }
373 fn resolver(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
374 None
375 }
376 fn event_stream(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
377 option_one_or_many_as_ref_context(&self.event_stream)
378 }
379 fn dictionary(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
380 option_one_or_many_as_ref_context(&self.dictionary)
381 }
382 fn config(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
383 self.config.as_ref().map(|s| ContextSpanned {
384 value: OneOrMany::One((s.value).as_ref()),
385 origin: s.origin.clone(),
386 })
387 }
388
389 fn decl_type(&self) -> &'static str {
390 "use"
391 }
392 fn supported(&self) -> &[&'static str] {
393 &[
394 "service",
395 "protocol",
396 "directory",
397 "storage",
398 "event_stream",
399 "runner",
400 "config",
401 "dictionary",
402 ]
403 }
404
405 fn are_many_names_allowed(&self) -> bool {
406 ["service", "protocol", "event_stream"].contains(&self.capability_type(None).unwrap())
407 }
408
409 fn set_service(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
410 self.service = o;
411 }
412 fn set_protocol(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
413 self.protocol = o;
414 }
415 fn set_directory(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
416 self.directory = always_one_context(o);
417 }
418 fn set_storage(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
419 self.storage = always_one_context(o);
420 }
421 fn set_runner(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
422 fn set_resolver(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
423 fn set_event_stream(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
424 self.event_stream = o;
425 }
426 fn set_dictionary(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
427 fn set_config(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
428 self.config = always_one_context(o);
429 }
430
431 fn origin(&self) -> &Arc<std::path::Path> {
432 &self.origin
433 }
434
435 fn availability(&self) -> Option<ContextSpanned<Availability>> {
436 self.availability.clone()
437 }
438 fn set_availability(&mut self, a: Option<ContextSpanned<Availability>>) {
439 self.availability = a;
440 }
441}
442
443impl CanonicalizeContext for ContextUse {
444 fn canonicalize_context(&mut self) {
445 if let Some(service) = &mut self.service {
447 service.value.canonicalize_context();
448 } else if let Some(protocol) = &mut self.protocol {
449 protocol.value.canonicalize_context();
450 } else if let Some(event_stream) = &mut self.event_stream {
451 event_stream.value.canonicalize_context();
452 if let Some(scope) = &mut self.scope {
453 scope.value.canonicalize_context();
454 }
455 }
456 }
457}
458
459impl FromClauseContext for ContextUse {
460 fn from_(&self) -> ContextSpanned<OneOrMany<AnyRef<'_>>> {
461 match &self.from {
462 Some(from) => {
463 return ContextSpanned {
464 value: OneOrMany::One(AnyRef::from(&from.value)),
465 origin: from.origin.clone(),
466 };
467 }
468 None => {
470 return ContextSpanned {
471 value: OneOrMany::One(AnyRef::Parent),
472 origin: self.origin.clone(),
473 };
474 }
475 }
476 }
477}
478
479impl RightsClause for ContextUse {
480 fn rights(&self) -> Option<&Rights> {
481 self.rights.as_ref().map(|r| &r.value)
482 }
483}
484
485impl PartialEq for ContextUse {
486 fn eq(&self, other: &Self) -> bool {
487 macro_rules! cmp {
488 ($field:ident) => {
489 match (&self.$field, &other.$field) {
490 (Some(a), Some(b)) => a.value == b.value,
491 (None, None) => true,
492 _ => false,
493 }
494 };
495 }
496
497 cmp!(service)
498 && cmp!(protocol)
499 && cmp!(directory)
500 && cmp!(storage)
501 && cmp!(event_stream)
502 && cmp!(runner)
503 && cmp!(config)
504 && cmp!(dictionary)
505 && cmp!(from)
506 && cmp!(path)
507 && cmp!(numbered_handle)
508 && cmp!(rights)
509 && cmp!(subdir)
510 && cmp!(scope)
511 && cmp!(filter)
512 && cmp!(dependency)
513 && cmp!(availability)
514 && cmp!(key)
515 && cmp!(config_type)
516 && cmp!(config_max_size)
517 && cmp!(config_max_count)
518 && cmp!(config_element_type)
519 && cmp!(config_default)
520 }
521}
522
523impl Eq for ContextUse {}
524
525impl Default for ContextUse {
526 fn default() -> Self {
527 let synthetic_origin: Arc<std::path::Path> = Arc::from(std::path::Path::new("synthetic"));
528
529 Self {
530 origin: synthetic_origin,
531 service: None,
532 protocol: None,
533 directory: None,
534 storage: None,
535 event_stream: None,
536 runner: None,
537 config: None,
538 dictionary: None,
539 from: None,
540 path: None,
541 numbered_handle: None,
542 rights: None,
543 subdir: None,
544 scope: None,
545 filter: None,
546 dependency: None,
547 availability: None,
548 key: None,
549 config_type: None,
550 config_max_size: None,
551 config_max_count: None,
552 config_element_type: None,
553 config_default: None,
554 }
555 }
556}
557
558impl ContextPathClause for ContextUse {
559 fn path(&self) -> Option<&ContextSpanned<Path>> {
560 self.path.as_ref()
561 }
562}
563
564impl Hydrate for Use {
565 type Output = ContextUse;
566
567 fn hydrate(self, file: &Arc<std::path::Path>) -> Result<Self::Output, Error> {
568 Ok(ContextUse {
569 origin: file.clone(),
570 service: hydrate_opt_simple(self.service, file),
571 protocol: hydrate_opt_simple(self.protocol, file),
572 directory: hydrate_opt_simple(self.directory, file),
573 storage: hydrate_opt_simple(self.storage, file),
574 event_stream: hydrate_opt_simple(self.event_stream, file),
575 runner: hydrate_opt_simple(self.runner, file),
576 config: hydrate_opt_simple(self.config, file),
577 dictionary: hydrate_opt_simple(self.dictionary, file),
578 from: hydrate_opt_simple(self.from, file),
579 path: hydrate_opt_simple(self.path, file),
580 numbered_handle: hydrate_opt_simple(self.numbered_handle, file),
581 rights: hydrate_opt_simple(self.rights, file),
582 subdir: hydrate_opt_simple(self.subdir, file),
583 scope: hydrate_opt_simple(self.scope, file),
584 filter: hydrate_opt_simple(self.filter, file),
585 dependency: hydrate_opt_simple(self.dependency, file),
586 availability: hydrate_opt_simple(self.availability, file),
587 key: hydrate_opt_simple(self.key, file),
588 config_type: hydrate_opt_simple(self.config_type, file),
589 config_max_size: hydrate_opt_simple(self.config_max_size, file),
590 config_max_count: hydrate_opt_simple(self.config_max_count, file),
591 config_element_type: hydrate_opt_simple(self.config_element_type, file),
592 config_default: hydrate_opt_simple(self.config_default, file),
593 })
594 }
595}