jsonpath_lib 0.1.7

JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath
Documentation
use super::cmp::*;
use super::value_filter::ValueFilterKey;
use super::value_wrapper::*;

#[derive(Debug)]
pub enum TermContext {
    Constants(ExprTerm),
    Json(Option<ValueFilterKey>, ValueWrapper),
}

impl TermContext {
    fn cmp<F: PrivCmp + IntoType>(&self, other: &TermContext, cmp_fn: F, default: bool) -> TermContext {
        match self {
            TermContext::Constants(et) => {
                match other {
                    TermContext::Constants(oet) => {
                        trace!("const-const");
                        TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default)))
                    }
                    TermContext::Json(key, v) => {
                        trace!("const-json");
                        TermContext::Json(None, v.take_with(key, et, cmp_fn, true))
                    }
                }
            }
            TermContext::Json(key, v) => {
                match other {
                    TermContext::Json(key_other, ov) => {
                        trace!("json-json");

                        fn is_json(t: &TermContext) -> bool {
                            match t {
                                TermContext::Json(_, _) => true,
                                _ => false
                            }
                        }

                        let mut c = v.into_term(key);
                        let mut oc = ov.into_term(key_other);
                        if is_json(&c) && is_json(&oc) {
                            v.cmp(&ov, cmp_fn.into_type())
                        } else {
                            c.cmp(&mut oc, cmp_fn, default)
                        }
                    }
                    TermContext::Constants(et) => {
                        trace!("json-const");
                        TermContext::Json(None, v.take_with(key, et, cmp_fn, false))
                    }
                }
            }
        }
    }

    fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext {
        match self {
            TermContext::Constants(et) => {
                match other {
                    TermContext::Constants(oet) => {
                        match cmp_cond_type {
                            CmpCondType::Or => {
                                TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpOr, false)))
                            }
                            CmpCondType::And => {
                                TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpAnd, false)))
                            }
                        }
                    }
                    TermContext::Json(_, v) => {
                        TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false))
                    }
                }
            }
            TermContext::Json(_, v) => {
                match other {
                    TermContext::Json(_, ov) => {
                        match cmp_cond_type {
                            CmpCondType::Or => TermContext::Json(None, v.union(ov)),
                            CmpCondType::And => TermContext::Json(None, v.intersect(ov)),
                        }
                    }
                    _ => {
                        TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false))
                    }
                }
            }
        }
    }

    pub fn eq(&self, other: &TermContext) -> TermContext {
        trace!("eq");
        self.cmp(other, CmpEq, false)
    }

    pub fn ne(&self, other: &TermContext) -> TermContext {
        trace!("ne");
        self.cmp(other, CmpNe, true)
    }

    pub fn gt(&self, other: &TermContext) -> TermContext {
        trace!("gt");
        self.cmp(other, CmpGt, false)
    }

    pub fn ge(&self, other: &TermContext) -> TermContext {
        trace!("ge");
        self.cmp(other, CmpGe, false)
    }

    pub fn lt(&self, other: &TermContext) -> TermContext {
        trace!("lt");
        self.cmp(other, CmpLt, false)
    }

    pub fn le(&self, other: &TermContext) -> TermContext {
        trace!("le");
        self.cmp(other, CmpLe, false)
    }

    pub fn and(&self, other: &TermContext) -> TermContext {
        self.cmp_cond(other, CmpCondType::And)
    }

    pub fn or(&self, other: &TermContext) -> TermContext {
        self.cmp_cond(other, CmpCondType::Or)
    }
}


#[derive(Debug)]
pub enum ExprTerm {
    String(String),
    Number(f64),
    Bool(bool),
}

impl ExprTerm {
    fn cmp<F: PrivCmp>(&self, other: &ExprTerm, cmp_fn: F, default: bool) -> bool {
        match self {
            ExprTerm::Bool(v1) => match other {
                ExprTerm::Bool(v2) => cmp_fn.cmp_bool(v1, v2),
                _ => default
            }
            ExprTerm::Number(v1) => match other {
                ExprTerm::Number(v2) => cmp_fn.cmp_f64(v1, v2),
                _ => default
            }
            ExprTerm::String(v1) => match other {
                ExprTerm::String(v2) => cmp_fn.cmp_string(v1, v2),
                _ => default
            }
        }
    }
}