refactoring done default

This commit is contained in:
freestrings 2019-05-26 23:30:01 +09:00
parent 9a35357ddb
commit d2a5d9092e
20 changed files with 1513 additions and 1172 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
.vscode .vscode
!.idea/runConfigurations/ !.idea/runConfigurations/
/target/ /target/
Cargo.lock Cargo.lock
callgrind.out.*

View File

@ -32,5 +32,5 @@ name = "jsonpath_lib"
path = "src/lib.rs" path = "src/lib.rs"
[profile.release] [profile.release]
#debug = true debug = true
#lto = false #lto = false

View File

@ -1,18 +1,20 @@
#![feature(test)] #![feature(test)]
extern crate bencher;
extern crate indexmap;
extern crate jsonpath_lib as jsonpath; extern crate jsonpath_lib as jsonpath;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate test; extern crate test;
extern crate bencher;
use std::io::Read; use std::io::Read;
use serde::Serialize;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use self::test::Bencher; use self::test::Bencher;
use jsonpath::ref_value::model::RefValue; use jsonpath::ref_value::model::{RefValue, RefValueWrapper};
use serde::ser::Serialize; use jsonpath::ref_value::ser::RefValueSerializer;
fn read_json(path: &str) -> String { fn read_json(path: &str) -> String {
let mut f = std::fs::File::open(path).unwrap(); let mut f = std::fs::File::open(path).unwrap();
@ -107,22 +109,55 @@ fn bench_select_as(b: &mut Bencher) {
} }
#[bench] #[bench]
fn bench_serde_ser(b: &mut Bencher) { fn refval_de(b: &mut Bencher) {
let json = get_json(); let json = get_json();
b.iter(move || { b.iter(move || {
for _ in 1..100 { for _ in 1..100 {
let _: RefValue = json.serialize(jsonpath::ref_value::ser::Serializer).unwrap().into(); let _ = RefValue::deserialize(&json).unwrap();
} }
}); });
} }
#[bench] #[bench]
fn bench_serde_de(b: &mut Bencher) { fn refval_se(b: &mut Bencher) {
let json_string = get_string(); let json = get_json();
let json_str = json_string.as_str(); b.iter(move || {
for _ in 1..100 {
let _ = &json.serialize(RefValueSerializer).unwrap();
}
});
}
b.iter(move || for _ in 1..100 { #[bench]
let _: RefValue = serde_json::from_str(json_str).unwrap(); fn refval_refcopy(b: &mut Bencher) {
use std::ops::Deref;
let json = get_json();
let ref_json: RefValue = json.serialize(RefValueSerializer).unwrap();
let store = ref_json.get("store".to_string()).unwrap();
let book = store.get("book".to_string()).unwrap();
b.iter(move || {
for _ in 1..100 {
if let RefValue::Array(vec) = book.deref() {
let _: Vec<RefValueWrapper> = vec.iter().map(|v| v.clone()).collect();
}
}
});
}
#[bench]
fn refval_copy(b: &mut Bencher) {
let json = get_json();
let store = json.get("store".to_string()).unwrap();
let book = store.get("book".to_string()).unwrap();
b.iter(move || {
for _ in 1..100 {
if let Value::Array(vec) = book {
let _: Vec<Value> = vec.iter().map(|v| v.clone()).collect();
}
}
}); });
} }

81
benches/bench_example.rs Normal file
View File

@ -0,0 +1,81 @@
#![feature(test)]
extern crate bencher;
extern crate indexmap;
extern crate jsonpath_lib as jsonpath;
extern crate serde;
extern crate serde_json;
extern crate test;
use std::io::Read;
use serde_json::Value;
use self::test::Bencher;
fn read_json(path: &str) -> String {
let mut f = std::fs::File::open(path).unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();
contents
}
fn get_string() -> String {
read_json("./benches/example.json")
}
fn get_json() -> Value {
let string = get_string();
serde_json::from_str(string.as_str()).unwrap()
}
fn get_path(i: usize) -> &'static str {
let paths = vec![
"$.store.book[*].author", //0
"$..author", //1
"$.store.*", //2
"$.store..price", //3
"$..book[2]", //4
"$..book[-2]", //5
"$..book[0,1]", //6
"$..book[:2]", //7
"$..book[1:2]", //8
"$..book[-2:]", //9
"$..book[2:]", //10
"$..book[?(@.isbn)]", //11
"$.store.book[?(@.price < 10)]", //12
"$..*", //13
"$..book[ ?( (@.price < 13 || $.store.bicycle.price < @.price) && @.price <=10 ) ]" //14
];
paths[i]
}
macro_rules! example {
($name:ident, $i:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
let json = get_json();
b.iter(move || {
for _ in 1..100 {
let _ = jsonpath::select(&json, get_path($i));
}
});
}
};
}
example!(example0, 0);
example!(example1, 1);
example!(example2, 2);
example!(example3, 3);
example!(example4, 4);
example!(example5, 5);
example!(example6, 6);
example!(example7, 7);
example!(example8, 8);
example!(example9, 9);
example!(example10, 10);
example!(example11, 11);
example!(example12, 12);
example!(example13, 13);
example!(example14, 14);

9
profiling.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -e
valgrind \
--tool=callgrind \
--dump-instr=yes \
--collect-jumps=yes \
--simulate-cache=yes $1 -- $2

View File

@ -1,4 +1,6 @@
mod cmp; mod cmp;
mod term; mod term;
pub mod value_filter; pub mod value_filter;
pub mod value_wrapper; pub mod value_manager;
#[deprecated(since = "0.1.14", note = "Please use the value_manager module instead")]
pub use self::value_manager as value_wrapper;

View File

@ -1,15 +1,18 @@
use super::cmp::*; use super::cmp::*;
use super::value_filter::ValueFilterKey; use super::value_filter::ValueFilterKey;
use super::value_wrapper::*; use super::value_manager::*;
use std::cell::RefCell;
use select::path_map::PathMap;
use std::sync::Arc;
#[derive(Debug)] #[derive(Debug)]
pub enum TermContext { pub enum TermContext {
Constants(ExprTerm), Constants(ExprTerm),
Json(Option<ValueFilterKey>, ValueWrapper), Json(Option<ValueFilterKey>, ValueManager),
} }
impl TermContext { impl TermContext {
fn cmp<F: PrivCmp + IntoType>(&self, other: &TermContext, cmp_fn: F, default: bool) -> TermContext { fn cmp<F: PrivCmp + IntoType>(&mut self, other: &mut TermContext, cmp_fn: F, default: bool) -> TermContext {
match self { match self {
TermContext::Constants(et) => { TermContext::Constants(et) => {
match other { match other {
@ -17,9 +20,9 @@ impl TermContext {
trace!("const-const"); trace!("const-const");
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default))) TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default)))
} }
TermContext::Json(key, v) => { TermContext::Json(ref mut key, ref mut v) => {
trace!("const-json"); trace!("const-json");
TermContext::Json(None, v.take_with(key, et, cmp_fn, true)) TermContext::Json(None, v.get_compare_with(key, et, cmp_fn, true))
} }
} }
} }
@ -35,24 +38,24 @@ impl TermContext {
} }
} }
let c = v.into_term(key); let mut c = v.into_term(key);
let oc = ov.into_term(key_other); let mut oc = ov.into_term(key_other);
if is_json(&c) && is_json(&oc) { if is_json(&c) && is_json(&oc) {
v.cmp(&ov, cmp_fn.into_type()) v.cmp(&ov, cmp_fn.into_type())
} else { } else {
c.cmp(&oc, cmp_fn, default) c.cmp(&mut oc, cmp_fn, default)
} }
} }
TermContext::Constants(et) => { TermContext::Constants(et) => {
trace!("json-const"); trace!("json-const");
TermContext::Json(None, v.take_with(key, et, cmp_fn, false)) TermContext::Json(None, v.get_compare_with(key, et, cmp_fn, false))
} }
} }
} }
} }
} }
fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext { fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType, path_map: Arc<RefCell<PathMap>>) -> TermContext {
match self { match self {
TermContext::Constants(et) => { TermContext::Constants(et) => {
match other { match other {
@ -67,7 +70,7 @@ impl TermContext {
} }
} }
TermContext::Json(_, v) => { TermContext::Json(_, v) => {
TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false)) TermContext::Json(None, ValueManager::new(v.get_val().clone(), false, path_map))
} }
} }
} }
@ -80,49 +83,49 @@ impl TermContext {
} }
} }
_ => { _ => {
TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false)) TermContext::Json(None, ValueManager::new(v.get_val().clone(), false, path_map))
} }
} }
} }
} }
} }
pub fn eq(&self, other: &TermContext) -> TermContext { pub fn eq(&mut self, other: &mut TermContext) -> TermContext {
trace!("eq"); trace!("eq");
self.cmp(other, CmpEq, false) self.cmp(other, CmpEq, false)
} }
pub fn ne(&self, other: &TermContext) -> TermContext { pub fn ne(&mut self, other: &mut TermContext) -> TermContext {
trace!("ne"); trace!("ne");
self.cmp(other, CmpNe, true) self.cmp(other, CmpNe, true)
} }
pub fn gt(&self, other: &TermContext) -> TermContext { pub fn gt(&mut self, other: &mut TermContext) -> TermContext {
trace!("gt"); trace!("gt");
self.cmp(other, CmpGt, false) self.cmp(other, CmpGt, false)
} }
pub fn ge(&self, other: &TermContext) -> TermContext { pub fn ge(&mut self, other: &mut TermContext) -> TermContext {
trace!("ge"); trace!("ge");
self.cmp(other, CmpGe, false) self.cmp(other, CmpGe, false)
} }
pub fn lt(&self, other: &TermContext) -> TermContext { pub fn lt(&mut self, other: &mut TermContext) -> TermContext {
trace!("lt"); trace!("lt");
self.cmp(other, CmpLt, false) self.cmp(other, CmpLt, false)
} }
pub fn le(&self, other: &TermContext) -> TermContext { pub fn le(&mut self, other: &mut TermContext) -> TermContext {
trace!("le"); trace!("le");
self.cmp(other, CmpLe, false) self.cmp(other, CmpLe, false)
} }
pub fn and(&self, other: &TermContext) -> TermContext { pub fn and(&mut self, other: &mut TermContext, path_map: Arc<RefCell<PathMap>>) -> TermContext {
self.cmp_cond(other, CmpCondType::And) self.cmp_cond(other, CmpCondType::And, path_map)
} }
pub fn or(&self, other: &TermContext) -> TermContext { pub fn or(&mut self, other: &mut TermContext, path_map: Arc<RefCell<PathMap>>) -> TermContext {
self.cmp_cond(other, CmpCondType::Or) self.cmp_cond(other, CmpCondType::Or, path_map)
} }
} }

View File

