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