diff options
Diffstat (limited to 'vendor/jsonpath_lib/src/select/cmp.rs')
-rw-r--r-- | vendor/jsonpath_lib/src/select/cmp.rs | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/vendor/jsonpath_lib/src/select/cmp.rs b/vendor/jsonpath_lib/src/select/cmp.rs new file mode 100644 index 000000000..209e67298 --- /dev/null +++ b/vendor/jsonpath_lib/src/select/cmp.rs @@ -0,0 +1,335 @@ +use array_tool::vec::{Intersect, Union}; +use serde_json::Value; + +pub(super) trait Cmp { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool; + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool; + + fn cmp_string(&self, v1: &str, v2: &str) -> bool; + + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>; + + fn default(&self) -> bool { + false + } +} + +pub(super) struct CmpEq; + +impl Cmp for CmpEq { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 == v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + (v1 - v2).abs() == 0_f64 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 == v2 + } + + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect(v2.to_vec()) + } +} + +pub(super) struct CmpNe; + +impl Cmp for CmpNe { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 != v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + (v1 - v2).abs() != 0_f64 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 != v2 + } + + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect_if(v2.to_vec(), |a, b| a != b) + } +} + +pub(super) struct CmpGt; + +impl Cmp for CmpGt { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 & !v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 > v2 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 > v2 + } + + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { + Vec::new() + } +} + +pub(super) struct CmpGe; + +impl Cmp for CmpGe { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 >= v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 >= v2 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 >= v2 + } + + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { + Vec::new() + } +} + +pub(super) struct CmpLt; + +impl Cmp for CmpLt { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + !v1 & v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 < v2 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 < v2 + } + + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { + Vec::new() + } +} + +pub(super) struct CmpLe; + +impl Cmp for CmpLe { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 <= v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 <= v2 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + v1 <= v2 + } + + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { + Vec::new() + } +} + +pub(super) struct CmpAnd; + +impl Cmp for CmpAnd { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 && v2 + } + + fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool { + true + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + !v1.is_empty() && !v2.is_empty() + } + + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect(v2.to_vec()) + } +} + +pub(super) struct CmpOr; + +impl Cmp for CmpOr { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 || v2 + } + + fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool { + true + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { + !v1.is_empty() || !v2.is_empty() + } + + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().union(v2.to_vec()) + } +} + + +#[cfg(test)] +mod cmp_inner_tests { + use serde_json::Value; + + use select::cmp::*; + + #[test] + fn cmp_eq() { + let cmp_fn = CmpEq; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), false); + assert_eq!(cmp_fn.cmp_bool(true, true), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false); + assert_eq!(cmp_fn.cmp_string("1", "1"), true); + assert_eq!(cmp_fn.cmp_string("1", "2"), false); + } + + #[test] + fn cmp_ne() { + let cmp_fn = CmpNe; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), true); + assert_eq!(cmp_fn.cmp_bool(true, true), false); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true); + assert_eq!(cmp_fn.cmp_string("1", "1"), false); + assert_eq!(cmp_fn.cmp_string("1", "2"), true); + } + + #[test] + fn cmp_gt() { + let cmp_fn = CmpGt; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), true); + assert_eq!(cmp_fn.cmp_bool(true, true), false); + assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false); + assert_eq!(cmp_fn.cmp_string("a", "a"), false); + assert_eq!(cmp_fn.cmp_string("b", "a"), true); + assert_eq!(cmp_fn.cmp_string("1", "2"), false); + } + + #[test] + fn cmp_ge() { + let cmp_fn = CmpGe; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), true); + assert_eq!(cmp_fn.cmp_bool(true, true), true); + assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false); + assert_eq!(cmp_fn.cmp_string("1", "1"), true); + assert_eq!(cmp_fn.cmp_string("ab", "a"), true); + assert_eq!(cmp_fn.cmp_string("1", "2"), false); + } + + #[test] + fn cmp_lt() { + let cmp_fn = CmpLt; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), false); + assert_eq!(cmp_fn.cmp_bool(false, true), true); + assert_eq!(cmp_fn.cmp_bool(true, true), false); + assert_eq!(cmp_fn.cmp_bool(false, false), false); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false); + assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false); + assert_eq!(cmp_fn.cmp_string("a", "a"), false); + assert_eq!(cmp_fn.cmp_string("ab", "b"), true); + assert_eq!(cmp_fn.cmp_string("1", "2"), true); + } + + #[test] + fn cmp_le() { + let cmp_fn = CmpLe; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), false); + assert_eq!(cmp_fn.cmp_bool(false, true), true); + assert_eq!(cmp_fn.cmp_bool(true, true), true); + assert_eq!(cmp_fn.cmp_bool(false, false), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true); + assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true); + assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false); + assert_eq!(cmp_fn.cmp_string("a", "a"), true); + assert_eq!(cmp_fn.cmp_string("ab", "b"), true); + assert_eq!(cmp_fn.cmp_string("abd", "abc"), false); + assert_eq!(cmp_fn.cmp_string("1", "2"), true); + } + + #[test] + fn cmp_and() { + let cmp_fn = CmpAnd; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), false); + assert_eq!(cmp_fn.cmp_bool(false, true), false); + assert_eq!(cmp_fn.cmp_bool(true, true), true); + assert_eq!(cmp_fn.cmp_bool(false, false), false); + assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true); + assert_eq!(cmp_fn.cmp_string("a", "a"), true); + } + + #[test] + fn cmp_or() { + let cmp_fn = CmpOr; + assert_eq!(cmp_fn.default(), false); + assert_eq!(cmp_fn.cmp_bool(true, false), true); + assert_eq!(cmp_fn.cmp_bool(false, true), true); + assert_eq!(cmp_fn.cmp_bool(true, true), true); + assert_eq!(cmp_fn.cmp_bool(false, false), false); + assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true); + assert_eq!(cmp_fn.cmp_string("a", "a"), true); + } + + #[test] + fn cmp_json() { + let v1 = Value::Bool(true); + let v2 = Value::String("1".to_string()); + let left = [&v1, &v2]; + let right = [&v1, &v2]; + let empty: Vec<&Value> = Vec::new(); + + assert_eq!(CmpEq.cmp_json(&left, &right), left.to_vec()); + assert_eq!(CmpNe.cmp_json(&left, &right), left.to_vec()); + assert_eq!(CmpGt.cmp_json(&left, &right), empty); + assert_eq!(CmpGe.cmp_json(&left, &right), empty); + assert_eq!(CmpLt.cmp_json(&left, &right), empty); + assert_eq!(CmpLe.cmp_json(&left, &right), empty); + assert_eq!(CmpAnd.cmp_json(&left, &right), left.to_vec()); + assert_eq!(CmpOr.cmp_json(&left, &right), left.to_vec()); + + assert_eq!( + CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]), + vec![&Value::Bool(true)] + ); + assert_eq!( + CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]), + empty + ); + assert_eq!( + CmpNe.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]), + empty + ); + assert_eq!( + CmpNe.cmp_json(&[&Value::Bool(false)], &[&Value::Bool(true)]), + vec![&Value::Bool(false)] + ); + assert_eq!( + CmpAnd.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]), + vec![&Value::Bool(true)] + ); + assert_eq!( + CmpOr.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]), + vec![&Value::Bool(true), &Value::Bool(false)] + ); + } +} |