1use super::env::Env;
4use super::error::CapabilityError;
5use super::key::CapabilityKey;
6use std::marker::PhantomData;
7use std::ops::{Deref, DerefMut};
8
9pub trait CapabilitySet {
11 fn verify(env: &Env) -> Result<(), CapabilityError>;
13}
14
15pub trait FromEnv: CapabilitySet + Sized {
17 fn from_env(env: Env) -> Self;
19}
20
21pub trait CapKeys {
23 fn verify_all(env: &Env) -> Result<(), CapabilityError>;
25}
26
27pub struct NoCaps;
29
30impl CapabilitySet for NoCaps {
31 fn verify(_env: &Env) -> Result<(), CapabilityError> {
32 Ok(())
33 }
34}
35
36impl FromEnv for NoCaps {
37 fn from_env(_env: Env) -> Self {
38 Self
39 }
40}
41
42impl CapabilitySet for () {
43 fn verify(_env: &Env) -> Result<(), CapabilityError> {
44 Ok(())
45 }
46}
47
48impl FromEnv for () {
49 fn from_env(_env: Env) -> Self {}
50}
51
52impl CapabilitySet for Env {
53 fn verify(_env: &Env) -> Result<(), CapabilityError> {
54 Ok(())
55 }
56}
57
58impl FromEnv for Env {
59 fn from_env(env: Env) -> Self {
60 env
61 }
62}
63
64impl CapKeys for () {
65 fn verify_all(_env: &Env) -> Result<(), CapabilityError> {
66 Ok(())
67 }
68}
69
70macro_rules! impl_cap_keys {
71 ($($k:ident),*) => {
72 impl<$($k: CapabilityKey),*> CapKeys for ($($k,)*) {
73 fn verify_all(env: &Env) -> Result<(), CapabilityError> {
74 $( env.try_get::<$k>()?; )*
75 Ok(())
76 }
77 }
78 };
79}
80
81impl_cap_keys!(K0);
82impl_cap_keys!(K0, K1);
83impl_cap_keys!(K0, K1, K2);
84impl_cap_keys!(K0, K1, K2, K3);
85impl_cap_keys!(K0, K1, K2, K3, K4);
86impl_cap_keys!(K0, K1, K2, K3, K4, K5);
87impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6);
88impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7);
89impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8);
90impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8, K9);
91impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10);
92impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11);
93impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12);
94impl_cap_keys!(K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13);
95impl_cap_keys!(
96 K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13, K14
97);
98impl_cap_keys!(
99 K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13, K14, K15
100);
101
102#[derive(Clone, Debug, Default, PartialEq, Eq)]
104pub struct CapList<Ks> {
105 inner: Env,
106 _marker: PhantomData<Ks>,
107}
108
109impl<Ks: CapKeys> CapList<Ks> {
110 #[inline]
112 pub fn new(inner: Env) -> Self {
113 Self {
114 inner,
115 _marker: PhantomData,
116 }
117 }
118
119 #[inline]
121 pub fn env(&self) -> &Env {
122 &self.inner
123 }
124
125 #[inline]
127 pub fn env_mut(&mut self) -> &mut Env {
128 &mut self.inner
129 }
130}
131
132impl<Ks: CapKeys> Deref for CapList<Ks> {
133 type Target = Env;
134
135 fn deref(&self) -> &Env {
136 &self.inner
137 }
138}
139
140impl<Ks: CapKeys> DerefMut for CapList<Ks> {
141 fn deref_mut(&mut self) -> &mut Env {
142 &mut self.inner
143 }
144}
145
146impl<Ks: CapKeys> CapabilitySet for CapList<Ks> {
147 fn verify(env: &Env) -> Result<(), CapabilityError> {
148 Ks::verify_all(env)
149 }
150}
151
152impl<Ks: CapKeys> FromEnv for CapList<Ks> {
153 fn from_env(env: Env) -> Self {
154 Self::new(env)
155 }
156}
157
158pub trait HasCap<K: CapabilityKey> {}
160
161impl<K: CapabilityKey> HasCap<K> for Env {}
162
163impl<K: CapabilityKey, T: Deref<Target = Env>> HasCap<K> for T {}
164
165pub trait CapWiden<Target> {
167 fn widen(self) -> Target;
169}
170
171impl<Ks: CapKeys> CapWiden<CapList<Ks>> for CapList<Ks> {
172 fn widen(self) -> CapList<Ks> {
173 self
174 }
175}
176
177impl<K0: CapabilityKey, K1: CapabilityKey> CapWiden<CapList<(K0,)>> for CapList<(K0, K1)> {
178 fn widen(self) -> CapList<(K0,)> {
179 CapList::new(self.inner)
180 }
181}
182
183impl<K0: CapabilityKey> CapList<(K0,)> {
185 #[inline]
186 pub fn project_at_0(self) -> CapList<(K0,)> {
188 CapList::new(self.inner)
189 }
190}
191
192impl<K0: CapabilityKey, K1: CapabilityKey> CapList<(K0, K1)> {
193 #[inline]
194 pub fn project_at_0(self) -> CapList<(K0,)> {
196 CapList::new(self.inner)
197 }
198 #[inline]
199 pub fn project_at_1(self) -> CapList<(K1,)> {
201 CapList::new(self.inner)
202 }
203}
204
205impl<K0: CapabilityKey, K1: CapabilityKey, K2: CapabilityKey> CapList<(K0, K1, K2)> {
206 #[inline]
207 pub fn project_at_0(self) -> CapList<(K0,)> {
209 CapList::new(self.inner)
210 }
211 #[inline]
212 pub fn project_at_1(self) -> CapList<(K1,)> {
214 CapList::new(self.inner)
215 }
216 #[inline]
217 pub fn project_at_2(self) -> CapList<(K2,)> {
219 CapList::new(self.inner)
220 }
221}
222
223impl<K0: CapabilityKey, K1: CapabilityKey, K2: CapabilityKey, K3: CapabilityKey>
224 CapList<(K0, K1, K2, K3)>
225{
226 #[inline]
227 pub fn project_at_0(self) -> CapList<(K0,)> {
229 CapList::new(self.inner)
230 }
231 #[inline]
232 pub fn project_at_1(self) -> CapList<(K1,)> {
234 CapList::new(self.inner)
235 }
236 #[inline]
237 pub fn project_at_2(self) -> CapList<(K2,)> {
239 CapList::new(self.inner)
240 }
241 #[inline]
242 pub fn project_at_3(self) -> CapList<(K3,)> {
244 CapList::new(self.inner)
245 }
246}
247
248impl<K0: CapabilityKey, K1: CapabilityKey, K2: CapabilityKey, K3: CapabilityKey, K4: CapabilityKey>
249 CapList<(K0, K1, K2, K3, K4)>
250{
251 #[inline]
252 pub fn project_at_0(self) -> CapList<(K0,)> {
254 CapList::new(self.inner)
255 }
256 #[inline]
257 pub fn project_at_1(self) -> CapList<(K1,)> {
259 CapList::new(self.inner)
260 }
261 #[inline]
262 pub fn project_at_2(self) -> CapList<(K2,)> {
264 CapList::new(self.inner)
265 }
266 #[inline]
267 pub fn project_at_3(self) -> CapList<(K3,)> {
269 CapList::new(self.inner)
270 }
271 #[inline]
272 pub fn project_at_4(self) -> CapList<(K4,)> {
274 CapList::new(self.inner)
275 }
276}
277
278impl<
279 K0: CapabilityKey,
280 K1: CapabilityKey,
281 K2: CapabilityKey,
282 K3: CapabilityKey,
283 K4: CapabilityKey,
284 K5: CapabilityKey,
285> CapList<(K0, K1, K2, K3, K4, K5)>
286{
287 #[inline]
288 pub fn project_at_0(self) -> CapList<(K0,)> {
290 CapList::new(self.inner)
291 }
292 #[inline]
293 pub fn project_at_1(self) -> CapList<(K1,)> {
295 CapList::new(self.inner)
296 }
297 #[inline]
298 pub fn project_at_2(self) -> CapList<(K2,)> {
300 CapList::new(self.inner)
301 }
302 #[inline]
303 pub fn project_at_3(self) -> CapList<(K3,)> {
305 CapList::new(self.inner)
306 }
307 #[inline]
308 pub fn project_at_4(self) -> CapList<(K4,)> {
310 CapList::new(self.inner)
311 }
312 #[inline]
313 pub fn project_at_5(self) -> CapList<(K5,)> {
315 CapList::new(self.inner)
316 }
317}
318
319impl<
320 K0: CapabilityKey,
321 K1: CapabilityKey,
322 K2: CapabilityKey,
323 K3: CapabilityKey,
324 K4: CapabilityKey,
325 K5: CapabilityKey,
326 K6: CapabilityKey,
327> CapList<(K0, K1, K2, K3, K4, K5, K6)>
328{
329 #[inline]
330 pub fn project_at_0(self) -> CapList<(K0,)> {
332 CapList::new(self.inner)
333 }
334 #[inline]
335 pub fn project_at_1(self) -> CapList<(K1,)> {
337 CapList::new(self.inner)
338 }
339 #[inline]
340 pub fn project_at_2(self) -> CapList<(K2,)> {
342 CapList::new(self.inner)
343 }
344 #[inline]
345 pub fn project_at_3(self) -> CapList<(K3,)> {
347 CapList::new(self.inner)
348 }
349 #[inline]
350 pub fn project_at_4(self) -> CapList<(K4,)> {
352 CapList::new(self.inner)
353 }
354 #[inline]
355 pub fn project_at_5(self) -> CapList<(K5,)> {
357 CapList::new(self.inner)
358 }
359 #[inline]
360 pub fn project_at_6(self) -> CapList<(K6,)> {
362 CapList::new(self.inner)
363 }
364}
365
366impl<
367 K0: CapabilityKey,
368 K1: CapabilityKey,
369 K2: CapabilityKey,
370 K3: CapabilityKey,
371 K4: CapabilityKey,
372 K5: CapabilityKey,
373 K6: CapabilityKey,
374 K7: CapabilityKey,
375> CapList<(K0, K1, K2, K3, K4, K5, K6, K7)>
376{
377 #[inline]
378 pub fn project_at_0(self) -> CapList<(K0,)> {
380 CapList::new(self.inner)
381 }
382 #[inline]
383 pub fn project_at_1(self) -> CapList<(K1,)> {
385 CapList::new(self.inner)
386 }
387 #[inline]
388 pub fn project_at_2(self) -> CapList<(K2,)> {
390 CapList::new(self.inner)
391 }
392 #[inline]
393 pub fn project_at_3(self) -> CapList<(K3,)> {
395 CapList::new(self.inner)
396 }
397 #[inline]
398 pub fn project_at_4(self) -> CapList<(K4,)> {
400 CapList::new(self.inner)
401 }
402 #[inline]
403 pub fn project_at_5(self) -> CapList<(K5,)> {
405 CapList::new(self.inner)
406 }
407 #[inline]
408 pub fn project_at_6(self) -> CapList<(K6,)> {
410 CapList::new(self.inner)
411 }
412 #[inline]
413 pub fn project_at_7(self) -> CapList<(K7,)> {
415 CapList::new(self.inner)
416 }
417}
418
419impl<K0: CapabilityKey, K1: CapabilityKey, K2: CapabilityKey> CapWiden<CapList<(K0,)>>
420 for CapList<(K0, K1, K2)>
421{
422 fn widen(self) -> CapList<(K0,)> {
423 CapList::new(self.inner)
424 }
425}
426
427impl<K0: CapabilityKey, K1: CapabilityKey, K2: CapabilityKey> CapWiden<CapList<(K0, K1)>>
428 for CapList<(K0, K1, K2)>
429{
430 fn widen(self) -> CapList<(K0, K1)> {
431 CapList::new(self.inner)
432 }
433}
434
435#[cfg(test)]
436#[allow(dead_code, clippy::new_ret_no_self)]
437mod tests {
438 use super::*;
439 use crate::Cap;
440 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
441 struct Test(pub u32);
442
443 #[test]
444 fn cap_list_verify_missing() {
445 let env = Env::new();
446 let err = CapList::<(Cap<Test>,)>::verify(&env).unwrap_err();
447 assert!(matches!(err, CapabilityError::Missing(_)));
448 }
449
450 #[test]
451 fn cap_list_verify_ok() {
452 let mut env = Env::new();
453 env.insert::<Cap<Test>>(Test(7u32));
454 CapList::<(Cap<Test>,)>::verify(&env).unwrap();
455 }
456
457 #[test]
458 fn cap_list_eight_keys() {
459 #[derive(Clone, Copy)]
460 struct Cap0(pub u8);
461 #[derive(Clone, Copy)]
462 struct Cap1(pub u8);
463 #[derive(Clone, Copy)]
464 struct Cap2(pub u8);
465 #[derive(Clone, Copy)]
466 struct Cap3(pub u8);
467 #[derive(Clone, Copy)]
468 struct Cap4(pub u8);
469 #[derive(Clone, Copy)]
470 struct Cap5(pub u8);
471 #[derive(Clone, Copy)]
472 struct Cap6(pub u8);
473 #[derive(Clone, Copy)]
474 struct Cap7(pub u8);
475 let mut env = Env::new();
476 env.insert::<Cap<Cap0>>(Cap0(0u8));
477 env.insert::<Cap<Cap1>>(Cap1(1u8));
478 env.insert::<Cap<Cap2>>(Cap2(2u8));
479 env.insert::<Cap<Cap3>>(Cap3(3u8));
480 env.insert::<Cap<Cap4>>(Cap4(4u8));
481 env.insert::<Cap<Cap5>>(Cap5(5u8));
482 env.insert::<Cap<Cap6>>(Cap6(6u8));
483 env.insert::<Cap<Cap7>>(Cap7(7u8));
484 CapList::<(
485 Cap<Cap0>,
486 Cap<Cap1>,
487 Cap<Cap2>,
488 Cap<Cap3>,
489 Cap<Cap4>,
490 Cap<Cap5>,
491 Cap<Cap6>,
492 Cap<Cap7>,
493 )>::verify(&env)
494 .unwrap();
495 }
496
497 #[test]
498 fn no_caps_and_unit_from_env() {
499 assert!(NoCaps::verify(&Env::new()).is_ok());
500 assert!(<() as CapabilitySet>::verify(&Env::new()).is_ok());
501 let _ = NoCaps::from_env(Env::new());
502 let _ = <() as FromEnv>::from_env(Env::new());
503 }
504
505 #[test]
506 fn env_as_capability_set() {
507 let env = Env::new();
508 assert!(Env::verify(&env).is_ok());
509 assert_eq!(Env::from_env(env.clone()).len(), env.len());
510 }
511
512 #[test]
513 fn cap_list_accessors_and_deref() {
514 let mut env = Env::new();
515 env.insert::<Cap<Test>>(Test(3u32));
516 let mut caps = CapList::<(Cap<Test>,)>::from_env(env);
517 assert_eq!(caps.env().len(), 1);
518 caps.env_mut().insert::<Cap<Test>>(Test(4u32));
519 assert_eq!(caps.get::<Cap<Test>>().0, 4);
520 }
521
522 #[test]
523 fn cap_list_project_four_through_eight() {
524 #[derive(Clone, Copy)]
525 struct A(pub i32);
526 #[derive(Clone, Copy)]
527 struct B(pub i32);
528 #[derive(Clone, Copy)]
529 struct C(pub i32);
530 #[derive(Clone, Copy)]
531 struct D(pub i32);
532 #[derive(Clone, Copy)]
533 struct E(pub i32);
534 #[derive(Clone, Copy)]
535 struct F(pub i32);
536 #[derive(Clone, Copy)]
537 struct G(pub i32);
538 #[derive(Clone, Copy)]
539 struct H(pub i32);
540 let mut env = Env::new();
541 env.insert::<Cap<A>>(A(1));
542 env.insert::<Cap<B>>(B(2));
543 env.insert::<Cap<C>>(C(3));
544 env.insert::<Cap<D>>(D(4));
545 env.insert::<Cap<E>>(E(5));
546 env.insert::<Cap<F>>(F(6));
547 env.insert::<Cap<G>>(G(7));
548 env.insert::<Cap<H>>(H(8));
549 CapList::<(Cap<A>, Cap<B>, Cap<C>, Cap<D>, Cap<E>)>::verify(&env).unwrap();
550 let wide8 = CapList::<(
551 Cap<A>,
552 Cap<B>,
553 Cap<C>,
554 Cap<D>,
555 Cap<E>,
556 Cap<F>,
557 Cap<G>,
558 Cap<H>,
559 )>::from_env(env.clone());
560 let _ = wide8.clone().project_at_4();
561 let _ = wide8.clone().project_at_5();
562 let _ = wide8.clone().project_at_6();
563 let _ = wide8.clone().project_at_7();
564 let four = CapList::<(Cap<A>, Cap<B>, Cap<C>, Cap<D>)>::from_env(env);
565 let _ = four.clone().project_at_0();
566 let _ = four.clone().project_at_1();
567 let _ = four.clone().project_at_2();
568 let _ = four.project_at_3();
569 }
570 #[test]
571 fn cap_widen_subset() {
572 #[derive(Clone, Copy)]
573 struct Db(pub u32);
574 #[derive(Clone, Copy)]
575 struct Log(pub u32);
576 let mut env = Env::new();
577 env.insert::<Cap<Db>>(Db(1u32));
578 env.insert::<Cap<Log>>(Log(2u32));
579 let wide = CapList::<(Cap<Db>, Cap<Log>)>::from_env(env);
580 let _narrow: CapList<(Cap<Db>,)> = wide.widen();
581 }
582}