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