1 use array_tool::vec::{Intersect, Union};
2 use serde_json::Value;
3 
4 pub(super) trait Cmp {
cmp_bool(&self, v1: bool, v2: bool) -> bool5     fn cmp_bool(&self, v1: bool, v2: bool) -> bool;
6 
cmp_f64(&self, v1: f64, v2: f64) -> bool7     fn cmp_f64(&self, v1: f64, v2: f64) -> bool;
8 
cmp_string(&self, v1: &str, v2: &str) -> bool9     fn cmp_string(&self, v1: &str, v2: &str) -> bool;
10 
cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>11     fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>;
12 
default(&self) -> bool13     fn default(&self) -> bool {
14         false
15     }
16 }
17 
18 pub(super) struct CmpEq;
19 
20 impl Cmp for CmpEq {
cmp_bool(&self, v1: bool, v2: bool) -> bool21     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
22         v1 == v2
23     }
24 
cmp_f64(&self, v1: f64, v2: f64) -> bool25     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
26         (v1 - v2).abs() == 0_f64
27     }
28 
cmp_string(&self, v1: &str, v2: &str) -> bool29     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
30         v1 == v2
31     }
32 
cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>33     fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
34         v1.to_vec().intersect(v2.to_vec())
35     }
36 }
37 
38 pub(super) struct CmpNe;
39 
40 impl Cmp for CmpNe {
cmp_bool(&self, v1: bool, v2: bool) -> bool41     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
42         v1 != v2
43     }
44 
cmp_f64(&self, v1: f64, v2: f64) -> bool45     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
46         (v1 - v2).abs() != 0_f64
47     }
48 
cmp_string(&self, v1: &str, v2: &str) -> bool49     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
50         v1 != v2
51     }
52 
cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>53     fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
54         v1.to_vec().intersect_if(v2.to_vec(), |a, b| a != b)
55     }
56 }
57 
58 pub(super) struct CmpGt;
59 
60 impl Cmp for CmpGt {
cmp_bool(&self, v1: bool, v2: bool) -> bool61     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
62         v1 & !v2
63     }
64 
cmp_f64(&self, v1: f64, v2: f64) -> bool65     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
66         v1 > v2
67     }
68 
cmp_string(&self, v1: &str, v2: &str) -> bool69     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
70         v1 > v2
71     }
72 
cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value>73     fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
74         Vec::new()
75     }
76 }
77 
78 pub(super) struct CmpGe;
79 
80 impl Cmp for CmpGe {
cmp_bool(&self, v1: bool, v2: bool) -> bool81     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
82         v1 >= v2
83     }
84 
cmp_f64(&self, v1: f64, v2: f64) -> bool85     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
86         v1 >= v2
87     }
88 
cmp_string(&self, v1: &str, v2: &str) -> bool89     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
90         v1 >= v2
91     }
92 
cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value>93     fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
94         Vec::new()
95     }
96 }
97 
98 pub(super) struct CmpLt;
99 
100 impl Cmp for CmpLt {
cmp_bool(&self, v1: bool, v2: bool) -> bool101     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
102         !v1 & v2
103     }
104 
cmp_f64(&self, v1: f64, v2: f64) -> bool105     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
106         v1 < v2
107     }
108 
cmp_string(&self, v1: &str, v2: &str) -> bool109     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
110         v1 < v2
111     }
112 
cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value>113     fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
114         Vec::new()
115     }
116 }
117 
118 pub(super) struct CmpLe;
119 
120 impl Cmp for CmpLe {
cmp_bool(&self, v1: bool, v2: bool) -> bool121     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
122         v1 <= v2
123     }
124 
cmp_f64(&self, v1: f64, v2: f64) -> bool125     fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
126         v1 <= v2
127     }
128 
cmp_string(&self, v1: &str, v2: &str) -> bool129     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
130         v1 <= v2
131     }
132 
cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value>133     fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
134         Vec::new()
135     }
136 }
137 
138 pub(super) struct CmpAnd;
139 
140 impl Cmp for CmpAnd {
cmp_bool(&self, v1: bool, v2: bool) -> bool141     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
142         v1 && v2
143     }
144 
cmp_f64(&self, _v1: f64, _v2: f64) -> bool145     fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
146         true
147     }
148 
cmp_string(&self, v1: &str, v2: &str) -> bool149     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
150         !v1.is_empty() && !v2.is_empty()
151     }
152 
cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>153     fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
154         v1.to_vec().intersect(v2.to_vec())
155     }
156 }
157 
158 pub(super) struct CmpOr;
159 
160 impl Cmp for CmpOr {
cmp_bool(&self, v1: bool, v2: bool) -> bool161     fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
162         v1 || v2
163     }
164 
cmp_f64(&self, _v1: f64, _v2: f64) -> bool165     fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
166         true
167     }
168 
cmp_string(&self, v1: &str, v2: &str) -> bool169     fn cmp_string(&self, v1: &str, v2: &str) -> bool {
170         !v1.is_empty() || !v2.is_empty()
171     }
172 
cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>173     fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
174         v1.to_vec().union(v2.to_vec())
175     }
176 }
177 
178 
179 #[cfg(test)]
180 mod cmp_inner_tests {
181     use serde_json::Value;
182 
183     use select::cmp::*;
184 
185     #[test]
cmp_eq()186     fn cmp_eq() {
187         let cmp_fn = CmpEq;
188         assert_eq!(cmp_fn.default(), false);
189         assert_eq!(cmp_fn.cmp_bool(true, false), false);
190         assert_eq!(cmp_fn.cmp_bool(true, true), true);
191         assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
192         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
193         assert_eq!(cmp_fn.cmp_string("1", "1"), true);
194         assert_eq!(cmp_fn.cmp_string("1", "2"), false);
195     }
196 
197     #[test]
cmp_ne()198     fn cmp_ne() {
199         let cmp_fn = CmpNe;
200         assert_eq!(cmp_fn.default(), false);
201         assert_eq!(cmp_fn.cmp_bool(true, false), true);
202         assert_eq!(cmp_fn.cmp_bool(true, true), false);
203         assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
204         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
205         assert_eq!(cmp_fn.cmp_string("1", "1"), false);
206         assert_eq!(cmp_fn.cmp_string("1", "2"), true);
207     }
208 
209     #[test]
cmp_gt()210     fn cmp_gt() {
211         let cmp_fn = CmpGt;
212         assert_eq!(cmp_fn.default(), false);
213         assert_eq!(cmp_fn.cmp_bool(true, false), true);
214         assert_eq!(cmp_fn.cmp_bool(true, true), false);
215         assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
216         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
217         assert_eq!(cmp_fn.cmp_string("a", "a"), false);
218         assert_eq!(cmp_fn.cmp_string("b", "a"), true);
219         assert_eq!(cmp_fn.cmp_string("1", "2"), false);
220     }
221 
222     #[test]
cmp_ge()223     fn cmp_ge() {
224         let cmp_fn = CmpGe;
225         assert_eq!(cmp_fn.default(), false);
226         assert_eq!(cmp_fn.cmp_bool(true, false), true);
227         assert_eq!(cmp_fn.cmp_bool(true, true), true);
228         assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
229         assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
230         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
231         assert_eq!(cmp_fn.cmp_string("1", "1"), true);
232         assert_eq!(cmp_fn.cmp_string("ab", "a"), true);
233         assert_eq!(cmp_fn.cmp_string("1", "2"), false);
234     }
235 
236     #[test]
cmp_lt()237     fn cmp_lt() {
238         let cmp_fn = CmpLt;
239         assert_eq!(cmp_fn.default(), false);
240         assert_eq!(cmp_fn.cmp_bool(true, false), false);
241         assert_eq!(cmp_fn.cmp_bool(false, true), true);
242         assert_eq!(cmp_fn.cmp_bool(true, true), false);
243         assert_eq!(cmp_fn.cmp_bool(false, false), false);
244         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
245         assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
246         assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
247         assert_eq!(cmp_fn.cmp_string("a", "a"), false);
248         assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
249         assert_eq!(cmp_fn.cmp_string("1", "2"), true);
250     }
251 
252     #[test]
cmp_le()253     fn cmp_le() {
254         let cmp_fn = CmpLe;
255         assert_eq!(cmp_fn.default(), false);
256         assert_eq!(cmp_fn.cmp_bool(true, false), false);
257         assert_eq!(cmp_fn.cmp_bool(false, true), true);
258         assert_eq!(cmp_fn.cmp_bool(true, true), true);
259         assert_eq!(cmp_fn.cmp_bool(false, false), true);
260         assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
261         assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
262         assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
263         assert_eq!(cmp_fn.cmp_string("a", "a"), true);
264         assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
265         assert_eq!(cmp_fn.cmp_string("abd", "abc"), false);
266         assert_eq!(cmp_fn.cmp_string("1", "2"), true);
267     }
268 
269     #[test]
cmp_and()270     fn cmp_and() {
271         let cmp_fn = CmpAnd;
272         assert_eq!(cmp_fn.default(), false);
273         assert_eq!(cmp_fn.cmp_bool(true, false), false);
274         assert_eq!(cmp_fn.cmp_bool(false, true), false);
275         assert_eq!(cmp_fn.cmp_bool(true, true), true);
276         assert_eq!(cmp_fn.cmp_bool(false, false), false);
277         assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
278         assert_eq!(cmp_fn.cmp_string("a", "a"), true);
279     }
280 
281     #[test]
cmp_or()282     fn cmp_or() {
283         let cmp_fn = CmpOr;
284         assert_eq!(cmp_fn.default(), false);
285         assert_eq!(cmp_fn.cmp_bool(true, false), true);
286         assert_eq!(cmp_fn.cmp_bool(false, true), true);
287         assert_eq!(cmp_fn.cmp_bool(true, true), true);
288         assert_eq!(cmp_fn.cmp_bool(false, false), false);
289         assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
290         assert_eq!(cmp_fn.cmp_string("a", "a"), true);
291     }
292 
293     #[test]
cmp_json()294     fn cmp_json() {
295         let v1 = Value::Bool(true);
296         let v2 = Value::String("1".to_string());
297         let left = [&v1, &v2];
298         let right = [&v1, &v2];
299         let empty: Vec<&Value> = Vec::new();
300 
301         assert_eq!(CmpEq.cmp_json(&left, &right), left.to_vec());
302         assert_eq!(CmpNe.cmp_json(&left, &right), left.to_vec());
303         assert_eq!(CmpGt.cmp_json(&left, &right), empty);
304         assert_eq!(CmpGe.cmp_json(&left, &right), empty);
305         assert_eq!(CmpLt.cmp_json(&left, &right), empty);
306         assert_eq!(CmpLe.cmp_json(&left, &right), empty);
307         assert_eq!(CmpAnd.cmp_json(&left, &right), left.to_vec());
308         assert_eq!(CmpOr.cmp_json(&left, &right), left.to_vec());
309 
310         assert_eq!(
311             CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
312             vec![&Value::Bool(true)]
313         );
314         assert_eq!(
315             CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
316             empty
317         );
318         assert_eq!(
319             CmpNe.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
320             empty
321         );
322         assert_eq!(
323             CmpNe.cmp_json(&[&Value::Bool(false)], &[&Value::Bool(true)]),
324             vec![&Value::Bool(false)]
325         );
326         assert_eq!(
327             CmpAnd.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
328             vec![&Value::Bool(true)]
329         );
330         assert_eq!(
331             CmpOr.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
332             vec![&Value::Bool(true), &Value::Bool(false)]
333         );
334     }
335 }
336