Skip to main content

rest_sql/
ast.rs

1use std::ops::{BitAnd, BitOr};
2
3/// Raw AST — unvalidated, produced directly by the parser.
4#[derive(Debug, Clone, PartialEq)]
5pub enum Ast {
6    And(Vec<Ast>),
7    Or(Vec<Ast>),
8    Constraint(Constraint),
9}
10
11impl Ast {
12    /// Combines `nodes` with AND. Panics if `nodes` is empty; unwraps if single element.
13    pub fn and(nodes: impl IntoIterator<Item = Ast>) -> Ast {
14        let v: Vec<_> = nodes.into_iter().collect();
15        assert!(!v.is_empty(), "Ast::and requires at least one node");
16        if v.len() == 1 {
17            v.into_iter().next().unwrap()
18        } else {
19            Ast::And(v)
20        }
21    }
22
23    /// Combines `nodes` with OR. Panics if `nodes` is empty; unwraps if single element.
24    pub fn or(nodes: impl IntoIterator<Item = Ast>) -> Ast {
25        let v: Vec<_> = nodes.into_iter().collect();
26        assert!(!v.is_empty(), "Ast::or requires at least one node");
27        if v.len() == 1 {
28            v.into_iter().next().unwrap()
29        } else {
30            Ast::Or(v)
31        }
32    }
33
34    /// Like `and`, but returns `None` for an empty iterator.
35    pub fn try_and(nodes: impl IntoIterator<Item = Ast>) -> Option<Ast> {
36        let v: Vec<_> = nodes.into_iter().collect();
37        if v.is_empty() {
38            None
39        } else if v.len() == 1 {
40            v.into_iter().next()
41        } else {
42            Some(Ast::And(v))
43        }
44    }
45
46    /// Like `or`, but returns `None` for an empty iterator.
47    pub fn try_or(nodes: impl IntoIterator<Item = Ast>) -> Option<Ast> {
48        let v: Vec<_> = nodes.into_iter().collect();
49        if v.is_empty() {
50            None
51        } else if v.len() == 1 {
52            v.into_iter().next()
53        } else {
54            Some(Ast::Or(v))
55        }
56    }
57}
58
59/// `And & And` → flat `And`; `And & other` → appends to the `And` list; otherwise wraps in a new `And`.
60impl BitAnd for Ast {
61    type Output = Ast;
62    fn bitand(self, rhs: Ast) -> Ast {
63        match (self, rhs) {
64            (Ast::And(mut a), Ast::And(b)) => {
65                a.extend(b);
66                Ast::And(a)
67            }
68            (Ast::And(mut a), rhs) => {
69                a.push(rhs);
70                Ast::And(a)
71            }
72            (lhs, rhs) => Ast::And(vec![lhs, rhs]),
73        }
74    }
75}
76
77/// `Or | Or` → flat `Or`; `Or | other` → appends to the `Or` list; otherwise wraps in a new `Or`.
78impl BitOr for Ast {
79    type Output = Ast;
80    fn bitor(self, rhs: Ast) -> Ast {
81        match (self, rhs) {
82            (Ast::Or(mut a), Ast::Or(b)) => {
83                a.extend(b);
84                Ast::Or(a)
85            }
86            (Ast::Or(mut a), rhs) => {
87                a.push(rhs);
88                Ast::Or(a)
89            }
90            (lhs, rhs) => Ast::Or(vec![lhs, rhs]),
91        }
92    }
93}
94
95#[derive(Debug, Clone, PartialEq)]
96pub struct Constraint {
97    pub field: String,
98    pub operator: Operator,
99    pub value: Value,
100}
101
102#[derive(Debug, Clone, PartialEq)]
103pub enum Operator {
104    Eq,
105    Neq,
106    Lt,
107    Lte,
108    Gt,
109    Gte,
110    In,
111    Out,
112    Like,
113    Ilike,
114    Between,
115    Null,
116    NotNull,
117}
118
119#[derive(Debug, Clone, PartialEq)]
120pub enum Value {
121    Null,
122    Bool(bool),
123    Int(i64),
124    Float(f64),
125    String(String),
126    Date(String),
127    DateTime(String),
128    List(Vec<Value>),
129}
130
131impl From<bool> for Value {
132    fn from(v: bool) -> Self {
133        Value::Bool(v)
134    }
135}
136
137impl From<i32> for Value {
138    fn from(v: i32) -> Self {
139        Value::Int(v as i64)
140    }
141}
142
143impl From<i64> for Value {
144    fn from(v: i64) -> Self {
145        Value::Int(v)
146    }
147}
148
149impl From<f32> for Value {
150    fn from(v: f32) -> Self {
151        Value::Float(v as f64)
152    }
153}
154
155impl From<f64> for Value {
156    fn from(v: f64) -> Self {
157        Value::Float(v)
158    }
159}
160
161impl From<&str> for Value {
162    fn from(v: &str) -> Self {
163        Value::String(v.to_owned())
164    }
165}
166
167impl From<String> for Value {
168    fn from(v: String) -> Self {
169        Value::String(v)
170    }
171}