1 | use serde_json::Value; |
2 | |
3 | pub(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 | |
17 | pub(super) struct CmpEq; |
18 | |
19 | impl 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 | |
47 | pub(super) struct CmpNe; |
48 | |
49 | impl 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 | |
77 | pub(super) struct CmpGt; |
78 | |
79 | impl 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 | |
97 | pub(super) struct CmpGe; |
98 | |
99 | impl 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 | |
117 | pub(super) struct CmpLt; |
118 | |
119 | impl 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 | |
137 | pub(super) struct CmpLe; |
138 | |
139 | impl 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 | |
157 | pub(super) struct CmpAnd; |
158 | |
159 | impl 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 | |
177 | pub(super) struct CmpOr; |
178 | |
179 | impl 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)] |
209 | mod 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 | |