ax_cap_access/lib.rs
1#![cfg_attr(not(test), no_std)]
2#![doc = include_str!("../README.md")]
3
4bitflags::bitflags! {
5 /// Capabilities (access rights).
6 #[derive(Default, Debug, Clone, Copy)]
7 pub struct Cap: u32 {
8 /// Readable access.
9 const READ = 1 << 0;
10 /// Writable access.
11 const WRITE = 1 << 1;
12 /// Executable access.
13 const EXECUTE = 1 << 2;
14 }
15}
16
17/// A wrapper that holds a type with a capability.
18pub struct WithCap<T> {
19 inner: T,
20 cap: Cap,
21}
22
23impl<T> WithCap<T> {
24 /// Create a new instance with the given capability.
25 pub fn new(inner: T, cap: Cap) -> Self {
26 Self { inner, cap }
27 }
28
29 /// Get the capability.
30 pub const fn cap(&self) -> Cap {
31 self.cap
32 }
33
34 /// Check if the inner data can be accessed with the given capability.
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use ax_cap_access::{Cap, WithCap};
40 ///
41 /// let data = WithCap::new(42, Cap::READ);
42 ///
43 /// assert!(data.can_access(Cap::READ));
44 /// assert!(!data.can_access(Cap::WRITE));
45 /// ```
46 pub const fn can_access(&self, cap: Cap) -> bool {
47 self.cap.contains(cap)
48 }
49
50 /// Access the inner value without capability check.
51 ///
52 /// # Safety
53 ///
54 /// Caller must ensure not to violate the capability.
55 pub unsafe fn access_unchecked(&self) -> &T {
56 &self.inner
57 }
58
59 /// Access the inner value with the given capability, or return `None`
60 /// if cannot access.
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// use ax_cap_access::{Cap, WithCap};
66 ///
67 /// let data = WithCap::new(42, Cap::READ);
68 ///
69 /// assert_eq!(data.access(Cap::READ).unwrap(), &42);
70 /// assert_eq!(data.access(Cap::WRITE), None);
71 /// ```
72 pub const fn access(&self, cap: Cap) -> Option<&T> {
73 if self.can_access(cap) {
74 Some(&self.inner)
75 } else {
76 None
77 }
78 }
79
80 /// Access the inner value with the given capability, or return the given
81 /// `err` if cannot access.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use ax_cap_access::{Cap, WithCap};
87 ///
88 /// let data = WithCap::new(42, Cap::READ);
89 ///
90 /// assert_eq!(data.access_or_err(Cap::READ, "cannot read").unwrap(), &42);
91 /// assert_eq!(
92 /// data.access_or_err(Cap::WRITE, "cannot write").err(),
93 /// Some("cannot write")
94 /// );
95 /// ```
96 pub fn access_or_err<E>(&self, cap: Cap, err: E) -> Result<&T, E> {
97 if self.can_access(cap) {
98 Ok(&self.inner)
99 } else {
100 Err(err)
101 }
102 }
103}