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::r#use::ContextUse;
9use crate::{AsClauseContext, ContextSpanned, Error, alias_or_name_context};
10pub use cm_types::{
11 Availability, BorrowedName, BoundedName, DeliveryType, DependencyType, HandleType, Name,
12 NamespacePath, OnTerminate, ParseError, Path, RelativePath, StartupMode, StorageId, Url,
13};
14
15use std::fmt;
16use std::path::PathBuf;
17use std::sync::Arc;
18
19#[derive(Debug, PartialEq, Eq, Hash, Clone)]
30pub enum CapabilityId<'a> {
31 Service(&'a BorrowedName),
32 Protocol(&'a BorrowedName),
33 Directory(&'a BorrowedName),
34 UsedService(Path),
36 UsedProtocol(Path),
38 UsedProtocolNumberedHandle(HandleType),
40 UsedDirectory(Path),
42 UsedStorage(Path),
44 UsedEventStream(Path),
46 UsedConfiguration(&'a BorrowedName),
48 UsedRunner(&'a BorrowedName),
49 UsedDictionary(Path),
51 Storage(&'a BorrowedName),
52 Runner(&'a BorrowedName),
53 Resolver(&'a BorrowedName),
54 EventStream(&'a BorrowedName),
55 Dictionary(&'a BorrowedName),
56 Configuration(&'a BorrowedName),
57}
58
59macro_rules! capability_ids_from_context_names {
61 ($name:ident, $variant:expr) => {
62 fn $name(names: Vec<ContextSpanned<&'a BorrowedName>>) -> Vec<(Self, Arc<PathBuf>)> {
63 names
64 .into_iter()
65 .map(|spanned_name| ($variant(spanned_name.value), spanned_name.origin))
66 .collect()
67 }
68 };
69}
70
71macro_rules! capability_ids_from_context_paths {
73 ($name:ident, $variant:expr) => {
74 fn $name(paths: Vec<ContextSpanned<Path>>) -> Vec<(Self, Arc<PathBuf>)> {
75 paths
76 .into_iter()
77 .map(|spanned_path| ($variant(spanned_path.value), spanned_path.origin))
78 .collect()
79 }
80 };
81}
82
83impl<'a> CapabilityId<'a> {
84 pub fn type_str(&self) -> &'static str {
86 match self {
87 CapabilityId::Service(_) => "service",
88 CapabilityId::Protocol(_) => "protocol",
89 CapabilityId::Directory(_) => "directory",
90 CapabilityId::UsedService(_) => "service",
91 CapabilityId::UsedProtocol(_) => "protocol",
92 CapabilityId::UsedProtocolNumberedHandle(_) => "protocol",
93 CapabilityId::UsedDirectory(_) => "directory",
94 CapabilityId::UsedStorage(_) => "storage",
95 CapabilityId::UsedEventStream(_) => "event_stream",
96 CapabilityId::UsedRunner(_) => "runner",
97 CapabilityId::UsedConfiguration(_) => "config",
98 CapabilityId::UsedDictionary(_) => "dictionary",
99 CapabilityId::Storage(_) => "storage",
100 CapabilityId::Runner(_) => "runner",
101 CapabilityId::Resolver(_) => "resolver",
102 CapabilityId::EventStream(_) => "event_stream",
103 CapabilityId::Dictionary(_) => "dictionary",
104 CapabilityId::Configuration(_) => "config",
105 }
106 }
107
108 pub fn get_dir_path(&self) -> Option<NamespacePath> {
110 match self {
111 CapabilityId::UsedService(p)
112 | CapabilityId::UsedProtocol(p)
113 | CapabilityId::UsedEventStream(p) => Some(p.parent()),
114 CapabilityId::UsedDirectory(p)
115 | CapabilityId::UsedStorage(p)
116 | CapabilityId::UsedDictionary(p) => Some(p.clone().into()),
117 _ => None,
118 }
119 }
120
121 pub fn get_target_path(&self) -> Option<NamespacePath> {
123 match self {
124 CapabilityId::UsedService(p)
125 | CapabilityId::UsedProtocol(p)
126 | CapabilityId::UsedEventStream(p)
127 | CapabilityId::UsedDirectory(p)
128 | CapabilityId::UsedStorage(p)
129 | CapabilityId::UsedDictionary(p) => Some(p.clone().into()),
130 _ => None,
131 }
132 }
133
134 pub fn from_context_capability(
135 capability_input: &'a ContextSpanned<ContextCapability>,
136 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
137 let capability = &capability_input.value;
138 let origin = &capability_input.origin;
139
140 if let Some(n) = capability.service() {
141 if n.value.is_many()
142 && let Some(cs_path) = &capability.path
143 {
144 return Err(Error::validate_context(
145 "\"path\" can only be specified when one `service` is supplied.",
146 Some(cs_path.origin.clone()),
147 ));
148 }
149 return Ok(Self::services_from_context(Self::get_one_or_many_names_context(
150 n,
151 None,
152 capability.capability_type(None).unwrap(),
153 )?));
154 } else if let Some(n) = capability.protocol() {
155 if n.value.is_many()
156 && let Some(cs_path) = &capability.path
157 {
158 return Err(Error::validate_context(
159 "\"path\" can only be specified when one `protocol` is supplied.",
160 Some(cs_path.origin.clone()),
161 ));
162 }
163 return Ok(Self::protocols_from_context(Self::get_one_or_many_names_context(
164 n,
165 None,
166 capability.capability_type(None).unwrap(),
167 )?));
168 } else if let Some(n) = capability.directory() {
169 return Ok(Self::directories_from_context(Self::get_one_or_many_names_context(
170 n,
171 None,
172 capability.capability_type(None).unwrap(),
173 )?));
174 } else if let Some(cs_storage) = capability.storage() {
175 if capability.storage_id.is_none() {
176 return Err(Error::validate_context(
177 "Storage declaration is missing \"storage_id\", but is required.",
178 Some(cs_storage.origin),
179 ));
180 }
181 return Ok(Self::storages_from_context(Self::get_one_or_many_names_context(
182 cs_storage,
183 None,
184 capability.capability_type(None).unwrap(),
185 )?));
186 } else if let Some(n) = capability.runner() {
187 return Ok(Self::runners_from_context(Self::get_one_or_many_names_context(
188 n,
189 None,
190 capability.capability_type(None).unwrap(),
191 )?));
192 } else if let Some(n) = capability.resolver() {
193 return Ok(Self::resolvers_from_context(Self::get_one_or_many_names_context(
194 n,
195 None,
196 capability.capability_type(None).unwrap(),
197 )?));
198 } else if let Some(n) = capability.event_stream() {
199 return Ok(Self::event_streams_from_context(Self::get_one_or_many_names_context(
200 n,
201 None,
202 capability.capability_type(None).unwrap(),
203 )?));
204 } else if let Some(n) = capability.dictionary() {
205 return Ok(Self::dictionaries_from_context(Self::get_one_or_many_names_context(
206 n,
207 None,
208 capability.capability_type(None).unwrap(),
209 )?));
210 } else if let Some(n) = capability.config() {
211 return Ok(Self::configurations_from_context(Self::get_one_or_many_names_context(
212 n,
213 None,
214 capability.capability_type(None).unwrap(),
215 )?));
216 }
217
218 let supported_keywords = capability
220 .supported()
221 .into_iter()
222 .map(|k| format!("\"{}\"", k))
223 .collect::<Vec<_>>()
224 .join(", ");
225 Err(Error::validate_context(
226 format!(
227 "`{}` declaration is missing a capability keyword, one of: {}",
228 capability.decl_type(),
229 supported_keywords,
230 ),
231 Some(origin.clone()),
232 ))
233 }
234
235 pub fn from_context_offer_expose<T>(
236 clause_input: &'a ContextSpanned<T>,
237 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error>
238 where
239 T: ContextCapabilityClause + AsClauseContext + fmt::Debug,
240 {
241 let clause = &clause_input.value;
242 let origin = &clause_input.origin;
243
244 let alias = clause.r#as();
245
246 if let Some(n) = clause.service() {
247 return Ok(Self::services_from_context(Self::get_one_or_many_names_context(
248 n,
249 alias,
250 clause.capability_type(Some(origin.clone())).unwrap(),
251 )?));
252 } else if let Some(n) = clause.protocol() {
253 return Ok(Self::protocols_from_context(Self::get_one_or_many_names_context(
254 n,
255 alias,
256 clause.capability_type(Some(origin.clone())).unwrap(),
257 )?));
258 } else if let Some(n) = clause.directory() {
259 return Ok(Self::directories_from_context(Self::get_one_or_many_names_context(
260 n,
261 alias,
262 clause.capability_type(Some(origin.clone())).unwrap(),
263 )?));
264 } else if let Some(n) = clause.storage() {
265 return Ok(Self::storages_from_context(Self::get_one_or_many_names_context(
266 n,
267 alias,
268 clause.capability_type(Some(origin.clone())).unwrap(),
269 )?));
270 } else if let Some(n) = clause.runner() {
271 return Ok(Self::runners_from_context(Self::get_one_or_many_names_context(
272 n,
273 alias,
274 clause.capability_type(Some(origin.clone())).unwrap(),
275 )?));
276 } else if let Some(n) = clause.resolver() {
277 return Ok(Self::resolvers_from_context(Self::get_one_or_many_names_context(
278 n,
279 alias,
280 clause.capability_type(Some(origin.clone())).unwrap(),
281 )?));
282 } else if let Some(event_stream) = clause.event_stream() {
283 return Ok(Self::event_streams_from_context(Self::get_one_or_many_names_context(
284 event_stream,
285 alias,
286 clause.capability_type(Some(origin.clone())).unwrap(),
287 )?));
288 } else if let Some(n) = clause.dictionary() {
289 return Ok(Self::dictionaries_from_context(Self::get_one_or_many_names_context(
290 n,
291 alias,
292 clause.capability_type(Some(origin.clone())).unwrap(),
293 )?));
294 } else if let Some(n) = clause.config() {
295 return Ok(Self::configurations_from_context(Self::get_one_or_many_names_context(
296 n,
297 alias,
298 clause.capability_type(Some(origin.clone())).unwrap(),
299 )?));
300 }
301
302 let supported_keywords = clause
304 .supported()
305 .into_iter()
306 .map(|k| format!("\"{}\"", k))
307 .collect::<Vec<_>>()
308 .join(", ");
309 Err(Error::validate_context(
310 format!(
311 "`{}` declaration is missing a capability keyword, one of: {}",
312 clause.decl_type(),
313 supported_keywords,
314 ),
315 Some(origin.clone()),
316 ))
317 }
318
319 pub fn from_context_use(
328 use_input: &'a ContextSpanned<ContextUse>,
329 ) -> Result<Vec<(Self, Arc<PathBuf>)>, Error> {
330 let use_ = &use_input.value;
331 let origin = &use_input.origin;
332
333 let alias = use_.path.as_ref();
334
335 if let Some(n) = option_one_or_many_as_ref_context(&use_.service) {
336 return Ok(Self::used_services_from_context(Self::get_one_or_many_svc_paths_context(
337 n,
338 alias,
339 use_input.capability_type(Some(origin.clone())).unwrap(),
340 )?));
341 } else if let Some(n) = option_one_or_many_as_ref_context(&use_.protocol) {
342 if let Some(numbered_handle) = &use_.numbered_handle {
343 return Ok(n
344 .value
345 .iter()
346 .map(|_| {
347 (
348 CapabilityId::UsedProtocolNumberedHandle(numbered_handle.value),
349 n.origin.clone(),
350 )
351 })
352 .collect());
353 }
354
355 return Ok(Self::used_protocols_from_context(Self::get_one_or_many_svc_paths_context(
356 n,
357 alias,
358 use_input.capability_type(Some(origin.clone())).unwrap(),
359 )?));
360 } else if let Some(_) = &use_.directory {
361 if use_.path.is_none() {
362 return Err(Error::validate_context(
363 "\"path\" should be present for `use directory`.",
364 Some(origin.clone()),
365 ));
366 }
367 return Ok(vec![(
368 CapabilityId::UsedDirectory(use_.path.as_ref().unwrap().value.clone()),
369 origin.clone(),
370 )]);
371 } else if let Some(_) = &use_.storage {
372 if use_.path.is_none() {
373 return Err(Error::validate_context(
374 "\"path\" should be present for `use storage`.",
375 Some(origin.clone()),
376 ));
377 }
378 return Ok(vec![(
379 CapabilityId::UsedStorage(use_.path.as_ref().unwrap().value.clone()),
380 origin.clone(),
381 )]);
382 } else if let Some(_) = &use_.event_stream {
383 if let Some(path) = &use_.path {
384 return Ok(vec![(
385 CapabilityId::UsedEventStream(path.value.clone()),
386 origin.clone(),
387 )]);
388 }
389 return Ok(vec![(
390 CapabilityId::UsedEventStream(Path::new("/svc/fuchsia.component.EventStream")?),
391 origin.clone(),
392 )]);
393 } else if let Some(n) = &use_.runner {
394 return Ok(vec![(CapabilityId::UsedRunner(&n.value), n.origin.clone())]);
395 } else if let Some(_) = &use_.config {
396 return match &use_.key {
397 None => Err(Error::validate_context(
398 "\"key\" should be present for `use config`.",
399 Some(origin.clone()),
400 )),
401 Some(name) => {
402 Ok(vec![(CapabilityId::UsedConfiguration(&name.value), origin.clone())])
403 }
404 };
405 } else if let Some(n) = option_one_or_many_as_ref_context(&use_.dictionary) {
406 return Ok(Self::used_dictionaries_from_context(
407 Self::get_one_or_many_svc_paths_context(
408 n,
409 alias,
410 use_input.capability_type(Some(origin.clone())).unwrap(),
411 )?,
412 ));
413 }
414
415 let supported_keywords = use_input
417 .supported()
418 .into_iter()
419 .map(|k| format!("\"{}\"", k))
420 .collect::<Vec<_>>()
421 .join(", ");
422
423 Err(Error::validate_context(
424 format!(
425 "`{}` declaration is missing a capability keyword, one of: {}",
426 use_input.decl_type(),
427 supported_keywords,
428 ),
429 Some(origin.clone()),
430 ))
431 }
432
433 fn get_one_or_many_names_context<'b>(
435 name_wrapper: ContextSpanned<OneOrMany<&'b BorrowedName>>,
436 alias: Option<ContextSpanned<&'b BorrowedName>>,
437 capability_type: &str,
438 ) -> Result<Vec<ContextSpanned<&'b BorrowedName>>, Error> {
439 let names_origin = name_wrapper.origin;
440 let names_vec: Vec<&'b BorrowedName> = name_wrapper.value.into_iter().collect();
441 let num_names = names_vec.len();
442
443 if num_names > 1 && alias.is_some() {
444 return Err(Error::validate_contexts(
445 format!("\"as\" can only be specified when one `{}` is supplied.", capability_type),
446 vec![alias.map(|s| s.origin).unwrap_or(names_origin)],
447 ));
448 }
449
450 if num_names == 1 {
451 let final_name_span = alias_or_name_context(alias, names_vec[0], names_origin);
452 return Ok(vec![final_name_span]);
453 }
454
455 let final_names = names_vec
456 .into_iter()
457 .map(|name| ContextSpanned { value: name, origin: names_origin.clone() })
458 .collect();
459
460 Ok(final_names)
461 }
462
463 fn get_one_or_many_svc_paths_context(
464 names: ContextSpanned<OneOrMany<&BorrowedName>>,
465 alias: Option<&ContextSpanned<Path>>,
466 capability_type: &str,
467 ) -> Result<Vec<ContextSpanned<Path>>, Error> {
468 let names_origin = &names.origin;
469 let names_vec: Vec<_> = names.value.into_iter().collect();
470
471 match (names_vec.len(), alias) {
472 (_, None) => {
473 let generated_paths = names_vec
474 .into_iter()
475 .map(|n| {
476 let new_path: Path = format!("/svc/{}", n).parse().unwrap();
477 ContextSpanned { value: new_path, origin: names_origin.clone() }
478 })
479 .collect();
480 Ok(generated_paths)
481 }
482
483 (1, Some(spanned_alias)) => Ok(vec![spanned_alias.clone()]),
484
485 (_, Some(spanned_alias)) => Err(Error::validate_contexts(
486 format!(
487 "\"path\" can only be specified when one `{}` is supplied.",
488 capability_type,
489 ),
490 vec![spanned_alias.origin.clone()],
491 )),
492 }
493 }
494
495 capability_ids_from_context_names!(services_from_context, CapabilityId::Service);
496 capability_ids_from_context_names!(protocols_from_context, CapabilityId::Protocol);
497 capability_ids_from_context_names!(directories_from_context, CapabilityId::Directory);
498 capability_ids_from_context_names!(storages_from_context, CapabilityId::Storage);
499 capability_ids_from_context_names!(runners_from_context, CapabilityId::Runner);
500 capability_ids_from_context_names!(resolvers_from_context, CapabilityId::Resolver);
501 capability_ids_from_context_names!(event_streams_from_context, CapabilityId::EventStream);
502 capability_ids_from_context_names!(dictionaries_from_context, CapabilityId::Dictionary);
503 capability_ids_from_context_names!(configurations_from_context, CapabilityId::Configuration);
504
505 capability_ids_from_context_paths!(used_services_from_context, CapabilityId::UsedService);
506 capability_ids_from_context_paths!(used_protocols_from_context, CapabilityId::UsedProtocol);
507 capability_ids_from_context_paths!(
508 used_dictionaries_from_context,
509 CapabilityId::UsedDictionary
510 );
511}
512
513impl fmt::Display for CapabilityId<'_> {
514 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
516 match self {
517 CapabilityId::Service(n)
518 | CapabilityId::Storage(n)
519 | CapabilityId::Runner(n)
520 | CapabilityId::UsedRunner(n)
521 | CapabilityId::Resolver(n)
522 | CapabilityId::EventStream(n)
523 | CapabilityId::Configuration(n)
524 | CapabilityId::UsedConfiguration(n)
525 | CapabilityId::Dictionary(n) => write!(f, "{}", n),
526 CapabilityId::UsedService(p)
527 | CapabilityId::UsedProtocol(p)
528 | CapabilityId::UsedDirectory(p)
529 | CapabilityId::UsedStorage(p)
530 | CapabilityId::UsedEventStream(p)
531 | CapabilityId::UsedDictionary(p) => write!(f, "{}", p),
532 CapabilityId::UsedProtocolNumberedHandle(p) => write!(f, "{}", p),
533 CapabilityId::Protocol(p) | CapabilityId::Directory(p) => write!(f, "{}", p),
534 }
535 }
536}
537
538#[cfg(test)]
539mod tests {
540 use super::*;
541 use crate::types::offer::ContextOffer;
542 use assert_matches::assert_matches;
543 use std::path::PathBuf;
544 use std::sync::Arc;
545
546 #[test]
547 fn test_offer_service() -> Result<(), Error> {
548 let a: Name = "a".parse().unwrap();
549 let b: Name = "b".parse().unwrap();
550
551 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
552
553 assert_eq!(
554 CapabilityId::from_context_offer_expose(&ContextSpanned {
555 value: ContextOffer {
556 service: Some(ContextSpanned {
557 value: OneOrMany::One(a.clone()),
558 origin: synthetic_origin.clone(),
559 }),
560 ..ContextOffer::default()
561 },
562 origin: synthetic_origin.clone(),
563 })?,
564 vec![(CapabilityId::Service(&a), synthetic_origin.clone())]
565 );
566
567 assert_eq!(
568 CapabilityId::from_context_offer_expose(&ContextSpanned {
569 value: ContextOffer {
570 service: Some(ContextSpanned {
571 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
572 origin: synthetic_origin.clone(),
573 }),
574 ..ContextOffer::default()
575 },
576 origin: synthetic_origin.clone(),
577 })?,
578 vec![
579 (CapabilityId::Service(&a), synthetic_origin.clone()),
580 (CapabilityId::Service(&b), synthetic_origin.clone())
581 ]
582 );
583
584 assert_eq!(
586 CapabilityId::from_context_offer_expose(&ContextSpanned {
587 value: ContextOffer {
588 service: Some(ContextSpanned {
589 value: OneOrMany::One(a.clone()),
590 origin: synthetic_origin.clone(),
591 }),
592 r#as: Some(ContextSpanned {
593 value: b.clone(),
594 origin: synthetic_origin.clone()
595 }),
596 ..ContextOffer::default()
597 },
598 origin: synthetic_origin.clone(),
599 })?,
600 vec![(CapabilityId::Service(&b), synthetic_origin)]
601 );
602
603 Ok(())
604 }
605
606 #[test]
607 fn test_use_service() -> Result<(), Error> {
608 let a: Name = "a".parse().unwrap();
609 let b: Name = "b".parse().unwrap();
610
611 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
612
613 assert_eq!(
614 CapabilityId::from_context_use(&ContextSpanned {
615 value: ContextUse {
616 service: Some(ContextSpanned {
617 value: OneOrMany::One(a.clone()),
618 origin: synthetic_origin.clone(),
619 }),
620 ..ContextUse::default()
621 },
622 origin: synthetic_origin.clone(),
623 })?,
624 vec![(CapabilityId::UsedService("/svc/a".parse().unwrap()), synthetic_origin.clone())]
625 );
626
627 assert_eq!(
628 CapabilityId::from_context_use(&ContextSpanned {
629 value: ContextUse {
630 service: Some(ContextSpanned {
631 value: OneOrMany::Many(vec![a.clone(), b.clone(),]),
632 origin: synthetic_origin.clone(),
633 }),
634 ..ContextUse::default()
635 },
636 origin: synthetic_origin.clone(),
637 })?,
638 vec![
639 (CapabilityId::UsedService("/svc/a".parse().unwrap()), synthetic_origin.clone()),
640 (CapabilityId::UsedService("/svc/b".parse().unwrap()), synthetic_origin.clone())
641 ]
642 );
643
644 assert_eq!(
645 CapabilityId::from_context_use(&ContextSpanned {
646 value: ContextUse {
647 service: Some(ContextSpanned {
648 value: OneOrMany::One(a.clone()),
649 origin: synthetic_origin.clone(),
650 }),
651 path: Some(ContextSpanned {
652 value: "/b".parse().unwrap(),
653 origin: synthetic_origin.clone(),
654 }),
655 ..ContextUse::default()
656 },
657 origin: synthetic_origin.clone(),
658 })?,
659 vec![(CapabilityId::UsedService("/b".parse().unwrap()), synthetic_origin.clone())]
660 );
661
662 Ok(())
663 }
664
665 #[test]
666 fn test_use_event_stream() -> Result<(), Error> {
667 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
668
669 assert_eq!(
670 CapabilityId::from_context_use(&ContextSpanned {
671 value: ContextUse {
672 event_stream: Some(ContextSpanned {
673 value: OneOrMany::One(Name::new("test".to_string()).unwrap()),
674 origin: synthetic_origin.clone(),
675 }),
676 path: Some(ContextSpanned {
677 value: cm_types::Path::new("/svc/myevent".to_string()).unwrap(),
678 origin: synthetic_origin.clone(),
679 }),
680 ..ContextUse::default()
681 },
682 origin: synthetic_origin.clone(),
683 })?,
684 vec![(
685 CapabilityId::UsedEventStream("/svc/myevent".parse().unwrap()),
686 synthetic_origin.clone()
687 )]
688 );
689
690 assert_eq!(
691 CapabilityId::from_context_use(&ContextSpanned {
692 value: ContextUse {
693 event_stream: Some(ContextSpanned {
694 value: OneOrMany::One(Name::new("test".to_string()).unwrap()),
695 origin: synthetic_origin.clone(),
696 }),
697 ..ContextUse::default()
698 },
699 origin: synthetic_origin.clone(),
700 })?,
701 vec![(
702 CapabilityId::UsedEventStream(
703 "/svc/fuchsia.component.EventStream".parse().unwrap()
704 ),
705 synthetic_origin.clone()
706 )]
707 );
708
709 Ok(())
710 }
711
712 #[test]
713 fn test_offer_protocol() -> Result<(), Error> {
714 let a: Name = "a".parse().unwrap();
715 let b: Name = "b".parse().unwrap();
716
717 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
718
719 assert_eq!(
720 CapabilityId::from_context_offer_expose(&ContextSpanned {
721 value: ContextOffer {
722 protocol: Some(ContextSpanned {
723 value: OneOrMany::One(a.clone()),
724 origin: synthetic_origin.clone(),
725 }),
726 ..ContextOffer::default()
727 },
728 origin: synthetic_origin.clone(),
729 })?,
730 vec![(CapabilityId::Protocol(&a), synthetic_origin.clone())]
731 );
732
733 assert_eq!(
734 CapabilityId::from_context_offer_expose(&ContextSpanned {
735 value: ContextOffer {
736 protocol: Some(ContextSpanned {
737 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
738 origin: synthetic_origin.clone(),
739 }),
740 ..ContextOffer::default()
741 },
742 origin: synthetic_origin.clone(),
743 })?,
744 vec![
745 (CapabilityId::Protocol(&a), synthetic_origin.clone()),
746 (CapabilityId::Protocol(&b), synthetic_origin)
747 ]
748 );
749
750 Ok(())
751 }
752
753 #[test]
754 fn test_use_protocol() -> Result<(), Error> {
755 let a: Name = "a".parse().unwrap();
756 let b: Name = "b".parse().unwrap();
757
758 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
759
760 assert_eq!(
761 CapabilityId::from_context_use(&ContextSpanned {
762 value: ContextUse {
763 protocol: Some(ContextSpanned {
764 value: OneOrMany::One(a.clone()),
765 origin: synthetic_origin.clone(),
766 }),
767 ..ContextUse::default()
768 },
769 origin: synthetic_origin.clone(),
770 })?,
771 vec![(CapabilityId::UsedProtocol("/svc/a".parse().unwrap()), synthetic_origin.clone())]
772 );
773
774 assert_eq!(
775 CapabilityId::from_context_use(&ContextSpanned {
776 value: ContextUse {
777 protocol: Some(ContextSpanned {
778 value: OneOrMany::Many(vec![a.clone(), b.clone(),]),
779 origin: synthetic_origin.clone(),
780 }),
781 ..ContextUse::default()
782 },
783 origin: synthetic_origin.clone(),
784 })?,
785 vec![
786 (CapabilityId::UsedProtocol("/svc/a".parse().unwrap()), synthetic_origin.clone()),
787 (CapabilityId::UsedProtocol("/svc/b".parse().unwrap()), synthetic_origin.clone())
788 ]
789 );
790
791 assert_eq!(
792 CapabilityId::from_context_use(&ContextSpanned {
793 value: ContextUse {
794 protocol: Some(ContextSpanned {
795 value: OneOrMany::One(a.clone()),
796 origin: synthetic_origin.clone(),
797 }),
798 path: Some(ContextSpanned {
799 value: "/b".parse().unwrap(),
800 origin: synthetic_origin.clone(),
801 }),
802 ..ContextUse::default()
803 },
804 origin: synthetic_origin.clone(),
805 })?,
806 vec![(CapabilityId::UsedProtocol("/b".parse().unwrap()), synthetic_origin.clone())]
807 );
808
809 Ok(())
810 }
811
812 #[test]
813 fn test_offer_directory() -> Result<(), Error> {
814 let a: Name = "a".parse().unwrap();
815 let b: Name = "b".parse().unwrap();
816
817 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
818
819 assert_eq!(
820 CapabilityId::from_context_offer_expose(&ContextSpanned {
821 value: ContextOffer {
822 directory: Some(ContextSpanned {
823 value: OneOrMany::One(a.clone()),
824 origin: synthetic_origin.clone(),
825 }),
826 ..ContextOffer::default()
827 },
828 origin: synthetic_origin.clone(),
829 })?,
830 vec![(CapabilityId::Directory(&a), synthetic_origin.clone())]
831 );
832
833 assert_eq!(
834 CapabilityId::from_context_offer_expose(&ContextSpanned {
835 value: ContextOffer {
836 directory: Some(ContextSpanned {
837 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
838 origin: synthetic_origin.clone(),
839 }),
840 ..ContextOffer::default()
841 },
842 origin: synthetic_origin.clone(),
843 })?,
844 vec![
845 (CapabilityId::Directory(&a), synthetic_origin.clone()),
846 (CapabilityId::Directory(&b), synthetic_origin.clone())
847 ]
848 );
849
850 Ok(())
851 }
852
853 #[test]
854 fn test_use_directory() -> Result<(), Error> {
855 let a: Name = "a".parse().unwrap();
856
857 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
858
859 assert_eq!(
860 CapabilityId::from_context_use(&ContextSpanned {
861 value: ContextUse {
862 directory: Some(ContextSpanned {
863 value: a.clone(),
864 origin: synthetic_origin.clone(),
865 }),
866 path: Some(ContextSpanned {
867 value: "/b".parse().unwrap(),
868 origin: synthetic_origin.clone(),
869 }),
870 ..ContextUse::default()
871 },
872 origin: synthetic_origin.clone(),
873 })?,
874 vec![(CapabilityId::UsedDirectory("/b".parse().unwrap()), synthetic_origin.clone())]
875 );
876
877 Ok(())
878 }
879
880 #[test]
881 fn test_offer_storage() -> Result<(), Error> {
882 let a: Name = "a".parse().unwrap();
883 let b: Name = "b".parse().unwrap();
884
885 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
886
887 assert_eq!(
888 CapabilityId::from_context_offer_expose(&ContextSpanned {
889 value: ContextOffer {
890 storage: Some(ContextSpanned {
891 value: OneOrMany::One(a.clone()),
892 origin: synthetic_origin.clone(),
893 }),
894 ..ContextOffer::default()
895 },
896 origin: synthetic_origin.clone(),
897 })?,
898 vec![(CapabilityId::Storage(&a), synthetic_origin.clone())]
899 );
900
901 assert_eq!(
902 CapabilityId::from_context_offer_expose(&ContextSpanned {
903 value: ContextOffer {
904 storage: Some(ContextSpanned {
905 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
906 origin: synthetic_origin.clone(),
907 }),
908 ..ContextOffer::default()
909 },
910 origin: synthetic_origin.clone(),
911 })?,
912 vec![
913 (CapabilityId::Storage(&a), synthetic_origin.clone()),
914 (CapabilityId::Storage(&b), synthetic_origin.clone())
915 ]
916 );
917
918 Ok(())
919 }
920
921 #[test]
922 fn test_use_storage() -> Result<(), Error> {
923 let a: Name = "a".parse().unwrap();
924
925 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
926
927 assert_eq!(
928 CapabilityId::from_context_use(&ContextSpanned {
929 value: ContextUse {
930 storage: Some(ContextSpanned {
931 value: a.clone(),
932 origin: synthetic_origin.clone(),
933 }),
934 path: Some(ContextSpanned {
935 value: "/b".parse().unwrap(),
936 origin: synthetic_origin.clone(),
937 }),
938 ..ContextUse::default()
939 },
940 origin: synthetic_origin.clone(),
941 })?,
942 vec![(CapabilityId::UsedStorage("/b".parse().unwrap()), synthetic_origin.clone())]
943 );
944
945 Ok(())
946 }
947
948 #[test]
949 fn test_use_runner() -> Result<(), Error> {
950 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
951
952 assert_eq!(
953 CapabilityId::from_context_use(&ContextSpanned {
954 value: ContextUse {
955 runner: Some(ContextSpanned {
956 value: "elf".parse().unwrap(),
957 origin: synthetic_origin.clone(),
958 }),
959 ..ContextUse::default()
960 },
961 origin: synthetic_origin.clone(),
962 })?,
963 vec![(
964 CapabilityId::UsedRunner(BorrowedName::new("elf").unwrap()),
965 synthetic_origin.clone()
966 )]
967 );
968
969 Ok(())
970 }
971
972 #[test]
973 fn test_offer_dictionary() -> Result<(), Error> {
974 let a: Name = "a".parse().unwrap();
975 let b: Name = "b".parse().unwrap();
976
977 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
978
979 assert_eq!(
980 CapabilityId::from_context_offer_expose(&ContextSpanned {
981 value: ContextOffer {
982 dictionary: Some(ContextSpanned {
983 value: OneOrMany::One(a.clone()),
984 origin: synthetic_origin.clone(),
985 }),
986 ..ContextOffer::default()
987 },
988 origin: synthetic_origin.clone(),
989 })?,
990 vec![(CapabilityId::Dictionary(&a), synthetic_origin.clone())]
991 );
992
993 assert_eq!(
994 CapabilityId::from_context_offer_expose(&ContextSpanned {
995 value: ContextOffer {
996 dictionary: Some(ContextSpanned {
997 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
998 origin: synthetic_origin.clone(),
999 }),
1000 ..ContextOffer::default()
1001 },
1002 origin: synthetic_origin.clone(),
1003 })?,
1004 vec![
1005 (CapabilityId::Dictionary(&a), synthetic_origin.clone()),
1006 (CapabilityId::Dictionary(&b), synthetic_origin.clone())
1007 ]
1008 );
1009
1010 Ok(())
1011 }
1012
1013 #[test]
1014 fn test_use_dictionary() -> Result<(), Error> {
1015 let a: Name = "a".parse().unwrap();
1016 let b: Name = "b".parse().unwrap();
1017
1018 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1019
1020 assert_eq!(
1021 CapabilityId::from_context_use(&ContextSpanned {
1022 value: ContextUse {
1023 dictionary: Some(ContextSpanned {
1024 value: OneOrMany::One(a.clone()),
1025 origin: synthetic_origin.clone(),
1026 }),
1027 ..ContextUse::default()
1028 },
1029 origin: synthetic_origin.clone(),
1030 })?,
1031 vec![(
1032 CapabilityId::UsedDictionary("/svc/a".parse().unwrap()),
1033 synthetic_origin.clone()
1034 )]
1035 );
1036
1037 assert_eq!(
1038 CapabilityId::from_context_use(&ContextSpanned {
1039 value: ContextUse {
1040 dictionary: Some(ContextSpanned {
1041 value: OneOrMany::Many(vec![a.clone(), b.clone()]),
1042 origin: synthetic_origin.clone(),
1043 }),
1044 ..ContextUse::default()
1045 },
1046 origin: synthetic_origin.clone(),
1047 })?,
1048 vec![
1049 (CapabilityId::UsedDictionary("/svc/a".parse().unwrap()), synthetic_origin.clone()),
1050 (CapabilityId::UsedDictionary("/svc/b".parse().unwrap()), synthetic_origin.clone())
1051 ]
1052 );
1053
1054 assert_eq!(
1055 CapabilityId::from_context_use(&ContextSpanned {
1056 value: ContextUse {
1057 dictionary: Some(ContextSpanned {
1058 value: OneOrMany::One(a.clone()),
1059 origin: synthetic_origin.clone(),
1060 }),
1061 path: Some(ContextSpanned {
1062 value: "/b".parse().unwrap(),
1063 origin: synthetic_origin.clone()
1064 }),
1065 ..ContextUse::default()
1066 },
1067 origin: synthetic_origin.clone(),
1068 })?,
1069 vec![(CapabilityId::UsedDictionary("/b".parse().unwrap()), synthetic_origin.clone())]
1070 );
1071
1072 Ok(())
1073 }
1074
1075 #[test]
1076 fn test_errors() -> Result<(), Error> {
1077 let synthetic_origin = Arc::new(PathBuf::from("synthetic"));
1078
1079 assert_matches!(
1080 CapabilityId::from_context_offer_expose(&ContextSpanned {
1081 value: ContextOffer::default(),
1082 origin: synthetic_origin
1083 }),
1084 Err(_)
1085 );
1086
1087 Ok(())
1088 }
1089}