Skip to main content

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}