1use crate::one_or_many::OneOrMany;
6use crate::types::capability::ContextCapability;
7use crate::types::common::{ContextCapabilityClause, option_one_or_many_as_ref_context};
8use crate::types::offer::ContextOffer;
9use crate::types::r#use::ContextUse;
10use crate::{
11 AsClause, AsClauseContext, Capability, CapabilityClause, ContextExpose, ContextSpanned, Error,
12 PathClause, Use, alias_or_name, alias_or_name_context,
13};
14pub use cm_types::{
15 Availability, BorrowedName, BoundedName, DeliveryType, DependencyType, HandleType, Name,
16 NamespacePath, OnTerminate, ParseError, Path, RelativePath, StartupMode, StorageId, Url,
17};
18
19use std::fmt;
20use std::path::PathBuf;
21use std::sync::Arc;
22
23#[derive(Debug, PartialEq, Eq, Hash, Clone)]
34pub enum CapabilityId<'a> {
35 Service(&'a BorrowedName),
36 Protocol(&'a BorrowedName),
37 Directory(&'a BorrowedName),
38 UsedService(Path),
40 UsedProtocol(Path),
42 UsedProtocolNumberedHandle(HandleType),
44 UsedDirectory(Path),
46 UsedStorage(Path),
48 UsedEventStream(Path),
50 UsedConfiguration(&'a BorrowedName),
52 UsedRunner(&'a BorrowedName),
53 UsedDictionary(Path),
55 Storage(&'a BorrowedName),
56 Runner(&'a BorrowedName),
57 Resolver(&'a BorrowedName),
58 EventStream(&'a BorrowedName),
59 Dictionary(&'a BorrowedName),
60 Configuration(&'a BorrowedName),
61}
62
63macro_rules! capability_ids_from_names {
65 ($name:ident, $variant:expr) => {
66 fn $name(names: Vec<&'a BorrowedName>) -> Vec<Self> {
67 names.into_iter().map(|n| $variant(n)).collect()
68 }
69 };
70}
71
72macro_rules! capability_ids_from_context_names {
74 ($name:ident, $variant:expr) => {
75 fn $name(names: Vec<ContextSpanned<&'a BorrowedName>>) -> Vec<(Self, Arc<PathBuf>)> {
76 names
77 .into_iter()
78 .map(|spanned_name| ($variant(spanned_name.value), spanned_name.origin))
79 .collect()
80 }
81 };
82}
83
84macro_rules! capability_ids_from_paths {
86 ($name:ident, $variant:expr) => {
87 fn $name(paths: Vec<Path>) -> Vec<Self> {
88 paths.into_iter().map(|p| $variant(p)).collect()
89 }
90 };
91}
92
93macro_rules! capability_ids_from_context_paths {
95 ($name:ident, $variant:expr) => {
96 fn $name(paths: Vec<ContextSpanned<Path>>) -> Vec<(Self, Arc<PathBuf>)> {
97 paths
98 .into_iter()
99 .map(|spanned_path| ($variant(spanned_path.value), spanned_path.origin))
100 .collect()
101 }
102 };
103}
104
105impl<'a> CapabilityId<'a> {
106 pub fn type_str(&self) -> &'static str {
108 match self {
109 CapabilityId::Service(_) => "service",
110 CapabilityId::Protocol(_) => "protocol",
111 CapabilityId::Directory(_) => "directory",
112 CapabilityId::UsedService(_) => "service",
113 CapabilityId::UsedProtocol(_) => "protocol",
114 CapabilityId::UsedProtocolNumberedHandle(_) => "protocol",
115 CapabilityId::UsedDirectory(_) => "directory",
116 CapabilityId::UsedStorage(_) => "storage",
117 CapabilityId::UsedEventStream(_) => "event_stream",
118 CapabilityId::UsedRunner(_) => "runner",
119 CapabilityId::UsedConfiguration(_) => "config",
120 CapabilityId::UsedDictionary(_) => "dictionary",
121 CapabilityId::Storage(_) => "storage",
122 CapabilityId::Runner(_) => "runner",
123 CapabilityId::Resolver(_) => "resolver",
124 CapabilityId::EventStream(_) => "event_stream",
125 CapabilityId::Dictionary(_) => "dictionary",
126 CapabilityId::Configuration(_) => "config",
127 }
128 }
129
130 pub fn get_dir_path(&self) -> Option<NamespacePath> {
132 match self {
133 CapabilityId::UsedService(p)
134 | CapabilityId::UsedProtocol(p)
135 | CapabilityId::UsedEventStream(p) => Some(p.parent()),
136 CapabilityId::UsedDirectory(p)
137 | CapabilityId::UsedStorage(p)
138 | CapabilityId::UsedDictionary(p) => Some(p.clone().into()),
139 _ => None,
140 }
141 }
142
143 pub fn get_target_path(&self) -> Option<NamespacePath> {
145 match self {
146 CapabilityId::UsedService(p)
147 | CapabilityId::UsedProtocol(p)
148 | CapabilityId::UsedEventStream(p)
149 | CapabilityId::UsedDirectory(p)
150 | CapabilityId::UsedStorage(p)
151 | CapabilityId::UsedDictionary(p) => Some(p.clone().into()),
152 _ => None,
153 }
154 }
155
156 pub fn from_use(use_: &'a Use) -> Result<Vec<Self>, Error> {
165 let alias = use_.path.as_ref();
167 if let Some(n) = use_.service() {
168 return Ok(Self::used_services_from(Self::get_one_or_many_svc_paths(
169 n,
170 alias,
171 use_.capability_type().unwrap(),
172 )?));
173 } else if let Some(n) = use_.protocol() {
174 if let Some(numbered_handle) = use_.numbered_handle {
175 return Ok(n
176 .iter()
177 .map(|_| CapabilityId::UsedProtocolNumberedHandle(numbered_handle))
178 .collect());
179 }
180 return Ok(Self::used_protocols_from(Self::get_one_or_many_svc_paths(
181 n,
182 alias,
183 use_.capability_type().unwrap(),
184 )?));
185 } else if let Some(_) = use_.directory.as_ref() {
186 if use_.path.is_none() {
187 return Err(Error::validate("\"path\" should be present for `use directory`."));
188 }
189 return Ok(vec![CapabilityId::UsedDirectory(use_.path.as_ref().unwrap().clone())]);
190 } else if let Some(_) = use_.storage.as_ref() {
191 if use_.path.is_none() {
192 return Err(Error::validate("\"path\" should be present for `use storage`."));
193 }
194 return Ok(vec![CapabilityId::UsedStorage(use_.path.as_ref().unwrap().clone())]);
195 } else if let Some(_) = use_.event_stream() {
196 if let Some(path) = use_.path() {
197 return Ok(vec![CapabilityId::UsedEventStream(path.clone())]);
198 }
199 return Ok(vec![CapabilityId::UsedEventStream(Path::new(
200 "/svc/fuchsia.component.EventStream",
201 )?)]);
202 } else if let Some(n) = use_.runner() {
203 match n {
204 OneOrMany::One(name) => {
205 return Ok(vec![CapabilityId::UsedRunner(name)]);
206 }
207 OneOrMany::Many(_) => {
208 return Err(Error::validate("`use runner` should occur at most once."));
209 }
210 }
211 } else if let Some(_) = use_.config() {
212 return match &use_.key {
213 None => Err(Error::validate("\"key\" should be present for `use config`.")),
214 Some(name) => Ok(vec![CapabilityId::UsedConfiguration(name)]),
215 };
216 } else if let Some(n) = use_.dictionary() {
217 return Ok(Self::used_dictionaries_from(Self::get_one_or_many_svc_paths(
218 n,
219 alias,
220 use_.capability_type().unwrap(),
221 )?));
222 }
223 let supported_keywords = use_
225 .supported()
226 .into_iter()
227 .map(|k| format!("\"{}\"", k))
228 .collect::<Vec<_>>()
229 .join(", ");
230 Err(Error::validate(format!(
231 "`{}` declaration is missing a capability keyword, one of: {}",
232 use_.decl_type(),
233 supported_keywords,
234 )))
235 }
236
237 pub fn from_capability(capability: &'a Capability) -> Result<Vec<Self>, Error> {
238 if let Some(n) = capability.service() {
240 if n.is_many() && capability.path.is_some() {
241 return Err(Error::validate(
242 "\"path\" can only be specified when one `service` is supplied.",
243 ));
244 }
245 return Ok(Self::services_from(Self::get_one_or_many_names_no_span(
246 n,
247 None,
248 capability.capability_type().unwrap(),
249 )?));
250 } else if let Some(n) = capability.protocol() {
251 if n.is_many() && capability.path.is_some() {
252 return Err(Error::validate(
253 "\"path\" can only be specified when one `protocol` is supplied.",
254 ));
255 }
256 return Ok(Self::protocols_from(Self::get_one_or_many_names_no_span(
257 n,
258 None,
259 capability.capability_type().unwrap(),
260 )?));
261 } else if let Some(n) = capability.directory() {
262 return Ok(Self::directories_from(Self::get_one_or_many_names_no_span(
263 n,
264 None,
265 capability.capability_type().unwrap(),
266 )?));
267 } else if let Some(n) = capability.storage() {
268 if capability.storage_id.is_none() {
269 return Err(Error::validate(
270 "Storage declaration is missing \"storage_id\", but is required.",
271 ));
272 }
273 return Ok(Self::storages_from(Self::get_one_or_many_names_no_span(
274 n,
275 None,
276 capability.capability_type().unwrap(),
277 )?));
278 } else if let Some(n) = capability.runner() {
279 return Ok(Self::runners_from(Self::get_one_or_many_names_no_span(
280 n,
281 None,
282 capability.capability_type().unwrap(),
283 )?));
284 } else if let Some(n) = capability.resolver() {
285 return Ok(Self::resolvers_from(Self::get_one_or_many_names_no_span(
286 n,
287 None,
288 capability.capability_type().unwrap(),
289 )?));
290 } else if let Some(n) = capability.event_stream() {
291 return Ok(Self::event_streams_from(Self::get_one_or_many_names_no_span(
292 n,
293 None,
294 capability.capability_type().unwrap(),
295 )?));
296 } else if let Some(n) = capability.dictionary() {
297 return Ok(Self::dictionaries_from(Self::get_one_or_many_names_no_span(
298 n,
299 None,
300 capability.capability_type().unwrap(),
301 )?));
302 } else if let Some(n) = capability.config() {
303 return Ok(Self::configurations_from(Self::get_one_or_many_names_no_span(
304 n,
305 None,
306 capability.capability_type().unwrap(),
307 )?));
308 }
309
310 let supported_keywords = capability
312 .supported()
313 .into_iter()
314 .map(|k| format!("\"{}\"", k))
315 .collect::<Vec<_>>()
316 .join(", ");
317 Err(Error::validate(format!(
318 "`{}` declaration is missing a capability keyword, one of: {}",
319 capability.decl_type(),
320 supported_keywords,
321 )))
322 }
323
324 pub fn from_offer_expose<T>(clause: &'a T) -> Result<Vec<Self>, Error>
333 where
334 T: CapabilityClause + AsClause + fmt::Debug,
335 {
336 let alias = clause.r#as();
338 if let Some(n) = clause.service() {
339 return Ok(Self::services_from(Self::get_one_or_many_names_no_span(
340 n,
341 alias,
342 clause.capability_type().unwrap(),
343 )?));
344 } else if let Some(n) = clause.protocol() {
345 return Ok(Self::protocols_from(Self::get_one_or_many_names_no_span(
346 n,
347 alias,
348 clause.capability_type().unwrap(),
349 )?));
350 } else if let Some(n) = clause.directory() {
351 return Ok(Self::directories_from(Self::get_one_or_many_names_no_span(
352 n,
353 alias,
354 clause.capability_type().unwrap(),
355 )?));
356 } else if let Some(n) = clause.storage() {
357 return Ok(Self::storages_from(Self::get_one_or_many_names_no_span(
358 n,
359 alias,
360 clause.capability_type().unwrap(),
361 )?));
362 } else if let Some(n) = clause.runner() {
363 return Ok(Self::runners_from(Self::get_one_or_many_names_no_span(
364 n,
365 alias,
366 clause.capability_type().unwrap(),
367 )?));
368 } else if let Some(n) = clause.resolver() {
369 return Ok(Self::resolvers_from(Self::get_one_or_many_names_no_span(
370 n,
371 alias,
372 clause.capability_type().unwrap(),
373 )?));
374 } else if let Some(event_stream) = clause.event_stream() {
375 return Ok(Self::event_streams_from(Self::get_one_or_many_names_no_span(
376 event_stream,
377 alias,
378 clause.capability_type().unwrap(),
379 )?));
380 } else if let Some(n) = clause.dictionary() {
381 return Ok(Self::dictionaries_from(Self::get_one_or_many_names_no_span(
382 n,
383 alias,
384 clause.capability_type().unwrap(),
385 )?));
386 } else if let Some(n) = clause.config() {
387 return Ok(Self::configurations_from(Self::get_one_or_many_names_no_span(
388 n,
389 alias,
390 clause.capability_type().unwrap(),
391 )?));
392 }
393
394 let supported_keywords = clause
396 .supported()
397 .into_iter()
398 .map(|k| format!("\"{}\"", k))
399 .collect::<Vec<_>>()
400 .join(", ");
401 Err(Error::validate(format!(
402 "`{}` declaration is missing a capability keyword, one of: {}",
403 clause.decl_type(),
404 supported_keywords,
405 )))
406 }
407
408 pub fn from_context_capability(
409 capability_input: &'a ContextSpanned<ContextCapability>,
410 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
411 let capability = &capability_input.value;
412 let origin = &capability_input.origin;
413
414 if let Some(n) = capability.service() {
415 if n.value.is_many()
416 && let Some(cs_path) = &capability.path
417 {
418 return Err(Error::validate_context(
419 "\"path\" can only be specified when one `service` is supplied.",
420 Some(cs_path.origin.clone()),
421 ));
422 }
423 return Ok(Self::services_from_context(Self::get_one_or_many_names_context(
424 n,
425 None,
426 capability.capability_type(None).unwrap(),
427 )?));
428 } else if let Some(n) = capability.protocol() {
429 if n.value.is_many()
430 && let Some(cs_path) = &capability.path
431 {
432 return Err(Error::validate_context(
433 "\"path\" can only be specified when one `protocol` is supplied.",
434 Some(cs_path.origin.clone()),
435 ));
436 }
437 return Ok(Self::protocols_from_context(Self::get_one_or_many_names_context(
438 n,
439 None,
440 capability.capability_type(None).unwrap(),
441 )?));
442 } else if let Some(n) = capability.directory() {
443 return Ok(Self::directories_from_context(Self::get_one_or_many_names_context(
444 n,
445 None,
446 capability.capability_type(None).unwrap(),
447 )?));
448 } else if let Some(cs_storage) = capability.storage() {
449 if capability.storage_id.is_none() {
450 return Err(Error::validate_context(
451 "Storage declaration is missing \"storage_id\", but is required.",
452 Some(cs_storage.origin),
453 ));
454 }
455 return Ok(Self::storages_from_context(Self::get_one_or_many_names_context(
456 cs_storage,
457 None,
458 capability.capability_type(None).unwrap(),
459 )?));
460 } else if let Some(n) = capability.runner() {
461 return Ok(Self::runners_from_context(Self::get_one_or_many_names_context(
462 n,
463 None,
464 capability.capability_type(None).unwrap(),
465 )?));
466 } else if let Some(n) = capability.resolver() {
467 return Ok(Self::resolvers_from_context(Self::get_one_or_many_names_context(
468 n,
469 None,
470 capability.capability_type(None).unwrap(),
471 )?));
472 } else if let Some(n) = capability.event_stream() {
473 return Ok(Self::event_streams_from_context(Self::get_one_or_many_names_context(
474 n,
475 None,
476 capability.capability_type(None).unwrap(),
477 )?));
478 } else if let Some(n) = capability.dictionary() {
479 return Ok(Self::dictionaries_from_context(Self::get_one_or_many_names_context(
480 n,
481 None,
482 capability.capability_type(None).unwrap(),
483 )?));
484 } else if let Some(n) = capability.config() {
485 return Ok(Self::configurations_from_context(Self::get_one_or_many_names_context(
486 n,
487 None,
488 capability.capability_type(None).unwrap(),
489 )?));
490 }
491
492 let supported_keywords = capability
494 .supported()
495 .into_iter()
496 .map(|k| format!("\"{}\"", k))
497 .collect::<Vec<_>>()
498 .join(", ");
499 Err(Error::validate_context(
500 format!(
501 "`{}` declaration is missing a capability keyword, one of: {}",
502 capability.decl_type(),
503 supported_keywords,
504 ),
505 Some(origin.clone()),
506 ))
507 }
508
509 pub fn from_context_offer(
510 offer_input: &'a ContextSpanned<ContextOffer>,
511 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
512 let offer = &offer_input.value;
513 let origin = &offer_input.origin;
514
515 let alias = offer.r#as();
516
517 if let Some(n) = offer.service() {
518 return Ok(Self::services_from_context(Self::get_one_or_many_names_context(
519 n,
520 alias,
521 offer.capability_type(Some(origin.clone())).unwrap(),
522 )?));
523 } else if let Some(n) = offer.protocol() {
524 return Ok(Self::protocols_from_context(Self::get_one_or_many_names_context(
525 n,
526 alias,
527 offer.capability_type(Some(origin.clone())).unwrap(),
528 )?));
529 } else if let Some(n) = offer.directory() {
530 return Ok(Self::directories_from_context(Self::get_one_or_many_names_context(
531 n,
532 alias,
533 offer.capability_type(Some(origin.clone())).unwrap(),
534 )?));
535 } else if let Some(n) = offer.storage() {
536 return Ok(Self::storages_from_context(Self::get_one_or_many_names_context(
537 n,
538 alias,
539 offer.capability_type(Some(origin.clone())).unwrap(),
540 )?));
541 } else if let Some(n) = offer.runner() {
542 return Ok(Self::runners_from_context(Self::get_one_or_many_names_context(
543 n,
544 alias,
545 offer.capability_type(Some(origin.clone())).unwrap(),
546 )?));
547 } else if let Some(n) = offer.resolver() {
548 return Ok(Self::resolvers_from_context(Self::get_one_or_many_names_context(
549 n,
550 alias,
551 offer.capability_type(Some(origin.clone())).unwrap(),
552 )?));
553 } else if let Some(event_stream) = offer.event_stream() {
554 return Ok(Self::event_streams_from_context(Self::get_one_or_many_names_context(
555 event_stream,
556 alias,
557 offer.capability_type(Some(origin.clone())).unwrap(),
558 )?));
559 } else if let Some(n) = offer.dictionary() {
560 return Ok(Self::dictionaries_from_context(Self::get_one_or_many_names_context(
561 n,
562 alias,
563 offer.capability_type(Some(origin.clone())).unwrap(),
564 )?));
565 } else if let Some(n) = offer.config() {
566 return Ok(Self::configurations_from_context(Self::get_one_or_many_names_context(
567 n,
568 alias,
569 offer.capability_type(Some(origin.clone())).unwrap(),
570 )?));
571 }
572
573 let supported_keywords = offer
575 .supported()
576 .into_iter()
577 .map(|k| format!("\"{}\"", k))
578 .collect::<Vec<_>>()
579 .join(", ");
580 Err(Error::validate_context(
581 format!(
582 "`{}` declaration is missing a capability keyword, one of: {}",
583 offer.decl_type(),
584 supported_keywords,
585 ),
586 Some(origin.clone()),
587 ))
588 }
589
590 pub fn from_context_expose(
591 expose_input: &'a ContextSpanned<ContextExpose>,
592 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
593 let expose = &expose_input.value;
594 let origin = &expose_input.origin;
595
596 let alias = expose.r#as();
597
598 if let Some(n) = expose.service() {
599 return Ok(Self::services_from_context(Self::get_one_or_many_names_context(
600 n,
601 alias,
602 expose.capability_type(Some(origin.clone())).unwrap(),
603 )?));
604 } else if let Some(n) = expose.protocol() {
605 return Ok(Self::protocols_from_context(Self::get_one_or_many_names_context(
606 n,
607 alias,
608 expose.capability_type(Some(origin.clone())).unwrap(),
609 )?));
610 } else if let Some(n) = expose.directory() {
611 return Ok(Self::directories_from_context(Self::get_one_or_many_names_context(
612 n,
613 alias,
614 expose.capability_type(Some(origin.clone())).unwrap(),
615 )?));
616 } else if let Some(n) = expose.storage() {
617 return Ok(Self::storages_from_context(Self::get_one_or_many_names_context(
618 n,
619 alias,
620 expose.capability_type(Some(origin.clone())).unwrap(),
621 )?));
622 } else if let Some(n) = expose.runner() {
623 return Ok(Self::runners_from_context(Self::get_one_or_many_names_context(
624 n,
625 alias,
626 expose.capability_type(Some(origin.clone())).unwrap(),
627 )?));
628 } else if let Some(n) = expose.resolver() {
629 return Ok(Self::resolvers_from_context(Self::get_one_or_many_names_context(
630 n,
631 alias,
632 expose.capability_type(Some(origin.clone())).unwrap(),
633 )?));
634 } else if let Some(event_stream) = expose.event_stream() {
635 return Ok(Self::event_streams_from_context(Self::get_one_or_many_names_context(
636 event_stream,
637 alias,
638 expose.capability_type(Some(origin.clone())).unwrap(),
639 )?));
640 } else if let Some(n) = expose.dictionary() {
641 return Ok(Self::dictionaries_from_context(Self::get_one_or_many_names_context(
642 n,
643 alias,
644 expose.capability_type(Some(origin.clone())).unwrap(),
645 )?));
646 } else if let Some(n) = expose.config() {
647 return Ok(Self::configurations_from_context(Self::get_one_or_many_names_context(
648 n,
649 alias,
650 expose.capability_type(Some(origin.clone())).unwrap(),
651 )?));
652 }
653
654 let supported_keywords = expose
656 .supported()
657 .into_iter()
658 .map(|k| format!("\"{}\"", k))
659 .collect::<Vec<_>>()
660 .join(", ");
661 Err(Error::validate_context(
662 format!(
663 "`{}` declaration is missing a capability keyword, one of: {}",
664 expose.decl_type(),
665 supported_keywords,
666 ),
667 Some(origin.clone()),
668 ))
669 }
670
671 pub fn from_context_use(
680 use_input: &'a ContextSpanned<ContextUse>,
681 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
682 let use_ = &use_input.value;
683 let origin = &use_input.origin;
684
685 let alias = use_.path.as_ref();
686
687 if let Some(n) = option_one_or_many_as_ref_context(&use_.service) {
688 return Ok(Self::used_services_from_context(Self::get_one_or_many_svc_paths_context(
689 n,
690 alias,
691 use_input.capability_type(Some(origin.clone())).unwrap(),
692 )?));
693 } else if let Some(n) = option_one_or_many_as_ref_context(&use_.protocol) {
694 return Ok(Self::used_protocols_from_context(Self::get_one_or_many_svc_paths_context(
695 n,
696 alias,
697 use_input.capability_type(Some(origin.clone())).unwrap(),
698 )?));
699 } else if let Some(_) = &use_.directory {
700 if use_.path.is_none() {
701 return Err(Error::validate_context(
702 "\"path\" should be present for `use directory`.",
703 Some(origin.clone()),
704 ));
705 }
706 return Ok(vec![(
707 CapabilityId::UsedDirectory(use_.path.as_ref().unwrap().value.clone()),
708 origin.clone(),
709 )]);
710 } else if let Some(_) = &use_.storage {
711 if use_.path.is_none() {
712 return Err(Error::validate_context(
713 "\"path\" should be present for `use storage`.",
714 Some(origin.clone()),
715 ));
716 }
717 return Ok(vec![(
718 CapabilityId::UsedStorage(use_.path.as_ref().unwrap().value.clone()),
719 origin.clone(),
720 )]);
721 } else if let Some(_) = &use_.event_stream {
722 if let Some(path) = &use_.path {
723 return Ok(vec![(
724 CapabilityId::UsedEventStream(path.value.clone()),
725 origin.clone(),
726 )]);
727 }
728 return Ok(vec![(
729 CapabilityId::UsedEventStream(Path::new("/svc/fuchsia.component.EventStream")?),
730 origin.clone(),
731 )]);
732 } else if let Some(n) = &use_.runner {
733 return Ok(vec![(CapabilityId::UsedRunner(&n.value), n.origin.clone())]);
734 } else if let Some(_) = &use_.config {
735 return match &use_.key {
736 None => Err(Error::validate_context(
737 "\"key\" should be present for `use config`.",
738 Some(origin.clone()),
739 )),
740 Some(name) => {
741 Ok(vec![(CapabilityId::UsedConfiguration(&name.value), origin.clone())])
742 }
743 };
744 } else if let Some(n) = option_one_or_many_as_ref_context(&use_.dictionary) {
745 return Ok(Self::used_dictionaries_from_context(
746 Self::get_one_or_many_svc_paths_context(
747 n,
748 alias,
749 use_input.capability_type(Some(origin.clone())).unwrap(),
750 )?,
751 ));
752 }
753
754 let supported_keywords = use_input
756 .supported()
757 .into_iter()
758 .map(|k| format!("\"{}\"", k))
759 .collect::<Vec<_>>()
760 .join(", ");
761
762 Err(Error::validate_context(
763 format!(
764 "`{}` declaration is missing a capability keyword, one of: {}",
765 use_input.decl_type(),
766 supported_keywords,
767 ),
768 Some(origin.clone()),
769 ))
770 }
771
772 fn get_one_or_many_names_no_span<'b>(
774 names: OneOrMany<&'b BorrowedName>,
775 alias: Option<&'b BorrowedName>,
776 capability_type: &str,
777 ) -> Result<Vec<&'b BorrowedName>, Error> {
778 let names: Vec<&BorrowedName> = names.into_iter().collect();
779 if names.len() == 1 {
780 Ok(vec![alias_or_name(alias, &names[0])])
781 } else {
782 if alias.is_some() {
783 return Err(Error::validate(format!(
784 "\"as\" can only be specified when one `{}` is supplied.",
785 capability_type,
786 )));
787 }
788 Ok(names)
789 }
790 }
791
792 fn get_one_or_many_names_context<'b>(
794 name_wrapper: ContextSpanned<OneOrMany<&'b BorrowedName>>,
795 alias: Option<ContextSpanned<&'b BorrowedName>>,
796 capability_type: &str,
797 ) -> Result<Vec<ContextSpanned<&'b BorrowedName>>, Error> {
798 let names_origin = name_wrapper.origin;
799 let names_vec: Vec<&'b BorrowedName> = name_wrapper.value.into_iter().collect();
800 let num_names = names_vec.len();
801
802 if num_names > 1 && alias.is_some() {
803 return Err(Error::validate_contexts(
804 format!("\"as\" can only be specified when one `{}` is supplied.", capability_type),
805 vec![alias.map(|s| s.origin).unwrap_or(names_origin)],
806 ));
807 }
808
809 if num_names == 1 {
810 let final_name_span = alias_or_name_context(alias, names_vec[0], names_origin);
811 return Ok(vec![final_name_span]);
812 }
813
814 let final_names = names_vec
815 .into_iter()
816 .map(|name| ContextSpanned { value: name, origin: names_origin.clone() })
817 .collect();
818
819 Ok(final_names)
820 }
821
822 fn get_one_or_many_svc_paths(
824 names: OneOrMany<&BorrowedName>,
825 alias: Option<&Path>,
826 capability_type: &str,
827 ) -> Result<Vec<Path>, Error> {
828 let names: Vec<_> = names.into_iter().collect();
829 match (names.len(), alias) {
830 (_, None) => {
831 Ok(names.into_iter().map(|n| format!("/svc/{}", n).parse().unwrap()).collect())
832 }
833 (1, Some(alias)) => Ok(vec![alias.clone()]),
834 (_, Some(_)) => {
835 return Err(Error::validate(format!(
836 "\"path\" can only be specified when one `{}` is supplied.",
837 capability_type,
838 )));
839 }
840 }
841 }
842
843 fn get_one_or_many_svc_paths_context(
844 names: ContextSpanned<OneOrMany<&BorrowedName>>,
845 alias: Option<&ContextSpanned<Path>>,
846 capability_type: &str,
847 ) -> Result<Vec<ContextSpanned<Path>>, Error> {
848 let names_origin = &names.origin;
849 let names_vec: Vec<_> = names.value.into_iter().collect();
850
851 match (names_vec.len(), alias) {
852 (_, None) => {
853 let generated_paths = names_vec
854 .into_iter()
855 .map(|n| {
856 let new_path: Path = format!("/svc/{}", n).parse().unwrap();
857 ContextSpanned { value: new_path, origin: names_origin.clone() }
858 })
859 .collect();
860 Ok(generated_paths)
861 }
862
863 (1, Some(spanned_alias)) => Ok(vec![spanned_alias.clone()]),
864
865 (_, Some(spanned_alias)) => Err(Error::validate_contexts(
866 format!(
867 "\"path\" can only be specified when one `{}` is supplied.",
868 capability_type,
869 ),
870 vec![spanned_alias.origin.clone()],
871 )),
872 }
873 }
874
875 capability_ids_from_names!(services_from, CapabilityId::Service);
876 capability_ids_from_names!(protocols_from, CapabilityId::Protocol);
877 capability_ids_from_names!(directories_from, CapabilityId::Directory);
878 capability_ids_from_names!(storages_from, CapabilityId::Storage);
879 capability_ids_from_names!(runners_from, CapabilityId::Runner);
880 capability_ids_from_names!(resolvers_from, CapabilityId::Resolver);
881 capability_ids_from_names!(event_streams_from, CapabilityId::EventStream);
882 capability_ids_from_names!(dictionaries_from, CapabilityId::Dictionary);
883 capability_ids_from_names!(configurations_from, CapabilityId::Configuration);
884
885 capability_ids_from_paths!(used_services_from, CapabilityId::UsedService);
886 capability_ids_from_paths!(used_protocols_from, CapabilityId::UsedProtocol);
887 capability_ids_from_paths!(used_dictionaries_from, CapabilityId::UsedDictionary);
888
889 capability_ids_from_context_names!(services_from_context, CapabilityId::Service);
890 capability_ids_from_context_names!(protocols_from_context, CapabilityId::Protocol);
891 capability_ids_from_context_names!(directories_from_context, CapabilityId::Directory);
892 capability_ids_from_context_names!(storages_from_context, CapabilityId::Storage);
893 capability_ids_from_context_names!(runners_from_context, CapabilityId::Runner);
894 capability_ids_from_context_names!(resolvers_from_context, CapabilityId::Resolver);
895 capability_ids_from_context_names!(event_streams_from_context, CapabilityId::EventStream);
896 capability_ids_from_context_names!(dictionaries_from_context, CapabilityId::Dictionary);
897 capability_ids_from_context_names!(configurations_from_context, CapabilityId::Configuration);
898
899 capability_ids_from_context_paths!(used_services_from_context, CapabilityId::UsedService);
900 capability_ids_from_context_paths!(used_protocols_from_context, CapabilityId::UsedProtocol);
901 capability_ids_from_context_paths!(
902 used_dictionaries_from_context,
903 CapabilityId::UsedDictionary
904 );
905}
906
907impl fmt::Display for CapabilityId<'_> {
908 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 match self {
911 CapabilityId::Service(n)
912 | CapabilityId::Storage(n)
913 | CapabilityId::Runner(n)
914 | CapabilityId::UsedRunner(n)
915 | CapabilityId::Resolver(n)
916 | CapabilityId::EventStream(n)
917 | CapabilityId::Configuration(n)
918 | CapabilityId::UsedConfiguration(n)
919 | CapabilityId::Dictionary(n) => write!(f, "{}", n),
920 CapabilityId::UsedService(p)
921 | CapabilityId::UsedProtocol(p)
922 | CapabilityId::UsedDirectory(p)
923 | CapabilityId::UsedStorage(p)
924 | CapabilityId::UsedEventStream(p)
925 | CapabilityId::UsedDictionary(p) => write!(f, "{}", p),
926 CapabilityId::UsedProtocolNumberedHandle(p) => write!(f, "{}", p),
927 CapabilityId::Protocol(p) | CapabilityId::Directory(p) => write!(f, "{}", p),
928 }
929 }
930}
931
932#[cfg(test)]
933mod tests {
934 use super::*;
935 use crate::types::offer::Offer;
936 use crate::types::r#use::Use;
937 use assert_matches::assert_matches;
938 use std::path::PathBuf;
939 use std::sync::Arc;
940
941 #[test]
942 fn test_offer_service() -> Result<(), Error> {
943 let a: Name = "a".parse().unwrap();
944 let b: Name = "b".parse().unwrap();
945 assert_eq!(
946 CapabilityId::from_offer_expose(&Offer {
947 service: Some(OneOrMany::One(a.clone())),
948 ..Offer::default()
949 },)?,
950 vec![CapabilityId::Service(&a)]
951 );
952
953 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
954
955 assert_eq!(
956 CapabilityId::from_context_offer(&ContextSpanned {
957 value: ContextOffer {
958 service: Some(ContextSpanned {
959 value: OneOrMany::One(a.clone()),
960 origin: synthetic_origin.clone(),
961 }),
962 ..ContextOffer::default()
963 },
964 origin: synthetic_origin.clone(),
965 })?,
966 vec![(CapabilityId::Service(&a), synthetic_origin.clone())]
967 );
968
969 assert_eq!(
970 CapabilityId::from_offer_expose(&Offer {
971 service: Some(OneOrMany::Many(vec![a.clone(), b.clone()],)),
972 ..Offer::default()
973 },)?,
974 vec![CapabilityId::Service(&a), CapabilityId::Service(&b)]
975 );
976
977 assert_eq!(
978 CapabilityId::from_context_offer(&ContextSpanned {
979 value: ContextOffer {
980 service: Some(ContextSpanned {
981 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
982 origin: synthetic_origin.clone(),
983 }),
984 ..ContextOffer::default()
985 },
986 origin: synthetic_origin.clone(),
987 })?,
988 vec![
989 (CapabilityId::Service(&a), synthetic_origin.clone()),
990 (CapabilityId::Service(&b), synthetic_origin.clone())
991 ]
992 );
993
994 assert_eq!(
996 CapabilityId::from_offer_expose(&Offer {
997 service: Some(OneOrMany::One(a.clone())),
998 r#as: Some(b.clone()),
999 ..Offer::default()
1000 },)?,
1001 vec![CapabilityId::Service(&b)]
1002 );
1003
1004 assert_eq!(
1005 CapabilityId::from_context_offer(&ContextSpanned {
1006 value: ContextOffer {
1007 service: Some(ContextSpanned {
1008 value: OneOrMany::One(a.clone()),
1009 origin: synthetic_origin.clone(),
1010 }),
1011 r#as: Some(ContextSpanned {
1012 value: b.clone(),
1013 origin: synthetic_origin.clone()
1014 }),
1015 ..ContextOffer::default()
1016 },
1017 origin: synthetic_origin.clone(),
1018 })?,
1019 vec![(CapabilityId::Service(&b), synthetic_origin)]
1020 );
1021
1022 Ok(())
1023 }
1024
1025 #[test]
1026 fn test_use_service() -> Result<(), Error> {
1027 let a: Name = "a".parse().unwrap();
1028 let b: Name = "b".parse().unwrap();
1029
1030 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1031
1032 assert_eq!(
1033 CapabilityId::from_use(&Use {
1034 service: Some(OneOrMany::One(a.clone())),
1035 ..Use::default()
1036 },)?,
1037 vec![CapabilityId::UsedService("/svc/a".parse().unwrap())]
1038 );
1039
1040 assert_eq!(
1041 CapabilityId::from_context_use(&ContextSpanned {
1042 value: ContextUse {
1043 service: Some(ContextSpanned {
1044 value: OneOrMany::One(a.clone()),
1045 origin: synthetic_origin.clone(),
1046 }),
1047 ..ContextUse::default()
1048 },
1049 origin: synthetic_origin.clone(),
1050 })?,
1051 vec![(CapabilityId::UsedService("/svc/a".parse().unwrap()), synthetic_origin.clone())]
1052 );
1053
1054 assert_eq!(
1055 CapabilityId::from_use(&Use {
1056 service: Some(OneOrMany::Many(vec![a.clone(), b.clone(),],)),
1057 ..Use::default()
1058 },)?,
1059 vec![
1060 CapabilityId::UsedService("/svc/a".parse().unwrap()),
1061 CapabilityId::UsedService("/svc/b".parse().unwrap())
1062 ]
1063 );
1064
1065 assert_eq!(
1066 CapabilityId::from_context_use(&ContextSpanned {
1067 value: ContextUse {
1068 service: Some(ContextSpanned {
1069 value: OneOrMany::Many(vec![a.clone(), b.clone(),]),
1070 origin: synthetic_origin.clone(),
1071 }),
1072 ..ContextUse::default()
1073 },
1074 origin: synthetic_origin.clone(),
1075 })?,
1076 vec![
1077 (CapabilityId::UsedService("/svc/a".parse().unwrap()), synthetic_origin.clone()),
1078 (CapabilityId::UsedService("/svc/b".parse().unwrap()), synthetic_origin.clone())
1079 ]
1080 );
1081
1082 assert_eq!(
1083 CapabilityId::from_use(&Use {
1084 service: Some(OneOrMany::One(a.clone())),
1085 path: Some("/b".parse().unwrap()),
1086 ..Use::default()
1087 },)?,
1088 vec![CapabilityId::UsedService("/b".parse().unwrap())]
1089 );
1090
1091 assert_eq!(
1092 CapabilityId::from_context_use(&ContextSpanned {
1093 value: ContextUse {
1094 service: Some(ContextSpanned {
1095 value: OneOrMany::One(a.clone()),
1096 origin: synthetic_origin.clone(),
1097 }),
1098 path: Some(ContextSpanned {
1099 value: "/b".parse().unwrap(),
1100 origin: synthetic_origin.clone(),
1101 }),
1102 ..ContextUse::default()
1103 },
1104 origin: synthetic_origin.clone(),
1105 })?,
1106 vec![(CapabilityId::UsedService("/b".parse().unwrap()), synthetic_origin.clone())]
1107 );
1108
1109 Ok(())
1110 }
1111
1112 #[test]
1113 fn test_use_event_stream() -> Result<(), Error> {
1114 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1115
1116 assert_eq!(
1117 CapabilityId::from_use(&Use {
1118 event_stream: Some(OneOrMany::One(Name::new("test".to_string()).unwrap())),
1119 path: Some(cm_types::Path::new("/svc/myevent".to_string()).unwrap()),
1120 ..Use::default()
1121 },)?,
1122 vec![CapabilityId::UsedEventStream("/svc/myevent".parse().unwrap()),]
1123 );
1124
1125 assert_eq!(
1126 CapabilityId::from_context_use(&ContextSpanned {
1127 value: ContextUse {
1128 event_stream: Some(ContextSpanned {
1129 value: OneOrMany::One(Name::new("test".to_string()).unwrap()),
1130 origin: synthetic_origin.clone(),
1131 }),
1132 path: Some(ContextSpanned {
1133 value: cm_types::Path::new("/svc/myevent".to_string()).unwrap(),
1134 origin: synthetic_origin.clone(),
1135 }),
1136 ..ContextUse::default()
1137 },
1138 origin: synthetic_origin.clone(),
1139 })?,
1140 vec![(
1141 CapabilityId::UsedEventStream("/svc/myevent".parse().unwrap()),
1142 synthetic_origin.clone()
1143 )]
1144 );
1145
1146 assert_eq!(
1147 CapabilityId::from_use(&Use {
1148 event_stream: Some(OneOrMany::One(Name::new("test".to_string()).unwrap())),
1149 ..Use::default()
1150 },)?,
1151 vec![CapabilityId::UsedEventStream(
1152 "/svc/fuchsia.component.EventStream".parse().unwrap()
1153 ),]
1154 );
1155
1156 assert_eq!(
1157 CapabilityId::from_context_use(&ContextSpanned {
1158 value: ContextUse {
1159 event_stream: Some(ContextSpanned {
1160 value: OneOrMany::One(Name::new("test".to_string()).unwrap()),
1161 origin: synthetic_origin.clone(),
1162 }),
1163 ..ContextUse::default()
1164 },
1165 origin: synthetic_origin.clone(),
1166 })?,
1167 vec![(
1168 CapabilityId::UsedEventStream(
1169 "/svc/fuchsia.component.EventStream".parse().unwrap()
1170 ),
1171 synthetic_origin.clone()
1172 )]
1173 );
1174
1175 Ok(())
1176 }
1177
1178 #[test]
1179 fn test_offer_protocol() -> Result<(), Error> {
1180 let a: Name = "a".parse().unwrap();
1181 let b: Name = "b".parse().unwrap();
1182
1183 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1184
1185 assert_eq!(
1186 CapabilityId::from_offer_expose(&Offer {
1187 protocol: Some(OneOrMany::One(a.clone())),
1188 ..Offer::default()
1189 },)?,
1190 vec![CapabilityId::Protocol(&a)]
1191 );
1192
1193 assert_eq!(
1194 CapabilityId::from_context_offer(&ContextSpanned {
1195 value: ContextOffer {
1196 protocol: Some(ContextSpanned {
1197 value: OneOrMany::One(a.clone()),
1198 origin: synthetic_origin.clone(),
1199 }),
1200 ..ContextOffer::default()
1201 },
1202 origin: synthetic_origin.clone(),
1203 })?,
1204 vec![(CapabilityId::Protocol(&a), synthetic_origin.clone())]
1205 );
1206
1207 assert_eq!(
1208 CapabilityId::from_offer_expose(&Offer {
1209 protocol: Some(OneOrMany::Many(vec![a.clone(), b.clone()],)),
1210 ..Offer::default()
1211 },)?,
1212 vec![CapabilityId::Protocol(&a), CapabilityId::Protocol(&b)]
1213 );
1214
1215 assert_eq!(
1216 CapabilityId::from_context_offer(&ContextSpanned {
1217 value: ContextOffer {
1218 protocol: Some(ContextSpanned {
1219 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1220 origin: synthetic_origin.clone(),
1221 }),
1222 ..ContextOffer::default()
1223 },
1224 origin: synthetic_origin.clone(),
1225 })?,
1226 vec![
1227 (CapabilityId::Protocol(&a), synthetic_origin.clone()),
1228 (CapabilityId::Protocol(&b), synthetic_origin)
1229 ]
1230 );
1231
1232 Ok(())
1233 }
1234
1235 #[test]
1236 fn test_use_protocol() -> Result<(), Error> {
1237 let a: Name = "a".parse().unwrap();
1238 let b: Name = "b".parse().unwrap();
1239
1240 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1241
1242 assert_eq!(
1243 CapabilityId::from_use(&Use {
1244 protocol: Some(OneOrMany::One(a.clone())),
1245 ..Use::default()
1246 },)?,
1247 vec![CapabilityId::UsedProtocol("/svc/a".parse().unwrap())]
1248 );
1249
1250 assert_eq!(
1251 CapabilityId::from_context_use(&ContextSpanned {
1252 value: ContextUse {
1253 protocol: Some(ContextSpanned {
1254 value: OneOrMany::One(a.clone()),
1255 origin: synthetic_origin.clone(),
1256 }),
1257 ..ContextUse::default()
1258 },
1259 origin: synthetic_origin.clone(),
1260 })?,
1261 vec![(CapabilityId::UsedProtocol("/svc/a".parse().unwrap()), synthetic_origin.clone())]
1262 );
1263 assert_eq!(
1264 CapabilityId::from_use(&Use {
1265 protocol: Some(OneOrMany::Many(vec![a.clone(), b.clone(),],)),
1266 ..Use::default()
1267 },)?,
1268 vec![
1269 CapabilityId::UsedProtocol("/svc/a".parse().unwrap()),
1270 CapabilityId::UsedProtocol("/svc/b".parse().unwrap())
1271 ]
1272 );
1273
1274 assert_eq!(
1275 CapabilityId::from_context_use(&ContextSpanned {
1276 value: ContextUse {
1277 protocol: Some(ContextSpanned {
1278 value: OneOrMany::Many(vec![a.clone(), b.clone(),]),
1279 origin: synthetic_origin.clone(),
1280 }),
1281 ..ContextUse::default()
1282 },
1283 origin: synthetic_origin.clone(),
1284 })?,
1285 vec![
1286 (CapabilityId::UsedProtocol("/svc/a".parse().unwrap()), synthetic_origin.clone()),
1287 (CapabilityId::UsedProtocol("/svc/b".parse().unwrap()), synthetic_origin.clone())
1288 ]
1289 );
1290
1291 assert_eq!(
1292 CapabilityId::from_use(&Use {
1293 protocol: Some(OneOrMany::One(a.clone())),
1294 path: Some("/b".parse().unwrap()),
1295 ..Use::default()
1296 },)?,
1297 vec![CapabilityId::UsedProtocol("/b".parse().unwrap())]
1298 );
1299
1300 assert_eq!(
1301 CapabilityId::from_context_use(&ContextSpanned {
1302 value: ContextUse {
1303 protocol: Some(ContextSpanned {
1304 value: OneOrMany::One(a.clone()),
1305 origin: synthetic_origin.clone(),
1306 }),
1307 path: Some(ContextSpanned {
1308 value: "/b".parse().unwrap(),
1309 origin: synthetic_origin.clone(),
1310 }),
1311 ..ContextUse::default()
1312 },
1313 origin: synthetic_origin.clone(),
1314 })?,
1315 vec![(CapabilityId::UsedProtocol("/b".parse().unwrap()), synthetic_origin.clone())]
1316 );
1317
1318 Ok(())
1319 }
1320
1321 #[test]
1322 fn test_offer_directory() -> Result<(), Error> {
1323 let a: Name = "a".parse().unwrap();
1324 let b: Name = "b".parse().unwrap();
1325
1326 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1327
1328 assert_eq!(
1329 CapabilityId::from_offer_expose(&Offer {
1330 directory: Some(OneOrMany::One(a.clone())),
1331 ..Offer::default()
1332 },)?,
1333 vec![CapabilityId::Directory(&a)]
1334 );
1335
1336 assert_eq!(
1337 CapabilityId::from_context_offer(&ContextSpanned {
1338 value: ContextOffer {
1339 directory: Some(ContextSpanned {
1340 value: OneOrMany::One(a.clone()),
1341 origin: synthetic_origin.clone(),
1342 }),
1343 ..ContextOffer::default()
1344 },
1345 origin: synthetic_origin.clone(),
1346 })?,
1347 vec![(CapabilityId::Directory(&a), synthetic_origin.clone())]
1348 );
1349
1350 assert_eq!(
1351 CapabilityId::from_offer_expose(&Offer {
1352 directory: Some(OneOrMany::Many(vec![a.clone(), b.clone()])),
1353 ..Offer::default()
1354 },)?,
1355 vec![CapabilityId::Directory(&a), CapabilityId::Directory(&b),]
1356 );
1357
1358 assert_eq!(
1359 CapabilityId::from_context_offer(&ContextSpanned {
1360 value: ContextOffer {
1361 directory: Some(ContextSpanned {
1362 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1363 origin: synthetic_origin.clone(),
1364 }),
1365 ..ContextOffer::default()
1366 },
1367 origin: synthetic_origin.clone(),
1368 })?,
1369 vec![
1370 (CapabilityId::Directory(&a), synthetic_origin.clone()),
1371 (CapabilityId::Directory(&b), synthetic_origin.clone())
1372 ]
1373 );
1374
1375 Ok(())
1376 }
1377
1378 #[test]
1379 fn test_use_directory() -> Result<(), Error> {
1380 let a: Name = "a".parse().unwrap();
1381
1382 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1383
1384 assert_eq!(
1385 CapabilityId::from_use(&Use {
1386 directory: Some(a.clone()),
1387 path: Some("/b".parse().unwrap()),
1388 ..Use::default()
1389 },)?,
1390 vec![CapabilityId::UsedDirectory("/b".parse().unwrap())]
1391 );
1392
1393 assert_eq!(
1394 CapabilityId::from_context_use(&ContextSpanned {
1395 value: ContextUse {
1396 directory: Some(ContextSpanned {
1397 value: a.clone(),
1398 origin: synthetic_origin.clone(),
1399 }),
1400 path: Some(ContextSpanned {
1401 value: "/b".parse().unwrap(),
1402 origin: synthetic_origin.clone(),
1403 }),
1404 ..ContextUse::default()
1405 },
1406 origin: synthetic_origin.clone(),
1407 })?,
1408 vec![(CapabilityId::UsedDirectory("/b".parse().unwrap()), synthetic_origin.clone())]
1409 );
1410
1411 Ok(())
1412 }
1413
1414 #[test]
1415 fn test_offer_storage() -> Result<(), Error> {
1416 let a: Name = "a".parse().unwrap();
1417 let b: Name = "b".parse().unwrap();
1418
1419 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1420
1421 assert_eq!(
1422 CapabilityId::from_offer_expose(&Offer {
1423 storage: Some(OneOrMany::One(a.clone())),
1424 ..Offer::default()
1425 },)?,
1426 vec![CapabilityId::Storage(&a)]
1427 );
1428
1429 assert_eq!(
1430 CapabilityId::from_context_offer(&ContextSpanned {
1431 value: ContextOffer {
1432 storage: Some(ContextSpanned {
1433 value: OneOrMany::One(a.clone()),
1434 origin: synthetic_origin.clone(),
1435 }),
1436 ..ContextOffer::default()
1437 },
1438 origin: synthetic_origin.clone(),
1439 })?,
1440 vec![(CapabilityId::Storage(&a), synthetic_origin.clone())]
1441 );
1442
1443 assert_eq!(
1444 CapabilityId::from_offer_expose(&Offer {
1445 storage: Some(OneOrMany::Many(vec![a.clone(), b.clone()])),
1446 ..Offer::default()
1447 },)?,
1448 vec![CapabilityId::Storage(&a), CapabilityId::Storage(&b),]
1449 );
1450
1451 assert_eq!(
1452 CapabilityId::from_context_offer(&ContextSpanned {
1453 value: ContextOffer {
1454 storage: Some(ContextSpanned {
1455 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1456 origin: synthetic_origin.clone(),
1457 }),
1458 ..ContextOffer::default()
1459 },
1460 origin: synthetic_origin.clone(),
1461 })?,
1462 vec![
1463 (CapabilityId::Storage(&a), synthetic_origin.clone()),
1464 (CapabilityId::Storage(&b), synthetic_origin.clone())
1465 ]
1466 );
1467
1468 Ok(())
1469 }
1470
1471 #[test]
1472 fn test_use_storage() -> Result<(), Error> {
1473 let a: Name = "a".parse().unwrap();
1474
1475 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1476
1477 assert_eq!(
1478 CapabilityId::from_use(&Use {
1479 storage: Some(a.clone()),
1480 path: Some("/b".parse().unwrap()),
1481 ..Use::default()
1482 },)?,
1483 vec![CapabilityId::UsedStorage("/b".parse().unwrap())]
1484 );
1485
1486 assert_eq!(
1487 CapabilityId::from_context_use(&ContextSpanned {
1488 value: ContextUse {
1489 storage: Some(ContextSpanned {
1490 value: a.clone(),
1491 origin: synthetic_origin.clone(),
1492 }),
1493 path: Some(ContextSpanned {
1494 value: "/b".parse().unwrap(),
1495 origin: synthetic_origin.clone(),
1496 }),
1497 ..ContextUse::default()
1498 },
1499 origin: synthetic_origin.clone(),
1500 })?,
1501 vec![(CapabilityId::UsedStorage("/b".parse().unwrap()), synthetic_origin.clone())]
1502 );
1503
1504 Ok(())
1505 }
1506
1507 #[test]
1508 fn test_use_runner() -> Result<(), Error> {
1509 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1510
1511 assert_eq!(
1512 CapabilityId::from_use(&Use {
1513 runner: Some("elf".parse().unwrap()),
1514 ..Use::default()
1515 })?,
1516 vec![CapabilityId::UsedRunner(BorrowedName::new("elf").unwrap())]
1517 );
1518
1519 assert_eq!(
1520 CapabilityId::from_context_use(&ContextSpanned {
1521 value: ContextUse {
1522 runner: Some(ContextSpanned {
1523 value: "elf".parse().unwrap(),
1524 origin: synthetic_origin.clone(),
1525 }),
1526 ..ContextUse::default()
1527 },
1528 origin: synthetic_origin.clone(),
1529 })?,
1530 vec![(
1531 CapabilityId::UsedRunner(BorrowedName::new("elf").unwrap()),
1532 synthetic_origin.clone()
1533 )]
1534 );
1535
1536 Ok(())
1537 }
1538
1539 #[test]
1540 fn test_offer_dictionary() -> Result<(), Error> {
1541 let a: Name = "a".parse().unwrap();
1542 let b: Name = "b".parse().unwrap();
1543
1544 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1545
1546 assert_eq!(
1547 CapabilityId::from_offer_expose(&Offer {
1548 dictionary: Some(OneOrMany::One(a.clone())),
1549 ..Offer::default()
1550 },)?,
1551 vec![CapabilityId::Dictionary(&a)]
1552 );
1553
1554 assert_eq!(
1555 CapabilityId::from_context_offer(&ContextSpanned {
1556 value: ContextOffer {
1557 dictionary: Some(ContextSpanned {
1558 value: OneOrMany::One(a.clone()),
1559 origin: synthetic_origin.clone(),
1560 }),
1561 ..ContextOffer::default()
1562 },
1563 origin: synthetic_origin.clone(),
1564 })?,
1565 vec![(CapabilityId::Dictionary(&a), synthetic_origin.clone())]
1566 );
1567
1568 assert_eq!(
1569 CapabilityId::from_offer_expose(&Offer {
1570 dictionary: Some(OneOrMany::Many(vec![a.clone(), b.clone()],)),
1571 ..Offer::default()
1572 },)?,
1573 vec![CapabilityId::Dictionary(&a), CapabilityId::Dictionary(&b)]
1574 );
1575
1576 assert_eq!(
1577 CapabilityId::from_context_offer(&ContextSpanned {
1578 value: ContextOffer {
1579 dictionary: Some(ContextSpanned {
1580 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1581 origin: synthetic_origin.clone(),
1582 }),
1583 ..ContextOffer::default()
1584 },
1585 origin: synthetic_origin.clone(),
1586 })?,
1587 vec![
1588 (CapabilityId::Dictionary(&a), synthetic_origin.clone()),
1589 (CapabilityId::Dictionary(&b), synthetic_origin.clone())
1590 ]
1591 );
1592
1593 Ok(())
1594 }
1595
1596 #[test]
1597 fn test_use_dictionary() -> Result<(), Error> {
1598 let a: Name = "a".parse().unwrap();
1599 let b: Name = "b".parse().unwrap();
1600
1601 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1602
1603 assert_eq!(
1604 CapabilityId::from_use(&Use {
1605 dictionary: Some(OneOrMany::One(a.clone())),
1606 ..Use::default()
1607 },)?,
1608 vec![CapabilityId::UsedDictionary("/svc/a".parse().unwrap())]
1609 );
1610
1611 assert_eq!(
1612 CapabilityId::from_context_use(&ContextSpanned {
1613 value: ContextUse {
1614 dictionary: Some(ContextSpanned {
1615 value: OneOrMany::One(a.clone()),
1616 origin: synthetic_origin.clone(),
1617 }),
1618 ..ContextUse::default()
1619 },
1620 origin: synthetic_origin.clone(),
1621 })?,
1622 vec![(
1623 CapabilityId::UsedDictionary("/svc/a".parse().unwrap()),
1624 synthetic_origin.clone()
1625 )]
1626 );
1627
1628 assert_eq!(
1629 CapabilityId::from_use(&Use {
1630 dictionary: Some(OneOrMany::Many(vec![a.clone(), b.clone(),],)),
1631 ..Use::default()
1632 },)?,
1633 vec![
1634 CapabilityId::UsedDictionary("/svc/a".parse().unwrap()),
1635 CapabilityId::UsedDictionary("/svc/b".parse().unwrap())
1636 ]
1637 );
1638
1639 assert_eq!(
1640 CapabilityId::from_context_use(&ContextSpanned {
1641 value: ContextUse {
1642 dictionary: Some(ContextSpanned {
1643 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1644 origin: synthetic_origin.clone(),
1645 }),
1646 ..ContextUse::default()
1647 },
1648 origin: synthetic_origin.clone(),
1649 })?,
1650 vec![
1651 (CapabilityId::UsedDictionary("/svc/a".parse().unwrap()), synthetic_origin.clone()),
1652 (CapabilityId::UsedDictionary("/svc/b".parse().unwrap()), synthetic_origin.clone())
1653 ]
1654 );
1655
1656 assert_eq!(
1657 CapabilityId::from_use(&Use {
1658 dictionary: Some(OneOrMany::One(a.clone())),
1659 path: Some("/b".parse().unwrap()),
1660 ..Use::default()
1661 },)?,
1662 vec![CapabilityId::UsedDictionary("/b".parse().unwrap())]
1663 );
1664
1665 assert_eq!(
1666 CapabilityId::from_context_use(&ContextSpanned {
1667 value: ContextUse {
1668 dictionary: Some(ContextSpanned {
1669 value: OneOrMany::One(a.clone()),
1670 origin: synthetic_origin.clone(),
1671 }),
1672 path: Some(ContextSpanned {
1673 value: "/b".parse().unwrap(),
1674 origin: synthetic_origin.clone()
1675 }),
1676 ..ContextUse::default()
1677 },
1678 origin: synthetic_origin.clone(),
1679 })?,
1680 vec![(CapabilityId::UsedDictionary("/b".parse().unwrap()), synthetic_origin.clone())]
1681 );
1682
1683 Ok(())
1684 }
1685
1686 #[test]
1687 fn test_errors() -> Result<(), Error> {
1688 assert_matches!(CapabilityId::from_offer_expose(&Offer::default()), Err(_));
1689
1690 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1691
1692 assert_matches!(
1693 CapabilityId::from_context_offer(&ContextSpanned {
1694 value: ContextOffer::default(),
1695 origin: synthetic_origin
1696 }),
1697 Err(_)
1698 );
1699
1700 Ok(())
1701 }
1702}