gix_sec/
permission.rs

1use std::fmt::{Debug, Display, Formatter};
2
3use crate::Permission;
4
5/// An error to use if an operation cannot proceed due to insufficient permissions.
6///
7/// It's up to the implementation to decide which permission is required for an operation, and which one
8/// causes errors.
9#[derive(Debug)]
10pub struct Error<R: std::fmt::Debug> {
11    /// The resource which cannot be used.
12    pub resource: R,
13}
14
15impl<R> Display for Error<R>
16where
17    R: std::fmt::Debug,
18{
19    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
20        write!(
21            f,
22            "Not allowed to handle resource {:?}: permission denied",
23            self.resource
24        )
25    }
26}
27
28impl<R> std::error::Error for Error<R> where R: std::fmt::Debug {}
29
30impl Permission {
31    /// Return true if this instance is `Permission::Allow`.
32    pub fn is_allowed(&self) -> bool {
33        matches!(self, Permission::Allow)
34    }
35    /// Check this permissions and produce a reply to indicate if the `resource` can be used and in which way.
36    ///
37    /// Only if this permission is set to `Allow` will the resource be usable.
38    pub fn check<R: std::fmt::Debug>(&self, resource: R) -> Result<Option<R>, Error<R>> {
39        match self {
40            Permission::Allow => Ok(Some(resource)),
41            Permission::Deny => Ok(None),
42            Permission::Forbid => Err(Error { resource }),
43        }
44    }
45
46    /// Like [`check()`][Self::check()], but degenerates the type to an option to make it more useful in cases where
47    /// `Forbid` shouldn't abort the entire operation.
48    pub fn check_opt<R: std::fmt::Debug>(&self, resource: R) -> Option<R> {
49        match self {
50            Permission::Allow => Some(resource),
51            Permission::Deny | Permission::Forbid => None,
52        }
53    }
54}