filter_expr/
expr.rs

1/// The expression.
2///
3/// It is an AST of the filter expression.
4#[derive(Debug, Clone, PartialEq)]
5pub enum Expr {
6    Field(String),
7    Str(String),
8    I64(i64),
9    F64(f64),
10    Bool(bool),
11    Null,
12    Array(Vec<Expr>),
13
14    FuncCall(String, Vec<Expr>),
15    MethodCall(String, Box<Expr>, Vec<Expr>),
16
17    Gt(Box<Expr>, Box<Expr>),
18    Lt(Box<Expr>, Box<Expr>),
19    Ge(Box<Expr>, Box<Expr>),
20    Le(Box<Expr>, Box<Expr>),
21    Eq(Box<Expr>, Box<Expr>),
22    Ne(Box<Expr>, Box<Expr>),
23    In(Box<Expr>, Box<Expr>),
24
25    And(Vec<Expr>),
26    Or(Vec<Expr>),
27    Not(Box<Expr>),
28}
29
30#[allow(unused)]
31impl Expr {
32    pub(crate) fn field_<T: Into<String>>(field: T) -> Self {
33        Self::Field(field.into())
34    }
35
36    pub(crate) fn str_<T: Into<String>>(value: T) -> Self {
37        Self::Str(value.into())
38    }
39
40    pub(crate) fn i64_<T: Into<i64>>(value: T) -> Self {
41        Self::I64(value.into())
42    }
43
44    pub(crate) fn f64_<T: Into<f64>>(value: T) -> Self {
45        Self::F64(value.into())
46    }
47
48    pub(crate) fn bool_<T: Into<bool>>(value: T) -> Self {
49        Self::Bool(value.into())
50    }
51
52    pub(crate) fn null_() -> Self {
53        Self::Null
54    }
55
56    pub(crate) fn array_<T: Into<Vec<Expr>>>(value: T) -> Self {
57        Self::Array(value.into())
58    }
59
60    pub(crate) fn func_call_(func: String, args: Vec<Expr>) -> Self {
61        Self::FuncCall(func, args)
62    }
63
64    pub(crate) fn method_call_(obj: Expr, method: String, args: Vec<Expr>) -> Self {
65        Self::MethodCall(method, Box::new(obj), args)
66    }
67
68    pub(crate) fn gt_(left: Expr, right: Expr) -> Self {
69        Self::Gt(Box::new(left), Box::new(right))
70    }
71
72    pub(crate) fn lt_(left: Expr, right: Expr) -> Self {
73        Self::Lt(Box::new(left), Box::new(right))
74    }
75
76    pub(crate) fn ge_(left: Expr, right: Expr) -> Self {
77        Self::Ge(Box::new(left), Box::new(right))
78    }
79
80    pub(crate) fn le_(left: Expr, right: Expr) -> Self {
81        Self::Le(Box::new(left), Box::new(right))
82    }
83
84    pub(crate) fn eq_(left: Expr, right: Expr) -> Self {
85        Self::Eq(Box::new(left), Box::new(right))
86    }
87
88    pub(crate) fn ne_(left: Expr, right: Expr) -> Self {
89        Self::Ne(Box::new(left), Box::new(right))
90    }
91
92    pub(crate) fn in_(left: Expr, right: Expr) -> Self {
93        Self::In(Box::new(left), Box::new(right))
94    }
95
96    pub(crate) fn and_<T: Into<Vec<Expr>>>(value: T) -> Self {
97        Self::And(value.into())
98    }
99
100    pub(crate) fn or_<T: Into<Vec<Expr>>>(value: T) -> Self {
101        Self::Or(value.into())
102    }
103
104    pub(crate) fn not_(self) -> Self {
105        Self::Not(Box::new(self))
106    }
107}
108
109/// A trait for transforming AST expressions.
110///
111/// This trait allows you to recursively transform expressions by visiting
112/// all sub-expressions. The `transform` method is called recursively on all
113/// sub-expressions, allowing you to transform the AST in a composable way.
114///
115/// # Example
116///
117/// ```rust
118/// use filter_expr::{Expr, Transform};
119///
120/// struct MyTransformer;
121///
122/// impl Transform for MyTransformer {
123///     fn transform(&mut self, expr: Expr) -> Expr {
124///         // Transform the expression before recursing
125///         match expr {
126///             Expr::Field(name) if name == "old_name" => {
127///                 Expr::Field("new_name".to_string())
128///             }
129///             other => other,
130///         }
131///     }
132/// }
133/// ```
134pub trait Transform {
135    /// Transform an expression by recursively transforming all sub-expressions.
136    fn transform(&mut self, expr: Expr) -> Expr
137    where
138        Self: Sized;
139}
140
141impl Expr {
142    /// Recursively transform an expression using the provided transformer.
143    ///
144    /// ```rust
145    /// use filter_expr::{Expr, Transform};
146    ///
147    /// struct MyTransformer;
148    ///
149    /// impl Transform for MyTransformer {
150    ///     fn transform(&mut self, expr: Expr) -> Expr {
151    ///         // Transform the expression before recursing
152    ///         match expr {
153    ///             Expr::Field(name) if name == "old_name" => {
154    ///                 Expr::Field("new_name".to_string())
155    ///             }
156    ///             other => other,
157    ///         }
158    ///     }
159    /// }
160    ///
161    /// let expr = Expr::Field("old_name".to_string());
162    /// let mut transformer = MyTransformer;
163    /// let result = expr.transform(&mut transformer);
164    /// assert_eq!(result, Expr::Field("new_name".to_string()));
165    /// ```
166    pub fn transform<F: Transform>(self, transformer: &mut F) -> Expr {
167        let this = transformer.transform(self);
168
169        match this {
170            Expr::Field(name) => Expr::Field(name),
171            Expr::Str(value) => Expr::Str(value),
172            Expr::I64(value) => Expr::I64(value),
173            Expr::F64(value) => Expr::F64(value),
174            Expr::Bool(value) => Expr::Bool(value),
175            Expr::Null => Expr::Null,
176            Expr::Array(value) => Expr::Array(value),
177
178            Expr::FuncCall(func, args) => {
179                let args = args
180                    .into_iter()
181                    .map(|arg| transformer.transform(arg))
182                    .collect();
183                Expr::FuncCall(func, args)
184            }
185            Expr::MethodCall(method, obj, args) => {
186                let obj = Box::new(transformer.transform(*obj));
187                let args = args
188                    .into_iter()
189                    .map(|arg| transformer.transform(arg))
190                    .collect();
191                Expr::MethodCall(method, obj, args)
192            }
193
194            Expr::Gt(left, right) => {
195                let left = Box::new(transformer.transform(*left));
196                let right = Box::new(transformer.transform(*right));
197                Expr::Gt(left, right)
198            }
199            Expr::Lt(left, right) => {
200                let left = Box::new(transformer.transform(*left));
201                let right = Box::new(transformer.transform(*right));
202                Expr::Lt(left, right)
203            }
204            Expr::Ge(left, right) => {
205                let left = Box::new(transformer.transform(*left));
206                let right = Box::new(transformer.transform(*right));
207                Expr::Ge(left, right)
208            }
209            Expr::Le(left, right) => {
210                let left = Box::new(transformer.transform(*left));
211                let right = Box::new(transformer.transform(*right));
212                Expr::Le(left, right)
213            }
214            Expr::Eq(left, right) => {
215                let left = Box::new(transformer.transform(*left));
216                let right = Box::new(transformer.transform(*right));
217                Expr::Eq(left, right)
218            }
219            Expr::Ne(left, right) => {
220                let left = Box::new(transformer.transform(*left));
221                let right = Box::new(transformer.transform(*right));
222                Expr::Ne(left, right)
223            }
224            Expr::In(left, right) => {
225                let left = Box::new(transformer.transform(*left));
226                let right = Box::new(transformer.transform(*right));
227                Expr::In(left, right)
228            }
229            Expr::And(exprs) => {
230                let exprs = exprs
231                    .into_iter()
232                    .map(|e| transformer.transform(e))
233                    .collect();
234                Expr::And(exprs)
235            }
236            Expr::Or(exprs) => {
237                let exprs = exprs
238                    .into_iter()
239                    .map(|e| transformer.transform(e))
240                    .collect();
241                Expr::Or(exprs)
242            }
243            Expr::Not(expr) => {
244                let expr = Box::new(transformer.transform(*expr));
245                Expr::Not(expr)
246            }
247        }
248    }
249}
250
251#[cfg(test)]
252mod tests {
253    use super::*;
254
255    #[test]
256    fn test_transform_expr() {
257        // Example: Rename field "old_name" to "new_name"
258        struct RenameField {
259            old_name: String,
260            new_name: String,
261        }
262
263        impl Transform for RenameField {
264            fn transform(&mut self, expr: Expr) -> Expr {
265                match expr {
266                    Expr::Field(name) if name == self.old_name => {
267                        Expr::Field(self.new_name.clone())
268                    }
269                    _ => expr,
270                }
271            }
272        }
273
274        let expr = Expr::Eq(
275            Box::new(Expr::field_("old_name")),
276            Box::new(Expr::str_("value")),
277        );
278
279        let mut transformer = RenameField {
280            old_name: "old_name".to_string(),
281            new_name: "new_name".to_string(),
282        };
283
284        let result = expr.transform(&mut transformer);
285        assert_eq!(
286            result,
287            Expr::Eq(
288                Box::new(Expr::field_("new_name")),
289                Box::new(Expr::str_("value"))
290            )
291        );
292    }
293}