Skip to main content

actix_security_core/http/security/expression/
ast.rs

1//! Abstract Syntax Tree for security expressions.
2
3/// Binary operators for combining expressions.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum BinaryOp {
6    /// Logical AND (both must be true)
7    And,
8    /// Logical OR (at least one must be true)
9    Or,
10}
11
12/// Unary operators for modifying expressions.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum UnaryOp {
15    /// Logical NOT (inverts the result)
16    Not,
17}
18
19/// A security expression AST node.
20#[derive(Debug, Clone, PartialEq)]
21pub enum Expression {
22    /// A boolean literal (true/false)
23    Boolean(bool),
24
25    /// A function call with name and arguments
26    /// e.g., `hasRole('ADMIN')` -> Function("hasRole", vec!["ADMIN"])
27    Function {
28        name: String,
29        args: Vec<String>,
30    },
31
32    /// A binary operation combining two expressions
33    /// e.g., `hasRole('ADMIN') AND hasRole('USER')`
34    Binary {
35        left: Box<Expression>,
36        op: BinaryOp,
37        right: Box<Expression>,
38    },
39
40    /// A unary operation on an expression
41    /// e.g., `NOT hasRole('ADMIN')`
42    Unary {
43        op: UnaryOp,
44        expr: Box<Expression>,
45    },
46
47    /// A grouped expression (parentheses)
48    /// e.g., `(hasRole('ADMIN') OR hasRole('USER'))`
49    Group(Box<Expression>),
50}
51
52impl Expression {
53    /// Creates a new function expression.
54    pub fn function(name: impl Into<String>, args: Vec<String>) -> Self {
55        Expression::Function {
56            name: name.into(),
57            args,
58        }
59    }
60
61    /// Creates a new AND expression.
62    pub fn and(left: Expression, right: Expression) -> Self {
63        Expression::Binary {
64            left: Box::new(left),
65            op: BinaryOp::And,
66            right: Box::new(right),
67        }
68    }
69
70    /// Creates a new OR expression.
71    pub fn or(left: Expression, right: Expression) -> Self {
72        Expression::Binary {
73            left: Box::new(left),
74            op: BinaryOp::Or,
75            right: Box::new(right),
76        }
77    }
78
79    /// Creates a new NOT expression.
80    #[allow(clippy::should_implement_trait)]
81    pub fn not(expr: Expression) -> Self {
82        Expression::Unary {
83            op: UnaryOp::Not,
84            expr: Box::new(expr),
85        }
86    }
87
88    /// Creates a grouped expression.
89    pub fn group(expr: Expression) -> Self {
90        Expression::Group(Box::new(expr))
91    }
92}