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