summaryrefslogtreecommitdiffstats
path: root/vendor/jsonpath_lib/src/select/expr_term.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsonpath_lib/src/select/expr_term.rs')
-rw-r--r--vendor/jsonpath_lib/src/select/expr_term.rs227
1 files changed, 227 insertions, 0 deletions
diff --git a/vendor/jsonpath_lib/src/select/expr_term.rs b/vendor/jsonpath_lib/src/select/expr_term.rs
new file mode 100644
index 000000000..ddbf64e53
--- /dev/null
+++ b/vendor/jsonpath_lib/src/select/expr_term.rs
@@ -0,0 +1,227 @@
+use serde_json::{Number, Value};
+use select::cmp::*;
+use select::{FilterKey, to_f64};
+
+#[derive(Debug, PartialEq)]
+pub(super) enum ExprTerm<'a> {
+ String(String),
+ Number(Number),
+ Bool(bool),
+ Json(Option<Vec<&'a Value>>, Option<FilterKey>, Vec<&'a Value>),
+}
+
+impl<'a> ExprTerm<'a> {
+ fn cmp<C1: Cmp, C2: Cmp>(
+ &self,
+ other: &Self,
+ cmp_fn: &C1,
+ reverse_cmp_fn: &C2,
+ ) -> ExprTerm<'a> {
+ match &self {
+ ExprTerm::String(s1) => match &other {
+ ExprTerm::String(s2) => ExprTerm::Bool(cmp_fn.cmp_string(s1, s2)),
+ ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
+ _ => ExprTerm::Bool(cmp_fn.default()),
+ },
+ ExprTerm::Number(n1) => match &other {
+ ExprTerm::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(to_f64(n1), to_f64(n2))),
+ ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
+ _ => ExprTerm::Bool(cmp_fn.default()),
+ },
+ ExprTerm::Bool(b1) => match &other {
+ ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(*b1, *b2)),
+ ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
+ _ => ExprTerm::Bool(cmp_fn.default()),
+ },
+ ExprTerm::Json(rel, fk1, vec1) => {
+ let ret: Vec<&Value> = match &other {
+ ExprTerm::String(s2) => vec1
+ .iter()
+ .filter(|v1| match v1 {
+ Value::String(s1) => cmp_fn.cmp_string(s1, s2),
+ Value::Object(map1) => {
+ if let Some(FilterKey::String(k)) = fk1 {
+ if let Some(Value::String(s1)) = map1.get(k) {
+ return cmp_fn.cmp_string(s1, s2);
+ }
+ }
+ cmp_fn.default()
+ }
+ _ => cmp_fn.default(),
+ })
+ .cloned()
+ .collect(),
+ ExprTerm::Number(n2) => vec1
+ .iter()
+ .filter(|v1| match v1 {
+ Value::Number(n1) => cmp_fn.cmp_f64(to_f64(n1), to_f64(n2)),
+ Value::Object(map1) => {
+ if let Some(FilterKey::String(k)) = fk1 {
+ if let Some(Value::Number(n1)) = map1.get(k) {
+ return cmp_fn.cmp_f64(to_f64(n1), to_f64(n2));
+ }
+ }
+ cmp_fn.default()
+ }
+ _ => cmp_fn.default(),
+ })
+ .cloned()
+ .collect(),
+ ExprTerm::Bool(b2) => vec1
+ .iter()
+ .filter(|v1| match v1 {
+ Value::Bool(b1) => cmp_fn.cmp_bool(*b1, *b2),
+ Value::Object(map1) => {
+ if let Some(FilterKey::String(k)) = fk1 {
+ if let Some(Value::Bool(b1)) = map1.get(k) {
+ return cmp_fn.cmp_bool(*b1, *b2);
+ }
+ }
+ cmp_fn.default()
+ }
+ _ => cmp_fn.default(),
+ })
+ .cloned()
+ .collect(),
+ ExprTerm::Json(parent, _, vec2) => {
+ if let Some(vec1) = rel {
+ cmp_fn.cmp_json(vec1, vec2)
+ } else if let Some(vec2) = parent {
+ cmp_fn.cmp_json(vec1, vec2)
+ } else {
+ cmp_fn.cmp_json(vec1, vec2)
+ }
+ }
+ };
+
+ if ret.is_empty() {
+ ExprTerm::Bool(cmp_fn.default())
+ } else if let Some(rel) = rel {
+ if let ExprTerm::Json(_, _, _) = &other {
+ ExprTerm::Json(Some(rel.to_vec()), None, ret)
+ } else {
+ let mut tmp = Vec::new();
+ for rel_value in rel {
+ if let Value::Object(map) = rel_value {
+ for map_value in map.values() {
+ for result_value in &ret {
+ if map_value.eq(*result_value) {
+ tmp.push(*rel_value);
+ }
+ }
+ }
+ }
+ }
+ ExprTerm::Json(Some(tmp), None, ret)
+ }
+ } else {
+ ExprTerm::Json(None, None, ret)
+ }
+ }
+ }
+ }
+
+ pub fn eq(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("eq - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpEq, &CmpEq);
+ debug!("eq = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn ne(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("ne - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpNe, &CmpNe);
+ debug!("ne = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn gt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("gt - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpGt, &CmpLt);
+ debug!("gt = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn ge(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("ge - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpGe, &CmpLe);
+ debug!("ge = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn lt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("lt - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpLt, &CmpGt);
+ debug!("lt = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn le(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("le - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpLe, &CmpGe);
+ debug!("le = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn and(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("and - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpAnd, &CmpAnd);
+ debug!("and = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+
+ pub fn or(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
+ debug!("or - {:?} : {:?}", &self, &other);
+ let _ = ret.take();
+ let tmp = self.cmp(other, &CmpOr, &CmpOr);
+ debug!("or = {:?}", tmp);
+ *ret = Some(tmp);
+ }
+}
+
+impl<'a> Into<ExprTerm<'a>> for &Vec<&'a Value> {
+ fn into(self) -> ExprTerm<'a> {
+ if self.len() == 1 {
+ match &self[0] {
+ Value::Number(v) => return ExprTerm::Number(v.clone()),
+ Value::String(v) => return ExprTerm::String(v.clone()),
+ Value::Bool(v) => return ExprTerm::Bool(*v),
+ _ => {}
+ }
+ }
+
+ ExprTerm::Json(None, None, self.to_vec())
+ }
+}
+
+
+#[cfg(test)]
+mod expr_term_inner_tests {
+ use serde_json::{Number, Value};
+ use select::expr_term::ExprTerm;
+
+ #[test]
+ fn value_vec_into() {
+ let v = Value::Bool(true);
+ let vec = &vec![&v];
+ let term: ExprTerm = vec.into();
+ assert_eq!(term, ExprTerm::Bool(true));
+
+ let v = Value::String("a".to_string());
+ let vec = &vec![&v];
+ let term: ExprTerm = vec.into();
+ assert_eq!(term, ExprTerm::String("a".to_string()));
+
+ let v = serde_json::from_str("1.0").unwrap();
+ let vec = &vec![&v];
+ let term: ExprTerm = vec.into();
+ assert_eq!(term, ExprTerm::Number(Number::from_f64(1.0).unwrap()));
+ }
+}