1use crate::{
6 AnyRef, AsClause, AsClauseContext, Canonicalize, CanonicalizeContext, CapabilityClause,
7 ConfigNestedValueType, ConfigType, Error, FilterClause, PathClause,
8};
9
10use crate::one_or_many::{OneOrMany, always_one, always_one_context, option_one_or_many_as_ref};
11use crate::types::common::*;
12use crate::types::right::{Rights, RightsClause};
13pub use cm_types::{
14 Availability, BorrowedName, BoundedName, DeliveryType, DependencyType, HandleType, Name,
15 OnTerminate, ParseError, Path, RelativePath, StartupMode, StorageId, 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(Deserialize, Debug, PartialEq, Clone, ReferenceDoc, Serialize, Default)]
28#[serde(deny_unknown_fields)]
29#[reference_doc(fields_as = "list")]
30pub struct Capability {
31 #[serde(skip_serializing_if = "Option::is_none")]
34 #[reference_doc(skip = true)]
35 pub service: Option<OneOrMany<Name>>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
40 #[reference_doc(skip = true)]
41 pub protocol: Option<OneOrMany<Name>>,
42
43 #[serde(skip_serializing_if = "Option::is_none")]
45 #[reference_doc(skip = true)]
46 pub directory: Option<Name>,
47
48 #[serde(skip_serializing_if = "Option::is_none")]
50 #[reference_doc(skip = true)]
51 pub storage: Option<Name>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 #[reference_doc(skip = true)]
56 pub runner: Option<Name>,
57
58 #[serde(skip_serializing_if = "Option::is_none")]
60 #[reference_doc(skip = true)]
61 pub resolver: Option<Name>,
62
63 #[serde(skip_serializing_if = "Option::is_none")]
65 #[reference_doc(skip = true)]
66 pub event_stream: Option<OneOrMany<Name>>,
67
68 #[serde(skip_serializing_if = "Option::is_none")]
70 #[reference_doc(skip = true)]
71 pub dictionary: Option<Name>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 #[reference_doc(skip = true)]
76 pub config: Option<Name>,
77
78 #[serde(skip_serializing_if = "Option::is_none")]
100 pub path: Option<Path>,
101
102 #[serde(skip_serializing_if = "Option::is_none")]
105 #[reference_doc(json_type = "array of string")]
106 pub rights: Option<Rights>,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
115 pub from: Option<CapabilityFromRef>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
120 pub backing_dir: Option<Name>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
125 pub subdir: Option<RelativePath>,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
136 pub storage_id: Option<StorageId>,
137
138 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
151 #[reference_doc(rename = "type")]
152 pub config_type: Option<ConfigType>,
153
154 #[serde(rename = "max_size", skip_serializing_if = "Option::is_none")]
157 #[reference_doc(rename = "max_size")]
158 pub config_max_size: Option<NonZeroU32>,
159
160 #[serde(rename = "max_count", skip_serializing_if = "Option::is_none")]
163 #[reference_doc(rename = "max_count")]
164 pub config_max_count: Option<NonZeroU32>,
165
166 #[serde(rename = "element", skip_serializing_if = "Option::is_none")]
184 #[reference_doc(rename = "element", json_type = "object")]
185 pub config_element_type: Option<ConfigNestedValueType>,
186
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub value: Option<serde_json::Value>,
190
191 #[serde(skip_serializing_if = "Option::is_none")]
201 pub delivery: Option<DeliveryType>,
202}
203
204impl Canonicalize for Capability {
205 fn canonicalize(&mut self) {
206 if let Some(service) = &mut self.service {
208 service.canonicalize()
209 } else if let Some(protocol) = &mut self.protocol {
210 protocol.canonicalize()
211 } else if let Some(event_stream) = &mut self.event_stream {
212 event_stream.canonicalize()
213 }
214 }
215}
216
217impl AsClause for Capability {
218 fn r#as(&self) -> Option<&BorrowedName> {
219 None
220 }
221}
222
223impl PathClause for Capability {
224 fn path(&self) -> Option<&Path> {
225 self.path.as_ref()
226 }
227}
228
229impl FilterClause for Capability {
230 fn filter(&self) -> Option<&Map<String, Value>> {
231 None
232 }
233}
234
235impl RightsClause for Capability {
236 fn rights(&self) -> Option<&Rights> {
237 self.rights.as_ref()
238 }
239}
240
241impl CapabilityClause for Capability {
242 fn service(&self) -> Option<OneOrMany<&BorrowedName>> {
243 option_one_or_many_as_ref(&self.service)
244 }
245 fn protocol(&self) -> Option<OneOrMany<&BorrowedName>> {
246 option_one_or_many_as_ref(&self.protocol)
247 }
248 fn directory(&self) -> Option<OneOrMany<&BorrowedName>> {
249 self.directory.as_ref().map(|n| OneOrMany::One(n.as_ref()))
250 }
251 fn storage(&self) -> Option<OneOrMany<&BorrowedName>> {
252 self.storage.as_ref().map(|n| OneOrMany::One(n.as_ref()))
253 }
254 fn runner(&self) -> Option<OneOrMany<&BorrowedName>> {
255 self.runner.as_ref().map(|n| OneOrMany::One(n.as_ref()))
256 }
257 fn resolver(&self) -> Option<OneOrMany<&BorrowedName>> {
258 self.resolver.as_ref().map(|n| OneOrMany::One(n.as_ref()))
259 }
260 fn event_stream(&self) -> Option<OneOrMany<&BorrowedName>> {
261 option_one_or_many_as_ref(&self.event_stream)
262 }
263 fn dictionary(&self) -> Option<OneOrMany<&BorrowedName>> {
264 self.dictionary.as_ref().map(|n| OneOrMany::One(n.as_ref()))
265 }
266 fn config(&self) -> Option<OneOrMany<&BorrowedName>> {
267 self.config.as_ref().map(|n| OneOrMany::One(n.as_ref()))
268 }
269
270 fn set_service(&mut self, o: Option<OneOrMany<Name>>) {
271 self.service = o;
272 }
273 fn set_protocol(&mut self, o: Option<OneOrMany<Name>>) {
274 self.protocol = o;
275 }
276 fn set_directory(&mut self, o: Option<OneOrMany<Name>>) {
277 self.directory = always_one(o);
278 }
279 fn set_storage(&mut self, o: Option<OneOrMany<Name>>) {
280 self.storage = always_one(o);
281 }
282 fn set_runner(&mut self, o: Option<OneOrMany<Name>>) {
283 self.runner = always_one(o);
284 }
285 fn set_resolver(&mut self, o: Option<OneOrMany<Name>>) {
286 self.resolver = always_one(o);
287 }
288 fn set_event_stream(&mut self, o: Option<OneOrMany<Name>>) {
289 self.event_stream = o;
290 }
291 fn set_dictionary(&mut self, o: Option<OneOrMany<Name>>) {
292 self.dictionary = always_one(o);
293 }
294
295 fn set_config(&mut self, o: Option<OneOrMany<Name>>) {
296 self.config = always_one(o);
297 }
298
299 fn availability(&self) -> Option<Availability> {
300 None
301 }
302 fn set_availability(&mut self, _a: Option<Availability>) {}
303
304 fn decl_type(&self) -> &'static str {
305 "capability"
306 }
307 fn supported(&self) -> &[&'static str] {
308 &[
309 "service",
310 "protocol",
311 "directory",
312 "storage",
313 "runner",
314 "resolver",
315 "event_stream",
316 "dictionary",
317 "config",
318 ]
319 }
320 fn are_many_names_allowed(&self) -> bool {
321 ["service", "protocol", "event_stream"].contains(&self.capability_type().unwrap())
322 }
323}
324
325#[derive(Debug, PartialEq, Eq, Hash, Clone, Reference)]
327#[reference(expected = "\"parent\", \"self\", or \"#<child-name>\"")]
328pub enum CapabilityFromRef {
329 Named(Name),
331 Parent,
333 Self_,
335}
336
337#[derive(Debug, Clone, Serialize)]
338pub struct ContextCapability {
339 #[serde(skip)]
340 pub origin: Arc<PathBuf>,
341 #[serde(skip_serializing_if = "Option::is_none")]
342 pub service: Option<ContextSpanned<OneOrMany<Name>>>,
343 #[serde(skip_serializing_if = "Option::is_none")]
344 pub protocol: Option<ContextSpanned<OneOrMany<Name>>>,
345 #[serde(skip_serializing_if = "Option::is_none")]
346 pub directory: Option<ContextSpanned<Name>>,
347 #[serde(skip_serializing_if = "Option::is_none")]
348 pub storage: Option<ContextSpanned<Name>>,
349 #[serde(skip_serializing_if = "Option::is_none")]
350 pub runner: Option<ContextSpanned<Name>>,
351 #[serde(skip_serializing_if = "Option::is_none")]
352 pub resolver: Option<ContextSpanned<Name>>,
353 #[serde(skip_serializing_if = "Option::is_none")]
354 pub event_stream: Option<ContextSpanned<OneOrMany<Name>>>,
355 #[serde(skip_serializing_if = "Option::is_none")]
356 pub dictionary: Option<ContextSpanned<Name>>,
357 #[serde(skip_serializing_if = "Option::is_none")]
358 pub config: Option<ContextSpanned<Name>>,
359 #[serde(skip_serializing_if = "Option::is_none")]
360 pub path: Option<ContextSpanned<Path>>,
361 #[serde(skip_serializing_if = "Option::is_none")]
362 pub rights: Option<ContextSpanned<Rights>>,
363 #[serde(skip_serializing_if = "Option::is_none")]
364 pub from: Option<ContextSpanned<CapabilityFromRef>>,
365 #[serde(skip_serializing_if = "Option::is_none")]
366 pub backing_dir: Option<ContextSpanned<Name>>,
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub subdir: Option<ContextSpanned<RelativePath>>,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub storage_id: Option<ContextSpanned<StorageId>>,
371 #[serde(skip_serializing_if = "Option::is_none")]
372 pub config_type: Option<ContextSpanned<ConfigType>>,
373 #[serde(skip_serializing_if = "Option::is_none")]
374 pub config_max_size: Option<ContextSpanned<NonZeroU32>>,
375 #[serde(skip_serializing_if = "Option::is_none")]
376 pub config_max_count: Option<ContextSpanned<NonZeroU32>>,
377 #[serde(skip_serializing_if = "Option::is_none")]
378 pub config_element_type: Option<ContextSpanned<ConfigNestedValueType>>,
379 #[serde(skip_serializing_if = "Option::is_none")]
380 pub value: Option<ContextSpanned<serde_json::Value>>,
381 #[serde(skip_serializing_if = "Option::is_none")]
382 pub delivery: Option<ContextSpanned<DeliveryType>>,
383}
384
385impl CanonicalizeContext for ContextCapability {
386 fn canonicalize_context(&mut self) {
387 if let Some(service) = &mut self.service {
389 service.value.canonicalize_context()
390 } else if let Some(protocol) = &mut self.protocol {
391 protocol.value.canonicalize_context()
392 } else if let Some(event_stream) = &mut self.event_stream {
393 event_stream.value.canonicalize_context()
394 }
395 }
396}
397
398impl RightsClause for ContextCapability {
399 fn rights(&self) -> Option<&Rights> {
400 self.rights.as_ref().map(|r| &r.value)
401 }
402}
403
404impl ContextCapabilityClause for ContextCapability {
405 fn service(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
406 option_one_or_many_as_ref_context(&self.service)
407 }
408 fn protocol(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
409 option_one_or_many_as_ref_context(&self.protocol)
410 }
411 fn directory(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
412 self.directory.as_ref().map(|s| ContextSpanned {
413 value: OneOrMany::One((s.value).as_ref()),
414 origin: s.origin.clone(),
415 })
416 }
417 fn storage(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
418 self.storage.as_ref().map(|s| ContextSpanned {
419 value: OneOrMany::One((s.value).as_ref()),
420 origin: s.origin.clone(),
421 })
422 }
423 fn runner(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
424 self.runner.as_ref().map(|s| ContextSpanned {
425 value: OneOrMany::One((s.value).as_ref()),
426 origin: s.origin.clone(),
427 })
428 }
429 fn resolver(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
430 self.resolver.as_ref().map(|s| ContextSpanned {
431 value: OneOrMany::One((s.value).as_ref()),
432 origin: s.origin.clone(),
433 })
434 }
435 fn event_stream(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
436 option_one_or_many_as_ref_context(&self.event_stream)
437 }
438 fn dictionary(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
439 self.dictionary.as_ref().map(|s| ContextSpanned {
440 value: OneOrMany::One((s.value).as_ref()),
441 origin: s.origin.clone(),
442 })
443 }
444 fn config(&self) -> Option<ContextSpanned<OneOrMany<&BorrowedName>>> {
445 self.config.as_ref().map(|s| ContextSpanned {
446 value: OneOrMany::One((s.value).as_ref()),
447 origin: s.origin.clone(),
448 })
449 }
450
451 fn decl_type(&self) -> &'static str {
452 "capability"
453 }
454 fn supported(&self) -> &[&'static str] {
455 &[
456 "service",
457 "protocol",
458 "directory",
459 "storage",
460 "event_stream",
461 "runner",
462 "resolver",
463 "config",
464 "dicitionary",
465 ]
466 }
467 fn are_many_names_allowed(&self) -> bool {
468 [
469 "service",
470 "protocol",
471 "directory",
472 "runner",
473 "resolver",
474 "event_stream",
475 "config",
476 "dicitionary",
477 ]
478 .contains(&self.capability_type(None).unwrap())
479 }
480
481 fn set_service(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
482 self.service = o;
483 }
484 fn set_protocol(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
485 self.protocol = o;
486 }
487 fn set_directory(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
488 self.directory = always_one_context(o);
489 }
490 fn set_storage(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
491 self.storage = always_one_context(o);
492 }
493 fn set_runner(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
494 self.runner = always_one_context(o);
495 }
496 fn set_resolver(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
497 self.resolver = always_one_context(o);
498 }
499 fn set_event_stream(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
500 self.event_stream = o;
501 }
502 fn set_dictionary(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
503 self.dictionary = always_one_context(o);
504 }
505 fn set_config(&mut self, o: Option<ContextSpanned<OneOrMany<Name>>>) {
506 self.config = always_one_context(o);
507 }
508
509 fn origin(&self) -> &Arc<PathBuf> {
511 &self.origin
512 }
513
514 fn availability(&self) -> Option<ContextSpanned<Availability>> {
515 None
516 }
517 fn set_availability(&mut self, _a: Option<ContextSpanned<Availability>>) {}
518}
519
520impl PartialEq for ContextCapability {
521 fn eq(&self, other: &Self) -> bool {
522 macro_rules! cmp {
523 ($field:ident) => {
524 match (&self.$field, &other.$field) {
525 (Some(a), Some(b)) => a.value == b.value,
526 (None, None) => true,
527 _ => false,
528 }
529 };
530 }
531
532 cmp!(service)
533 && cmp!(protocol)
534 && cmp!(directory)
535 && cmp!(storage)
536 && cmp!(runner)
537 && cmp!(resolver)
538 && cmp!(dictionary)
539 && cmp!(config)
540 && cmp!(path)
541 && cmp!(rights)
542 && cmp!(from)
543 && cmp!(event_stream)
544 && cmp!(backing_dir)
545 && cmp!(subdir)
546 && cmp!(storage_id)
547 && cmp!(config_type)
548 && cmp!(config_max_size)
549 && cmp!(config_max_count)
550 && cmp!(config_element_type)
551 && cmp!(value)
552 && cmp!(delivery)
553 }
554}
555
556impl Eq for ContextCapability {}
557
558impl ContextPathClause for ContextCapability {
559 fn path(&self) -> Option<&ContextSpanned<Path>> {
560 self.path.as_ref()
561 }
562}
563
564impl AsClauseContext for ContextCapability {
565 fn r#as(&self) -> Option<ContextSpanned<&BorrowedName>> {
566 None
567 }
568}
569
570impl Hydrate for Capability {
571 type Output = ContextCapability;
572
573 fn hydrate(self, file: &Arc<PathBuf>) -> Result<Self::Output, Error> {
574 Ok(ContextCapability {
575 origin: file.clone(),
576 service: hydrate_opt_simple(self.service, file),
577 protocol: hydrate_opt_simple(self.protocol, file),
578 directory: hydrate_opt_simple(self.directory, file),
579 storage: hydrate_opt_simple(self.storage, file),
580 runner: hydrate_opt_simple(self.runner, file),
581 resolver: hydrate_opt_simple(self.resolver, file),
582 dictionary: hydrate_opt_simple(self.dictionary, file),
583 config: hydrate_opt_simple(self.config, file),
584 path: hydrate_opt_simple(self.path, file),
585 rights: hydrate_opt_simple(self.rights, file),
586 from: hydrate_opt_simple(self.from, file),
587 event_stream: hydrate_opt_simple(self.event_stream, file),
588 backing_dir: hydrate_opt_simple(self.backing_dir, file),
589 subdir: hydrate_opt_simple(self.subdir, file),
590 storage_id: hydrate_opt_simple(self.storage_id, file),
591 config_type: hydrate_opt_simple(self.config_type, file),
592 config_max_size: hydrate_opt_simple(self.config_max_size, file),
593 config_max_count: hydrate_opt_simple(self.config_max_count, file),
594 config_element_type: hydrate_opt_simple(self.config_element_type, file),
595 value: hydrate_opt_simple(self.value, file),
596 delivery: hydrate_opt_simple(self.delivery, file),
597 })
598 }
599}