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 { name: String, args: Vec<String> },
28
29    /// A binary operation combining two expressions
30    /// e.g., `hasRole('ADMIN') AND hasRole('USER')`
31    Binary {
32        left: Box<Expression>,
33        op: BinaryOp,
34        right: Box<Expression>,
35    },
36
37    /// A unary operation on an expression
38    /// e.g., `NOT hasRole('ADMIN')`
39    Unary { op: UnaryOp, expr: Box<Expression> },
40
41    /// A grouped expression (parentheses)
42    /// e.g., `(hasRole('ADMIN') OR hasRole('USER'))`
43    Group(Box<Expression>),
44}
45
46impl Expression {
47    /// Creates a new function expression.
48    pub fn function(name: impl Into<String>, args: Vec<String>) -> Self {
49        Expression::Function {
50            name: name.into(),
51            args,
52        }
53    }
54
55    /// Creates a new AND expression.
56    pub fn and(left: Expression, right: Expression) -> Self {
57        Expression::Binary {
58            left: Box::new(left),
59            op: BinaryOp::And,
60            right: Box::new(right),
61        }
62    }
63
64    /// Creates a new OR expression.
65    pub fn or(left: Expression, right: Expression) -> Self {
66        Expression::Binary {
67            left: Box::new(left),
68            op: BinaryOp::Or,
69            right: Box::new(right),
70        }
71    }
72
73    /// Creates a new NOT expression.
74    #[allow(clippy::should_implement_trait)]
75    pub fn not(expr: Expression) -> Self {
76        Expression::Unary {
77            op: UnaryOp::Not,
78            expr: Box::new(expr),
79        }
80    }
81
82    /// Creates a grouped expression.
83    pub fn group(expr: Expression) -> Self {
84        Expression::Group(Box::new(expr))
85    }
86}