@ -1,51 +1,14 @@
use std::error::Error; use std::cell::RefCell;
use std::ops::Deref; use std::ops::Deref;
use std::result::Result; use std::sync::Arc;
use serde_json::Value; use serde_json::Value;
use filter::term::*; use filter::term::*;
use filter::value_wrapper::*; use filter::value_manager::*;
use parser::parser::{FilterToken, NodeVisitor, ParseToken}; use parser::parser::{FilterToken, NodeVisitor, ParseToken};
use ref_value::model::*; use ref_value::model::*;
use select::path_map::PathMap;
trait ArrayIndex {
fn index(&self, v: &RefValueWrapper) -> usize;
fn take_value(&self, v: &RefValueWrapper) -> RefValueWrapper {
let idx = self.index(v);
match v.get(idx) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
}
impl ArrayIndex for f64 {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_f64 {
(v.as_array().unwrap().len() as f64 + self) as usize
} else {
*self as usize
}
}
}
impl ArrayIndex for isize {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_isize {
(v.as_array().unwrap().len() as isize + self) as usize
} else {
*self as usize
}
}
}
impl ArrayIndex for usize {
fn index(&self, _: &RefValueWrapper) -> usize {
*self as usize
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ValueFilterKey { pub enum ValueFilterKey {
@ -54,248 +17,136 @@ pub enum ValueFilterKey {
All, All,
} }
fn iter_to_value_vec<'a, I: Iterator<Item=&'a RefValueWrapper>>(iter: I) -> Vec<RefValueWrapper> { fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec<RefValueWrapper>) {
iter
.map(|v| v.clone())
.filter(|v| !v.is_null())
.collect()
}
fn get_nested_array<F: ArrayIndex>(v: &RefValueWrapper, key: F, filter_mode: bool) -> RefValueWrapper {
if v.is_array() && v.as_array().unwrap().get(key.index(v)).is_some() {
if filter_mode {
v.clone()
} else {
let idx = key.index(v);
v.get(idx).unwrap().clone()
}
} else {
key.take_value(v)
}
}
fn get_nested_object(v: &RefValueWrapper, key: &String, filter_mode: bool) -> RefValueWrapper {
if v.is_object() && v.as_object().unwrap().contains_key(key) {
if filter_mode {
v.clone()
} else {
v.get(key.clone()).unwrap().clone()
}
} else {
RefValue::Null.into()
}
}
fn traverse(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec<RefValueWrapper>) {
match v.deref() { match v.deref() {
RefValue::Array(vec) => { RefValue::Array(vec) => {
if key.is_none() { if key.is_none() {
for v in vec { for v in vec.iter() {
buf.push(v.clone()); buf.push(v.clone());
} }
} }
for i in vec {
traverse(key, i, buf); for v in vec {
collect_all(key, v, buf);
} }
} }
RefValue::Object(v) => { RefValue::Object(map) => {
for (k, v) in v.into_iter() { if let Some(k) = key {
if match key { if let Some(val) = map.get(k) {
Some(map_key) => map_key == k, buf.push(val.clone());
_ => true
} {
buf.push(v.clone());
} }
} else {
let mut c = map.values().map(|v| v.clone()).collect();
buf.append(&mut c);
} }
for (_, v) in v.into_iter() { for (_, v) in map {
traverse(key, v, buf); collect_all(key, v, buf);
} }
} }
_ => {} _ => {}
} }
} }
fn collect_all(key: Option<&String>, v: &RefValueWrapper) -> Vec<RefValueWrapper> {
let mut buf = Vec::new();
traverse(key, v, &mut buf);
buf
}
#[derive(Debug)] #[derive(Debug)]
pub struct ValueFilter { pub struct ValueFilter {
val_wrapper: ValueWrapper, value_mgr: ValueManager,
last_key: Option<ValueFilterKey>, last_key: Option<ValueFilterKey>,
filter_mode: bool, is_relative: bool,
path_map: Arc<RefCell<PathMap>>,
} }
impl ValueFilter { impl ValueFilter {
pub fn new(v: RefValueWrapper, is_leaves: bool, filter_mode: bool) -> Self { pub fn new(v: RefValueWrapper, is_leaves: bool, is_relative: bool, path_map: Arc<RefCell<PathMap>>) -> Self {
ValueFilter { val_wrapper: ValueWrapper::new(v, is_leaves), last_key: None, filter_mode } ValueFilter {
value_mgr: ValueManager::new(v, is_leaves, path_map.clone()),
last_key: None,
is_relative,
path_map,
}
} }
fn step_leaves(&mut self, key: Option<&String>) { fn step_leaves(&mut self, key: Option<&String>) {
let buf = collect_all(key, &self.val_wrapper.get_val()); let mut buf = Vec::new();
collect_all(key, &self.value_mgr.get_val(), &mut buf);
trace!("step_leaves - {:?}", buf); trace!("step_leaves - {:?}", buf);
self.val_wrapper = ValueWrapper::new(RefValue::Array(buf).into(), true); self.value_mgr = ValueManager::new(RefValue::Array(buf).into(), true, self.path_map.clone());
} }
pub fn step_leaves_all(&mut self) -> &ValueWrapper { pub fn step_leaves_all(&mut self) -> &ValueManager {
debug!("step_leaves_all"); debug!("step_leaves_all");
self.step_leaves(None); self.step_leaves(None);
self.last_key = Some(ValueFilterKey::All); self.last_key = Some(ValueFilterKey::All);
&self.val_wrapper &self.value_mgr
} }
pub fn step_leaves_str(&mut self, key: &str) -> &ValueWrapper { pub fn step_leaves_str(&mut self, key: &str) -> &ValueManager {
self.step_leaves_string(&key.to_string()) self.step_leaves_string(&key.to_string())
} }
pub fn step_leaves_string(&mut self, key: &String) -> &ValueWrapper { pub fn step_leaves_string(&mut self, key: &String) -> &ValueManager {
debug!("step_leaves_string"); debug!("step_leaves_string");
self.step_leaves(Some(key)); self.step_leaves(Some(key));
self.last_key = Some(ValueFilterKey::String(key.clone())); self.last_key = Some(ValueFilterKey::String(key.clone()));
&self.val_wrapper &self.value_mgr
} }
pub fn step_in_all(&mut self) -> &ValueWrapper { pub fn step_in_all(&mut self) -> &ValueManager {
debug!("step_in_all"); debug!("step_in_all");
let vec = match self.val_wrapper.get_val().deref() {
RefValue::Object(ref map) => {
iter_to_value_vec(map.values())
}
RefValue::Array(ref list) => {
iter_to_value_vec(list.iter())
}
RefValue::Null => Vec::new(),
_ => vec![self.val_wrapper.get_val().clone()]
};
self.last_key = Some(ValueFilterKey::All); self.last_key = Some(ValueFilterKey::All);
self.val_wrapper.replace(RefValue::Array(vec).into()); self.value_mgr.replace(self.value_mgr.get_as_array());
trace!("step_in_all - {:?}", self.val_wrapper.get_val()); trace!("step_in_all - {:?}", self.value_mgr.get_val());
&self.val_wrapper &self.value_mgr
} }
pub fn step_in_num(&mut self, key: &f64) -> &ValueWrapper { pub fn step_in_num(&mut self, key: &f64) -> &ValueManager {
debug!("step_in_num"); debug!("step_in_num");
trace!("step_in_num - before: leaves {}, filterMode {} - {:?}" trace!("step_in_num - before: leaves {}, filterMode {} - {:?}"
, self.val_wrapper.is_leaves() , self.value_mgr.is_leaves()
, self.filter_mode , self.is_relative
, self.val_wrapper.get_val()); , self.value_mgr.get_val());
let v = if self.val_wrapper.is_leaves() {
let filter_mode = self.filter_mode;
match self.val_wrapper.get_val().deref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
let wrapper = get_nested_array(v, *key, filter_mode);
if !wrapper.is_null() {
ret.push(wrapper.clone());
}
}
RefValue::Array(ret).into()
}
_ => key.take_value(&self.val_wrapper.get_val())
}
} else {
key.take_value(&self.val_wrapper.get_val())
};
self.last_key = Some(ValueFilterKey::Num(key.index(&v))); self.last_key = Some(ValueFilterKey::Num(self.value_mgr.get_index(*key)));
self.val_wrapper.replace(v); let v = self.value_mgr.get_with_num(key, self.is_relative);
trace!("step_in_num - after: {:?}", self.val_wrapper.get_val()); self.value_mgr.replace(v);
&self.val_wrapper trace!("step_in_num - after: {:?}", self.value_mgr.get_val());
&self.value_mgr
} }
pub fn step_in_str(&mut self, key: &str) -> &ValueWrapper { pub fn step_in_str(&mut self, key: &str) -> &ValueManager {
self.step_in_string(&key.to_string()) self.step_in_string(&key.to_string())
} }
pub fn step_in_string(&mut self, key: &String) -> &ValueWrapper { pub fn step_in_string(&mut self, key: &String) -> &ValueManager {
debug!("step_in_string"); debug!("step_in_string");
trace!("step_in_string - before: {},{},{:?}" trace!("step_in_string - before: {},{},{:?}"
, self.val_wrapper.is_leaves() , self.value_mgr.is_leaves()
, self.filter_mode , self.is_relative
, self.val_wrapper.get_val()); , self.value_mgr.get_val());
let filter_mode = self.filter_mode;
let is_leaves = self.val_wrapper.is_leaves();
let val = match self.val_wrapper.get_val().deref() {
RefValue::Array(ref vec) if is_leaves => {
let mut buf = Vec::new();
for v in vec {
if v.is_array() {
let vec = v.as_array().unwrap();
let mut ret = Vec::new();
for v in vec {
let nested_wrapper = get_nested_object(v, key, filter_mode);
if !nested_wrapper.is_null() {
ret.push(nested_wrapper);
}
}
buf.append(&mut ret);
} else if v.is_object() {
let nested_wrapper = get_nested_object(v, key, filter_mode);
if !nested_wrapper.is_null() {
buf.push(nested_wrapper);
}
} else {
match v.get(key.clone()) {
Some(v) => buf.push(v.clone()),
_ => {}
}
}
}
RefValue::Array(buf).into()
}
RefValue::Array(ref vec) if !is_leaves => {
let mut ret = Vec::new();
for v in vec {
let wrapper = get_nested_object(v, key, filter_mode);
if !wrapper.is_null() {
ret.push(wrapper);
}
}
RefValue::Array(ret).into()
}
_ => {
match self.val_wrapper.get_val().get(key.clone()) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
};
self.last_key = Some(ValueFilterKey::String(key.clone())); self.last_key = Some(ValueFilterKey::String(key.clone()));
self.val_wrapper.replace(val); self.value_mgr.replace(self.value_mgr.get_with_str(key, self.is_relative));
trace!("step_in_string - after: {},{},{:?}" trace!("step_in_string - after: {},{},{:?}"
, self.val_wrapper.is_leaves() , self.value_mgr.is_leaves()
, self.filter_mode , self.is_relative
, self.val_wrapper.get_val()); , self.value_mgr.get_val());
&self.val_wrapper &self.value_mgr
} }
} }
pub struct JsonValueFilter { pub struct JsonValueFilter {
json: RefValueWrapper, json: RefValueWrapper,
path_map: Arc<RefCell<PathMap>>,
filter_stack: Vec<ValueFilter>, filter_stack: Vec<ValueFilter>,
token_stack: Vec<ParseToken>, token_stack: Vec<ParseToken>,
term_stack: Vec<TermContext>, term_stack: Vec<TermContext>,
} }
impl JsonValueFilter { impl JsonValueFilter {
pub fn new(json: &str) -> Result<Self, String> { pub fn new(json: RefValueWrapper, path_map: Arc<RefCell<PathMap>>) -> Self {
let json: RefValue = serde_json::from_str(json)
.map_err(|e| e.description().to_string())?;
Ok(JsonValueFilter::new_from_value(json.into()))
}
pub fn new_from_value(json: RefValueWrapper) -> Self {
JsonValueFilter { JsonValueFilter {
json, json,
path_map,
filter_stack: Vec::new(), filter_stack: Vec::new(),
token_stack: Vec::new(), token_stack: Vec::new(),
term_stack: Vec::new(), term_stack: Vec::new(),
@ -303,90 +154,86 @@ impl JsonValueFilter {
} }
fn is_peek_token_array(&self) -> bool { fn is_peek_token_array(&self) -> bool {
if let Some(ParseToken::Array) = self.token_stack.last() { if let Some(ParseToken::Array) = self.token_stack.last() { true } else { false }
true
} else {
false
}
} }
fn push_value_filter(&mut self, from_current: bool) { fn create_new_filter(&mut self, is_relative: bool) {
if from_current { if is_relative {
self.filter_stack.last() self.filter_stack.last()
.map(|vf| { .map(|vf| {
ValueFilter::new(vf.val_wrapper.get_val().clone(), vf.val_wrapper.is_leaves(), from_current) ValueFilter::new(vf.value_mgr.get_val().clone(),
vf.value_mgr.is_leaves(),
is_relative,
self.path_map.clone(),
)
}) })
.and_then(|vf| { .and_then(|vf| {
Some(self.filter_stack.push(vf)) Some(self.filter_stack.push(vf))
}); });
} else { } else {
self.filter_stack.push({ let vf = ValueFilter::new(
ValueFilter::new(self.json.clone(), false, from_current) self.json.clone(),
}); false,
is_relative,
self.path_map.clone(),
);
self.filter_stack.push(vf);
} }
} }
fn replace_filter_stack(&mut self, v: RefValueWrapper, is_leaves: bool) { fn append_to_current_filter(&mut self, v: RefValueWrapper, is_leaves: bool) {
if self.filter_stack.is_empty() { if self.filter_stack.is_empty() {
self.filter_stack.push(ValueFilter::new(v, is_leaves, false)); self.filter_stack.push(ValueFilter::new(
} else { v,
match self.filter_stack.last_mut() { is_leaves,
Some(vf) => { false,
vf.val_wrapper.set_leaves(is_leaves); self.path_map.clone(),
if v.is_null() { ));
vf.val_wrapper.replace(v); return;
} else if v.is_array() && v.as_array().unwrap().is_empty() { }
vf.val_wrapper.replace(RefValue::Null.into());
} else if vf.val_wrapper.is_array() { match self.filter_stack.last_mut() {
vf.val_wrapper.replace(v); Some(vf) => {
} vf.value_mgr.set_leaves(is_leaves);
if v.is_null() || v.is_empty() {
vf.value_mgr.replace(RefValue::Null.into());
} else if vf.value_mgr.is_array() {
vf.value_mgr.replace(v);
} else {
// ignore. the current filter context is object that include v: RefValueWrapper as a child.
} }
_ => {}
} }
_ => {}
} }
} }
pub fn into_value(&self) -> Value { pub fn into_value(&self) -> Value {
match self.filter_stack.last() { match self.filter_stack.last() {
Some(v) => v.val_wrapper.into_value(), Some(v) => v.value_mgr.into_value(),
_ => Value::Null _ => Value::Null
} }
} }
#[deprecated(since = "0.1.14", note = "Please use the clone_value function instead")]
pub fn take_value(&mut self) -> RefValueWrapper { pub fn take_value(&mut self) -> RefValueWrapper {
match self.filter_stack.last_mut() { self.clone_value()
Some(v) => v.val_wrapper.get_val().clone(), }
pub fn clone_value(&mut self) -> RefValueWrapper {
match self.filter_stack.last() {
Some(v) => v.value_mgr.get_val().clone(),
_ => RefValue::Null.into() _ => RefValue::Null.into()
} }
} }
fn token_union<F: ArrayIndex>(&mut self, indices: Vec<F>) { fn token_union(&mut self, indices: Vec<isize>) {
self.token_stack.pop(); self.token_stack.pop();
match self.filter_stack.last_mut() { match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.val_wrapper.is_array() && vf.val_wrapper.is_leaves() => { Some(vf) => {
let mut ret = Vec::new(); if let Some(vec) = vf.value_mgr.pick_with_nums(indices) {
if let RefValue::Array(val) = vf.val_wrapper.get_val().deref() { vf.value_mgr.replace(vec);
for v in val {
for i in &indices {
let v = i.take_value(v);
if !v.is_null() {
ret.push(v.clone());
}
}
}
} }
vf.val_wrapper.replace(RefValue::Array(ret).into());
}
Some(ref mut vf) if vf.val_wrapper.is_array() && !vf.val_wrapper.is_leaves() => {
let mut ret = Vec::new();
for i in indices {
let wrapper = i.take_value(&vf.val_wrapper.get_val());
if !wrapper.is_null() {
ret.push(wrapper.clone());
}
}
vf.val_wrapper.replace(RefValue::Array(ret).into());
} }
_ => {} _ => {}
} }
@ -395,50 +242,11 @@ impl JsonValueFilter {
fn token_range(&mut self, from: Option<isize>, to: Option<isize>) { fn token_range(&mut self, from: Option<isize>, to: Option<isize>) {
self.token_stack.pop(); self.token_stack.pop();
fn _from_to<F: ArrayIndex>(from: Option<F>, to: Option<F>, val: &RefValueWrapper) -> (usize, usize) {
let from = match from {
Some(v) => v.index(val),
_ => 0
};
let to = match to {
Some(v) => v.index(val),
_ => {
if let RefValue::Array(v) = val.deref() {
v.len()
} else {
0
}
}
};
(from, to)
}
fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec<RefValueWrapper> {
trace!("range - {}:{}", from, to);
(from..to).into_iter()
.map(|i| i.take_value(v))
.filter(|v| !v.is_null())
.map(|v| v.clone())
.collect()
}
match self.filter_stack.last_mut() { match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.val_wrapper.is_array() && vf.val_wrapper.is_leaves() => { Some(ref mut vf) => {
let mut buf = Vec::new(); if let Some(vec) = vf.value_mgr.range_with(from, to) {
if let RefValue::Array(vec) = vf.val_wrapper.get_val().deref() { vf.value_mgr.replace(vec);
for v in vec {
let (from, to) = _from_to(from, to, v);
let mut v: Vec<RefValueWrapper> = _range(from, to, v);
buf.append(&mut v);
}
} }
vf.val_wrapper.replace(RefValue::Array(buf).into());
}
Some(ref mut vf) if vf.val_wrapper.is_array() && !vf.val_wrapper.is_leaves() => {
let (from, to) = _from_to(from, to, &vf.val_wrapper.get_val());
let vec: Vec<RefValueWrapper> = _range(from, to, vf.val_wrapper.get_val());
vf.val_wrapper.replace(RefValue::Array(vec).into());
} }
_ => {} _ => {}
} }
@ -494,21 +302,25 @@ impl JsonValueFilter {
} }
} }
Some(TermContext::Constants(ExprTerm::Bool(false))) => { Some(TermContext::Constants(ExprTerm::Bool(false))) => {
self.replace_filter_stack(RefValue::Null.into(), false); self.append_to_current_filter(RefValue::Null.into(), false);
} }
Some(TermContext::Json(_, vw)) => { Some(TermContext::Json(_, vw)) => {
self.replace_filter_stack(vw.get_val().clone(), vw.is_leaves()); self.append_to_current_filter(vw.get_val().clone(), vw.is_leaves());
} }
_ => { _ => {
//
// None, TermContext::Constants(ExprTerm::Bool(true))
//
match self.filter_stack.pop() { match self.filter_stack.pop() {
Some(vf) => { Some(vf) => {
let is_leaves = vf.val_wrapper.is_leaves(); match vf.value_mgr.get_val().deref() {
match vf.val_wrapper.get_val().deref() {
RefValue::Null | RefValue::Bool(false) => { RefValue::Null | RefValue::Bool(false) => {
self.replace_filter_stack(RefValue::Null.into(), is_leaves); self.append_to_current_filter(RefValue::Null.into(), vf.value_mgr.is_leaves());
} }
_ => { _ => {
self.replace_filter_stack(vf.val_wrapper.get_val().clone(), is_leaves); self.append_to_current_filter(vf.value_mgr.get_val().clone(), vf.value_mgr.is_leaves());
} }
} }
} }
@ -526,18 +338,18 @@ impl JsonValueFilter {
trace!("right {:?}", right); trace!("right {:?}", right);
if left.is_some() && right.is_some() { if left.is_some() && right.is_some() {
let left = left.unwrap(); let mut left = left.unwrap();
let right = right.unwrap(); let mut right = right.unwrap();
let tc = match ft { let tc = match ft {
FilterToken::Equal => left.eq(&right), FilterToken::Equal => left.eq(&mut right),
FilterToken::NotEqual => left.ne(&right), FilterToken::NotEqual => left.ne(&mut right),
FilterToken::Greater => left.gt(&right), FilterToken::Greater => left.gt(&mut right),
FilterToken::GreaterOrEqual => left.ge(&right), FilterToken::GreaterOrEqual => left.ge(&mut right),
FilterToken::Little => left.lt(&right), FilterToken::Little => left.lt(&mut right),
FilterToken::LittleOrEqual => left.le(&right), FilterToken::LittleOrEqual => left.le(&mut right),
FilterToken::And => left.and(&right), FilterToken::And => left.and(&mut right, self.path_map.clone()),
FilterToken::Or => left.or(&right), FilterToken::Or => left.or(&mut right, self.path_map.clone()),
}; };
self.term_stack.push(tc); self.term_stack.push(tc);
} }
@ -556,7 +368,7 @@ impl NodeVisitor for JsonValueFilter {
if self.is_peek_token_array() { if self.is_peek_token_array() {
self.token_stack.pop(); self.token_stack.pop();
} }
self.push_value_filter(ParseToken::Relative == token); self.create_new_filter(ParseToken::Relative == token);
} }
ParseToken::In ParseToken::In
| ParseToken::Leaves => { | ParseToken::Leaves => {
@ -609,7 +421,7 @@ impl NodeVisitor for JsonValueFilter {
if self.token_stack.is_empty() && self.filter_stack.len() > 1 { if self.token_stack.is_empty() && self.filter_stack.len() > 1 {
match self.filter_stack.pop() { match self.filter_stack.pop() {
Some(vf) => { Some(vf) => {
self.term_stack.push(TermContext::Json(vf.last_key, vf.val_wrapper)); self.term_stack.push(TermContext::Json(vf.last_key, vf.value_mgr));
} }
_ => {} _ => {}
} }

524
src/filter/value_manager.rs Normal file
View File

@ -0,0 +1,524 @@
use std::cell::RefCell;
use std::ops::Deref;
use std::sync::Arc;
use indexmap::{IndexMap, IndexSet};
use serde_json::Value;
use ref_value::model::*;
use select::path_map::PathMap;
use super::cmp::*;
use super::term::*;
use super::value_filter::*;
pub trait ArrayIndex {
fn index(&self, v: &RefValueWrapper) -> usize;
fn ref_value(&self, v: &RefValueWrapper) -> RefValueWrapper {
let idx = self.index(v);
match v.get(idx) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
}
impl ArrayIndex for f64 {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_f64 {
(v.len() as f64 + self) as usize
} else {
*self as usize
}
}
}
impl ArrayIndex for isize {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_isize {
(v.len() as isize + self) as usize
} else {
*self as usize
}
}
}
impl ArrayIndex for usize {
fn index(&self, _: &RefValueWrapper) -> usize {
*self as usize
}
}
fn cmp_with_term<F: PrivCmp>(val: &RefValueWrapper, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool {
match val.deref() {
RefValue::Bool(ref v1) => {
match et {
ExprTerm::Bool(v2) => if reverse {
cmp_fn.cmp_bool(v2, v1)
} else {
cmp_fn.cmp_bool(v1, v2)
},
_ => default
}
}
RefValue::Number(ref v1) => match et {
ExprTerm::Number(v2) => if reverse {
cmp_fn.cmp_f64(v2, &v1.as_f64().unwrap())
} else {
cmp_fn.cmp_f64(&v1.as_f64().unwrap(), v2)
},
_ => default
},
RefValue::String(ref v1) => {
match et {
ExprTerm::String(v2) => if reverse {
cmp_fn.cmp_string(v2, v1)
} else {
cmp_fn.cmp_string(v1, v2)
},
_ => default
}
}
_ => default
}
}
fn collect_not_null<'a,
I: Iterator<Item=&'a RefValueWrapper>,
F: FnMut(&RefValueWrapper) -> RefValueWrapper>(iter: I, func: F) -> Vec<RefValueWrapper>
{
iter.map(func)
.filter(|v| !v.is_null())
.collect()
}
fn collect_some<'a,
I: Iterator<Item=&'a RefValueWrapper>,
F: FnMut(&RefValueWrapper) -> Option<RefValueWrapper>>(iter: I, func: F) -> Vec<RefValueWrapper>
{
iter.map(func)
.filter(|v| v.is_some())
.map(|v| v.unwrap())
.collect()
}
fn get_in_array<I: ArrayIndex>(v: &RefValueWrapper, key: &I, is_relative: bool) -> Option<RefValueWrapper> {
match v.deref() {
RefValue::Array(vec) if vec.get(key.index(v)).is_some() => {
Some(if is_relative { v.clone() } else { v.get(key.index(v)).unwrap().clone() })
}
_ => None
}
}
fn get_in_object(v: &RefValueWrapper, key: &str, is_relative: bool) -> Option<RefValueWrapper> {
match v.deref() {
RefValue::Object(map) if map.contains_key(key) => {
Some(if is_relative { v.clone() } else { v.get(key.to_string()).unwrap().clone() })
}
_ => None
}
}
fn get_in_nested_array<I: ArrayIndex>(v: &RefValueWrapper, key: &I, is_relative: bool) -> Option<RefValueWrapper> {
match v.deref() {
RefValue::Array(vec) => {
let ret = collect_some(vec.iter(), |v| { get_in_array(v, key, is_relative) });
Some(RefValue::Array(ret).into())
}
_ => None
}
}
fn get_object_in_array(val: &RefValueWrapper, key: &str, is_relative: bool) -> Option<RefValueWrapper> {
match val.deref() {
RefValue::Array(vec) => {
let ret = collect_some(vec.iter(), |v| get_in_object(v, key, is_relative));
Some(RefValue::Array(ret).into())
}
_ => None
}
}
fn get_in_nested_object(val: &RefValueWrapper, key: &str, is_relative: bool) -> Option<RefValueWrapper> {
match val.deref() {
RefValue::Array(vec) => {
let ret = vec.iter()
.map(|v| {
match v.deref() {
RefValue::Array(vec) => {
Some(collect_some(vec.iter(), |v| get_in_object(v, key, is_relative)))
}
RefValue::Object(_) => {
match get_in_object(v, key, is_relative) {
Some(v) => Some(vec![v]),
_ => None
}
}
_ => None
}
})
.filter(|v| v.is_some())
.map(|v| v.unwrap())
.filter(|v| !v.is_empty())
.flatten()
.collect();
Some(RefValue::Array(ret).into())
}
_ => None
}
}
#[deprecated(since = "0.1.14", note = "Please use the ValueManager instead")]
pub type ValueWrapper = ValueManager;
#[derive(Debug)]
pub struct ValueManager {
val: RefValueWrapper,
path_map: Arc<RefCell<PathMap>>,
is_leaves: bool,
}
impl ValueManager {
pub fn new(val: RefValueWrapper, is_leaves: bool, path_map: Arc<RefCell<PathMap>>) -> Self {
ValueManager { val, is_leaves, path_map }
}
pub fn is_leaves(&self) -> bool {
self.is_leaves
}
pub fn set_leaves(&mut self, is_leaves: bool) {
self.is_leaves = is_leaves;
}
pub fn cmp(&self, other: &Self, cmp_type: CmpType) -> TermContext {
match cmp_type {
CmpType::Eq => {
TermContext::Json(None, self.intersect(other))
}
CmpType::Ne => {
TermContext::Json(None, self.except(other))
}
CmpType::Gt | CmpType::Ge | CmpType::Lt | CmpType::Le => {
TermContext::Constants(ExprTerm::Bool(false))
}
}
}
pub fn get_compare_with<F: PrivCmp>(&self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: F, reverse: bool) -> Self {
match self.val.deref() {
RefValue::Array(vec) => {
let mut set = IndexSet::new();
for v in vec {
if let Some(ValueFilterKey::String(key)) = key {
if let Some(ret_v) = get_in_object(v, key, false) {
if cmp_with_term(&ret_v, et, &cmp, false, reverse) {
set.insert(v.clone());
}
}
} else {
if cmp_with_term(v, et, &cmp, false, reverse) {
set.insert(v.clone());
}
}
}
let ret = set.into_iter().collect();
Self::new(
RefValue::Array(ret).into(),
false,
self.path_map.clone())
}
_ => {
if cmp_with_term(&self.val, et, &cmp, false, reverse) {
Self::new(self.val.clone(), false, self.path_map.clone())
} else {
Self::new(RefValue::Null.into(), false, self.path_map.clone())
}
}
}
}
pub fn get_index<I: ArrayIndex>(&self, i: I) -> usize {
i.index(&self.val)
}
pub fn get_with_num<I: ArrayIndex>(&self, key: &I, is_relative: bool) -> RefValueWrapper {
if self.val.is_array() && self.is_leaves {
match get_in_nested_array(&self.val, key, is_relative) {
Some(v) => v,
_ => RefValue::Null.into()
}
} else {
key.ref_value(&self.val)
}
}
pub fn get_as_array(&self) -> RefValueWrapper {
let vec = match self.val.deref() {
RefValue::Object(ref map) => {
collect_not_null(map.values(), |v| v.clone())
}
RefValue::Array(ref vec) => {
vec.clone()
}
RefValue::Null => Vec::new(),
_ => vec![self.val.clone()]
};
RefValue::Array(vec).into()
}
pub fn get_with_str(&self, key: &String, is_relative: bool) -> RefValueWrapper {
if self.val.is_array() && self.is_leaves {
match get_in_nested_object(&self.val, key, is_relative) {
Some(v) => v,
_ => RefValue::Null.into()
}
} else if self.val.is_array() && !self.is_leaves {
match get_object_in_array(&self.val, key, is_relative) {
Some(v) => v,
_ => RefValue::Null.into()
}
} else {
match self.val.get(key.clone()) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
}
pub fn range_with(&self, from: Option<isize>, to: Option<isize>) -> Option<RefValueWrapper> {
fn _from<F: ArrayIndex>(from: Option<F>, val: &RefValueWrapper) -> usize {
match from {
Some(v) => v.index(val),
_ => 0
}
}
fn _to<F: ArrayIndex>(to: Option<F>, val: &RefValueWrapper) -> usize {
match to {
Some(v) => v.index(val),
_ => {
if let RefValue::Array(v) = val.deref() {
v.len()
} else {
0
}
}
}
}
fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec<RefValueWrapper> {
trace!("range - {}:{}", from, to);
(from..to).into_iter()
.map(|i| i.ref_value(v))
.filter(|v| !v.is_null())
.map(|v| v.clone())
.collect()
}
if let RefValue::Array(vec) = &self.val.deref() {
let ret = if self.is_leaves {
vec.iter()
.map(|v| _range(_from(from, v), _to(to, v), v))
.flatten()
.collect()
} else {
_range(_from(from, &self.val), _to(to, &self.val), &self.val)
};
Some(RefValue::Array(ret).into())
} else {
None
}
}
pub fn pick_with_nums<I: ArrayIndex>(&self, indices: Vec<I>) -> Option<RefValueWrapper> {
if let RefValue::Array(vec) = &self.val.deref() {
let ret = if self.is_leaves {
indices.iter()
.map(|index| collect_not_null(vec.iter(), |v| { index.ref_value(v) }))
.flatten()
.collect()
} else {
indices.iter()
.map(|index| index.ref_value(&self.val))
.filter(|v| !v.is_null())
.collect()
};
Some(RefValue::Array(ret).into())
} else {
None
}
}
pub fn replace(&mut self, val: RefValueWrapper) {
self.val = match val.deref() {
RefValue::Array(v) if v.is_empty() => RefValue::Null.into(),
RefValue::Object(m) if m.is_empty() => RefValue::Null.into(),
_ => val
};
}
pub fn get_val(&self) -> &RefValueWrapper {
&self.val
}
pub fn into_value(&self) -> Value {
self.get_val().into()
}
pub fn is_array(&self) -> bool {
self.val.is_array()
}
fn into_hashset(&self) -> IndexSet<&RefValue> {
trace!("into_hashset");
let mut hashset = IndexSet::new();
match self.val.deref() {
RefValue::Array(vec) => {
for v in vec {
hashset.insert(v.deref());
}
}
_ => {
hashset.insert(self.val.deref());
}
}
hashset
}
fn into_hashmap(&self) -> IndexMap<&RefValue, RefValueWrapper> {
trace!("into_hashmap");
let mut hashmap = IndexMap::new();
match self.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
hashmap.insert(v.deref(), v.clone());
}
}
_ => {
hashmap.insert(self.val.deref(), self.val.clone());
}
}
hashmap
}
pub fn except(&self, other: &Self) -> Self {
trace!("except");
let hashset = self.into_hashset();
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
match other.val.deref() {
RefValue::Array(ref vec) => {
for v in vec {
if !hashset.contains(v.deref()) {
ret.insert(v.clone());
}
}
}
_ => {
if !hashset.contains(&other.val.deref()) {
ret.insert(other.val.clone());
}
}
}
let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone())
}
pub fn intersect(&self, other: &Self) -> Self {
trace!("intersect");
let hashset = self.into_hashset();
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
if hashset.contains(v.deref()) {
ret.insert(v.clone());
}
}
}
e => {
if hashset.contains(e) {
ret.insert(other.val.clone());
}
}
}
let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone())
}
pub fn union(&self, other: &Self) -> Self {
trace!("union");
let origin = self.into_hashmap();
let mut ret = IndexSet::new();
for o in origin.values() {
ret.insert(o.clone());
}
match other.val.deref() {
RefValue::Array(vec) => {
for v in vec {
if !origin.contains_key(v.deref()) {
ret.insert(v.clone());
}
}
}
_ => {
if !origin.contains_key(&other.val.deref()) {
ret.insert(other.val.clone());
}
}
}
let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone())
}
pub fn into_term(&self, key: &Option<ValueFilterKey>) -> TermContext {
match self.val.deref() {
RefValue::String(ref s) => TermContext::Constants(ExprTerm::String(s.clone())),
RefValue::Number(ref n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())),
RefValue::Bool(b) => TermContext::Constants(ExprTerm::Bool(*b)),
_ => TermContext::Json(match key {
Some(vk) => Some(vk.clone()),
_ => None
}, ValueManager::new(self.val.clone(), false, self.path_map.clone()))
}
}
pub fn filter(&self, key: &Option<ValueFilterKey>) -> Self {
trace!("filter");
let v = match self.val.deref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
if let Some(ValueFilterKey::String(k)) = key {
if v.get(k.clone()).is_some() {
ret.push(v.clone());
}
}
}
RefValue::Array(ret).into()
}
RefValue::Object(ref map) => {
match key {
Some(ValueFilterKey::String(k)) => match map.get(k) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
},
_ => RefValue::Null.into()
}
}
_ => self.val.clone()
};
ValueManager::new(v, false, self.path_map.clone())
}
}

View File

@ -1,307 +0,0 @@
use std::ops::Deref;
use indexmap::{IndexSet, IndexMap};
use serde_json::Value;
use ref_value::model::*;
use super::cmp::*;
use super::term::*;
use super::value_filter::*;
fn cmp_with_term<F: PrivCmp>(val: &RefValueWrapper, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool {
match val.deref() {
RefValue::Bool(ref v1) => {
match et {
ExprTerm::Bool(v2) => if reverse { cmp_fn.cmp_bool(v2, v1) } else { cmp_fn.cmp_bool(v1, v2) },
_ => default
}
}
RefValue::Number(ref v1) => match et {
ExprTerm::Number(v2) => if reverse { cmp_fn.cmp_f64(v2, &v1.as_f64().unwrap()) } else { cmp_fn.cmp_f64(&v1.as_f64().unwrap(), v2) },
_ => default
},
RefValue::String(ref v1) => {
match et {
ExprTerm::String(v2) => if reverse { cmp_fn.cmp_string(v2, v1) } else { cmp_fn.cmp_string(v1, v2) },
_ => default
}
}
_ => default
}
}
#[derive(Debug)]
pub struct ValueWrapper {
val: RefValueWrapper,
is_leaves: bool,
}
impl ValueWrapper {
pub fn new(val: RefValueWrapper, leaves: bool) -> Self {
ValueWrapper { val, is_leaves: leaves }
}
pub fn is_leaves(&self) -> bool {
self.is_leaves
}
pub fn set_leaves(&mut self, is_leaves: bool) {
self.is_leaves = is_leaves;
}
pub fn cmp(&self, other: &ValueWrapper, cmp_type: CmpType) -> TermContext {
match cmp_type {
CmpType::Eq => {
TermContext::Json(None, self.intersect(other))
}
CmpType::Ne => {
TermContext::Json(None, self.except(other))
}
CmpType::Gt | CmpType::Ge | CmpType::Lt | CmpType::Le => {
TermContext::Constants(ExprTerm::Bool(false))
}
}
}
fn take_object_in_array<F: PrivCmp>(&self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
fn _filter_with_object<F: Fn(&RefValueWrapper) -> bool>(v: &RefValueWrapper, key: &String, fun: F) -> bool {
match v.deref() {
RefValue::Object(map) => {
match map.get(key) {
Some(val) => fun(val),
_ => false
}
}
_ => false
}
}
match self.val.deref() {
RefValue::Array(vec) => {
let mut set = IndexSet::new();
for v in vec {
if _filter_with_object(v, key, |vv| {
cmp_with_term(vv, et, cmp, false, reverse)
}) {
set.insert(v.clone());
}
}
let ret = set.into_iter().collect();
Some(ValueWrapper::new(RefValue::Array(ret).into(), false))
}
_ => None
}
}
fn take_with_key_type<F: PrivCmp>(&self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
match key {
Some(ValueFilterKey::String(key)) => {
self.take_object_in_array(key, et, cmp, reverse)
}
_ => None
}
}
pub fn take_with<F: PrivCmp>(&self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: F, reverse: bool) -> Self {
match self.take_with_key_type(key, et, &cmp, reverse) {
Some(vw) => vw,
_ => {
match &(*self.val) {
RefValue::Array(vec) => {
let mut set = IndexSet::new();
for v in vec {
if cmp_with_term(v, et, &cmp, false, reverse) {
set.insert(v.clone());
}
}
let ret = set.into_iter().collect();
ValueWrapper::new(RefValue::Array(ret).into(), false)
}
_ => {
if cmp_with_term(&self.val, et, &cmp, false, reverse) {
ValueWrapper::new(self.val.clone(), false)
} else {
ValueWrapper::new(RefValue::Null.into(), false)
}
}
}
}
}
}
pub fn replace(&mut self, val: RefValueWrapper) {
let is_null = match val.deref() {
RefValue::Array(v) => v.is_empty(),
RefValue::Object(m) => m.is_empty(),
_ => val.is_null()
};
self.val = if is_null {
RefValue::Null.into()
} else {
val
};
}
pub fn get_val(&self) -> &RefValueWrapper {
&self.val
}
pub fn into_value(&self) -> Value {
self.get_val().into()
}
pub fn is_array(&self) -> bool {
self.val.is_array()
}
fn into_hashset(&self) -> IndexSet<&RefValue> {
trace!("into_hashset");
let mut hashset = IndexSet::new();
match self.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
hashset.insert(v.deref());
}
}
_ => {
hashset.insert(self.val.deref());
}
}
hashset
}
fn into_hashmap(&self) -> IndexMap<&RefValue, RefValueWrapper> {
trace!("into_hashmap");
let mut hashmap = IndexMap::new();
match self.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
hashmap.insert(v.deref(), v.clone());
}
}
_ => {
hashmap.insert(self.val.deref(), self.val.clone());
}
}
hashmap
}
pub fn except(&self, other: &Self) -> Self {
trace!("except");
let hashset = self.into_hashset();
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
if !hashset.contains(v.deref()) {
ret.insert(v.clone());
}
}
}
_ => {
if !hashset.contains(&other.val.deref()) {
ret.insert(other.val.clone());
}
}
}
let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn intersect(&self, other: &Self) -> Self {
trace!("intersect");
let hashset = self.into_hashset();
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
if hashset.contains(v.deref()) {
ret.insert(v.clone());
}
}
}
e => {
if hashset.contains(e) {
ret.insert(other.val.clone());
}
}
}
let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn union(&self, other: &Self) -> Self {
trace!("union");
let origin = self.into_hashmap();
let mut ret = IndexSet::new();
for o in origin.values() {
ret.insert(o.clone());
}
match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
if !origin.contains_key(v.deref()) {
ret.insert(v.clone());
}
}
}
_ => {
if !origin.contains_key(&other.val.deref()) {
ret.insert(other.val.clone());
}
}
}
let mut vw = ValueWrapper::new(RefValue::Null.into(), false);
let list = ret.iter().map(|v| v.clone()).collect();
vw.replace(RefValue::Array(list).into());
vw
}
pub fn into_term(&self, key: &Option<ValueFilterKey>) -> TermContext {
match self.val.deref() {
RefValue::String(ref s) => TermContext::Constants(ExprTerm::String(s.clone())),
RefValue::Number(ref n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())),
RefValue::Bool(b) => TermContext::Constants(ExprTerm::Bool(*b)),
_ => TermContext::Json(match key {
Some(vk) => Some(vk.clone()),
_ => None
}, ValueWrapper::new(self.val.clone(), false))
}
}
pub fn filter(&self, key: &Option<ValueFilterKey>) -> Self {
trace!("filter");
let v = match self.val.deref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
if let Some(ValueFilterKey::String(k)) = key {
if v.get(k.clone()).is_some() {
ret.push(v.clone());
}
}
}
RefValue::Array(ret).into()
}
RefValue::Object(ref map) => {
match key {
Some(ValueFilterKey::String(k)) => match map.get(k) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
},
_ => RefValue::Null.into()
}
}
_ => self.val.clone()
};
ValueWrapper::new(v, false)
}
}

