2019-06-09 22:55:35 +09:00
|
|
|
use std::collections::HashSet;
|
2019-06-19 15:09:42 +09:00
|
|
|
use std::fmt;
|
2019-06-09 22:55:35 +09:00
|
|
|
|
2019-06-02 22:03:35 +09:00
|
|
|
use array_tool::vec::{Intersect, Union};
|
2019-06-11 16:12:40 +09:00
|
|
|
use indexmap::IndexMap;
|
2019-06-02 22:03:35 +09:00
|
|
|
use serde_json::{Number, Value};
|
|
|
|
|
|
|
|
use parser::parser::*;
|
|
|
|
|
|
|
|
fn to_f64(n: &Number) -> f64 {
|
|
|
|
if n.is_i64() {
|
|
|
|
n.as_i64().unwrap() as f64
|
|
|
|
} else if n.is_f64() {
|
|
|
|
n.as_f64().unwrap()
|
|
|
|
} else {
|
|
|
|
n.as_u64().unwrap() as f64
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: &String, v2: &String) -> bool;
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value>;
|
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
fn default(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_string(&self, v1: &String, v2: &String) -> bool {
|
|
|
|
v1 == v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
v1.intersect(v2.to_vec())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_string(&self, v1: &String, v2: &String) -> bool {
|
|
|
|
v1 != v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
v1.intersect_if(v2.to_vec(), |a, b| a != b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: &String, v2: &String) -> bool {
|
|
|
|
v1 > v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: &String, v2: &String) -> bool {
|
|
|
|
v1 >= v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: &String, v2: &String) -> bool {
|
|
|
|
v1 < v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: &String, v2: &String) -> bool {
|
|
|
|
v1 <= v2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
v1 > &0_f64 && v2 > &0_f64
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_string(&self, v1: &String, v2: &String) -> bool {
|
|
|
|
!v1.is_empty() && !v2.is_empty()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
v1.intersect(v2.to_vec())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
v1 > &0_f64 || v2 > &0_f64
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_string(&self, v1: &String, v2: &String) -> bool {
|
|
|
|
!v1.is_empty() || !v2.is_empty()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> {
|
|
|
|
v1.union(v2.to_vec())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum ExprTerm<'a> {
|
|
|
|
String(String),
|
|
|
|
Number(Number),
|
|
|
|
Bool(bool),
|
|
|
|
Json(Option<FilterKey>, Vec<&'a Value>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ExprTerm<'a> {
|
|
|
|
fn is_string(&self) -> bool {
|
|
|
|
match &self {
|
|
|
|
ExprTerm::String(_) => true,
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => false,
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_number(&self) -> bool {
|
|
|
|
match &self {
|
|
|
|
ExprTerm::Number(_) => true,
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => false,
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_bool(&self) -> bool {
|
|
|
|
match &self {
|
|
|
|
ExprTerm::Bool(_) => true,
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => false,
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_json(&self) -> bool {
|
|
|
|
match &self {
|
|
|
|
ExprTerm::Json(_, _) => true,
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => false,
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
fn cmp<C1: Cmp, C2: Cmp>(
|
|
|
|
&self,
|
|
|
|
other: &Self,
|
|
|
|
cmp_fn: &C1,
|
|
|
|
reverse_cmp_fn: &C2,
|
|
|
|
) -> ExprTerm<'a> {
|
2019-06-02 22:03:35 +09:00
|
|
|
match &self {
|
|
|
|
ExprTerm::String(s1) => match &other {
|
|
|
|
ExprTerm::String(s2) => ExprTerm::Bool(cmp_fn.cmp_string(s1, s2)),
|
2019-06-19 11:34:47 +09:00
|
|
|
ExprTerm::Json(_, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
|
|
|
|
_ => ExprTerm::Bool(cmp_fn.default()),
|
|
|
|
},
|
2019-06-02 22:03:35 +09:00
|
|
|
ExprTerm::Number(n1) => match &other {
|
|
|
|
ExprTerm::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2))),
|
2019-06-19 11:34:47 +09:00
|
|
|
ExprTerm::Json(_, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
|
|
|
|
_ => ExprTerm::Bool(cmp_fn.default()),
|
|
|
|
},
|
2019-06-02 22:03:35 +09:00
|
|
|
ExprTerm::Bool(b1) => match &other {
|
|
|
|
ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(b1, b2)),
|
2019-06-19 11:34:47 +09:00
|
|
|
ExprTerm::Json(_, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
|
|
|
|
_ => ExprTerm::Bool(cmp_fn.default()),
|
|
|
|
},
|
2019-06-02 22:03:35 +09:00
|
|
|
ExprTerm::Json(fk1, vec1) if other.is_string() => {
|
2019-06-19 11:34:47 +09:00
|
|
|
let s2 = if let ExprTerm::String(s2) = &other {
|
|
|
|
s2
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
2019-06-03 21:41:08 +09:00
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
let ret: Vec<&Value> = vec1
|
|
|
|
.iter()
|
|
|
|
.filter(|v1| match v1 {
|
2019-06-03 21:41:08 +09:00
|
|
|
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);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
2019-06-03 21:41:08 +09:00
|
|
|
cmp_fn.default()
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => cmp_fn.default(),
|
|
|
|
})
|
|
|
|
.map(|v| *v)
|
|
|
|
.collect();
|
2019-06-03 21:41:08 +09:00
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
if ret.is_empty() {
|
|
|
|
ExprTerm::Bool(cmp_fn.default())
|
|
|
|
} else {
|
|
|
|
ExprTerm::Json(None, ret)
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
ExprTerm::Json(fk1, vec1) if other.is_number() => {
|
2019-06-19 11:34:47 +09:00
|
|
|
let n2 = if let ExprTerm::Number(n2) = &other {
|
|
|
|
n2
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
|
|
|
let ret: Vec<&Value> = vec1
|
|
|
|
.iter()
|
|
|
|
.filter(|v1| match v1 {
|
2019-06-03 21:41:08 +09:00
|
|
|
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));
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
2019-06-03 21:41:08 +09:00
|
|
|
cmp_fn.default()
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => cmp_fn.default(),
|
|
|
|
})
|
|
|
|
.map(|v| *v)
|
|
|
|
.collect();
|
2019-06-03 21:41:08 +09:00
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
if ret.is_empty() {
|
|
|
|
ExprTerm::Bool(cmp_fn.default())
|
|
|
|
} else {
|
|
|
|
ExprTerm::Json(None, ret)
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
ExprTerm::Json(fk1, vec1) if other.is_bool() => {
|
2019-06-19 11:34:47 +09:00
|
|
|
let b2 = if let ExprTerm::Bool(b2) = &other {
|
|
|
|
b2
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
|
|
|
let ret: Vec<&Value> = vec1
|
|
|
|
.iter()
|
|
|
|
.filter(|v1| match v1 {
|
2019-06-03 21:41:08 +09:00
|
|
|
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);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
2019-06-03 21:41:08 +09:00
|
|
|
cmp_fn.default()
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => cmp_fn.default(),
|
|
|
|
})
|
|
|
|
.map(|v| *v)
|
|
|
|
.collect();
|
2019-06-03 21:41:08 +09:00
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
if ret.is_empty() {
|
|
|
|
ExprTerm::Bool(cmp_fn.default())
|
|
|
|
} else {
|
|
|
|
ExprTerm::Json(None, ret)
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
ExprTerm::Json(_, vec1) if other.is_json() => match &other {
|
|
|
|
ExprTerm::Json(_, vec2) => {
|
|
|
|
let vec = cmp_fn.cmp_json(vec1, vec2);
|
|
|
|
if vec.is_empty() {
|
|
|
|
ExprTerm::Bool(cmp_fn.default())
|
|
|
|
} else {
|
|
|
|
ExprTerm::Json(None, vec)
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
_ => unreachable!(),
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
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, self.to_vec())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
fn walk_all_with_str<'a>(
|
|
|
|
vec: &Vec<&'a Value>,
|
|
|
|
tmp: &mut Vec<&'a Value>,
|
|
|
|
key: &str,
|
|
|
|
is_filter: bool,
|
|
|
|
) {
|
2019-06-02 22:03:35 +09:00
|
|
|
if is_filter {
|
2019-06-03 21:41:08 +09:00
|
|
|
walk(vec, tmp, &|v| match v {
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Object(map) if map.contains_key(key) => Some(vec![v]),
|
|
|
|
_ => None,
|
2019-06-02 22:03:35 +09:00
|
|
|
});
|
|
|
|
} else {
|
2019-06-03 21:41:08 +09:00
|
|
|
walk(vec, tmp, &|v| match v {
|
|
|
|
Value::Object(map) => match map.get(key) {
|
|
|
|
Some(v) => Some(vec![v]),
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
_ => None,
|
2019-06-02 22:03:35 +09:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn walk_all<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>) {
|
|
|
|
walk(vec, tmp, &|v| match v {
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Array(vec) => Some(vec.iter().collect()),
|
2019-06-02 22:03:35 +09:00
|
|
|
Value::Object(map) => {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
for (_, v) in map {
|
|
|
|
tmp.push(v);
|
|
|
|
}
|
|
|
|
Some(tmp)
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => None,
|
2019-06-02 22:03:35 +09:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn walk<'a, F>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, fun: &F)
|
2019-06-19 11:34:47 +09:00
|
|
|
where
|
|
|
|
F: Fn(&Value) -> Option<Vec<&Value>>,
|
2019-06-23 17:22:58 +09:00
|
|
|
{
|
|
|
|
fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F)
|
|
|
|
where
|
|
|
|
F: Fn(&Value) -> Option<Vec<&Value>>,
|
2019-06-02 22:03:35 +09:00
|
|
|
{
|
|
|
|
if let Some(mut ret) = fun(v) {
|
|
|
|
tmp.append(&mut ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
match v {
|
|
|
|
Value::Array(vec) => {
|
|
|
|
for v in vec {
|
|
|
|
_walk(v, tmp, fun);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Value::Object(map) => {
|
|
|
|
for (_, v) in map {
|
|
|
|
_walk(&v, tmp, fun);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for v in vec {
|
|
|
|
_walk(v, tmp, fun);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn abs_index(n: &isize, len: usize) -> usize {
|
|
|
|
if n < &0_isize {
|
|
|
|
(n + len as isize) as usize
|
|
|
|
} else {
|
|
|
|
*n as usize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum FilterKey {
|
|
|
|
String(String),
|
|
|
|
All,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum JsonPathError {
|
|
|
|
EmptyPath,
|
|
|
|
EmptyValue,
|
|
|
|
Path(String),
|
|
|
|
Serde(String),
|
|
|
|
}
|
|
|
|
|
2019-06-19 15:09:42 +09:00
|
|
|
impl fmt::Debug for JsonPathError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for JsonPathError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
JsonPathError::EmptyPath => f.write_str("path not set"),
|
|
|
|
JsonPathError::EmptyValue => f.write_str("json value not set"),
|
|
|
|
JsonPathError::Path(msg) => f.write_str(&format!("path error: \n{}\n", msg)),
|
|
|
|
JsonPathError::Serde(msg) => f.write_str(&format!("serde error: \n{}\n", msg)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-02 22:03:35 +09:00
|
|
|
#[derive(Debug)]
|
2019-06-11 16:12:40 +09:00
|
|
|
pub struct Selector<'a, 'b> {
|
2019-06-02 22:03:35 +09:00
|
|
|
node: Option<Node>,
|
2019-06-11 16:12:40 +09:00
|
|
|
node_ref: Option<&'b Node>,
|
2019-06-02 22:03:35 +09:00
|
|
|
value: Option<&'a Value>,
|
|
|
|
tokens: Vec<ParseToken>,
|
|
|
|
terms: Vec<Option<ExprTerm<'a>>>,
|
|
|
|
current: Option<Vec<&'a Value>>,
|
2019-06-11 16:12:40 +09:00
|
|
|
selectors: Vec<Selector<'a, 'b>>,
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
impl<'a, 'b> Selector<'a, 'b> {
|
2019-06-02 22:03:35 +09:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Selector {
|
|
|
|
node: None,
|
2019-06-11 16:12:40 +09:00
|
|
|
node_ref: None,
|
2019-06-02 22:03:35 +09:00
|
|
|
value: None,
|
|
|
|
tokens: Vec::new(),
|
|
|
|
terms: Vec::new(),
|
|
|
|
current: None,
|
|
|
|
selectors: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
2019-06-02 22:03:35 +09:00
|
|
|
debug!("path : {}", path);
|
2019-06-11 16:12:40 +09:00
|
|
|
|
|
|
|
if self.node_ref.is_some() {
|
|
|
|
self.node_ref.take();
|
|
|
|
}
|
|
|
|
|
2019-06-03 18:45:26 +09:00
|
|
|
self.node = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?);
|
2019-06-02 22:03:35 +09:00
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
pub fn node_ref(&self) -> Option<&Node> {
|
|
|
|
if let Some(node) = &self.node {
|
|
|
|
Some(node)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn compiled_path(&mut self, node: &'b Node) -> &mut Self {
|
|
|
|
if self.node.is_some() {
|
|
|
|
self.node.take();
|
|
|
|
}
|
|
|
|
|
|
|
|
self.node_ref = Some(node);
|
2019-06-02 22:03:35 +09:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
pub fn reset_value(&mut self) -> &mut Self {
|
|
|
|
self.current = None;
|
2019-06-02 22:03:35 +09:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn value(&mut self, v: &'a Value) -> &mut Self {
|
|
|
|
self.value = Some(v);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _select(&mut self) -> Result<(), JsonPathError> {
|
2019-06-11 16:12:40 +09:00
|
|
|
if self.node_ref.is_some() {
|
|
|
|
let node_ref = self.node_ref.take().unwrap();
|
|
|
|
self.visit(node_ref);
|
|
|
|
return Ok(());
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
2019-06-11 16:12:40 +09:00
|
|
|
|
|
|
|
if self.node.is_none() {
|
|
|
|
return Err(JsonPathError::EmptyPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
let node = self.node.take().unwrap();
|
|
|
|
self.visit(&node);
|
|
|
|
self.node = Some(node);
|
|
|
|
|
|
|
|
Ok(())
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
|
|
|
|
self._select()?;
|
|
|
|
|
|
|
|
match &self.current {
|
|
|
|
Some(vec) => {
|
|
|
|
let mut ret = Vec::new();
|
|
|
|
for v in vec {
|
|
|
|
match T::deserialize(*v) {
|
|
|
|
Ok(v) => ret.push(v),
|
2019-06-19 11:34:47 +09:00
|
|
|
Err(e) => return Err(JsonPathError::Serde(e.to_string())),
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(ret)
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => Err(JsonPathError::EmptyValue),
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn select_as_str(&mut self) -> Result<String, JsonPathError> {
|
|
|
|
self._select()?;
|
|
|
|
|
|
|
|
match &self.current {
|
|
|
|
Some(r) => {
|
2019-06-19 11:34:47 +09:00
|
|
|
Ok(serde_json::to_string(r).map_err(|e| JsonPathError::Serde(e.to_string()))?)
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => Err(JsonPathError::EmptyValue),
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn select(&mut self) -> Result<Vec<&'a Value>, JsonPathError> {
|
|
|
|
self._select()?;
|
|
|
|
|
|
|
|
match &self.current {
|
|
|
|
Some(r) => Ok(r.to_vec()),
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => Err(JsonPathError::EmptyValue),
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_filter_context(&mut self) {
|
|
|
|
self.terms.push(None);
|
|
|
|
debug!("new_filter_context: {:?}", self.terms);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn in_filter<F: Fn(&Vec<&'a Value>, &mut Vec<&'a Value>) -> FilterKey>(&mut self, fun: F) {
|
|
|
|
match self.terms.pop() {
|
2019-06-03 21:41:08 +09:00
|
|
|
Some(peek) => match peek {
|
|
|
|
Some(v) => {
|
|
|
|
debug!("in_filter 1.: {:?}", v);
|
2019-06-02 22:03:35 +09:00
|
|
|
|
2019-06-03 21:41:08 +09:00
|
|
|
match v {
|
|
|
|
ExprTerm::Json(_, vec) => {
|
2019-06-02 22:03:35 +09:00
|
|
|
let mut tmp = Vec::new();
|
2019-06-03 21:41:08 +09:00
|
|
|
let filter_key = fun(&vec, &mut tmp);
|
2019-06-02 22:03:35 +09:00
|
|
|
self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp)));
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => unreachable!(),
|
2019-06-03 21:41:08 +09:00
|
|
|
};
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
debug!("in_filter 2.: {:?}", &self.current);
|
|
|
|
|
|
|
|
if let Some(current) = &self.current {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
let filter_key = fun(current, &mut tmp);
|
|
|
|
self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp)));
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
2019-06-03 21:41:08 +09:00
|
|
|
}
|
|
|
|
},
|
2019-06-02 22:03:35 +09:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_in_filter_with_str(&mut self, key: &str) {
|
|
|
|
self.in_filter(|vec, tmp| {
|
|
|
|
walk_all_with_str(&vec, tmp, key, true);
|
|
|
|
FilterKey::All
|
|
|
|
});
|
|
|
|
|
|
|
|
debug!("all_in_filter_with_str : {}, {:?}", key, self.terms);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_in_filter_with_str(&mut self, key: &str) {
|
2019-06-19 11:34:47 +09:00
|
|
|
fn _collect<'a>(
|
|
|
|
v: &'a Value,
|
|
|
|
tmp: &mut Vec<&'a Value>,
|
|
|
|
key: &str,
|
|
|
|
visited: &mut HashSet<*const Value>,
|
|
|
|
) {
|
2019-06-02 22:03:35 +09:00
|
|
|
match v {
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Object(map) => {
|
|
|
|
if map.contains_key(key) {
|
|
|
|
let ptr = v as *const Value;
|
|
|
|
if !visited.contains(&ptr) {
|
|
|
|
visited.insert(ptr);
|
|
|
|
tmp.push(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Value::Array(vec) => {
|
|
|
|
for v in vec {
|
|
|
|
_collect(v, tmp, key, visited);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.in_filter(|vec, tmp| {
|
|
|
|
let mut visited = HashSet::new();
|
|
|
|
for v in vec {
|
|
|
|
_collect(v, tmp, key, &mut visited);
|
|
|
|
}
|
|
|
|
FilterKey::String(key.to_owned())
|
|
|
|
});
|
|
|
|
|
|
|
|
debug!("next_in_filter_with_str : {}, {:?}", key, self.terms);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_from_current_with_num(&mut self, index: f64) {
|
|
|
|
if let Some(current) = self.current.take() {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
for c in current {
|
|
|
|
if let Value::Array(vec) = c {
|
|
|
|
let index = abs_index(&(index as isize), vec.len());
|
|
|
|
if let Some(v) = c.get(index) {
|
|
|
|
tmp.push(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.current = Some(tmp);
|
|
|
|
}
|
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
debug!(
|
|
|
|
"next_from_current_with_num : {:?}, {:?}",
|
|
|
|
&index, self.current
|
|
|
|
);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
|
2019-06-18 11:46:24 +09:00
|
|
|
fn next_from_current_with_str(&mut self, keys: &Vec<String>) {
|
2019-06-19 11:34:47 +09:00
|
|
|
fn _collect<'a>(
|
|
|
|
v: &'a Value,
|
|
|
|
tmp: &mut Vec<&'a Value>,
|
|
|
|
keys: &Vec<String>,
|
|
|
|
visited: &mut HashSet<*const Value>,
|
|
|
|
) {
|
2019-06-02 22:03:35 +09:00
|
|
|
match v {
|
|
|
|
Value::Object(map) => {
|
2019-06-18 11:46:24 +09:00
|
|
|
for key in keys {
|
|
|
|
if let Some(v) = map.get(key) {
|
|
|
|
let ptr = v as *const Value;
|
|
|
|
if !visited.contains(&ptr) {
|
|
|
|
visited.insert(ptr);
|
|
|
|
tmp.push(v)
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Array(vec) => {
|
|
|
|
for v in vec {
|
|
|
|
_collect(v, tmp, keys, visited);
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(current) = self.current.take() {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
let mut visited = HashSet::new();
|
|
|
|
for c in current {
|
2019-06-18 11:46:24 +09:00
|
|
|
_collect(c, &mut tmp, keys, &mut visited);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
self.current = Some(tmp);
|
|
|
|
}
|
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
debug!(
|
|
|
|
"next_from_current_with_str : {:?}, {:?}",
|
|
|
|
keys, self.current
|
|
|
|
);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
fn next_all_from_current(&mut self) {
|
|
|
|
fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>) {
|
|
|
|
match v {
|
|
|
|
Value::Object(map) => {
|
|
|
|
for (_, v) in map {
|
|
|
|
tmp.push(v)
|
|
|
|
}
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Array(vec) => {
|
|
|
|
for v in vec {
|
|
|
|
_collect(v, tmp);
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(current) = self.current.take() {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
for c in current {
|
|
|
|
_collect(c, &mut tmp);
|
|
|
|
}
|
|
|
|
self.current = Some(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug!("next_all_from_current : {:?}", self.current);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_from_current(&mut self) {
|
|
|
|
if let Some(current) = self.current.take() {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
walk_all(¤t, &mut tmp);
|
|
|
|
self.current = Some(tmp);
|
|
|
|
}
|
|
|
|
debug!("all_from_current: {:?}", self.current);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_from_current_with_str(&mut self, key: &str) {
|
|
|
|
if let Some(current) = self.current.take() {
|
|
|
|
let mut tmp = Vec::new();
|
|
|
|
walk_all_with_str(¤t, &mut tmp, key, false);
|
|
|
|
self.current = Some(tmp);
|
|
|
|
}
|
|
|
|
debug!("all_from_current_with_str: {}, {:?}", key, self.current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
impl<'a, 'b> NodeVisitor for Selector<'a, 'b> {
|
2019-06-02 22:03:35 +09:00
|
|
|
fn visit_token(&mut self, token: &ParseToken) {
|
|
|
|
debug!("token: {:?}, stack: {:?}", token, self.tokens);
|
|
|
|
|
|
|
|
if !self.selectors.is_empty() {
|
|
|
|
match token {
|
|
|
|
ParseToken::Absolute | ParseToken::Relative | ParseToken::Filter(_) => {
|
2019-06-09 22:55:35 +09:00
|
|
|
let selector = self.selectors.pop().unwrap();
|
|
|
|
|
|
|
|
if let Some(current) = &selector.current {
|
|
|
|
let term = current.into();
|
2019-06-02 22:03:35 +09:00
|
|
|
|
|
|
|
if let Some(s) = self.selectors.last_mut() {
|
|
|
|
s.terms.push(Some(term));
|
|
|
|
} else {
|
|
|
|
self.terms.push(Some(term));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
if let Some(selector) = self.selectors.last_mut() {
|
|
|
|
selector.visit_token(token);
|
2019-06-02 22:03:35 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
match token {
|
|
|
|
ParseToken::Absolute => {
|
|
|
|
if self.current.is_some() {
|
2019-06-09 22:55:35 +09:00
|
|
|
let mut selector = Selector::new();
|
|
|
|
|
2019-06-02 22:03:35 +09:00
|
|
|
if let Some(value) = self.value {
|
2019-06-09 22:55:35 +09:00
|
|
|
selector.value = Some(value);
|
|
|
|
selector.current = Some(vec![value]);
|
|
|
|
self.selectors.push(selector);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
match &self.value {
|
|
|
|
Some(v) => self.current = Some(vec![v]),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ParseToken::Relative => {
|
2019-06-23 17:22:58 +09:00
|
|
|
if let Some(ParseToken::Array) = self.tokens.last() {
|
|
|
|
let array_token = self.tokens.pop();
|
|
|
|
if let Some(ParseToken::Leaves) = self.tokens.last() {
|
|
|
|
self.tokens.pop();
|
|
|
|
self.all_from_current();
|
|
|
|
}
|
|
|
|
self.tokens.push(array_token.unwrap());
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
self.new_filter_context();
|
|
|
|
}
|
2019-06-23 17:22:58 +09:00
|
|
|
ParseToken::In | ParseToken::Leaves | ParseToken::Array => {
|
2019-06-02 22:03:35 +09:00
|
|
|
self.tokens.push(token.clone());
|
|
|
|
}
|
|
|
|
ParseToken::ArrayEof => {
|
|
|
|
if let Some(Some(e)) = self.terms.pop() {
|
|
|
|
match e {
|
|
|
|
ExprTerm::Number(n) => {
|
|
|
|
self.next_from_current_with_num(to_f64(&n));
|
|
|
|
}
|
|
|
|
ExprTerm::String(key) => {
|
2019-06-18 11:46:24 +09:00
|
|
|
self.next_from_current_with_str(&vec![key]);
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
ExprTerm::Json(_, v) => {
|
|
|
|
if v.is_empty() {
|
|
|
|
self.current = Some(vec![&Value::Null]);
|
|
|
|
} else {
|
|
|
|
self.current = Some(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExprTerm::Bool(false) => {
|
|
|
|
self.current = Some(vec![&Value::Null]);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.tokens.pop();
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
ParseToken::All => match self.tokens.last() {
|
|
|
|
Some(ParseToken::Leaves) => {
|
|
|
|
self.tokens.pop();
|
|
|
|
self.all_from_current();
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
Some(ParseToken::In) => {
|
|
|
|
self.tokens.pop();
|
|
|
|
self.next_all_from_current();
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
},
|
2019-06-02 22:03:35 +09:00
|
|
|
ParseToken::Bool(b) => {
|
|
|
|
self.terms.push(Some(ExprTerm::Bool(*b)));
|
|
|
|
}
|
|
|
|
ParseToken::Key(key) => {
|
|
|
|
if let Some(ParseToken::Array) = self.tokens.last() {
|
|
|
|
self.terms.push(Some(ExprTerm::String(key.clone())));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
match self.tokens.pop() {
|
|
|
|
Some(t) => {
|
|
|
|
if self.terms.is_empty() {
|
|
|
|
match t {
|
2019-06-19 11:34:47 +09:00
|
|
|
ParseToken::Leaves => self.all_from_current_with_str(key.as_str()),
|
2019-06-02 22:03:35 +09:00
|
|
|
ParseToken::In => {
|
2019-06-18 11:46:24 +09:00
|
|
|
self.next_from_current_with_str(&vec![key.clone()])
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match t {
|
|
|
|
ParseToken::Leaves => {
|
|
|
|
self.all_in_filter_with_str(key.as_str());
|
|
|
|
}
|
|
|
|
ParseToken::In => {
|
|
|
|
self.next_in_filter_with_str(key.as_str());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2019-06-18 11:46:24 +09:00
|
|
|
ParseToken::Keys(keys) => {
|
|
|
|
if !self.terms.is_empty() {
|
|
|
|
unimplemented!("keys in filter");
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(ParseToken::Array) = self.tokens.pop() {
|
|
|
|
self.next_from_current_with_str(keys);
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
ParseToken::Number(v) => {
|
2019-06-19 11:34:47 +09:00
|
|
|
self.terms
|
|
|
|
.push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap())));
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
ParseToken::Filter(ref ft) => {
|
2019-06-20 18:55:41 +09:00
|
|
|
let ref right = match self.terms.pop() {
|
|
|
|
Some(Some(right)) => right,
|
|
|
|
Some(None) => ExprTerm::Json(
|
|
|
|
None,
|
|
|
|
match &self.current {
|
|
|
|
Some(current) => current.to_vec(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
_ => panic!("empty term right"),
|
|
|
|
};
|
|
|
|
|
|
|
|
let left = match self.terms.pop() {
|
|
|
|
Some(Some(left)) => left,
|
|
|
|
Some(None) => ExprTerm::Json(
|
|
|
|
None,
|
|
|
|
match &self.current {
|
|
|
|
Some(current) => current.to_vec(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
_ => panic!("empty term left"),
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ret = None;
|
|
|
|
match ft {
|
|
|
|
FilterToken::Equal => left.eq(right, &mut ret),
|
|
|
|
FilterToken::NotEqual => left.ne(right, &mut ret),
|
|
|
|
FilterToken::Greater => left.gt(right, &mut ret),
|
|
|
|
FilterToken::GreaterOrEqual => left.ge(right, &mut ret),
|
|
|
|
FilterToken::Little => left.lt(right, &mut ret),
|
|
|
|
FilterToken::LittleOrEqual => left.le(right, &mut ret),
|
|
|
|
FilterToken::And => left.and(right, &mut ret),
|
|
|
|
FilterToken::Or => left.or(right, &mut ret),
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(e) = ret {
|
|
|
|
self.terms.push(Some(e));
|
2019-06-02 22:03:35 +09:00
|
|
|
}
|
|
|
|
}
|
2019-06-17 18:05:02 +09:00
|
|
|
ParseToken::Range(from, to, step) => {
|
2019-06-02 22:03:35 +09:00
|
|
|
if !self.terms.is_empty() {
|
|
|
|
unimplemented!("range syntax in filter");
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(ParseToken::Array) = self.tokens.pop() {
|
|
|
|
let mut tmp = Vec::new();
|
2019-06-03 21:41:08 +09:00
|
|
|
if let Some(current) = &self.current {
|
|
|
|
for v in current {
|
2019-06-02 22:03:35 +09:00
|
|
|
if let Value::Array(vec) = v {
|
|
|
|
let from = if let Some(from) = from {
|
|
|
|
abs_index(from, vec.len())
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
let to = if let Some(to) = to {
|
|
|
|
abs_index(to, vec.len())
|
|
|
|
} else {
|
|
|
|
vec.len()
|
|
|
|
};
|
|
|
|
|
2019-06-17 18:05:02 +09:00
|
|
|
for i in (from..to).step_by(match step {
|
|
|
|
Some(step) => *step,
|
2019-06-19 11:34:47 +09:00
|
|
|
_ => 1,
|
2019-06-17 18:05:02 +09:00
|
|
|
}) {
|
2019-06-02 22:03:35 +09:00
|
|
|
if let Some(v) = vec.get(i) {
|
|
|
|
tmp.push(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.current = Some(tmp);
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ParseToken::Union(indices) => {
|
|
|
|
if !self.terms.is_empty() {
|
|
|
|
unimplemented!("union syntax in filter");
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(ParseToken::Array) = self.tokens.pop() {
|
|
|
|
let mut tmp = Vec::new();
|
2019-06-03 21:41:08 +09:00
|
|
|
if let Some(current) = &self.current {
|
|
|
|
for v in current {
|
2019-06-02 22:03:35 +09:00
|
|
|
if let Value::Array(vec) = v {
|
|
|
|
for i in indices {
|
|
|
|
if let Some(v) = vec.get(abs_index(i, vec.len())) {
|
|
|
|
tmp.push(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.current = Some(tmp);
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ParseToken::Eof => {
|
|
|
|
debug!("visit_token eof");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
pub struct SelectorMut {
|
|
|
|
path: Option<Node>,
|
|
|
|
value: Option<Value>,
|
2019-06-03 21:41:08 +09:00
|
|
|
}
|
2019-06-02 22:03:35 +09:00
|
|
|
|
2019-06-11 18:40:18 +09:00
|
|
|
fn replace_value<F: FnMut(&Value) -> Value>(tokens: Vec<String>, value: &mut Value, fun: &mut F) {
|
|
|
|
let mut target = value;
|
|
|
|
|
|
|
|
for (i, token) in tokens.iter().enumerate() {
|
|
|
|
let target_once = target;
|
|
|
|
let is_last = i == tokens.len() - 1;
|
|
|
|
let target_opt = match *target_once {
|
|
|
|
Value::Object(ref mut map) => {
|
|
|
|
if is_last {
|
|
|
|
let v = if let Some(v) = map.get(token) {
|
|
|
|
fun(v)
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
map.insert(token.clone(), v);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
map.get_mut(token)
|
|
|
|
}
|
|
|
|
Value::Array(ref mut vec) => {
|
|
|
|
if let Ok(x) = token.parse::<usize>() {
|
|
|
|
if is_last {
|
|
|
|
let v = { fun(&vec[x]) };
|
|
|
|
vec[x] = v;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vec.get_mut(x)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(t) = target_opt {
|
|
|
|
target = t;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
impl SelectorMut {
|
|
|
|
pub fn new() -> Self {
|
2019-06-19 11:34:47 +09:00
|
|
|
SelectorMut {
|
|
|
|
path: None,
|
|
|
|
value: None,
|
|
|
|
}
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
|
|
|
self.path = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?);
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn value(&mut self, value: Value) -> &mut Self {
|
|
|
|
self.value = Some(value);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn take(&mut self) -> Option<Value> {
|
|
|
|
self.value.take()
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
fn compute_paths(&self, mut result: Vec<&Value>) -> Vec<Vec<String>> {
|
2019-06-19 11:34:47 +09:00
|
|
|
fn _walk(
|
|
|
|
origin: &Value,
|
|
|
|
target: &mut Vec<&Value>,
|
|
|
|
tokens: &mut Vec<String>,
|
|
|
|
visited: &mut IndexMap<*const Value, Vec<String>>,
|
|
|
|
) -> bool {
|
2019-06-11 16:12:40 +09:00
|
|
|
trace!("{:?}, {:?}", target, tokens);
|
2019-06-09 22:55:35 +09:00
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
if target.is_empty() {
|
2019-06-09 22:55:35 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
target.retain(|t| {
|
|
|
|
if std::ptr::eq(origin, *t) {
|
|
|
|
visited.insert(*t, tokens.to_vec());
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-06-09 22:55:35 +09:00
|
|
|
match origin {
|
2019-06-19 11:34:47 +09:00
|
|
|
Value::Array(vec) => {
|
|
|
|
for (i, v) in vec.iter().enumerate() {
|
|
|
|
tokens.push(i.to_string());
|
|
|
|
if _walk(v, target, tokens, visited) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
tokens.pop();
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
}
|
|
|
|
Value::Object(map) => {
|
|
|
|
for (k, v) in map {
|
|
|
|
tokens.push(k.clone());
|
|
|
|
if _walk(v, target, tokens, visited) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
tokens.pop();
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
let mut visited = IndexMap::new();
|
2019-06-09 22:55:35 +09:00
|
|
|
|
|
|
|
if let Some(origin) = &self.value {
|
2019-06-11 16:12:40 +09:00
|
|
|
let mut tokens = Vec::new();
|
|
|
|
_walk(origin, &mut result, &mut tokens, &mut visited);
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
|
|
|
|
2019-06-11 16:12:40 +09:00
|
|
|
visited.iter().map(|(_, v)| v.to_vec()).collect()
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> {
|
|
|
|
self.replace_with(&mut |_| Value::Null)
|
|
|
|
}
|
|
|
|
|
2019-06-11 18:40:18 +09:00
|
|
|
fn select(&self) -> Result<Vec<&Value>, JsonPathError> {
|
|
|
|
if let Some(node) = &self.path {
|
|
|
|
let mut selector = Selector::new();
|
|
|
|
selector.compiled_path(&node);
|
2019-06-09 22:55:35 +09:00
|
|
|
|
2019-06-11 18:40:18 +09:00
|
|
|
if let Some(value) = &self.value {
|
|
|
|
selector.value(value);
|
|
|
|
}
|
2019-06-11 16:12:40 +09:00
|
|
|
|
2019-06-11 18:40:18 +09:00
|
|
|
Ok(selector.select()?)
|
|
|
|
} else {
|
|
|
|
Err(JsonPathError::EmptyPath)
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
2019-06-11 18:40:18 +09:00
|
|
|
}
|
2019-06-09 22:55:35 +09:00
|
|
|
|
2019-06-19 11:34:47 +09:00
|
|
|
pub fn replace_with<F: FnMut(&Value) -> Value>(
|
|
|
|
&mut self,
|
|
|
|
fun: &mut F,
|
|
|
|
) -> Result<&mut Self, JsonPathError> {
|
2019-06-11 18:40:18 +09:00
|
|
|
let paths = {
|
|
|
|
let result = self.select()?;
|
|
|
|
self.compute_paths(result)
|
|
|
|
};
|
2019-06-09 22:55:35 +09:00
|
|
|
|
2019-06-11 18:40:18 +09:00
|
|
|
if let Some(ref mut value) = &mut self.value {
|
2019-06-09 22:55:35 +09:00
|
|
|
for tokens in paths {
|
2019-06-11 18:40:18 +09:00
|
|
|
replace_value(tokens, value, fun);
|
2019-06-09 22:55:35 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(self)
|
|
|
|
}
|
2019-06-19 11:34:47 +09:00
|
|
|
}
|