1use crate::types::common::*;
6use crate::{
7 AnyRef, Canonicalize, CanonicalizeContext, CapabilityClause, ConfigNestedValueType, ConfigType,
8 DictionaryRef, Error, EventScope, FilterClause, FromClause, FromClauseContext, PathClause,
9};
10
11use crate::one_or_many::{OneOrMany, always_one, always_one_context, option_one_or_many_as_ref};
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::path::PathBuf;
25use std::sync::Arc;
26
27#[derive(Debug, PartialEq, Eq, Hash, Clone, Reference)]
29#[reference(
30 expected = "\"parent\", \"framework\", \"debug\", \"self\", \"#<capability-name>\", \"#<child-name>\", \"#<collection-name>\", dictionary path, or none"
31)]
32pub enum UseFromRef {
33 Parent,
35 Framework,
37 Debug,
39 Named(Name),
51 Self_,
53 Dictionary(DictionaryRef),
55}
56
57#[derive(Deserialize, Debug, Default, PartialEq, Clone, ReferenceDoc, Serialize)]
90#[serde(deny_unknown_fields)]
91#[reference_doc(fields_as = "list", top_level_doc_after_fields)]
92pub struct Use {
93 #[serde(skip_serializing_if = "Option::is_none")]
95 #[reference_doc(skip = true)]
96 pub service: Option<OneOrMany<Name>>,
97
98 #[serde(skip_serializing_if = "Option::is_none")]
100 #[reference_doc(skip = true)]
101 pub protocol: Option<OneOrMany<Name>>,
102
103 #[serde(skip_serializing_if = "Option::is_none")]
105 #[reference_doc(skip = true)]
106 pub directory: Option<Name>,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
110 #[reference_doc(skip = true)]
111 pub storage: Option<Name>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
115 #[reference_doc(skip = true)]
116 pub event_stream: Option<OneOrMany<Name>>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 #[reference_doc(skip = true)]
121 pub runner: Option<Name>,
122
123 #[serde(skip_serializing_if = "Option::is_none")]
125 #[reference_doc(skip = true)]
126 pub config: Option<Name>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
130 #[reference_doc(skip = true)]
131 pub dictionary: Option<OneOrMany<Name>>,
132
133 #[serde(skip_serializing_if = "Option::is_none")]
146 pub from: Option<UseFromRef>,
147
148 #[serde(skip_serializing_if = "Option::is_none")]
152 pub path: Option<Path>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
160 pub numbered_handle: Option<HandleType>,
161
162 #[serde(skip_serializing_if = "Option::is_none")]
165 #[reference_doc(json_type = "array of string")]
166 pub rights: Option<Rights>,
167
168 #[serde(skip_serializing_if = "Option::is_none")]
171 pub subdir: Option<RelativePath>,
172
173 #[serde(skip_serializing_if = "Option::is_none")]
176 pub scope: Option<OneOrMany<EventScope>>,
177
178 #[serde(skip_serializing_if = "Option::is_none")]
182 pub filter: Option<Map<String, Value>>,
183
184 #[serde(skip_serializing_if = "Option::is_none")]
194 pub dependency: Option<DependencyType>,
195
196 #[serde(skip_serializing_if = "Option::is_none")]
210 pub availability: Option<Availability>,
211
212 #[serde(skip_serializing_if = "Option::is_none")]
215 pub key: Option<Name>,
216
217 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
230 #[reference_doc(rename = "type")]
231 pub config_type: Option<ConfigType>,
232
233 #[serde(rename = "max_size", skip_serializing_if = "Option::is_none")]
236 #[reference_doc(rename = "max_size")]
237 pub config_max_size: Option<NonZeroU32>,
238
239 #[serde(rename = "max_count", skip_serializing_if = "Option::is_none")]
242 #[reference_doc(rename = "max_count")]
243 pub config_max_count: Option<NonZeroU32>,
244
245 #[serde(rename = "element", skip_serializing_if = "Option::is_none")]
263 #[reference_doc(rename = "element", json_type = "object")]
264 pub config_element_type: Option<ConfigNestedValueType>,
265
266 #[serde(rename = "default", skip_serializing_if = "Option::is_none")]
270 #[reference_doc(rename = "default")]
271 pub config_default: Option<serde_json::Value>,
272}
273
274impl Canonicalize for Use {
275 fn canonicalize(&mut self) {
276 if let Some(service) = &mut self.service {
278 service.canonicalize();
279 } else if let Some(protocol) = &mut self.protocol {
280 protocol.canonicalize();
281 } else if let Some(event_stream) = &mut self.event_stream {
282 event_stream.canonicalize();
283 if let Some(scope) = &mut self.scope {
284 scope.canonicalize();
285 }
286 }
287 }
288}
289
290impl RightsClause for Use {
291 fn rights(&self) -> Option<&Rights> {
292 self.rights.as_ref()
293 }
294}
295
296impl CapabilityClause for Use {
297 fn service(&self) -> Option<OneOrMany<&BorrowedName>> {
298 option_one_or_many_as_ref(&self.service)
299 }
300 fn protocol(&self) -> Option<OneOrMany<&BorrowedName>> {
301 option_one_or_many_as_ref(&self.protocol)
302 }
303 fn directory(&self) -> Option<OneOrMany<&BorrowedName>> {
304 self.directory.as_ref().map(|n| OneOrMany::One(n.as_ref()))
305 }
306 fn storage(&self) -> Option<OneOrMany<&BorrowedName>> {
307 self.storage.as_ref().map(|n| OneOrMany::One(n.as_ref()))
308 }
309 fn runner(&self) -> Option<OneOrMany<&BorrowedName>> {
310 self.runner.as_ref().map(|n| OneOrMany::One(n.as_ref()))
311 }
312 fn resolver(&self) -> Option<OneOrMany<&BorrowedName>> {
313 None
314 }
315 fn event_stream(&self) -> Option<OneOrMany<&BorrowedName>> {
316 option_one_or_many_as_ref(&self.event_stream)
317 }
318 fn dictionary(&self) -> Option<OneOrMany<&BorrowedName>> {
319 option_one_or_many_as_ref(&self.dictionary)
320 }
321 fn config(&self) -> Option<OneOrMany<&BorrowedName>> {
322 self.config.as_ref().map(|n| OneOrMany::One(n.as_ref()))
323 }
324
325 fn set_service(&mut self, o: Option<OneOrMany<Name>>) {
326 self.service = o;
327 }
328 fn set_protocol(&mut self, o: Option<OneOrMany<Name>>) {
329 self.protocol = o;
330 }
331 fn set_directory(&mut self, o: Option<OneOrMany<Name>>) {
332 self.directory = always_one(o);
333 }
334 fn set_storage(&mut self, o: Option<OneOrMany<Name>>) {
335 self.storage = always_one(o);
336 }
337 fn set_runner(&mut self, _o: Option<OneOrMany<Name>>) {}
338 fn set_resolver(&mut self, _o: Option<OneOrMany<Name>>) {}
339 fn set_event_stream(&mut self, o: Option<OneOrMany<Name>>) {
340 self.event_stream = o;
341 }
342 fn set_dictionary(&mut self, _o: Option<OneOrMany<Name>>) {}
343 fn set_config(&mut self, o: Option<OneOrMany<Name>>) {
344 self.config = always_one(o);
345 }
346
347 fn availability(&self) -> Option<Availability> {
348 self.availability
349 }
350 fn set_availability(&mut self, a: Option<Availability>) {
351 self.availability = a;
352 }
353
354 fn decl_type(&self) -> &'static str {
355 "use"
356 }
357 fn supported(&self) -> &[&'static str] {
358 &[
359 "service",
360 "protocol",
361 "directory",
362 "storage",
363 "event_stream",
364 "runner",
365 "config",
366 "dictionary",
367 ]
368 }
369 fn are_many_names_allowed(&self) -> bool {
370 ["service", "protocol", "event_stream"].contains(&self.capability_type().unwrap())
371 }
372}
373
374impl FilterClause for Use {
375 fn filter(&self) -> Option<&Map<String, Value>> {
376 self.filter.as_ref()
377 }
378}
379
380impl PathClause for Use {
381 fn path(&self) -> Option<&Path> {
382 self.path.as_ref()
383 }
384}
385
386impl FromClause for Use {
387 fn from_(&self) -> OneOrMany<AnyRef<'_>> {
388 let one = match &self.from {
389 Some(from) => AnyRef::from(from),
390 None => AnyRef::Parent,
392 };
393 OneOrMany::One(one)
394 }
395}
396
397#[derive(Debug, Clone, Default, Serialize)]
398pub struct ContextUse {
399 #[serde(skip)]
400 pub origin: Arc<PathBuf>,
401 #[serde(skip_serializing_if = "Option::is_none")]
402 pub service: Option<ContextSpanned<OneOrMany<Name>>>,
403 #[serde(skip_serializing_if = "Option::is_none")]
404 pub protocol: Option<ContextSpanned<OneOrMany<Name>>>,
405 #[serde(skip_serializing_if = "Option::is_none")]
406 pub directory: Option<ContextSpanned<Name>>,
407 #[serde(skip_serializing_if = "Option::is_none")]
408 pub storage: Option<ContextSpanned<Name>>,
409 #[serde(skip_serializing_if = "Option::is_none")]
410 pub event_stream: Option<ContextSpanned<OneOrMany<Name>>>,
411 #[serde(skip_serializing_if = "Option::is_none")]
412 pub runner: Option<ContextSpanned<Name>>,
413 #[serde(skip_serializing_if = "Option::is_none")]
414 pub config: Option<ContextSpanned<Name>>,
415 #[serde(skip_serializing_if = "Option::is_none")]
416 pub dictionary: Option<ContextSpanned<OneOrMany<Name>>>,
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub from: Option<ContextSpanned<UseFromRef>>,
419 #[serde(skip_serializing_if = "Option::is_none")]
420 pub path: Option<ContextSpanned<Path>>,
421 #[serde(skip_serializing_if = "Option::is_none")]
422 pub numbered_handle: Option<ContextSpanned<HandleType>>,
423 #[serde(skip_serializing_if = "Option::is_none")]
424 pub rights: Option<ContextSpanned<Rights>>,
425 #[serde(skip_serializing_if = "Option::is_none")]
426 pub subdir: Option<ContextSpanned<RelativePath>>,
427 #[serde(skip_serializing_if = "Option::is_none")]
428 pub scope: Option<ContextSpanned<OneOrMany<EventScope>>>,
429 #[serde(skip_serializing_if = "Option::is_none")]
430 pub filter: Option<ContextSpanned<Map<String, Value>>>,
431 #[serde(skip_serializing_if = "Option::is_none")]
432 pub dependency: Option<ContextSpanned<DependencyType>>,
433 #[serde(skip_serializing_if = "Option::is_none")]
434 pub availability: Option<ContextSpanned<Availability>>,
435 #[serde(skip_serializing_if = "Option::is_none")]
436 pub key: Option<ContextSpanned<Name>>,
437 #[serde(skip_serializing_if = "Option::is_none")]
438 pub config_type: Option<ContextSpanned<ConfigType>>, #[serde(skip_serializing_if = "Option::is_none")]
440 pub config_max_size: Option<ContextSpanned<NonZeroU32>>,
441 #[serde(skip_serializing_if = "Option::is_none")]
442 pub config_max_count: Option<ContextSpanned<NonZeroU32>>,
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub config_element_type: Option<ContextSpanned<ConfigNestedValueType>>,
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub config_default: Option<ContextSpanned<serde_json::Value>>,
447}
448
449impl ContextCapabilityClause for ContextUse {
450 fn service(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
451 option_one_or_many_as_ref_context(&self.service)
452 }
453 fn protocol(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
454 option_one_or_many_as_ref_context(&self.protocol)
455 }
456 fn directory(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
457 self.directory.as_ref().map(|s| ContextSpanned {
458 value: OneOrMany::One((s.value).as_ref()),
459 origin: s.origin.clone(),
460 })
461 }
462 fn storage(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
463 self.storage.as_ref().map(|s| ContextSpanned {
464 value: OneOrMany::One((s.value).as_ref()),
465 origin: s.origin.clone(),
466 })
467 }
468 fn runner(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
469 self.runner.as_ref().map(|s| ContextSpanned {
470 value: OneOrMany::One((s.value).as_ref()),
471 origin: s.origin.clone(),
472 })
473 }
474 fn resolver(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
475 None
476 }
477 fn event_stream(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
478 option_one_or_many_as_ref_context(&self.event_stream)
479 }
480 fn dictionary(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
481 option_one_or_many_as_ref_context(&self.dictionary)
482 }
483 fn config(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
484 self.config.as_ref().map(|s| ContextSpanned {
485 value: OneOrMany::One((s.value).as_ref()),
486 origin: s.origin.clone(),
487 })
488 }
489
490 fn decl_type(&self) -> &'static str {
491 "use"
492 }
493 fn supported(&self) -> &[&'static str] {
494 &[
495 "service",
496 "protocol",
497 "directory",
498 "storage",
499 "event_stream",
500 "runner",
501 "config",
502 "dictionary",
503 ]
504 }
505
506 fn are_many_names_allowed(&self) -> bool {
507 ["service", "protocol", "event_stream"].contains(&self.capability_type(None).unwrap())
508 }
509
510 fn set_service(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
511 self.service = o;
512 }
513 fn set_protocol(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
514 self.protocol = o;
515 }
516 fn set_directory(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
517 self.directory = always_one_context(o);
518 }
519 fn set_storage(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
520 self.storage = always_one_context(o);
521 }
522 fn set_runner(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
523 fn set_resolver(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
524 fn set_event_stream(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
525 self.event_stream = o;
526 }
527 fn set_dictionary(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
528 fn set_config(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
529 self.config = always_one_context(o);
530 }
531
532 fn origin(&self) -> &Arc<PathBuf> {
533 &self.origin
534 }
535
536 fn availability(&self) -> Option<ContextSpanned<Availability>> {
537 self.availability.clone()
538 }
539 fn set_availability(&mut self, a: Option<ContextSpanned<Availability>>) {
540 self.availability = a;
541 }
542}
543
544impl CanonicalizeContext for ContextUse {
545 fn canonicalize_context(&mut self) {
546 if let Some(service) = &mut self.service {
548 service.value.canonicalize_context();
549 } else if let Some(protocol) = &mut self.protocol {
550 protocol.value.canonicalize_context();
551 } else if let Some(event_stream) = &mut self.event_stream {
552 event_stream.value.canonicalize_context();
553 if let Some(scope) = &mut self.scope {
554 scope.value.canonicalize_context();
555 }
556 }
557 }
558}
559
560impl FromClauseContext for ContextUse {
561 fn from_(&self) -> ContextSpanned<OneOrMany<AnyRef<'_>>> {
562 match &self.from {
563 Some(from) => {
564 return ContextSpanned {
565 value: OneOrMany::One(AnyRef::from(&from.value)),
566 origin: from.origin.clone(),
567 };
568 }
569 None => {
571 return ContextSpanned {
572 value: OneOrMany::One(AnyRef::Parent),
573 origin: self.origin.clone(),
574 };
575 }
576 }
577 }
578}
579
580impl RightsClause for ContextUse {
581 fn rights(&self) -> Option<&Rights> {
582 self.rights.as_ref().map(|r| &r.value)
583 }
584}
585
586impl PartialEq for ContextUse {
587 fn eq(&self, other: &Self) -> bool {
588 macro_rules! cmp {
589 ($field:ident) => {
590 match (&self.$field, &other.$field) {
591 (Some(a), Some(b)) => a.value == b.value,
592 (None, None) => true,
593 _ => false,
594 }
595 };
596 }
597
598 cmp!(service)
599 && cmp!(protocol)
600 && cmp!(directory)
601 && cmp!(storage)
602 && cmp!(event_stream)
603 && cmp!(runner)
604 && cmp!(config)
605 && cmp!(dictionary)
606 && cmp!(from)
607 && cmp!(path)
608 && cmp!(numbered_handle)
609 && cmp!(rights)
610 && cmp!(subdir)
611 && cmp!(scope)
612 && cmp!(filter)
613 && cmp!(dependency)
614 && cmp!(availability)
615 && cmp!(key)
616 && cmp!(config_type)
617 && cmp!(config_max_size)
618 && cmp!(config_max_count)
619 && cmp!(config_element_type)
620 && cmp!(config_default)
621 }
622}
623
624impl Eq for ContextUse {}
625
626impl ContextPathClause for ContextUse {
627 fn path(&self) -> Option<&ContextSpanned<Path>> {
628 self.path.as_ref()
629 }
630}
631
632impl Hydrate for Use {
633 type Output = ContextUse;
634
635 fn hydrate(self, file: &Arc<PathBuf>) -> Result<Self::Output, Error> {
636 Ok(ContextUse {
637 origin: file.clone(),
638 service: hydrate_opt_simple(self.service, file),
639 protocol: hydrate_opt_simple(self.protocol, file),
640 directory: hydrate_opt_simple(self.directory, file),
641 storage: hydrate_opt_simple(self.storage, file),
642 event_stream: hydrate_opt_simple(self.event_stream, file),
643 runner: hydrate_opt_simple(self.runner, file),
644 config: hydrate_opt_simple(self.config, file),
645 dictionary: hydrate_opt_simple(self.dictionary, file),
646 from: hydrate_opt_simple(self.from, file),
647 path: hydrate_opt_simple(self.path, file),
648 numbered_handle: hydrate_opt_simple(self.numbered_handle, file),
649 rights: hydrate_opt_simple(self.rights, file),
650 subdir: hydrate_opt_simple(self.subdir, file),
651 scope: hydrate_opt_simple(self.scope, file),
652 filter: hydrate_opt_simple(self.filter, file),
653 dependency: hydrate_opt_simple(self.dependency, file),
654 availability: hydrate_opt_simple(self.availability, file),
655 key: hydrate_opt_simple(self.key, file),
656 config_type: hydrate_opt_simple(self.config_type, file),
657 config_max_size: hydrate_opt_simple(self.config_max_size, file),
658 config_max_count: hydrate_opt_simple(self.config_max_count, file),
659 config_element_type: hydrate_opt_simple(self.config_element_type, file),
660 config_default: hydrate_opt_simple(self.config_default, file),
661 })
662 }
663}