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::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
274#[derive(Debug, Clone, Default, Serialize)]
275pub struct ContextUse {
276 #[serde(skip)]
277 pub origin: Arc<PathBuf>,
278
279 #[serde(skip_serializing_if = "Option::is_none")]
280 pub service: Option<ContextSpanned<OneOrMany<Name>>>,
281
282 #[serde(skip_serializing_if = "Option::is_none")]
283 pub protocol: Option<ContextSpanned<OneOrMany<Name>>>,
284
285 #[serde(skip_serializing_if = "Option::is_none")]
286 pub directory: Option<ContextSpanned<Name>>,
287
288 #[serde(skip_serializing_if = "Option::is_none")]
289 pub storage: Option<ContextSpanned<Name>>,
290
291 #[serde(skip_serializing_if = "Option::is_none")]
292 pub event_stream: Option<ContextSpanned<OneOrMany<Name>>>,
293
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub runner: Option<ContextSpanned<Name>>,
296
297 #[serde(skip_serializing_if = "Option::is_none")]
298 pub config: Option<ContextSpanned<Name>>,
299
300 #[serde(skip_serializing_if = "Option::is_none")]
301 pub dictionary: Option<ContextSpanned<OneOrMany<Name>>>,
302
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub from: Option<ContextSpanned<UseFromRef>>,
305
306 #[serde(skip_serializing_if = "Option::is_none")]
307 pub path: Option<ContextSpanned<Path>>,
308
309 #[serde(skip_serializing_if = "Option::is_none")]
310 pub numbered_handle: Option<ContextSpanned<HandleType>>,
311
312 #[serde(skip_serializing_if = "Option::is_none")]
313 pub rights: Option<ContextSpanned<Rights>>,
314
315 #[serde(skip_serializing_if = "Option::is_none")]
316 pub subdir: Option<ContextSpanned<RelativePath>>,
317
318 #[serde(skip_serializing_if = "Option::is_none")]
319 pub scope: Option<ContextSpanned<OneOrMany<EventScope>>>,
320
321 #[serde(skip_serializing_if = "Option::is_none")]
322 pub filter: Option<ContextSpanned<Map<String, Value>>>,
323
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub dependency: Option<ContextSpanned<DependencyType>>,
326
327 #[serde(skip_serializing_if = "Option::is_none")]
328 pub availability: Option<ContextSpanned<Availability>>,
329
330 #[serde(skip_serializing_if = "Option::is_none")]
331 pub key: Option<ContextSpanned<Name>>,
332
333 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
334 pub config_type: Option<ContextSpanned<ConfigType>>,
335
336 #[serde(rename = "max_size", skip_serializing_if = "Option::is_none")]
337 pub config_max_size: Option<ContextSpanned<NonZeroU32>>,
338
339 #[serde(rename = "max_count", skip_serializing_if = "Option::is_none")]
340 pub config_max_count: Option<ContextSpanned<NonZeroU32>>,
341
342 #[serde(rename = "element", skip_serializing_if = "Option::is_none")]
343 pub config_element_type: Option<ContextSpanned<ConfigNestedValueType>>,
344
345 #[serde(rename = "default", skip_serializing_if = "Option::is_none")]
346 pub config_default: Option<ContextSpanned<serde_json::Value>>,
347}
348
349impl ContextCapabilityClause for ContextUse {
350 fn service(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
351 option_one_or_many_as_ref_context(&self.service)
352 }
353 fn protocol(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
354 option_one_or_many_as_ref_context(&self.protocol)
355 }
356 fn directory(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
357 self.directory.as_ref().map(|s| ContextSpanned {
358 value: OneOrMany::One((s.value).as_ref()),
359 origin: s.origin.clone(),
360 })
361 }
362 fn storage(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
363 self.storage.as_ref().map(|s| ContextSpanned {
364 value: OneOrMany::One((s.value).as_ref()),
365 origin: s.origin.clone(),
366 })
367 }
368 fn runner(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
369 self.runner.as_ref().map(|s| ContextSpanned {
370 value: OneOrMany::One((s.value).as_ref()),
371 origin: s.origin.clone(),
372 })
373 }
374 fn resolver(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
375 None
376 }
377 fn event_stream(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
378 option_one_or_many_as_ref_context(&self.event_stream)
379 }
380 fn dictionary(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
381 option_one_or_many_as_ref_context(&self.dictionary)
382 }
383 fn config(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
384 self.config.as_ref().map(|s| ContextSpanned {
385 value: OneOrMany::One((s.value).as_ref()),
386 origin: s.origin.clone(),
387 })
388 }
389
390 fn decl_type(&self) -> &'static str {
391 "use"
392 }
393 fn supported(&self) -> &[&'static str] {
394 &[
395 "service",
396 "protocol",
397 "directory",
398 "storage",
399 "event_stream",
400 "runner",
401 "config",
402 "dictionary",
403 ]
404 }
405
406 fn are_many_names_allowed(&self) -> bool {
407 ["service", "protocol", "event_stream"].contains(&self.capability_type(None).unwrap())
408 }
409
410 fn set_service(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
411 self.service = o;
412 }
413 fn set_protocol(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
414 self.protocol = o;
415 }
416 fn set_directory(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
417 self.directory = always_one_context(o);
418 }
419 fn set_storage(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
420 self.storage = always_one_context(o);
421 }
422 fn set_runner(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
423 fn set_resolver(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
424 fn set_event_stream(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
425 self.event_stream = o;
426 }
427 fn set_dictionary(&mut self, _o: Option<ContextSpanned<OneOrMany<Name>>>) {}
428 fn set_config(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
429 self.config = always_one_context(o);
430 }
431
432 fn origin(&self) -> &Arc<PathBuf> {
433 &self.origin
434 }
435
436 fn availability(&self) -> Option<ContextSpanned<Availability>> {
437 self.availability.clone()
438 }
439 fn set_availability(&mut self, a: Option<ContextSpanned<Availability>>) {
440 self.availability = a;
441 }
442}
443
444impl CanonicalizeContext for ContextUse {
445 fn canonicalize_context(&mut self) {
446 if let Some(service) = &mut self.service {
448 service.value.canonicalize_context();
449 } else if let Some(protocol) = &mut self.protocol {
450 protocol.value.canonicalize_context();
451 } else if let Some(event_stream) = &mut self.event_stream {
452 event_stream.value.canonicalize_context();
453 if let Some(scope) = &mut self.scope {
454 scope.value.canonicalize_context();
455 }
456 }
457 }
458}
459
460impl FromClauseContext for ContextUse {
461 fn from_(&self) -> ContextSpanned<OneOrMany<AnyRef<'_>>> {
462 match &self.from {
463 Some(from) => {
464 return ContextSpanned {
465 value: OneOrMany::One(AnyRef::from(&from.value)),
466 origin: from.origin.clone(),
467 };
468 }
469 None => {
471 return ContextSpanned {
472 value: OneOrMany::One(AnyRef::Parent),
473 origin: self.origin.clone(),
474 };
475 }
476 }
477 }
478}
479
480impl RightsClause for ContextUse {
481 fn rights(&self) -> Option<&Rights> {
482 self.rights.as_ref().map(|r| &r.value)
483 }
484}
485
486impl PartialEq for ContextUse {
487 fn eq(&self, other: &Self) -> bool {
488 macro_rules! cmp {
489 ($field:ident) => {
490 match (&self.$field, &other.$field) {
491 (Some(a), Some(b)) => a.value == b.value,
492 (None, None) => true,
493 _ => false,
494 }
495 };
496 }
497
498 cmp!(service)
499 && cmp!(protocol)
500 && cmp!(directory)
501 && cmp!(storage)
502 && cmp!(event_stream)
503 && cmp!(runner)
504 && cmp!(config)
505 && cmp!(dictionary)
506 && cmp!(from)
507 && cmp!(path)
508 && cmp!(numbered_handle)
509 && cmp!(rights)
510 && cmp!(subdir)
511 && cmp!(scope)
512 && cmp!(filter)
513 && cmp!(dependency)
514 && cmp!(availability)
515 && cmp!(key)
516 && cmp!(config_type)
517 && cmp!(config_max_size)
518 && cmp!(config_max_count)
519 && cmp!(config_element_type)
520 && cmp!(config_default)
521 }
522}
523
524impl Eq for ContextUse {}
525
526impl ContextPathClause for ContextUse {
527 fn path(&self) -> Option<&ContextSpanned<Path>> {
528 self.path.as_ref()
529 }
530}
531
532impl Hydrate for Use {
533 type Output = ContextUse;
534
535 fn hydrate(self, file: &Arc<PathBuf>) -> Result<Self::Output, Error> {
536 Ok(ContextUse {
537 origin: file.clone(),
538 service: hydrate_opt_simple(self.service, file),
539 protocol: hydrate_opt_simple(self.protocol, file),
540 directory: hydrate_opt_simple(self.directory, file),
541 storage: hydrate_opt_simple(self.storage, file),
542 event_stream: hydrate_opt_simple(self.event_stream, file),
543 runner: hydrate_opt_simple(self.runner, file),
544 config: hydrate_opt_simple(self.config, file),
545 dictionary: hydrate_opt_simple(self.dictionary, file),
546 from: hydrate_opt_simple(self.from, file),
547 path: hydrate_opt_simple(self.path, file),
548 numbered_handle: hydrate_opt_simple(self.numbered_handle, file),
549 rights: hydrate_opt_simple(self.rights, file),
550 subdir: hydrate_opt_simple(self.subdir, file),
551 scope: hydrate_opt_simple(self.scope, file),
552 filter: hydrate_opt_simple(self.filter, file),
553 dependency: hydrate_opt_simple(self.dependency, file),
554 availability: hydrate_opt_simple(self.availability, file),
555 key: hydrate_opt_simple(self.key, file),
556 config_type: hydrate_opt_simple(self.config_type, file),
557 config_max_size: hydrate_opt_simple(self.config_max_size, file),
558 config_max_count: hydrate_opt_simple(self.config_max_count, file),
559 config_element_type: hydrate_opt_simple(self.config_element_type, file),
560 config_default: hydrate_opt_simple(self.config_default, file),
561 })
562 }
563}