1 | use serde_json::{Number, Value}; |
2 | use select::cmp::*; |
3 | use select::{FilterKey, to_f64}; |
4 | |
5 | #[derive (Debug, PartialEq)] |
6 | pub(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 | |
13 | impl<'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 | |
189 | impl<'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)] |
205 | mod 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 | |