View File

@ -172,6 +172,8 @@ use std::result;
use serde_json::Value; use serde_json::Value;
pub use select::selector::Selector;
#[doc(hidden)] #[doc(hidden)]
pub mod parser; pub mod parser;
#[doc(hidden)] #[doc(hidden)]
@ -181,8 +183,6 @@ pub mod ref_value;
#[doc(hidden)] #[doc(hidden)]
pub mod select; pub mod select;
pub use select::Selector;
/// It is a high-order function. it compile a JsonPath and then returns a function. this return-function can be reused for different JsonObjects. /// It is a high-order function. it compile a JsonPath and then returns a function. this return-function can be reused for different JsonObjects.
/// ///
/// ```rust /// ```rust
@ -349,7 +349,7 @@ pub fn reader<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result<Value,
/// ``` /// ```
pub fn select(json: &Value, path: &str) -> result::Result<Value, String> { pub fn select(json: &Value, path: &str) -> result::Result<Value, String> {
let mut selector = Selector::new(); let mut selector = Selector::new();
selector.path(path)?.value(json.into())?.select_as_value() selector.path(path)?.value(json)?.select_as_value()
} }
#[deprecated(since = "0.1.4", note = "Please use the select function instead")] #[deprecated(since = "0.1.4", note = "Please use the select function instead")]

