cel_eval/
ast.rs

1use crate::models::{PassableMap, PassableValue};
2use cel_parser::Member::{Attribute, Fields, Index};
3use cel_parser::{ArithmeticOp, Atom, Expression, Member, RelationOp, UnaryOp};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
9pub(crate) struct ASTExecutionContext {
10    pub(crate) variables: PassableMap,
11    pub(crate) expression: JSONExpression,
12    pub(crate) computed: Option<HashMap<String, Vec<PassableValue>>>,
13    pub(crate) device: Option<HashMap<String, Vec<PassableValue>>>
14}
15
16#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
17#[serde(tag = "type", content = "value")]
18pub enum JSONRelationOp {
19    LessThan,
20    LessThanEq,
21    GreaterThan,
22    GreaterThanEq,
23    Equals,
24    NotEquals,
25    In,
26}
27
28#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
29#[serde(tag = "type", content = "value")]
30pub enum JSONArithmeticOp {
31    Add,
32    Subtract,
33    Divide,
34    Multiply,
35    Modulus,
36}
37
38#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
39#[serde(tag = "type", content = "value")]
40pub enum JSONUnaryOp {
41    Not,
42    DoubleNot,
43    Minus,
44    DoubleMinus,
45}
46
47#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
48#[serde(tag = "type", content = "value")]
49pub enum JSONExpression {
50    Arithmetic(Box<JSONExpression>, JSONArithmeticOp, Box<JSONExpression>),
51    Relation(Box<JSONExpression>, JSONRelationOp, Box<JSONExpression>),
52    Ternary(
53        Box<JSONExpression>,
54        Box<JSONExpression>,
55        Box<JSONExpression>,
56    ),
57    Or(Box<JSONExpression>, Box<JSONExpression>),
58    And(Box<JSONExpression>, Box<JSONExpression>),
59    Unary(JSONUnaryOp, Box<JSONExpression>),
60    Member(Box<JSONExpression>, Box<JSONMember>),
61    FunctionCall(
62        Box<JSONExpression>,
63        Option<Box<JSONExpression>>,
64        Vec<JSONExpression>,
65    ),
66    List(Vec<JSONExpression>),
67    Map(Vec<(JSONExpression, JSONExpression)>),
68    Atom(JSONAtom),
69    Ident(String),
70}
71
72#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
73#[serde(tag = "type", content = "value")]
74pub enum JSONMember {
75    Attribute(String),
76    Index(Box<JSONExpression>),
77    Fields(Vec<(String, JSONExpression)>),
78}
79
80#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
81#[serde(tag = "type", content = "value")]
82pub enum JSONAtom {
83    Int(i64),
84    UInt(u64),
85    Float(f64),
86    String(String),
87    Bytes(Vec<u8>),
88    Bool(bool),
89    Null,
90}
91
92// Conversion functions
93impl From<JSONRelationOp> for RelationOp {
94    fn from(op: JSONRelationOp) -> Self {
95        match op {
96            JSONRelationOp::LessThan => RelationOp::LessThan,
97            JSONRelationOp::LessThanEq => RelationOp::LessThanEq,
98            JSONRelationOp::GreaterThan => RelationOp::GreaterThan,
99            JSONRelationOp::GreaterThanEq => RelationOp::GreaterThanEq,
100            JSONRelationOp::Equals => RelationOp::Equals,
101            JSONRelationOp::NotEquals => RelationOp::NotEquals,
102            JSONRelationOp::In => RelationOp::In,
103        }
104    }
105}
106
107impl From<JSONArithmeticOp> for ArithmeticOp {
108    fn from(op: JSONArithmeticOp) -> Self {
109        match op {
110            JSONArithmeticOp::Add => ArithmeticOp::Add,
111            JSONArithmeticOp::Subtract => ArithmeticOp::Subtract,
112            JSONArithmeticOp::Divide => ArithmeticOp::Divide,
113            JSONArithmeticOp::Multiply => ArithmeticOp::Multiply,
114            JSONArithmeticOp::Modulus => ArithmeticOp::Modulus,
115        }
116    }
117}
118
119impl From<JSONUnaryOp> for UnaryOp {
120    fn from(op: JSONUnaryOp) -> Self {
121        match op {
122            JSONUnaryOp::Not => UnaryOp::Not,
123            JSONUnaryOp::DoubleNot => UnaryOp::DoubleNot,
124            JSONUnaryOp::Minus => UnaryOp::Minus,
125            JSONUnaryOp::DoubleMinus => UnaryOp::DoubleMinus,
126        }
127    }
128}
129
130impl From<JSONExpression> for Expression {
131    fn from(expr: JSONExpression) -> Self {
132        match expr {
133            JSONExpression::Arithmetic(left, op, right) => Expression::Arithmetic(
134                Box::new((*left).into()),
135                op.into(),
136                Box::new((*right).into()),
137            ),
138            JSONExpression::Relation(left, op, right) => Expression::Relation(
139                Box::new((*left).into()),
140                op.into(),
141                Box::new((*right).into()),
142            ),
143            JSONExpression::Ternary(cond, true_expr, false_expr) => Expression::Ternary(
144                Box::new((*cond).into()),
145                Box::new((*true_expr).into()),
146                Box::new((*false_expr).into()),
147            ),
148            JSONExpression::Or(left, right) => {
149                Expression::Or(Box::new((*left).into()), Box::new((*right).into()))
150            }
151            JSONExpression::And(left, right) => {
152                Expression::And(Box::new((*left).into()), Box::new((*right).into()))
153            }
154            JSONExpression::Unary(op, expr) => {
155                Expression::Unary(op.into(), Box::new((*expr).into()))
156            }
157            JSONExpression::Member(expr, member) => {
158                Expression::Member(Box::new((*expr).into()), Box::new((*member).into()))
159            }
160            JSONExpression::FunctionCall(func, optional_expr, args) => Expression::FunctionCall(
161                Box::new((*func).into()),
162                optional_expr.map(|e| Box::new((*e).into())),
163                args.into_iter().map(|e| e.into()).collect(),
164            ),
165            JSONExpression::List(items) => {
166                Expression::List(items.into_iter().map(|e| e.into()).collect())
167            }
168            JSONExpression::Map(items) => Expression::Map(
169                items
170                    .into_iter()
171                    .map(|(k, v)| (k.into(), v.into()))
172                    .collect(),
173            ),
174            JSONExpression::Atom(atom) => Expression::Atom(atom.into()),
175            JSONExpression::Ident(s) => Expression::Ident(Arc::new(s)),
176        }
177    }
178}
179
180impl From<JSONMember> for Member {
181    fn from(member: JSONMember) -> Self {
182        match member {
183            JSONMember::Attribute(s) => Attribute(Arc::new(s)),
184            JSONMember::Index(expr) => Index(Box::new((*expr).into())),
185            JSONMember::Fields(fields) => Fields(
186                fields
187                    .into_iter()
188                    .map(|(k, v)| (Arc::new(k), v.into()))
189                    .collect(),
190            ),
191        }
192    }
193}
194
195impl From<JSONAtom> for Atom {
196    fn from(atom: JSONAtom) -> Self {
197        match atom {
198            JSONAtom::Int(i) => Atom::Int(i),
199            JSONAtom::UInt(u) => Atom::UInt(u),
200            JSONAtom::Float(f) => Atom::Float(f),
201            JSONAtom::String(s) => Atom::String(Arc::new(s)),
202            JSONAtom::Bytes(b) => Atom::Bytes(Arc::new(b)),
203            JSONAtom::Bool(b) => Atom::Bool(b),
204            JSONAtom::Null => Atom::Null,
205        }
206    }
207}
208
209impl From<Expression> for JSONExpression {
210    fn from(expr: Expression) -> Self {
211        match expr {
212            Expression::Arithmetic(left, op, right) => JSONExpression::Arithmetic(
213                Box::new((*left).into()),
214                op.into(),
215                Box::new((*right).into()),
216            ),
217            Expression::Relation(left, op, right) => JSONExpression::Relation(
218                Box::new((*left).into()),
219                op.into(),
220                Box::new((*right).into()),
221            ),
222            Expression::Ternary(cond, true_expr, false_expr) => JSONExpression::Ternary(
223                Box::new((*cond).into()),
224                Box::new((*true_expr).into()),
225                Box::new((*false_expr).into()),
226            ),
227            Expression::Or(left, right) => {
228                JSONExpression::Or(Box::new((*left).into()), Box::new((*right).into()))
229            }
230            Expression::And(left, right) => {
231                JSONExpression::And(Box::new((*left).into()), Box::new((*right).into()))
232            }
233            Expression::Unary(op, expr) => {
234                JSONExpression::Unary(op.into(), Box::new((*expr).into()))
235            }
236            Expression::Member(expr, member) => {
237                JSONExpression::Member(Box::new((*expr).into()), Box::new((*member).into()))
238            }
239            Expression::FunctionCall(func, optional_expr, args) => JSONExpression::FunctionCall(
240                Box::new((*func).into()),
241                optional_expr.map(|e| Box::new((*e).into())),
242                args.into_iter().map(|e| e.into()).collect(),
243            ),
244            Expression::List(items) => {
245                JSONExpression::List(items.into_iter().map(|e| e.into()).collect())
246            }
247            Expression::Map(items) => JSONExpression::Map(
248                items
249                    .into_iter()
250                    .map(|(k, v)| (k.into(), v.into()))
251                    .collect(),
252            ),
253            Expression::Atom(atom) => JSONExpression::Atom(atom.into()),
254            Expression::Ident(s) => JSONExpression::Ident((*s).clone()),
255        }
256    }
257}
258
259// Implement From for other types
260impl From<RelationOp> for JSONRelationOp {
261    fn from(op: RelationOp) -> Self {
262        match op {
263            RelationOp::LessThan => JSONRelationOp::LessThan,
264            RelationOp::LessThanEq => JSONRelationOp::LessThanEq,
265            RelationOp::GreaterThan => JSONRelationOp::GreaterThan,
266            RelationOp::GreaterThanEq => JSONRelationOp::GreaterThanEq,
267            RelationOp::Equals => JSONRelationOp::Equals,
268            RelationOp::NotEquals => JSONRelationOp::NotEquals,
269            RelationOp::In => JSONRelationOp::In,
270        }
271    }
272}
273
274impl From<ArithmeticOp> for JSONArithmeticOp {
275    fn from(op: ArithmeticOp) -> Self {
276        match op {
277            ArithmeticOp::Add => JSONArithmeticOp::Add,
278            ArithmeticOp::Subtract => JSONArithmeticOp::Subtract,
279            ArithmeticOp::Divide => JSONArithmeticOp::Divide,
280            ArithmeticOp::Multiply => JSONArithmeticOp::Multiply,
281            ArithmeticOp::Modulus => JSONArithmeticOp::Modulus,
282        }
283    }
284}
285
286impl From<UnaryOp> for JSONUnaryOp {
287    fn from(op: UnaryOp) -> Self {
288        match op {
289            UnaryOp::Not => JSONUnaryOp::Not,
290            UnaryOp::DoubleNot => JSONUnaryOp::DoubleNot,
291            UnaryOp::Minus => JSONUnaryOp::Minus,
292            UnaryOp::DoubleMinus => JSONUnaryOp::DoubleMinus,
293        }
294    }
295}
296
297impl From<Member> for JSONMember {
298    fn from(member: Member) -> Self {
299        match member {
300            Attribute(s) => JSONMember::Attribute((*s).clone()),
301            Index(expr) => JSONMember::Index(Box::new((*expr).into())),
302            Fields(fields) => JSONMember::Fields(
303                fields
304                    .into_iter()
305                    .map(|(k, v)| ((*k).clone(), v.into()))
306                    .collect(),
307            ),
308        }
309    }
310}
311
312impl From<Atom> for JSONAtom {
313    fn from(atom: Atom) -> Self {
314        match atom {
315            Atom::Int(i) => JSONAtom::Int(i),
316            Atom::UInt(u) => JSONAtom::UInt(u),
317            Atom::Float(f) => JSONAtom::Float(f),
318            Atom::String(s) => JSONAtom::String((*s).clone()),
319            Atom::Bytes(b) => JSONAtom::Bytes((*b).clone()),
320            Atom::Bool(b) => JSONAtom::Bool(b),
321            Atom::Null => JSONAtom::Null,
322        }
323    }
324}
325
326#[cfg(test)]
327mod tests {
328    use super::*;
329    use cel_interpreter::Program;
330    use cel_parser::parser::ExpressionParser;
331
332    #[test]
333    fn test_ast_serializing() {
334        // ((5 + 3) > 7) && (name.length() in [5, 10, 15])
335        let expr = Expression::And(
336            Box::new(Expression::Relation(
337                Box::new(Expression::Arithmetic(
338                    Box::new(Expression::Atom(Atom::Int(5))),
339                    ArithmeticOp::Add,
340                    Box::new(Expression::Atom(Atom::Int(3))),
341                )),
342                RelationOp::GreaterThan,
343                Box::new(Expression::Atom(Atom::Int(7))),
344            )),
345            Box::new(Expression::Relation(
346                Box::new(Expression::FunctionCall(
347                    Box::new(Expression::Member(
348                        Box::new(Expression::Ident(Arc::new("name".to_string()))),
349                        Box::new(Attribute(Arc::new("length".to_string()))),
350                    )),
351                    None,
352                    vec![],
353                )),
354                RelationOp::In,
355                Box::new(Expression::List(vec![
356                    Expression::Atom(Atom::Int(5)),
357                    Expression::Atom(Atom::Int(10)),
358                    Expression::Atom(Atom::Int(15)),
359                ])),
360            )),
361        );
362
363        // Convert to JSONExpression
364        let json_expr: JSONExpression = expr.clone().into();
365
366        // Serialize to JSON
367        let json_string = serde_json::to_string_pretty(&json_expr).unwrap();
368
369        println!("JSON representation:");
370        println!("{}", json_string);
371
372        let text = "platform.myMethod(\"test\") == platform.name && user.test == 1";
373        let program = ExpressionParser::new().parse(text).unwrap();
374        let program: JSONExpression = program.into();
375        let serialized = serde_json::to_string_pretty(&program).unwrap();
376        println!("-----------–\n\n\n{}--------------\n\n", serialized);
377        // Deserialize back to JSONExpression
378        let deserialized_json_expr: JSONExpression = serde_json::from_str(&json_string).unwrap();
379
380        // Convert back to original Expression
381        let deserialized_expr: Expression = deserialized_json_expr.into();
382
383        println!("\nDeserialized Expression:");
384        println!("{:?}", deserialized_expr);
385
386        // Check if the original and deserialized expressions are equal
387        assert_eq!(expr, deserialized_expr);
388        println!("\nOriginal and deserialized expressions are equal!");
389    }
390}