1use serde_json::Value;
2
3pub(super) trait Cmp {
4 fn cmp_bool(&self, v1: bool, v2: bool) -> bool;
5
6 fn cmp_f64(&self, v1: f64, v2: f64) -> bool;
7
8 fn cmp_string(&self, v1: &str, v2: &str) -> bool;
9
10 fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>;
11
12 fn default(&self) -> bool {
13 false
14 }
15}
16
17pub(super) struct CmpEq;
18
19impl Cmp for CmpEq {
20 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
21 v1 == v2
22 }
23
24 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
25 (v1 - v2).abs() == 0_f64
26 }
27
28 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
29 v1 == v2
30 }
31
32 fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
33 let mut ret = vec![];
34
35 for a in v1 {
36 for b in v2 {
37 if a == b {
38 ret.push(*a);
39 }
40 }
41 }
42
43 ret
44 }
45}
46
47pub(super) struct CmpNe;
48
49impl Cmp for CmpNe {
50 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
51 v1 != v2
52 }
53
54 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
55 (v1 - v2).abs() != 0_f64
56 }
57
58 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
59 v1 != v2
60 }
61
62 fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
63 let mut ret = vec![];
64
65 for a in v1 {
66 for b in v2 {
67 if a != b {
68 ret.push(*a);
69 }
70 }
71 }
72
73 ret
74 }
75}
76
77pub(super) struct CmpGt;
78
79impl Cmp for CmpGt {
80 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
81 v1 & !v2
82 }
83
84 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
85 v1 > v2
86 }
87
88 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
89 v1 > v2
90 }
91
92 fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
93 Vec::new()
94 }
95}
96
97pub(super) struct CmpGe;
98
99impl Cmp for CmpGe {
100 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
101 v1 >= v2
102 }
103
104 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
105 v1 >= v2
106 }
107
108 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
109 v1 >= v2
110 }
111
112 fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
113 Vec::new()
114 }
115}
116
117pub(super) struct CmpLt;
118
119impl Cmp for CmpLt {
120 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
121 !v1 & v2
122 }
123
124 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
125 v1 < v2
126 }
127
128 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
129 v1 < v2
130 }
131
132 fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
133 Vec::new()
134 }
135}
136
137pub(super) struct CmpLe;
138
139impl Cmp for CmpLe {
140 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
141 v1 <= v2
142 }
143
144 fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
145 v1 <= v2
146 }
147
148 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
149 v1 <= v2
150 }
151
152 fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
153 Vec::new()
154 }
155}
156
157pub(super) struct CmpAnd;
158
159impl Cmp for CmpAnd {
160 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
161 v1 && v2
162 }
163
164 fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
165 true
166 }
167
168 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
169 !v1.is_empty() && !v2.is_empty()
170 }
171
172 fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
173 CmpEq.cmp_json(v1, v2)
174 }
175}
176
177pub(super) struct CmpOr;
178
179impl Cmp for CmpOr {
180 fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
181 v1 || v2
182 }
183
184 fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
185 true
186 }
187
188 fn cmp_string(&self, v1: &str, v2: &str) -> bool {
189 !v1.is_empty() || !v2.is_empty()
190 }
191
192 fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
193 let mut ret = [v1, v2].concat();
194
195 for x in (0..ret.len()).rev() {
196 for y in (x+1..ret.len()).rev() {
197 if ret[x] == ret[y] {
198 ret.remove(y);
199 }
200 }
201 }
202
203 ret
204 }
205}
206
207
208#[cfg(test)]
209mod cmp_inner_tests {
210 use serde_json::Value;
211
212 use select::cmp::*;
213
214 #[test]
215 fn cmp_eq() {
216 let cmp_fn = CmpEq;
217 assert_eq!(cmp_fn.default(), false);
218 assert_eq!(cmp_fn.cmp_bool(true, false), false);
219 assert_eq!(cmp_fn.cmp_bool(true, true), true);
220 assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
221 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
222 assert_eq!(cmp_fn.cmp_string("1", "1"), true);
223 assert_eq!(cmp_fn.cmp_string("1", "2"), false);
224 }
225
226 #[test]
227 fn cmp_ne() {
228 let cmp_fn = CmpNe;
229 assert_eq!(cmp_fn.default(), false);
230 assert_eq!(cmp_fn.cmp_bool(true, false), true);
231 assert_eq!(cmp_fn.cmp_bool(true, true), false);
232 assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
233 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
234 assert_eq!(cmp_fn.cmp_string("1", "1"), false);
235 assert_eq!(cmp_fn.cmp_string("1", "2"), true);
236 }
237
238 #[test]
239 fn cmp_gt() {
240 let cmp_fn = CmpGt;
241 assert_eq!(cmp_fn.default(), false);
242 assert_eq!(cmp_fn.cmp_bool(true, false), true);
243 assert_eq!(cmp_fn.cmp_bool(true, true), false);
244 assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
245 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
246 assert_eq!(cmp_fn.cmp_string("a", "a"), false);
247 assert_eq!(cmp_fn.cmp_string("b", "a"), true);
248 assert_eq!(cmp_fn.cmp_string("1", "2"), false);
249 }
250
251 #[test]
252 fn cmp_ge() {
253 let cmp_fn = CmpGe;
254 assert_eq!(cmp_fn.default(), false);
255 assert_eq!(cmp_fn.cmp_bool(true, false), true);
256 assert_eq!(cmp_fn.cmp_bool(true, true), true);
257 assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
258 assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
259 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
260 assert_eq!(cmp_fn.cmp_string("1", "1"), true);
261 assert_eq!(cmp_fn.cmp_string("ab", "a"), true);
262 assert_eq!(cmp_fn.cmp_string("1", "2"), false);
263 }
264
265 #[test]
266 fn cmp_lt() {
267 let cmp_fn = CmpLt;
268 assert_eq!(cmp_fn.default(), false);
269 assert_eq!(cmp_fn.cmp_bool(true, false), false);
270 assert_eq!(cmp_fn.cmp_bool(false, true), true);
271 assert_eq!(cmp_fn.cmp_bool(true, true), false);
272 assert_eq!(cmp_fn.cmp_bool(false, false), false);
273 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
274 assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
275 assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
276 assert_eq!(cmp_fn.cmp_string("a", "a"), false);
277 assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
278 assert_eq!(cmp_fn.cmp_string("1", "2"), true);
279 }
280
281 #[test]
282 fn cmp_le() {
283 let cmp_fn = CmpLe;
284 assert_eq!(cmp_fn.default(), false);
285 assert_eq!(cmp_fn.cmp_bool(true, false), false);
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), true);
289 assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
290 assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
291 assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
292 assert_eq!(cmp_fn.cmp_string("a", "a"), true);
293 assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
294 assert_eq!(cmp_fn.cmp_string("abd", "abc"), false);
295 assert_eq!(cmp_fn.cmp_string("1", "2"), true);
296 }
297
298 #[test]
299 fn cmp_and() {
300 let cmp_fn = CmpAnd;
301 assert_eq!(cmp_fn.default(), false);
302 assert_eq!(cmp_fn.cmp_bool(true, false), false);
303 assert_eq!(cmp_fn.cmp_bool(false, true), false);
304 assert_eq!(cmp_fn.cmp_bool(true, true), true);
305 assert_eq!(cmp_fn.cmp_bool(false, false), false);
306 assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
307 assert_eq!(cmp_fn.cmp_string("a", "a"), true);
308 }
309
310 #[test]
311 fn cmp_or() {
312 let cmp_fn = CmpOr;
313 assert_eq!(cmp_fn.default(), false);
314 assert_eq!(cmp_fn.cmp_bool(true, false), true);
315 assert_eq!(cmp_fn.cmp_bool(false, true), true);
316 assert_eq!(cmp_fn.cmp_bool(true, true), true);
317 assert_eq!(cmp_fn.cmp_bool(false, false), false);
318 assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
319 assert_eq!(cmp_fn.cmp_string("a", "a"), true);
320 }
321
322 #[test]
323 fn cmp_json() {
324 let v1 = Value::Bool(true);
325 let v2 = Value::String("1".to_string());
326 let left = [&v1, &v2];
327 let right = [&v1, &v2];
328 let empty: Vec<&Value> = Vec::new();
329
330 assert_eq!(CmpEq.cmp_json(&left, &right), left.to_vec());
331 assert_eq!(CmpNe.cmp_json(&left, &right), left.to_vec());
332 assert_eq!(CmpGt.cmp_json(&left, &right), empty);
333 assert_eq!(CmpGe.cmp_json(&left, &right), empty);
334 assert_eq!(CmpLt.cmp_json(&left, &right), empty);
335 assert_eq!(CmpLe.cmp_json(&left, &right), empty);
336 assert_eq!(CmpAnd.cmp_json(&left, &right), left.to_vec());
337 assert_eq!(CmpOr.cmp_json(&left, &right), left.to_vec());
338
339 assert_eq!(
340 CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
341 vec![&Value::Bool(true)]
342 );
343 assert_eq!(
344 CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
345 empty
346 );
347 assert_eq!(
348 CmpNe.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
349 empty
350 );
351 assert_eq!(
352 CmpNe.cmp_json(&[&Value::Bool(false)], &[&Value::Bool(true)]),
353 vec![&Value::Bool(false)]
354 );
355 assert_eq!(
356 CmpAnd.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
357 vec![&Value::Bool(true)]
358 );
359 assert_eq!(
360 CmpOr.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
361 vec![&Value::Bool(true), &Value::Bool(false)]
362 );
363 }
364}
365