View File

@ -1,3 +1,5 @@
use std::cell::RefCell;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Deref; use std::ops::Deref;
use std::sync::Arc; use std::sync::Arc;
@ -5,13 +7,25 @@ use std::sync::Arc;
use indexmap::map::IndexMap; use indexmap::map::IndexMap;
use serde::ser::Serialize; use serde::ser::Serialize;
use serde_json::{Number, Value}; use serde_json::{Number, Value};
use std::collections::hash_map::DefaultHasher; use std::fmt;
type TypeRefValue = Arc<Box<RefValue>>; type TypeRefValue = Arc<RefCell<RefValue>>;
#[derive(Debug)]
pub struct RefValueWrapper { pub struct RefValueWrapper {
data: TypeRefValue data: TypeRefValue,
}
impl fmt::Debug for RefValueWrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(f)
}
}
impl RefValueWrapper {
pub fn ref_count(&self) -> usize {
Arc::strong_count(&self.data)
}
} }
impl PartialEq for RefValueWrapper { impl PartialEq for RefValueWrapper {
@ -26,10 +40,16 @@ impl Deref for RefValueWrapper {
type Target = RefValue; type Target = RefValue;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&(**self.data) unsafe { self.data.as_ptr().as_mut().unwrap() }
} }
} }
//impl DerefMut for RefValueWrapper {
// fn deref_mut(&mut self) -> &mut RefValue {
// unsafe { self.data.as_ptr().as_mut().unwrap() }
// }
//}
impl Hash for RefValueWrapper { impl Hash for RefValueWrapper {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state) self.deref().hash(state)
@ -120,7 +140,6 @@ impl RefIndex for String {
} }
} }
#[derive(Debug)]
pub enum RefValue { pub enum RefValue {
Null, Null,
Bool(bool), Bool(bool),
@ -130,6 +149,12 @@ pub enum RefValue {
Object(IndexMap<String, RefValueWrapper>), Object(IndexMap<String, RefValueWrapper>),
} }
impl fmt::Debug for RefValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", serde_json::to_string(&self).unwrap())
}
}
impl PartialEq for RefValue { impl PartialEq for RefValue {
fn eq(&self, other: &RefValue) -> bool { fn eq(&self, other: &RefValue) -> bool {
let mut hasher1 = DefaultHasher::new(); let mut hasher1 = DefaultHasher::new();
@ -146,6 +171,9 @@ static REF_VALUE_NULL: &'static str = "$jsonpath::ref_value::model::RefValue::Nu
impl Hash for RefValue { impl Hash for RefValue {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
// println!("###hash - RefValue - {:?}", self);
match self { match self {
RefValue::Null => { RefValue::Null => {
REF_VALUE_NULL.hash(state) REF_VALUE_NULL.hash(state)
@ -188,71 +216,40 @@ impl RefValue {
} }
pub fn is_object(&self) -> bool { pub fn is_object(&self) -> bool {
self.as_object().is_some()
}
pub fn as_object(&self) -> Option<&IndexMap<String, RefValueWrapper>> {
match *self { match *self {
RefValue::Object(ref map) => Some(map), RefValue::Object(_) => true,
_ => None,
}
}
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub fn as_array(&self) -> Option<&Vec<RefValueWrapper>> {
match *self {
RefValue::Array(ref array) => Some(&*array),
_ => None,
}
}
pub fn is_string(&self) -> bool {
self.as_str().is_some()
}
pub fn as_str(&self) -> Option<&str> {
match *self {
RefValue::String(ref s) => Some(s),
_ => None,
}
}
pub fn is_number(&self) -> bool {
match *self {
RefValue::Number(_) => true,
_ => false, _ => false,
} }
} }
pub fn as_number(&self) -> Option<Number> { pub fn is_array(&self) -> bool {
match *self { match *self {
RefValue::Number(ref n) => Some(n.clone()), RefValue::Array(_) => true,
_ => None, _ => false,
} }
} }
pub fn is_boolean(&self) -> bool { pub fn len(&self) -> usize {
self.as_bool().is_some() match &self {
RefValue::Object(m) => m.len(),
RefValue::Array(v) => v.len(),
_ => 0,
}
} }
pub fn as_bool(&self) -> Option<bool> { pub fn is_empty(&self) -> bool {
match *self { match &self {
RefValue::Bool(b) => Some(b), RefValue::Object(m) => m.is_empty(),
_ => None, RefValue::Array(v) => v.is_empty(),
RefValue::Null => true,
_ => false,
} }
} }
pub fn is_null(&self) -> bool { pub fn is_null(&self) -> bool {
self.as_null().is_some()
}
pub fn as_null(&self) -> Option<()> {
match *self { match *self {
RefValue::Null => Some(()), RefValue::Null => true,
_ => None, _ => false,
} }
} }
} }
@ -260,14 +257,14 @@ impl RefValue {
impl Into<RefValueWrapper> for RefValue { impl Into<RefValueWrapper> for RefValue {
fn into(self) -> RefValueWrapper { fn into(self) -> RefValueWrapper {
RefValueWrapper { RefValueWrapper {
data: Arc::new(Box::new(self)) data: Arc::new(RefCell::new(self))
} }
} }
} }
impl Into<RefValue> for &Value { impl Into<RefValue> for &Value {
fn into(self) -> RefValue { fn into(self) -> RefValue {
match self.serialize(super::ser::Serializer) { match self.serialize(super::ser::RefValueSerializer) {
Ok(v) => v, Ok(v) => v,
Err(e) => panic!("Error Value into RefValue: {:?}", e) Err(e) => panic!("Error Value into RefValue: {:?}", e)
} }
@ -276,7 +273,7 @@ impl Into<RefValue> for &Value {
impl Into<RefValueWrapper> for &Value { impl Into<RefValueWrapper> for &Value {
fn into(self) -> RefValueWrapper { fn into(self) -> RefValueWrapper {
match self.serialize(super::ser::Serializer) { match self.serialize(super::ser::RefValueSerializer) {
Ok(v) => v.into(), Ok(v) => v.into(),
Err(e) => panic!("Error Value into RefValue: {:?}", e) Err(e) => panic!("Error Value into RefValue: {:?}", e)
} }

View File

@ -41,9 +41,9 @@ impl Serialize for RefValue {
} }
} }
pub struct Serializer; pub struct RefValueSerializer;
impl serde::Serializer for Serializer { impl serde::Serializer for RefValueSerializer {
type Ok = RefValue; type Ok = RefValue;
type Error = SerdeError; type Error = SerdeError;
@ -170,7 +170,7 @@ impl serde::Serializer for Serializer {
{ {
let mut values: IndexMap<String, RefValueWrapper> = IndexMap::new(); let mut values: IndexMap<String, RefValueWrapper> = IndexMap::new();
values.insert(String::from(variant), { values.insert(String::from(variant), {
value.serialize(Serializer)?.into() value.serialize(RefValueSerializer)?.into()
}); });
Ok(RefValue::Object(values)) Ok(RefValue::Object(values))
} }
@ -280,7 +280,7 @@ impl serde::ser::SerializeSeq for SerializeVec {
T: Serialize, T: Serialize,
{ {
self.vec.push({ self.vec.push({
value.serialize(Serializer)?.into() value.serialize(RefValueSerializer)?.into()
}); });
Ok(()) Ok(())
} }
@ -331,7 +331,7 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
T: Serialize, T: Serialize,
{ {
self.vec.push({ self.vec.push({
let a: RefValue = value.serialize(Serializer)?; let a: RefValue = value.serialize(RefValueSerializer)?;
a.into() a.into()
}); });
Ok(()) Ok(())
@ -378,7 +378,7 @@ impl serde::ser::SerializeMap for SerializeMap {
// expected failure. // expected failure.
let key = key.expect("serialize_value called before serialize_key"); let key = key.expect("serialize_value called before serialize_key");
map.insert(key, { map.insert(key, {
let a: RefValue = value.serialize(Serializer)?; let a: RefValue = value.serialize(RefValueSerializer)?;
a.into() a.into()
}); });
Ok(()) Ok(())
@ -608,7 +608,7 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant {
T: Serialize, T: Serialize,
{ {
self.map.insert(String::from(key), { self.map.insert(String::from(key), {
let a: RefValue = value.serialize(Serializer)?; let a: RefValue = value.serialize(RefValueSerializer)?;
a.into() a.into()
}); });
Ok(()) Ok(())

View File

@ -1,239 +1,3 @@
use std::{fmt, result}; pub mod selector;
use std::ops::Deref; pub mod modifiable;
pub mod path_map;
use serde_json::Value;
use super::filter::value_filter::*;
use super::parser::parser::*;
use super::ref_value::model::*;
/// Utility. Functions like jsonpath::selector or jsonpath::compile are also implemented using this structure.
///
/// ```rust
/// extern crate jsonpath_lib as jsonpath;
/// extern crate serde;
/// extern crate serde_json;
///
/// use serde::{Deserialize, Serialize};
/// use serde_json::Value;
///
/// use jsonpath::Selector;
///
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct Person {
/// name: String,
/// age: Option<u8>,
/// phone: String,
/// }
///
/// fn input_str() -> &'static str {
/// r#"[
/// {
/// "name": "이름1",
/// "age": 40,
/// "phone": "+33 12341234"
/// },
/// {
/// "name": "이름2",
/// "age": 42,
/// "phone": "++44 12341234"
/// }
/// ]"#
/// }
///
/// fn input_json() -> Value {
/// serde_json::from_str(input_str()).unwrap()
/// }
///
/// fn input_person() -> Vec<Person> {
/// serde_json::from_str(input_str()).unwrap()
/// }
///
///
/// let mut selector = Selector::new();
///
/// let result = selector
/// .path("$..[?(@.age > 40)]").unwrap()
/// .value_from_str(input_str()).unwrap()
/// .select_as_value().unwrap();
/// assert_eq!(input_json()[1], result[0]);
///
/// let result = selector.select_as_str().unwrap();
/// assert_eq!(serde_json::to_string(&vec![&input_json()[1].clone()]).unwrap(), result);
///
/// let result = selector.select_as::<Vec<Person>>().unwrap();
/// assert_eq!(input_person()[1], result[0]);
///
/// let _ = selector.path("$..[?(@.age == 40)]");
///
/// let result = selector.select_as_value().unwrap();
/// assert_eq!(input_json()[0], result[0]);
///
/// let result = selector.select_as_str().unwrap();
/// assert_eq!(serde_json::to_string(&vec![&input_json()[0].clone()]).unwrap(), result);
///
/// let result = selector.select_as::<Vec<Person>>().unwrap();
/// assert_eq!(input_person()[0], result[0]);
///
/// selector.map(|v| {
/// let r = match v {
/// Value::Array(mut vec) => {
/// for mut v in &mut vec {
/// v.as_object_mut().unwrap().remove("age");
/// }
/// Value::Array(vec)
/// }
/// _ => Value::Null
/// };
/// Some(r)
/// });
/// assert_eq!(
/// serde_json::from_str::<Value>(r#"[{ "name": "이름1", "phone": "+33 12341234"}]"#).unwrap(),
/// selector.get().unwrap());
///
/// selector.value_from_str(input_str()).unwrap()
/// .map_as(|mut v: Vec<Person>| {
/// let mut p = v.pop().unwrap();
/// p.name = "name1".to_string();
/// p.age = None;
/// Some(vec![p])
/// });
/// assert_eq!(
/// vec![Person { name: "name1".to_string(), age: None, phone: "+33 12341234".to_string() }],
/// selector.get_as::<Vec<Person>>().unwrap());
/// ```
#[derive(Debug)]
pub struct Selector {
pub(crate) node: Option<Node>,
pub(crate) value: Option<RefValueWrapper>,
}
impl Selector {
pub fn new() -> Self {
Selector { node: None, value: None }
}
pub fn path(&mut self, path: &str) -> result::Result<&mut Self, String> {
let mut parser = Parser::new(path);
self.node = Some(parser.compile()?);
Ok(self)
}
pub fn value(&mut self, value: &Value) -> result::Result<&mut Self, String> {
self.value = Some(value.into());
Ok(self)
}
pub fn value_from(&mut self, serializable: &impl serde::ser::Serialize) -> result::Result<&mut Self, String> {
let ref_value: RefValue = serializable
.serialize(super::ref_value::ser::Serializer)
.map_err(|e| e.to_string())?;
self.value = Some(ref_value.into());
Ok(self)
}
pub fn value_from_str(&mut self, json_str: &str) -> result::Result<&mut Self, String> {
let value = serde_json::from_str(json_str)
.map_err(|e| e.to_string())?;
self.value(&value)
}
fn jf(&self) -> result::Result<JsonValueFilter, String> {
match &self.value {
Some(v) => Ok(JsonValueFilter::new_from_value(v.clone())),
_ => return Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
fn select(&self) -> result::Result<RefValueWrapper, String> {
let mut jf = self.jf()?;
match &self.node {
Some(node) => {
jf.visit(node.clone());
Ok(jf.take_value())
}
_ => Err(SelectorErrorMessage::EmptyPath.to_string())
}
}
#[deprecated(since = "0.1.13", note = "Please use the select_as_str function instead")]
pub fn select_to_str(&self) -> result::Result<String, String> {
self.select_as_str()
}
#[deprecated(since = "0.1.13", note = "Please use the select_as_value function instead")]
pub fn select_to_value(&self) -> result::Result<Value, String> {
self.select_as_value()
}
#[deprecated(since = "0.1.13", note = "Please use the select_as function instead")]
pub fn select_to<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
self.select_as()
}
pub fn select_as_str(&self) -> result::Result<String, String> {
serde_json::to_string(self.select()?.deref()).map_err(|e| e.to_string())
}
pub fn select_as_value(&self) -> result::Result<Value, String> {
Ok((&self.select()?).into())
}
pub fn select_as<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
T::deserialize(self.select()?.deref()).map_err(|e| e.to_string())
}
pub fn map<F>(&mut self, func: F) -> result::Result<&mut Self, String>
where F: FnOnce(Value) -> Option<Value>
{
self.value = func((&self.select()?).into()).map(|ref v| v.into());
Ok(self)
}
pub fn map_as<F, D, S>(&mut self, func: F) -> result::Result<&mut Self, String>
where F: FnOnce(D) -> Option<S>,
D: serde::de::DeserializeOwned,
S: serde::ser::Serialize
{
let ret = func(D::deserialize(self.select()?.deref()).map_err(|e| e.to_string())?)
.map(|ref ser| ser.serialize(super::ref_value::ser::Serializer));
self.value = match ret {
Some(ret) => match ret {
Ok(v) => Some(v.into()),
Err(e) => return Err(e.to_string())
}
_ => None
};
Ok(self)
}
pub fn get(&self) -> result::Result<Value, String> {
match &self.value {
Some(value) => Ok(value.into()),
_ => Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
pub fn get_as<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
match &self.value {
Some(value) => T::deserialize(value.deref()).map_err(|e| e.to_string()),
_ => Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
}
enum SelectorErrorMessage {
EmptyValue,
EmptyPath,
}
impl fmt::Display for SelectorErrorMessage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SelectorErrorMessage::EmptyValue => write!(f, "Empty value"),
SelectorErrorMessage::EmptyPath => write!(f, "Empty path"),
}
}
}

60
src/select/modifiable.rs Normal file
View File

@ -0,0 +1,60 @@
use std::collections::HashMap;
use std::ops::Deref;
use ref_value::model::{RefValue, RefValueWrapper};
use Selector;
pub trait Modifiable {
fn delete(&mut self) -> Result<&mut Self, String>;
}
impl Modifiable for Selector {
fn delete(&mut self) -> Result<&mut Self, String> {
Ok(self)
}
}
fn traverse(parent_path: String, v: &RefValueWrapper, buf: &mut HashMap<RefValueWrapper, String>, depth: usize, limit: usize) {
if depth >= limit {
return;
}
match v.deref() {
RefValue::Array(vec) => {
for (i, v) in vec.iter().enumerate() {
buf.insert(v.clone(), format!("{}/{}", parent_path, i.to_string()));
}
for (i, v) in vec.iter().enumerate() {
traverse(format!("{}/{}", parent_path, i.to_string()), v, buf, depth + 1, limit);
}
}
RefValue::Object(map) => {
for (k, v) in map.into_iter() {
buf.insert(v.clone(), format!("{}/{}", parent_path, k.to_string()));
}
for (k, v) in map.into_iter() {
traverse(format!("{}/{}", parent_path, k.to_string()), v, buf, depth + 1, limit);
}
}
_ => {
buf.insert(v.clone(), parent_path);
}
}
}
pub struct PathFinder {
map: HashMap<RefValueWrapper, String>,
}
impl PathFinder {
pub fn new(v: RefValueWrapper) -> Self {
let mut map = HashMap::new();
traverse("/".to_string(), &v, &mut map, 0, 1);
debug!("map: {:?}", map);
PathFinder { map }
}
pub fn get(&self, v: &RefValueWrapper) -> Option<&String> {
self.map.get(v)
}
}

53
src/select/path_map.rs Normal file
View File

@ -0,0 +1,53 @@
//use std::collections::HashMap;
use std::ops::Deref;
use ref_value::model::{RefValue, RefValueWrapper};
use indexmap::IndexMap;
#[derive(Debug)]
pub struct PathMap {
map: IndexMap<RefValueWrapper, String>
}
impl PathMap {
pub(in select) fn new() -> Self {
PathMap { map: IndexMap::new() }
}
pub fn get_path(&self, v: &RefValueWrapper) -> Option<&String> {
self.map.get(v)
}
pub(in select) fn replace(&mut self, v: &RefValueWrapper) {
self.map.clear();
self.walk("".to_string(), v);
}
fn walk(&mut self, parent_path: String, v: &RefValueWrapper) {
if &parent_path == "" {
self.map.insert(v.clone(), "/".to_string());
} else {
self.map.insert(v.clone(), parent_path.clone());
}
match v.deref() {
RefValue::Object(map) => {
for (key, value) in map {
self.walk(format!("{}/{}", &parent_path, key), value);
}
}
RefValue::Array(vec) => {
for (index, value) in vec.iter().enumerate() {
self.walk(format!("{}/{}", &parent_path, index), value);
}
}
_ => {}
};
}
pub fn print(&self) {
for (k, v) in &self.map {
println!("{:?} : {}", k, v);
}
}
}

266
src/select/selector.rs Normal file
View File

@ -0,0 +1,266 @@
use std::{fmt, result};
use std::ops::Deref;
use serde_json::Value;
use filter::value_filter::*;
use parser::parser::*;
use ref_value;
use ref_value::model::*;
use select::path_map::PathMap;
use std::sync::Arc;
use std::cell::RefCell;
/// Utility. Functions like jsonpath::selector or jsonpath::compile are also implemented using this structure.
///
/// ```rust
/// extern crate jsonpath_lib as jsonpath;
/// extern crate serde;
/// extern crate serde_json;
///
/// use serde::{Deserialize, Serialize};
/// use serde_json::Value;
///
/// use jsonpath::Selector;
///
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct Person {
/// name: String,
/// age: Option<u8>,
/// phone: String,
/// }
///
/// fn input_str() -> &'static str {
/// r#"[
/// {
/// "name": "이름1",
/// "age": 40,
/// "phone": "+33 12341234"
/// },
/// {
/// "name": "이름2",
/// "age": 42,
/// "phone": "++44 12341234"
/// }
/// ]"#
/// }
///
/// fn input_json() -> Value {
/// serde_json::from_str(input_str()).unwrap()
/// }
///
/// fn input_person() -> Vec<Person> {
/// serde_json::from_str(input_str()).unwrap()
/// }
///
///
/// let mut selector = Selector::new();
///
/// let result = selector
/// .path("$..[?(@.age > 40)]").unwrap()
/// .value_from_str(input_str()).unwrap()
/// .select_as_value().unwrap();
/// assert_eq!(input_json()[1], result[0]);
///
/// let result = selector.select_as_str().unwrap();
/// assert_eq!(serde_json::to_string(&vec![&input_json()[1].clone()]).unwrap(), result);
///
/// let result = selector.select_as::<Vec<Person>>().unwrap();
/// assert_eq!(input_person()[1], result[0]);
///
/// let _ = selector.path("$..[?(@.age == 40)]");
///
/// let result = selector.select_as_value().unwrap();
/// assert_eq!(input_json()[0], result[0]);
///
/// let result = selector.select_as_str().unwrap();
/// assert_eq!(serde_json::to_string(&vec![&input_json()[0].clone()]).unwrap(), result);
///
/// let result = selector.select_as::<Vec<Person>>().unwrap();
/// assert_eq!(input_person()[0], result[0]);
///
/// selector.map(|v| {
/// let r = match v {
/// Value::Array(mut vec) => {
/// for mut v in &mut vec {
/// v.as_object_mut().unwrap().remove("age");
/// }
/// Value::Array(vec)
/// }
/// _ => Value::Null
/// };
/// Some(r)
/// });
/// assert_eq!(
/// serde_json::from_str::<Value>(r#"[{ "name": "이름1", "phone": "+33 12341234"}]"#).unwrap(),
/// selector.get().unwrap());
///
/// selector.value_from_str(input_str()).unwrap()
/// .map_as(|mut v: Vec<Person>| {
/// let mut p = v.pop().unwrap();
/// p.name = "name1".to_string();
/// p.age = None;
/// Some(vec![p])
/// });
/// assert_eq!(
/// vec![Person { name: "name1".to_string(), age: None, phone: "+33 12341234".to_string() }],
/// selector.get_as::<Vec<Person>>().unwrap());
/// ```
#[derive(Debug)]
pub struct Selector {
pub(crate) node: Option<Node>,
pub(crate) value: Option<RefValueWrapper>,
path_builder: Arc<RefCell<PathMap>>,
}
impl Selector {
pub fn new() -> Self {
Selector { node: None, value: None, path_builder: Arc::new(RefCell::new(PathMap::new())) }
}
fn set_value(&mut self, value: RefValueWrapper) {
// (*self.path_builder).borrow_mut().replace(&value);
self.value = Some(value);
}
pub fn path(&mut self, path: &str) -> result::Result<&mut Self, String> {
let mut parser = Parser::new(path);
self.node = Some(parser.compile()?);
Ok(self)
}
pub fn value(&mut self, value: &Value) -> result::Result<&mut Self, String> {
self.set_value(value.into());
// (*self.path_builder).borrow_mut().print();
Ok(self)
}
pub fn value_from_ref_value(&mut self, value: RefValueWrapper) -> result::Result<&mut Self, String> {
self.set_value(value);
Ok(self)
}
pub fn value_from(&mut self, serializable: &impl serde::ser::Serialize) -> result::Result<&mut Self, String> {
let ref_value: RefValue = serializable
.serialize(ref_value::ser::RefValueSerializer)
.map_err(|e| e.to_string())?;
self.set_value(ref_value.into());
Ok(self)
}
pub fn value_from_str(&mut self, json_str: &str) -> result::Result<&mut Self, String> {
let value: RefValue = serde_json::from_str(json_str)
.map_err(|e| e.to_string())?;
self.set_value(value.into());
Ok(self)
}
fn jf(&self) -> result::Result<JsonValueFilter, String> {
match &self.value {
Some(v) => Ok(JsonValueFilter::new(v.clone(),
self.path_builder.clone())),
_ => return Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
fn select(&self) -> result::Result<RefValueWrapper, String> {
let mut jf = self.jf()?;
match &self.node {
Some(node) => {
jf.visit(node.clone());
Ok(jf.clone_value())
}
_ => Err(SelectorErrorMessage::EmptyPath.to_string())
}
}
#[deprecated(since = "0.1.13", note = "Please use the select_as_str function instead")]
pub fn select_to_str(&self) -> result::Result<String, String> {
self.select_as_str()
}
#[deprecated(since = "0.1.13", note = "Please use the select_as_value function instead")]
pub fn select_to_value(&self) -> result::Result<Value, String> {
self.select_as_value()
}
#[deprecated(since = "0.1.13", note = "Please use the select_as function instead")]
pub fn select_to<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
self.select_as()
}
pub fn select_as_str(&self) -> result::Result<String, String> {
serde_json::to_string(self.select()?.deref()).map_err(|e| e.to_string())
}
pub fn select_as_value2(&self) {
let _ = &self.select();
}
pub fn select_as_value(&self) -> result::Result<Value, String> {
Ok((&self.select()?).into())
}
pub fn select_as<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
T::deserialize(self.select()?.deref()).map_err(|e| e.to_string())
}
pub fn map<F>(&mut self, func: F) -> result::Result<&mut Self, String>
where F: FnOnce(Value) -> Option<Value>
{
match func((&self.select()?).into()).map(|ref v| v.into()) {
Some(value) => {
self.set_value(value)
},
_ => {}
}
Ok(self)
}
pub fn map_as<F, D, S>(&mut self, func: F) -> result::Result<&mut Self, String>
where F: FnOnce(D) -> Option<S>,
D: serde::de::DeserializeOwned,
S: serde::ser::Serialize
{
let ret = func(D::deserialize(self.select()?.deref()).map_err(|e| e.to_string())?)
.map(|ref ser| ser.serialize(ref_value::ser::RefValueSerializer));
match ret {
Some(ret) => match ret {
Ok(v) => self.set_value(v.into()),
Err(e) => return Err(e.to_string())
}
_ => {}
};
Ok(self)
}
pub fn get(&self) -> result::Result<Value, String> {
match &self.value {
Some(value) => Ok(value.into()),
_ => Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
pub fn get_as<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
match &self.value {
Some(value) => T::deserialize(value.deref()).map_err(|e| e.to_string()),
_ => Err(SelectorErrorMessage::EmptyValue.to_string())
}
}
}
enum SelectorErrorMessage {
EmptyValue,
EmptyPath,
}
impl fmt::Display for SelectorErrorMessage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SelectorErrorMessage::EmptyValue => write!(f, "Empty value"),
SelectorErrorMessage::EmptyPath => write!(f, "Empty path"),
}
}
}

View File

@ -10,23 +10,24 @@ use serde_json::Value;
use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter}; use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter};
use jsonpath::parser::parser::Parser; use jsonpath::parser::parser::Parser;
use jsonpath::Selector;
fn setup() { fn setup() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();
} }
fn new_value_filter(file: &str) -> ValueFilter { //fn new_value_filter(file: &str) -> ValueFilter {
let string = read_json(file); // let string = read_json(file);
let json: Value = serde_json::from_str(string.as_str()).unwrap(); // let json: Value = serde_json::from_str(string.as_str()).unwrap();
ValueFilter::new((&json).into(), false, false) // ValueFilter::new((&json).into(), false, false)
} //}
fn do_filter(path: &str, file: &str) -> JsonValueFilter { fn selector(path: &str, file: &str) -> Selector {
let string = read_json(file); let string = read_json(file);
let mut jf = JsonValueFilter::new(string.as_str()).unwrap(); let mut s = Selector::new();
let mut parser = Parser::new(path); let _ = s.path(path);
parser.parse(&mut jf).unwrap(); let _ = s.value_from_str(&string);
jf s
} }
fn read_json(path: &str) -> String { fn read_json(path: &str) -> String {
@ -36,53 +37,53 @@ fn read_json(path: &str) -> String {
contents contents
} }
#[test] //#[test]
fn step_in() { //fn step_in() {
setup(); // setup();
//
let mut jf = new_value_filter("./benches/data_obj.json"); // let mut jf = new_value_filter("./benches/data_obj.json");
{ // {
let current = jf.step_in_str("friends"); // let current = jf.step_in_str("friends");
assert_eq!(current.is_array(), true); // assert_eq!(current.is_array(), true);
} // }
//
let mut jf = new_value_filter("./benches/data_array.json"); // let mut jf = new_value_filter("./benches/data_array.json");
{ // {
let current = jf.step_in_num(&1.0); // let current = jf.step_in_num(&1.0);
assert_eq!(current.get_val().is_object(), true); // assert_eq!(current.get_val().is_object(), true);
} // }
{ // {
let current = jf.step_in_str("friends"); // let current = jf.step_in_str("friends");
assert_eq!(current.is_array(), true); // assert_eq!(current.is_array(), true);
} // }
let mut jf = new_value_filter("./benches/data_obj.json"); // let mut jf = new_value_filter("./benches/data_obj.json");
{ // {
jf.step_in_str("school"); // jf.step_in_str("school");
jf.step_in_str("friends"); // jf.step_in_str("friends");
jf.step_in_all(); // jf.step_in_all();
let current = jf.step_in_str("name"); // let current = jf.step_in_str("name");
let friends = json!([ // let friends = json!([
"Millicent Norman", // "Millicent Norman",
"Vincent Cannon", // "Vincent Cannon",
"Gray Berry" // "Gray Berry"
]); // ]);
//
assert_eq!(friends, current.into_value()); // assert_eq!(friends, current.into_value());
} // }
let mut jf = new_value_filter("./benches/data_obj.json"); // let mut jf = new_value_filter("./benches/data_obj.json");
{ // {
let current = jf.step_leaves_str("name"); // let current = jf.step_leaves_str("name");
let names = json!([ // let names = json!([
"Leonor Herman", // "Leonor Herman",
"Millicent Norman", // "Millicent Norman",
"Vincent Cannon", // "Vincent Cannon",
"Gray Berry", // "Gray Berry",
"Vincent Cannon", // "Vincent Cannon",
"Gray Berry" // "Gray Berry"
]); // ]);
assert_eq!(names, current.into_value()); // assert_eq!(names, current.into_value());
} // }
} //}
#[test] #[test]
fn array() { fn array() {
@ -93,33 +94,33 @@ fn array() {
{"id": 2, "name": "Gray Berry"} {"id": 2, "name": "Gray Berry"}
]); ]);
let jf = do_filter("$.school.friends[1, 2]", "./benches/data_obj.json"); let s = selector("$.school.friends[1, 2]", "./benches/data_obj.json");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.school.friends[1:]", "./benches/data_obj.json"); let s = selector("$.school.friends[1:]", "./benches/data_obj.json");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.school.friends[:-2]", "./benches/data_obj.json"); let s = selector("$.school.friends[:-2]", "./benches/data_obj.json");
let friends = json!([ let friends = json!([
{"id": 0, "name": "Millicent Norman"} {"id": 0, "name": "Millicent Norman"}
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$..friends[2].name", "./benches/data_obj.json"); let s = selector("$..friends[2].name", "./benches/data_obj.json");
let friends = json!(["Gray Berry", "Gray Berry"]); let friends = json!(["Gray Berry", "Gray Berry"]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$..friends[*].name", "./benches/data_obj.json"); let s = selector("$..friends[*].name", "./benches/data_obj.json");
let friends = json!(["Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry"]); let friends = json!(["Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry"]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$['school']['friends'][*].['name']", "./benches/data_obj.json"); let s = selector("$['school']['friends'][*].['name']", "./benches/data_obj.json");
let friends = json!(["Millicent Norman","Vincent Cannon","Gray Berry"]); let friends = json!(["Millicent Norman","Vincent Cannon","Gray Berry"]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$['school']['friends'][0].['name']", "./benches/data_obj.json"); let s = selector("$['school']['friends'][0].['name']", "./benches/data_obj.json");
let friends = json!("Millicent Norman"); let friends = json!("Millicent Norman");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
} }
#[test] #[test]
@ -134,32 +135,32 @@ fn return_type() {
] ]
}); });
let jf = do_filter("$.school", "./benches/data_obj.json"); let s = selector("$.school", "./benches/data_obj.json");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.school[?(@.friends[0])]", "./benches/data_obj.json"); let s = selector("$.school[?(@.friends[0])]", "./benches/data_obj.json");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.school[?(@.friends[10])]", "./benches/data_obj.json"); let s = selector("$.school[?(@.friends[10])]", "./benches/data_obj.json");
assert_eq!(Value::Null, jf.into_value()); assert_eq!(Value::Null, s.select_as_value().unwrap());
let jf = do_filter("$.school[?(1==1)]", "./benches/data_obj.json"); let s = selector("$.school[?(1==1)]", "./benches/data_obj.json");
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.school.friends[?(1==1)]", "./benches/data_obj.json"); let s = selector("$.school.friends[?(1==1)]", "./benches/data_obj.json");
let friends = json!([ let friends = json!([
{"id": 0, "name": "Millicent Norman"}, {"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" }, {"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"} {"id": 2, "name": "Gray Berry"}
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
} }
#[test] #[test]
fn op_default() { fn op_default() {
setup(); setup();
let jf = do_filter("$.school[?(@.friends == @.friends)]", "./benches/data_obj.json"); let s = selector("$.school[?(@.friends == @.friends)]", "./benches/data_obj.json");
let friends = json!({ let friends = json!({
"friends": [ "friends": [
{"id": 0, "name": "Millicent Norman"}, {"id": 0, "name": "Millicent Norman"},
@ -167,54 +168,55 @@ fn op_default() {
{"id": 2, "name": "Gray Berry"} {"id": 2, "name": "Gray Berry"}
] ]
}); });
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.friends[?(@.name)]", "./benches/data_obj.json"); let s = selector("$.friends[?(@.name)]", "./benches/data_obj.json");
let friends = json!([ let friends = json!([
{ "id" : 1, "name" : "Vincent Cannon" }, { "id" : 1, "name" : "Vincent Cannon" },
{ "id" : 2, "name" : "Gray Berry" } { "id" : 2, "name" : "Gray Berry" }
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.friends[?(@.id >= 2)]", "./benches/data_obj.json"); let s = selector("$.friends[?(@.id >= 2)]", "./benches/data_obj.json");
let friends = json!([ let friends = json!([
{ "id" : 2, "name" : "Gray Berry" } { "id" : 2, "name" : "Gray Berry" }
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json"); let s = selector("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json");
let friends = json!([ let friends = json!([
{ "id" : 2, "name" : "Gray Berry" }, { "id" : 2, "name" : "Gray Berry" },
{ "id" : 1, "name" : "Vincent Cannon" } { "id" : 1, "name" : "Vincent Cannon" }
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json"); let s = selector("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json");
assert_eq!(Value::Null, jf.into_value()); assert_eq!(Value::Null, s.select_as_value().unwrap());
let jf = do_filter("$..friends[?(@.id == $.index)].id", "./benches/data_obj.json"); let s = selector("$..friends[?(@.id == $.index)].id", "./benches/data_obj.json");
let friends = json!([0, 0]); let friends = json!([0, 0]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$..book[?($.store.bicycle.price < @.price)].price", "./benches/example.json"); let s = selector("$..book[?($.store.bicycle.price < @.price)].price", "./benches/example.json");
let friends = json!([22.99]); let friends = json!([22.99]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let jf = do_filter("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", "./benches/example.json"); let s = selector("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", "./benches/example.json");
let friends = json!([12.99]); let friends = json!([12.99]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let ref value = json!([ let ref value = json!([
{ "name": "이름1", "age": 40, "phone": "+33 12341234" }, { "name": "이름1", "age": 40, "phone": "+33 12341234" },
{ "name": "이름2", "age": 42, "phone": "++44 12341234" } { "name": "이름2", "age": 42, "phone": "++44 12341234" }
]); ]);
let mut jf = JsonValueFilter::new_from_value(value.into());
let mut parser = Parser::new("$..[?(@.age > 40)]"); let mut s = Selector::new();
parser.parse(&mut jf).unwrap(); let _ = s.path("$..[?(@.age > 40)]");
let _ = s.value(value);
let friends = json!([ let friends = json!([
{ "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" }
]); ]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
let ref value = json!({ let ref value = json!({
"school": { "school": {
@ -227,11 +229,11 @@ fn op_default() {
{"name": "친구3", "age": 30}, {"name": "친구3", "age": 30},
{"name": "친구4"} {"name": "친구4"}
]}); ]});
let mut jf = JsonValueFilter::new_from_value(value.into()); let mut s = Selector::new();
let mut parser = Parser::new("$..[?(@.age >= 30)]"); let _ = s.path("$..[?(@.age >= 30)]");
parser.parse(&mut jf).unwrap(); let _ = s.value(value);
let friends = json!([{ "name" : "친구3", "age" : 30 }]); let friends = json!([{ "name" : "친구3", "age" : 30 }]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, s.select_as_value().unwrap());
} }
#[test] #[test]
@ -314,14 +316,14 @@ fn op_complex() {
fn example() { fn example() {
setup(); setup();
let jf = do_filter("$.store.book[*].author", "./benches/example.json"); let s = selector("$.store.book[*].author", "./benches/example.json");
let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..author", "./benches/example.json"); let s = selector("$..author", "./benches/example.json");
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$.store.*", "./benches/example.json"); let s = selector("$.store.*", "./benches/example.json");
let ret = json!([ let ret = json!([
[ [
{"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95},
@ -331,13 +333,13 @@ fn example() {
], ],
{"color" : "red","price" : 19.95}, {"color" : "red","price" : 19.95},
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$.store..price", "./benches/example.json"); let s = selector("$.store..price", "./benches/example.json");
let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[2]", "./benches/example.json"); let s = selector("$..book[2]", "./benches/example.json");
let ret = json!([{ let ret = json!([{
"category" : "fiction", "category" : "fiction",
"author" : "Herman Melville", "author" : "Herman Melville",
@ -345,9 +347,9 @@ fn example() {
"isbn" : "0-553-21311-3", "isbn" : "0-553-21311-3",
"price" : 8.99 "price" : 8.99
}]); }]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[-2]", "./benches/example.json"); let s = selector("$..book[-2]", "./benches/example.json");
let ret = json!([{ let ret = json!([{
"category" : "fiction", "category" : "fiction",
"author" : "Herman Melville", "author" : "Herman Melville",
@ -355,9 +357,9 @@ fn example() {
"isbn" : "0-553-21311-3", "isbn" : "0-553-21311-3",
"price" : 8.99 "price" : 8.99
}]); }]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[0,1]", "./benches/example.json"); let s = selector("$..book[0,1]", "./benches/example.json");
let ret = json!([ let ret = json!([
{ {
"category" : "reference", "category" : "reference",
@ -372,9 +374,9 @@ fn example() {
"price" : 12.99 "price" : 12.99
} }
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[:2]", "./benches/example.json"); let s = selector("$..book[:2]", "./benches/example.json");
let ret = json!([ let ret = json!([
{ {
"category" : "reference", "category" : "reference",
@ -389,9 +391,9 @@ fn example() {
"price" : 12.99 "price" : 12.99
} }
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[2:]", "./benches/example.json"); let s = selector("$..book[2:]", "./benches/example.json");
let ret = json!([ let ret = json!([
{ {
"category" : "fiction", "category" : "fiction",
@ -408,9 +410,9 @@ fn example() {
"price" : 22.99 "price" : 22.99
} }
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..book[?(@.isbn)]", "./benches/example.json"); let s = selector("$..book[?(@.isbn)]", "./benches/example.json");
let ret = json!([ let ret = json!([
{ {
"category" : "fiction", "category" : "fiction",
@ -427,9 +429,9 @@ fn example() {
"price" : 22.99 "price" : 22.99
} }
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$.store.book[?(@.price < 10)]", "./benches/example.json"); let s = selector("$.store.book[?(@.price < 10)]", "./benches/example.json");
let ret = json!([ let ret = json!([
{ {
"category" : "reference", "category" : "reference",
@ -445,28 +447,27 @@ fn example() {
"price" : 8.99 "price" : 8.99
} }
]); ]);
assert_eq!(ret, jf.into_value()); assert_eq!(ret, s.select_as_value().unwrap());
let jf = do_filter("$..*", "./benches/example.json"); let s = selector("$..*", "./benches/example.json");
let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap(); let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap();
assert_eq!(json, jf.into_value()); assert_eq!(json, s.select_as_value().unwrap());
} }
#[test] #[test]
fn filer_same_obj() { fn filer_same_obj() {
setup(); setup();
let mut jf = JsonValueFilter::new(r#" let mut s = Selector::new();
let _ = s.path("$..[?(@.a == 1)]");
let _ = s.value_from_str(r#"
{ {
"a": 1, "a": 1,
"b" : {"a": 1}, "b" : {"a": 1},
"c" : {"a": 1} "c" : {"a": 1}
} }
"#).unwrap(); "#);
let mut parser = Parser::new("$..[?(@.a == 1)]"); assert_eq!(s.select_as_value().unwrap(), json!([
parser.parse(&mut jf).unwrap();
let ret = jf.into_value();
assert_eq!(ret, json!([
{"a": 1}, {"a": 1},
{"a": 1} {"a": 1}
])); ]));

31
tests/modifiable.rs Normal file
View File

@ -0,0 +1,31 @@
//extern crate indexmap;
//extern crate jsonpath_lib;
//#[macro_use]
//extern crate serde_json;
//
//use std::io::Read;
//
//use serde_json::Value;
//
//use jsonpath_lib::filter::value_filter::JsonValueFilter;
//use jsonpath_lib::parser::parser::Parser;
//use jsonpath_lib::ref_value::model::RefValue;
//
//fn setup() {
// let _ = env_logger::try_init();
//}
//
//fn do_filter(path: &str, file: &str) -> JsonValueFilter {
// let string = read_json(file);
// let mut jf = JsonValueFilter::new(string.as_str()).unwrap();
// let mut parser = Parser::new(path);
// parser.parse(&mut jf).unwrap();
// jf
//}
//
//fn read_json(path: &str) -> String {
// let mut f = std::fs::File::open(path).unwrap();
// let mut contents = String::new();
// f.read_to_string(&mut contents).unwrap();
// contents
//}

View File

@ -12,7 +12,7 @@ use std::collections::HashMap;
use std::ops::Deref; use std::ops::Deref;
use std::result; use std::result;
use std::result::Result; use std::result::Result;
use std::sync::Mutex; use std::sync::{Mutex, Arc};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use jsonpath::filter::value_filter::JsonValueFilter; use jsonpath::filter::value_filter::JsonValueFilter;
@ -23,6 +23,8 @@ use serde_json::Value;
use wasm_bindgen::*; use wasm_bindgen::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use web_sys::console; use web_sys::console;
use std::cell::RefCell;
use jsonpath::select::path_map::PathMap;
cfg_if! { cfg_if! {
if #[cfg(feature = "wee_alloc")] { if #[cfg(feature = "wee_alloc")] {
@ -43,13 +45,14 @@ cfg_if! {
} }
fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue { fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue {
let mut jf = JsonValueFilter::new_from_value(json); // let mut jf = JsonValueFilter::new(json, Arc::new(RefCell::new(PathMap::new())));
jf.visit(node); // jf.visit(node);
let taken = &jf.take_value(); // let taken = &jf.clone_value();
match JsValue::from_serde(taken.deref()) { // match JsValue::from_serde(taken.deref()) {
Ok(js_value) => js_value, // Ok(js_value) => js_value,
Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e)) // Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e))
} // }
JsValue::from_str("")
} }
fn into_serde_json<D>(js_value: &JsValue) -> Result<D, String> fn into_serde_json<D>(js_value: &JsValue) -> Result<D, String>
@ -77,48 +80,51 @@ fn into_ref_value(js_value: &JsValue, node: Node) -> JsValue {
} }
fn get_ref_value(js_value: JsValue, node: Node) -> JsValue { fn get_ref_value(js_value: JsValue, node: Node) -> JsValue {
match js_value.as_f64() { // match js_value.as_f64() {
Some(val) => { // Some(val) => {
match CACHE_JSON.lock().unwrap().get(&(val as usize)) { // match CACHE_JSON.lock().unwrap().get(&(val as usize)) {
Some(json) => filter_ref_value(json.clone(), node), // Some(json) => filter_ref_value(json.clone(), node),
_ => JsValue::from_str("Invalid pointer") // _ => JsValue::from_str("Invalid pointer")
} // }
} // }
_ => into_ref_value(&js_value, node) // _ => into_ref_value(&js_value, node)
} // }
JsValue::from_str("")
} }
lazy_static! { //lazy_static! {
static ref CACHE_JSON: Mutex<HashMap<usize, RefValueWrapper>> = Mutex::new(HashMap::new()); // static ref CACHE_JSON: Mutex<HashMap<usize, RefValueWrapper>> = Mutex::new(HashMap::new());
static ref CACHE_JSON_IDX: Mutex<usize> = Mutex::new(0); // static ref CACHE_JSON_IDX: Mutex<usize> = Mutex::new(0);
} //}
#[wasm_bindgen(js_name = allocJson)] #[wasm_bindgen(js_name = allocJson)]
pub extern fn alloc_json(js_value: JsValue) -> usize { pub extern fn alloc_json(js_value: JsValue) -> usize {
let result: result::Result<RefValue, String> = into_serde_json(&js_value); // let result: result::Result<RefValue, String> = into_serde_json(&js_value);
match result { // match result {
Ok(json) => { // Ok(json) => {
let mut map = CACHE_JSON.lock().unwrap(); // let mut map = CACHE_JSON.lock().unwrap();
if map.len() >= std::u8::MAX as usize { // if map.len() >= std::u8::MAX as usize {
return 0; // return 0;
} // }
//
let mut idx = CACHE_JSON_IDX.lock().unwrap(); // let mut idx = CACHE_JSON_IDX.lock().unwrap();
*idx += 1; // *idx += 1;
map.insert(*idx, json.into()); // map.insert(*idx, json.into());
*idx // *idx
} // }
Err(e) => { // Err(e) => {
console::error_1(&e.into()); // console::error_1(&e.into());
0 // 0
} // }
} // }
0
} }
#[wasm_bindgen(js_name = deallocJson)] #[wasm_bindgen(js_name = deallocJson)]
pub extern fn dealloc_json(ptr: usize) -> bool { pub extern fn dealloc_json(ptr: usize) -> bool {
let mut map = CACHE_JSON.lock().unwrap(); // let mut map = CACHE_JSON.lock().unwrap();
map.remove(&ptr).is_some() // map.remove(&ptr).is_some()
false
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -139,32 +145,35 @@ pub fn compile(path: &str) -> JsValue {
#[wasm_bindgen] #[wasm_bindgen]
pub fn selector(js_value: JsValue) -> JsValue { pub fn selector(js_value: JsValue) -> JsValue {
let json = match js_value.as_f64() { // let json = match js_value.as_f64() {
Some(val) => { // Some(val) => {
match CACHE_JSON.lock().unwrap().get(&(val as usize)) { // match CACHE_JSON.lock().unwrap().get(&(val as usize)) {
Some(json) => json.clone(), // Some(json) => json.clone(),
_ => return JsValue::from_str("Invalid pointer") // _ => return JsValue::from_str("Invalid pointer")
} // }
} // }
_ => { // _ => {
match into_serde_json::<RefValue>(&js_value) { // match into_serde_json::<RefValue>(&js_value) {
Ok(json) => json.into(), // Ok(json) => json.into(),
Err(e) => return JsValue::from_str(e.as_str()) // Err(e) => return JsValue::from_str(e.as_str())
} // }
} // }
};
let cb = Closure::wrap(Box::new(move |path: String| { // };
let mut parser = Parser::new(path.as_str());
match parser.compile() {
Ok(node) => filter_ref_value(json.clone(), node),
Err(e) => return JsValue::from_str(e.as_str())
}
}) as Box<Fn(String) -> JsValue>);
let ret = cb.as_ref().clone(); // let cb = Closure::wrap(Box::new(move |path: String| {
cb.forget(); // let mut parser = Parser::new(path.as_str());
ret // match parser.compile() {
// Ok(node) => filter_ref_value(json.clone(), node),
// Err(e) => return JsValue::from_str(e.as_str())
// }
// }) as Box<Fn(String) -> JsValue>);
//
// let ret = cb.as_ref().clone();
// cb.forget();
// ret
JsValue::from_str("")
} }
#[wasm_bindgen] #[wasm_bindgen]