1use serde_json::{Number, Value};
2use select::cmp::*;
3use select::{FilterKey, to_f64};
4
5#[derive(Debug, PartialEq)]
6pub(super) enum ExprTerm<'a> {
7 String(String),
8 Number(Number),
9 Bool(bool),
10 Json(Option<Vec<&'a Value>>, Option<FilterKey>, Vec<&'a Value>),
11}
12
13impl<'a> ExprTerm<'a> {
14 fn cmp<C1: Cmp, C2: Cmp>(
15 &self,
16 other: &Self,
17 cmp_fn: &C1,
18 reverse_cmp_fn: &C2,
19 ) -> ExprTerm<'a> {
20 match &self {
21 ExprTerm::String(s1) => match &other {
22 ExprTerm::String(s2) => ExprTerm::Bool(cmp_fn.cmp_string(s1, s2)),
23 ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
24 _ => ExprTerm::Bool(cmp_fn.default()),
25 },
26 ExprTerm::Number(n1) => match &other {
27 ExprTerm::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(to_f64(n1), to_f64(n2))),
28 ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
29 _ => ExprTerm::Bool(cmp_fn.default()),
30 },
31 ExprTerm::Bool(b1) => match &other {
32 ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(*b1, *b2)),
33 ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
34 _ => ExprTerm::Bool(cmp_fn.default()),
35 },
36 ExprTerm::Json(rel, fk1, vec1) => {
37 let ret: Vec<&Value> = match &other {
38 ExprTerm::String(s2) => vec1
39 .iter()
40 .filter(|v1| match v1 {
41 Value::String(s1) => cmp_fn.cmp_string(s1, s2),
42 Value::Object(map1) => {
43 if let Some(FilterKey::String(k)) = fk1 {
44 if let Some(Value::String(s1)) = map1.get(k) {
45 return cmp_fn.cmp_string(s1, s2);
46 }
47 }
48 cmp_fn.default()
49 }
50 _ => cmp_fn.default(),
51 })
52 .cloned()
53 .collect(),
54 ExprTerm::Number(n2) => vec1
55 .iter()
56 .filter(|v1| match v1 {
57 Value::Number(n1) => cmp_fn.cmp_f64(to_f64(n1), to_f64(n2)),
58 Value::Object(map1) => {
59 if let Some(FilterKey::String(k)) = fk1 {
60 if let Some(Value::Number(n1)) = map1.get(k) {
61 return cmp_fn.cmp_f64(to_f64(n1), to_f64(n2));
62 }
63 }
64 cmp_fn.default()
65 }
66 _ => cmp_fn.default(),
67 })
68 .cloned()
69 .collect(),
70 ExprTerm::Bool(b2) => vec1
71 .iter()
72 .filter(|v1| match v1 {
73 Value::Bool(b1) => cmp_fn.cmp_bool(*b1, *b2),
74 Value::Object(map1) => {
75 if let Some(FilterKey::String(k)) = fk1 {
76 if let Some(Value::Bool(b1)) = map1.get(k) {
77 return cmp_fn.cmp_bool(*b1, *b2);
78 }
79 }
80 cmp_fn.default()
81 }
82 _ => cmp_fn.default(),
83 })
84 .cloned()
85 .collect(),
86 ExprTerm::Json(parent, _, vec2) => {
87 if let Some(vec1) = rel {
88 cmp_fn.cmp_json(vec1, vec2)
89 } else if let Some(vec2) = parent {
90 cmp_fn.cmp_json(vec1, vec2)
91 } else {
92 cmp_fn.cmp_json(vec1, vec2)
93 }
94 }
95 };
96
97 if ret.is_empty() {
98 ExprTerm::Bool(cmp_fn.default())
99 } else if let Some(rel) = rel {
100 if let ExprTerm::Json(_, _, _) = &other {
101 ExprTerm::Json(Some(rel.to_vec()), None, ret)
102 } else {
103 let mut tmp = Vec::new();
104 for rel_value in rel {
105 if let Value::Object(map) = rel_value {
106 for map_value in map.values() {
107 for result_value in &ret {
108 if map_value.eq(*result_value) {
109 tmp.push(*rel_value);
110 }
111 }
112 }
113 }
114 }
115 ExprTerm::Json(Some(tmp), None, ret)
116 }
117 } else {
118 ExprTerm::Json(None, None, ret)
119 }
120 }
121 }
122 }
123
124 pub fn eq(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
125 debug!("eq - {:?} : {:?}", &self, &other);
126 let _ = ret.take();
127 let tmp = self.cmp(other, &CmpEq, &CmpEq);
128 debug!("eq = {:?}", tmp);
129 *ret = Some(tmp);
130 }
131
132 pub fn ne(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
133 debug!("ne - {:?} : {:?}", &self, &other);
134 let _ = ret.take();
135 let tmp = self.cmp(other, &CmpNe, &CmpNe);
136 debug!("ne = {:?}", tmp);
137 *ret = Some(tmp);
138 }
139
140 pub fn gt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
141 debug!("gt - {:?} : {:?}", &self, &other);
142 let _ = ret.take();
143 let tmp = self.cmp(other, &CmpGt, &CmpLt);
144 debug!("gt = {:?}", tmp);
145 *ret = Some(tmp);
146 }
147
148 pub fn ge(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
149 debug!("ge - {:?} : {:?}", &self, &other);
150 let _ = ret.take();
151 let tmp = self.cmp(other, &CmpGe, &CmpLe);
152 debug!("ge = {:?}", tmp);
153 *ret = Some(tmp);
154 }
155
156 pub fn lt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
157 debug!("lt - {:?} : {:?}", &self, &other);
158 let _ = ret.take();
159 let tmp = self.cmp(other, &CmpLt, &CmpGt);
160 debug!("lt = {:?}", tmp);
161 *ret = Some(tmp);
162 }
163
164 pub fn le(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
165 debug!("le - {:?} : {:?}", &self, &other);
166 let _ = ret.take();
167 let tmp = self.cmp(other, &CmpLe, &CmpGe);
168 debug!("le = {:?}", tmp);
169 *ret = Some(tmp);
170 }
171
172 pub fn and(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
173 debug!("and - {:?} : {:?}", &self, &other);
174 let _ = ret.take();
175 let tmp = self.cmp(other, &CmpAnd, &CmpAnd);
176 debug!("and = {:?}", tmp);
177 *ret = Some(tmp);
178 }
179
180 pub fn or(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
181 debug!("or - {:?} : {:?}", &self, &other);
182 let _ = ret.take();
183 let tmp = self.cmp(other, &CmpOr, &CmpOr);
184 debug!("or = {:?}", tmp);
185 *ret = Some(tmp);
186 }
187}
188
189impl<'a> From<&Vec<&'a Value>> for ExprTerm<'a> {
190 fn from(vec: &Vec<&'a Value>) -> Self {
191 if vec.len() == 1 {
192 match &vec[0] {
193 Value::Number(v: &Number) => return ExprTerm::Number(v.clone()),
194 Value::String(v: &String) => return ExprTerm::String(v.clone()),
195 Value::Bool(v: &bool) => return ExprTerm::Bool(*v),
196 _ => {}
197 }
198 }
199
200 ExprTerm::Json(None, None, vec.to_vec())
201 }
202}
203
204#[cfg(test)]
205mod expr_term_inner_tests {
206 use serde_json::{Number, Value};
207 use select::expr_term::ExprTerm;
208
209 #[test]
210 fn value_vec_into() {
211 let v = Value::Bool(true);
212 let vec = &vec![&v];
213 let term: ExprTerm = vec.into();
214 assert_eq!(term, ExprTerm::Bool(true));
215
216 let v = Value::String("a".to_string());
217 let vec = &vec![&v];
218 let term: ExprTerm = vec.into();
219 assert_eq!(term, ExprTerm::String("a".to_string()));
220
221 let v = serde_json::from_str("1.0").unwrap();
222 let vec = &vec![&v];
223 let term: ExprTerm = vec.into();
224 assert_eq!(term, ExprTerm::Number(Number::from_f64(1.0).unwrap()));
225 }
226}
227