Skip to main content

steel_core/permission/
expression.rs

1use std::ops::{BitAnd, BitOr};
2
3use super::PermissionKey;
4
5/// Boolean permission expression evaluated with tri-state allow/deny/unset semantics.
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub enum PermissionExpr {
8    /// Resolves one permission key.
9    Key(PermissionKey),
10    /// A child permission that may also inherit a broader parent grant.
11    ScopedKey {
12        /// Broad permission accepted as a fallback grant.
13        parent: PermissionKey,
14        /// Specific child permission being checked.
15        key: PermissionKey,
16    },
17    /// Requires every nested expression to allow.
18    All(Vec<Self>),
19    /// Requires at least one nested expression to allow.
20    Any(Vec<Self>),
21}
22
23impl PermissionExpr {
24    /// Creates a single-key expression.
25    #[must_use]
26    pub const fn key(key: PermissionKey) -> Self {
27        Self::Key(key)
28    }
29
30    /// Creates a child expression with a broad parent fallback.
31    #[must_use]
32    pub const fn scoped_key(parent: PermissionKey, key: PermissionKey) -> Self {
33        Self::ScopedKey { parent, key }
34    }
35}
36
37impl BitAnd for PermissionExpr {
38    type Output = Self;
39
40    fn bitand(self, rhs: Self) -> Self::Output {
41        match (self, rhs) {
42            (Self::All(mut left), Self::All(mut right)) => {
43                left.append(&mut right);
44                Self::All(left)
45            }
46            (Self::All(mut left), right) => {
47                left.push(right);
48                Self::All(left)
49            }
50            (left, Self::All(mut right)) => {
51                right.insert(0, left);
52                Self::All(right)
53            }
54            (left, right) => Self::All(vec![left, right]),
55        }
56    }
57}
58
59impl BitOr for PermissionExpr {
60    type Output = Self;
61
62    fn bitor(self, rhs: Self) -> Self::Output {
63        match (self, rhs) {
64            (Self::Any(mut left), Self::Any(mut right)) => {
65                left.append(&mut right);
66                Self::Any(left)
67            }
68            (Self::Any(mut left), right) => {
69                left.push(right);
70                Self::Any(left)
71            }
72            (left, Self::Any(mut right)) => {
73                right.insert(0, left);
74                Self::Any(right)
75            }
76            (left, right) => Self::Any(vec![left, right]),
77        }
78    }
79}