diff --git a/.gitignore b/.gitignore index 8647db2..5e2c017 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .vscode !.idea/runConfigurations/ /target/ -Cargo.lock \ No newline at end of file +Cargo.lock +callgrind.out.* \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 52ca42a..80354a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,5 +32,5 @@ name = "jsonpath_lib" path = "src/lib.rs" [profile.release] -#debug = true +debug = true #lto = false diff --git a/benches/bench.rs b/benches/bench.rs index 33c5cbf..55fcb58 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,18 +1,20 @@ #![feature(test)] +extern crate bencher; +extern crate indexmap; extern crate jsonpath_lib as jsonpath; extern crate serde; extern crate serde_json; extern crate test; -extern crate bencher; use std::io::Read; +use serde::Serialize; use serde::Deserialize; use serde_json::Value; use self::test::Bencher; -use jsonpath::ref_value::model::RefValue; -use serde::ser::Serialize; +use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; +use jsonpath::ref_value::ser::RefValueSerializer; fn read_json(path: &str) -> String { let mut f = std::fs::File::open(path).unwrap(); @@ -107,22 +109,55 @@ fn bench_select_as(b: &mut Bencher) { } #[bench] -fn bench_serde_ser(b: &mut Bencher) { +fn refval_de(b: &mut Bencher) { let json = get_json(); - b.iter(move || { for _ in 1..100 { - let _: RefValue = json.serialize(jsonpath::ref_value::ser::Serializer).unwrap().into(); + let _ = RefValue::deserialize(&json).unwrap(); } }); } #[bench] -fn bench_serde_de(b: &mut Bencher) { - let json_string = get_string(); - let json_str = json_string.as_str(); +fn refval_se(b: &mut Bencher) { + let json = get_json(); + b.iter(move || { + for _ in 1..100 { + let _ = &json.serialize(RefValueSerializer).unwrap(); + } + }); +} - b.iter(move || for _ in 1..100 { - let _: RefValue = serde_json::from_str(json_str).unwrap(); +#[bench] +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 = 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 = vec.iter().map(|v| v.clone()).collect(); + } + } }); } \ No newline at end of file diff --git a/benches/bench_example.rs b/benches/bench_example.rs new file mode 100644 index 0000000..d2e8322 --- /dev/null +++ b/benches/bench_example.rs @@ -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); diff --git a/profiling.sh b/profiling.sh new file mode 100755 index 0000000..c262a73 --- /dev/null +++ b/profiling.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +valgrind \ + --tool=callgrind \ + --dump-instr=yes \ + --collect-jumps=yes \ + --simulate-cache=yes $1 -- $2 \ No newline at end of file diff --git a/src/filter/mod.rs b/src/filter/mod.rs index b3b7581..472c2b9 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -1,4 +1,6 @@ mod cmp; mod term; pub mod value_filter; -pub mod value_wrapper; \ No newline at end of file +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; \ No newline at end of file diff --git a/src/filter/term.rs b/src/filter/term.rs index 8a1571f..a5b8d03 100644 --- a/src/filter/term.rs +++ b/src/filter/term.rs @@ -1,15 +1,18 @@ use super::cmp::*; 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)] pub enum TermContext { Constants(ExprTerm), - Json(Option, ValueWrapper), + Json(Option, ValueManager), } impl TermContext { - fn cmp(&self, other: &TermContext, cmp_fn: F, default: bool) -> TermContext { + fn cmp(&mut self, other: &mut TermContext, cmp_fn: F, default: bool) -> TermContext { match self { TermContext::Constants(et) => { match other { @@ -17,9 +20,9 @@ impl TermContext { trace!("const-const"); 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"); - 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 oc = ov.into_term(key_other); + let mut c = v.into_term(key); + let mut oc = ov.into_term(key_other); if is_json(&c) && is_json(&oc) { v.cmp(&ov, cmp_fn.into_type()) } else { - c.cmp(&oc, cmp_fn, default) + c.cmp(&mut oc, cmp_fn, default) } } TermContext::Constants(et) => { 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>) -> TermContext { match self { TermContext::Constants(et) => { match other { @@ -67,7 +70,7 @@ impl TermContext { } } 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"); self.cmp(other, CmpEq, false) } - pub fn ne(&self, other: &TermContext) -> TermContext { + pub fn ne(&mut self, other: &mut TermContext) -> TermContext { trace!("ne"); self.cmp(other, CmpNe, true) } - pub fn gt(&self, other: &TermContext) -> TermContext { + pub fn gt(&mut self, other: &mut TermContext) -> TermContext { trace!("gt"); self.cmp(other, CmpGt, false) } - pub fn ge(&self, other: &TermContext) -> TermContext { + pub fn ge(&mut self, other: &mut TermContext) -> TermContext { trace!("ge"); self.cmp(other, CmpGe, false) } - pub fn lt(&self, other: &TermContext) -> TermContext { + pub fn lt(&mut self, other: &mut TermContext) -> TermContext { trace!("lt"); self.cmp(other, CmpLt, false) } - pub fn le(&self, other: &TermContext) -> TermContext { + pub fn le(&mut self, other: &mut TermContext) -> TermContext { trace!("le"); self.cmp(other, CmpLe, false) } - pub fn and(&self, other: &TermContext) -> TermContext { - self.cmp_cond(other, CmpCondType::And) + pub fn and(&mut self, other: &mut TermContext, path_map: Arc>) -> TermContext { + self.cmp_cond(other, CmpCondType::And, path_map) } - pub fn or(&self, other: &TermContext) -> TermContext { - self.cmp_cond(other, CmpCondType::Or) + pub fn or(&mut self, other: &mut TermContext, path_map: Arc>) -> TermContext { + self.cmp_cond(other, CmpCondType::Or, path_map) } } diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs index fb8c82b..839f4b8 100644 --- a/src/filter/value_filter.rs +++ b/src/filter/value_filter.rs @@ -1,51 +1,14 @@ -use std::error::Error; +use std::cell::RefCell; use std::ops::Deref; -use std::result::Result; +use std::sync::Arc; use serde_json::Value; use filter::term::*; -use filter::value_wrapper::*; +use filter::value_manager::*; use parser::parser::{FilterToken, NodeVisitor, ParseToken}; use ref_value::model::*; - -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 - } -} +use select::path_map::PathMap; #[derive(Debug, Clone)] pub enum ValueFilterKey { @@ -54,248 +17,136 @@ pub enum ValueFilterKey { All, } -fn iter_to_value_vec<'a, I: Iterator>(iter: I) -> Vec { - iter - .map(|v| v.clone()) - .filter(|v| !v.is_null()) - .collect() -} - -fn get_nested_array(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) { +fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec) { match v.deref() { RefValue::Array(vec) => { if key.is_none() { - for v in vec { + for v in vec.iter() { buf.push(v.clone()); } } - for i in vec { - traverse(key, i, buf); + + for v in vec { + collect_all(key, v, buf); } } - RefValue::Object(v) => { - for (k, v) in v.into_iter() { - if match key { - Some(map_key) => map_key == k, - _ => true - } { - buf.push(v.clone()); + RefValue::Object(map) => { + if let Some(k) = key { + if let Some(val) = map.get(k) { + buf.push(val.clone()); } + } else { + let mut c = map.values().map(|v| v.clone()).collect(); + buf.append(&mut c); } - for (_, v) in v.into_iter() { - traverse(key, v, buf); + for (_, v) in map { + collect_all(key, v, buf); } } _ => {} } } -fn collect_all(key: Option<&String>, v: &RefValueWrapper) -> Vec { - let mut buf = Vec::new(); - traverse(key, v, &mut buf); - buf -} - #[derive(Debug)] pub struct ValueFilter { - val_wrapper: ValueWrapper, + value_mgr: ValueManager, last_key: Option, - filter_mode: bool, + is_relative: bool, + path_map: Arc>, } impl ValueFilter { - pub fn new(v: RefValueWrapper, is_leaves: bool, filter_mode: bool) -> Self { - ValueFilter { val_wrapper: ValueWrapper::new(v, is_leaves), last_key: None, filter_mode } + pub fn new(v: RefValueWrapper, is_leaves: bool, is_relative: bool, path_map: Arc>) -> Self { + 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>) { - 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); - 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"); self.step_leaves(None); 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()) } - pub fn step_leaves_string(&mut self, key: &String) -> &ValueWrapper { + pub fn step_leaves_string(&mut self, key: &String) -> &ValueManager { debug!("step_leaves_string"); self.step_leaves(Some(key)); 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"); - - 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.val_wrapper.replace(RefValue::Array(vec).into()); - trace!("step_in_all - {:?}", self.val_wrapper.get_val()); - &self.val_wrapper + self.value_mgr.replace(self.value_mgr.get_as_array()); + trace!("step_in_all - {:?}", self.value_mgr.get_val()); + &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"); trace!("step_in_num - before: leaves {}, filterMode {} - {:?}" - , self.val_wrapper.is_leaves() - , self.filter_mode - , self.val_wrapper.get_val()); + , self.value_mgr.is_leaves() + , self.is_relative + , 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.val_wrapper.replace(v); - trace!("step_in_num - after: {:?}", self.val_wrapper.get_val()); - &self.val_wrapper + self.last_key = Some(ValueFilterKey::Num(self.value_mgr.get_index(*key))); + let v = self.value_mgr.get_with_num(key, self.is_relative); + self.value_mgr.replace(v); + 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()) } - pub fn step_in_string(&mut self, key: &String) -> &ValueWrapper { + pub fn step_in_string(&mut self, key: &String) -> &ValueManager { debug!("step_in_string"); trace!("step_in_string - before: {},{},{:?}" - , self.val_wrapper.is_leaves() - , self.filter_mode - , self.val_wrapper.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.value_mgr.is_leaves() + , self.is_relative + , self.value_mgr.get_val()); 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: {},{},{:?}" - , self.val_wrapper.is_leaves() - , self.filter_mode - , self.val_wrapper.get_val()); - &self.val_wrapper + , self.value_mgr.is_leaves() + , self.is_relative + , self.value_mgr.get_val()); + &self.value_mgr } } pub struct JsonValueFilter { json: RefValueWrapper, + path_map: Arc>, filter_stack: Vec, token_stack: Vec, term_stack: Vec, } impl JsonValueFilter { - pub fn new(json: &str) -> Result { - 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 { + pub fn new(json: RefValueWrapper, path_map: Arc>) -> Self { JsonValueFilter { json, + path_map, filter_stack: Vec::new(), token_stack: Vec::new(), term_stack: Vec::new(), @@ -303,90 +154,86 @@ impl JsonValueFilter { } fn is_peek_token_array(&self) -> bool { - if let Some(ParseToken::Array) = self.token_stack.last() { - true - } else { - false - } + if let Some(ParseToken::Array) = self.token_stack.last() { true } else { false } } - fn push_value_filter(&mut self, from_current: bool) { - if from_current { + fn create_new_filter(&mut self, is_relative: bool) { + if is_relative { self.filter_stack.last() .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| { Some(self.filter_stack.push(vf)) }); } else { - self.filter_stack.push({ - ValueFilter::new(self.json.clone(), false, from_current) - }); + let vf = ValueFilter::new( + 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() { - self.filter_stack.push(ValueFilter::new(v, is_leaves, false)); - } else { - match self.filter_stack.last_mut() { - Some(vf) => { - vf.val_wrapper.set_leaves(is_leaves); - if v.is_null() { - vf.val_wrapper.replace(v); - } 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() { - vf.val_wrapper.replace(v); - } + self.filter_stack.push(ValueFilter::new( + v, + is_leaves, + false, + self.path_map.clone(), + )); + return; + } + + match self.filter_stack.last_mut() { + 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 { match self.filter_stack.last() { - Some(v) => v.val_wrapper.into_value(), + Some(v) => v.value_mgr.into_value(), _ => Value::Null } } + #[deprecated(since = "0.1.14", note = "Please use the clone_value function instead")] pub fn take_value(&mut self) -> RefValueWrapper { - match self.filter_stack.last_mut() { - Some(v) => v.val_wrapper.get_val().clone(), + self.clone_value() + } + + pub fn clone_value(&mut self) -> RefValueWrapper { + match self.filter_stack.last() { + Some(v) => v.value_mgr.get_val().clone(), _ => RefValue::Null.into() } } - fn token_union(&mut self, indices: Vec) { + fn token_union(&mut self, indices: Vec) { self.token_stack.pop(); match self.filter_stack.last_mut() { - Some(ref mut vf) if vf.val_wrapper.is_array() && vf.val_wrapper.is_leaves() => { - let mut ret = Vec::new(); - if let RefValue::Array(val) = vf.val_wrapper.get_val().deref() { - for v in val { - for i in &indices { - let v = i.take_value(v); - if !v.is_null() { - ret.push(v.clone()); - } - } - } + Some(vf) => { + if let Some(vec) = vf.value_mgr.pick_with_nums(indices) { + vf.value_mgr.replace(vec); } - 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, to: Option) { self.token_stack.pop(); - fn _from_to(from: Option, to: Option, 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 { - 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() { - Some(ref mut vf) if vf.val_wrapper.is_array() && vf.val_wrapper.is_leaves() => { - let mut buf = Vec::new(); - if let RefValue::Array(vec) = vf.val_wrapper.get_val().deref() { - for v in vec { - let (from, to) = _from_to(from, to, v); - let mut v: Vec = _range(from, to, v); - buf.append(&mut v); - } + Some(ref mut vf) => { + if let Some(vec) = vf.value_mgr.range_with(from, to) { + vf.value_mgr.replace(vec); } - 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 = _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))) => { - self.replace_filter_stack(RefValue::Null.into(), false); + self.append_to_current_filter(RefValue::Null.into(), false); } 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() { Some(vf) => { - let is_leaves = vf.val_wrapper.is_leaves(); - match vf.val_wrapper.get_val().deref() { + match vf.value_mgr.get_val().deref() { 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); if left.is_some() && right.is_some() { - let left = left.unwrap(); - let right = right.unwrap(); + let mut left = left.unwrap(); + let mut right = right.unwrap(); let tc = match ft { - FilterToken::Equal => left.eq(&right), - FilterToken::NotEqual => left.ne(&right), - FilterToken::Greater => left.gt(&right), - FilterToken::GreaterOrEqual => left.ge(&right), - FilterToken::Little => left.lt(&right), - FilterToken::LittleOrEqual => left.le(&right), - FilterToken::And => left.and(&right), - FilterToken::Or => left.or(&right), + FilterToken::Equal => left.eq(&mut right), + FilterToken::NotEqual => left.ne(&mut right), + FilterToken::Greater => left.gt(&mut right), + FilterToken::GreaterOrEqual => left.ge(&mut right), + FilterToken::Little => left.lt(&mut right), + FilterToken::LittleOrEqual => left.le(&mut right), + FilterToken::And => left.and(&mut right, self.path_map.clone()), + FilterToken::Or => left.or(&mut right, self.path_map.clone()), }; self.term_stack.push(tc); } @@ -556,7 +368,7 @@ impl NodeVisitor for JsonValueFilter { if self.is_peek_token_array() { self.token_stack.pop(); } - self.push_value_filter(ParseToken::Relative == token); + self.create_new_filter(ParseToken::Relative == token); } ParseToken::In | ParseToken::Leaves => { @@ -609,7 +421,7 @@ impl NodeVisitor for JsonValueFilter { if self.token_stack.is_empty() && self.filter_stack.len() > 1 { match self.filter_stack.pop() { 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)); } _ => {} } diff --git a/src/filter/value_manager.rs b/src/filter/value_manager.rs new file mode 100644 index 0000000..e0a7690 --- /dev/null +++ b/src/filter/value_manager.rs @@ -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(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, + F: FnMut(&RefValueWrapper) -> RefValueWrapper>(iter: I, func: F) -> Vec +{ + iter.map(func) + .filter(|v| !v.is_null()) + .collect() +} + +fn collect_some<'a, + I: Iterator, + F: FnMut(&RefValueWrapper) -> Option>(iter: I, func: F) -> Vec +{ + iter.map(func) + .filter(|v| v.is_some()) + .map(|v| v.unwrap()) + .collect() +} + +fn get_in_array(v: &RefValueWrapper, key: &I, is_relative: bool) -> Option { + 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 { + 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(v: &RefValueWrapper, key: &I, is_relative: bool) -> Option { + 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 { + 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 { + 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>, + is_leaves: bool, +} + +impl ValueManager { + pub fn new(val: RefValueWrapper, is_leaves: bool, path_map: Arc>) -> 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(&self, key: &Option, 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(&self, i: I) -> usize { + i.index(&self.val) + } + + pub fn get_with_num(&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, to: Option) -> Option { + fn _from(from: Option, val: &RefValueWrapper) -> usize { + match from { + Some(v) => v.index(val), + _ => 0 + } + } + + fn _to(to: Option, 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 { + 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(&self, indices: Vec) -> Option { + 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 = 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 = 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) -> 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) -> 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()) + } +} diff --git a/src/filter/value_wrapper.rs b/src/filter/value_wrapper.rs deleted file mode 100644 index 7782f8e..0000000 --- a/src/filter/value_wrapper.rs +++ /dev/null @@ -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(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(&self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { - fn _filter_with_object 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(&self, key: &Option, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { - match key { - Some(ValueFilterKey::String(key)) => { - self.take_object_in_array(key, et, cmp, reverse) - } - _ => None - } - } - - pub fn take_with(&self, key: &Option, 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 = 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 = 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) -> 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) -> 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) - } -} diff --git a/src/lib.rs b/src/lib.rs index 6fa94e4..5121a55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -172,6 +172,8 @@ use std::result; use serde_json::Value; +pub use select::selector::Selector; + #[doc(hidden)] pub mod parser; #[doc(hidden)] @@ -181,8 +183,6 @@ pub mod ref_value; #[doc(hidden)] 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. /// /// ```rust @@ -349,7 +349,7 @@ pub fn reader<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result result::Result { 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")] diff --git a/src/ref_value/model.rs b/src/ref_value/model.rs index 694dd9d..5c6e76a 100644 --- a/src/ref_value/model.rs +++ b/src/ref_value/model.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; +use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::sync::Arc; @@ -5,13 +7,25 @@ use std::sync::Arc; use indexmap::map::IndexMap; use serde::ser::Serialize; use serde_json::{Number, Value}; -use std::collections::hash_map::DefaultHasher; +use std::fmt; -type TypeRefValue = Arc>; +type TypeRefValue = Arc>; -#[derive(Debug)] 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 { @@ -26,10 +40,16 @@ impl Deref for RefValueWrapper { type Target = RefValue; 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 { fn hash(&self, state: &mut H) { self.deref().hash(state) @@ -120,7 +140,6 @@ impl RefIndex for String { } } -#[derive(Debug)] pub enum RefValue { Null, Bool(bool), @@ -130,6 +149,12 @@ pub enum RefValue { Object(IndexMap), } +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 { fn eq(&self, other: &RefValue) -> bool { 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 { fn hash(&self, state: &mut H) { + +// println!("###hash - RefValue - {:?}", self); + match self { RefValue::Null => { REF_VALUE_NULL.hash(state) @@ -188,71 +216,40 @@ impl RefValue { } pub fn is_object(&self) -> bool { - self.as_object().is_some() - } - - pub fn as_object(&self) -> Option<&IndexMap> { match *self { - RefValue::Object(ref map) => Some(map), - _ => None, - } - } - - pub fn is_array(&self) -> bool { - self.as_array().is_some() - } - - pub fn as_array(&self) -> Option<&Vec> { - 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, + RefValue::Object(_) => true, _ => false, } } - pub fn as_number(&self) -> Option { + pub fn is_array(&self) -> bool { match *self { - RefValue::Number(ref n) => Some(n.clone()), - _ => None, + RefValue::Array(_) => true, + _ => false, } } - pub fn is_boolean(&self) -> bool { - self.as_bool().is_some() + pub fn len(&self) -> usize { + match &self { + RefValue::Object(m) => m.len(), + RefValue::Array(v) => v.len(), + _ => 0, + } } - pub fn as_bool(&self) -> Option { - match *self { - RefValue::Bool(b) => Some(b), - _ => None, + pub fn is_empty(&self) -> bool { + match &self { + RefValue::Object(m) => m.is_empty(), + RefValue::Array(v) => v.is_empty(), + RefValue::Null => true, + _ => false, } } pub fn is_null(&self) -> bool { - self.as_null().is_some() - } - - pub fn as_null(&self) -> Option<()> { match *self { - RefValue::Null => Some(()), - _ => None, + RefValue::Null => true, + _ => false, } } } @@ -260,14 +257,14 @@ impl RefValue { impl Into for RefValue { fn into(self) -> RefValueWrapper { RefValueWrapper { - data: Arc::new(Box::new(self)) + data: Arc::new(RefCell::new(self)) } } } impl Into for &Value { fn into(self) -> RefValue { - match self.serialize(super::ser::Serializer) { + match self.serialize(super::ser::RefValueSerializer) { Ok(v) => v, Err(e) => panic!("Error Value into RefValue: {:?}", e) } @@ -276,7 +273,7 @@ impl Into for &Value { impl Into for &Value { fn into(self) -> RefValueWrapper { - match self.serialize(super::ser::Serializer) { + match self.serialize(super::ser::RefValueSerializer) { Ok(v) => v.into(), Err(e) => panic!("Error Value into RefValue: {:?}", e) } diff --git a/src/ref_value/ser.rs b/src/ref_value/ser.rs index c4b65fb..22e0c68 100644 --- a/src/ref_value/ser.rs +++ b/src/ref_value/ser.rs @@ -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 Error = SerdeError; @@ -170,7 +170,7 @@ impl serde::Serializer for Serializer { { let mut values: IndexMap = IndexMap::new(); values.insert(String::from(variant), { - value.serialize(Serializer)?.into() + value.serialize(RefValueSerializer)?.into() }); Ok(RefValue::Object(values)) } @@ -280,7 +280,7 @@ impl serde::ser::SerializeSeq for SerializeVec { T: Serialize, { self.vec.push({ - value.serialize(Serializer)?.into() + value.serialize(RefValueSerializer)?.into() }); Ok(()) } @@ -331,7 +331,7 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { T: Serialize, { self.vec.push({ - let a: RefValue = value.serialize(Serializer)?; + let a: RefValue = value.serialize(RefValueSerializer)?; a.into() }); Ok(()) @@ -378,7 +378,7 @@ impl serde::ser::SerializeMap for SerializeMap { // expected failure. let key = key.expect("serialize_value called before serialize_key"); map.insert(key, { - let a: RefValue = value.serialize(Serializer)?; + let a: RefValue = value.serialize(RefValueSerializer)?; a.into() }); Ok(()) @@ -608,7 +608,7 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant { T: Serialize, { self.map.insert(String::from(key), { - let a: RefValue = value.serialize(Serializer)?; + let a: RefValue = value.serialize(RefValueSerializer)?; a.into() }); Ok(()) diff --git a/src/select/mod.rs b/src/select/mod.rs index 66fd576..45c77d9 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -1,239 +1,3 @@ -use std::{fmt, result}; -use std::ops::Deref; - -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, -/// 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 { -/// 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::>().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::>().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::(r#"[{ "name": "이름1", "phone": "+33 12341234"}]"#).unwrap(), -/// selector.get().unwrap()); -/// -/// selector.value_from_str(input_str()).unwrap() -/// .map_as(|mut v: Vec| { -/// 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::>().unwrap()); -/// ``` -#[derive(Debug)] -pub struct Selector { - pub(crate) node: Option, - pub(crate) value: Option, -} - -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 { - match &self.value { - Some(v) => Ok(JsonValueFilter::new_from_value(v.clone())), - _ => return Err(SelectorErrorMessage::EmptyValue.to_string()) - } - } - - fn select(&self) -> result::Result { - 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 { - 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 { - self.select_as_value() - } - - #[deprecated(since = "0.1.13", note = "Please use the select_as function instead")] - pub fn select_to(&self) -> result::Result { - self.select_as() - } - - pub fn select_as_str(&self) -> result::Result { - serde_json::to_string(self.select()?.deref()).map_err(|e| e.to_string()) - } - - pub fn select_as_value(&self) -> result::Result { - Ok((&self.select()?).into()) - } - - pub fn select_as(&self) -> result::Result { - T::deserialize(self.select()?.deref()).map_err(|e| e.to_string()) - } - - pub fn map(&mut self, func: F) -> result::Result<&mut Self, String> - where F: FnOnce(Value) -> Option - { - self.value = func((&self.select()?).into()).map(|ref v| v.into()); - Ok(self) - } - - pub fn map_as(&mut self, func: F) -> result::Result<&mut Self, String> - where F: FnOnce(D) -> Option, - 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 { - match &self.value { - Some(value) => Ok(value.into()), - _ => Err(SelectorErrorMessage::EmptyValue.to_string()) - } - } - - pub fn get_as(&self) -> result::Result { - 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"), - } - } -} +pub mod selector; +pub mod modifiable; +pub mod path_map; \ No newline at end of file diff --git a/src/select/modifiable.rs b/src/select/modifiable.rs new file mode 100644 index 0000000..3fca8f2 --- /dev/null +++ b/src/select/modifiable.rs @@ -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, 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, +} + +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) + } +} \ No newline at end of file diff --git a/src/select/path_map.rs b/src/select/path_map.rs new file mode 100644 index 0000000..82154a0 --- /dev/null +++ b/src/select/path_map.rs @@ -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 +} + +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); + } + } +} \ No newline at end of file diff --git a/src/select/selector.rs b/src/select/selector.rs new file mode 100644 index 0000000..2447ee3 --- /dev/null +++ b/src/select/selector.rs @@ -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, +/// 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 { +/// 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::>().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::>().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::(r#"[{ "name": "이름1", "phone": "+33 12341234"}]"#).unwrap(), +/// selector.get().unwrap()); +/// +/// selector.value_from_str(input_str()).unwrap() +/// .map_as(|mut v: Vec| { +/// 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::>().unwrap()); +/// ``` +#[derive(Debug)] +pub struct Selector { + pub(crate) node: Option, + pub(crate) value: Option, + path_builder: Arc>, +} + +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 { + 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 { + 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 { + 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 { + self.select_as_value() + } + + #[deprecated(since = "0.1.13", note = "Please use the select_as function instead")] + pub fn select_to(&self) -> result::Result { + self.select_as() + } + + pub fn select_as_str(&self) -> result::Result { + 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 { + Ok((&self.select()?).into()) + } + + pub fn select_as(&self) -> result::Result { + T::deserialize(self.select()?.deref()).map_err(|e| e.to_string()) + } + + pub fn map(&mut self, func: F) -> result::Result<&mut Self, String> + where F: FnOnce(Value) -> Option + { + match func((&self.select()?).into()).map(|ref v| v.into()) { + Some(value) => { + self.set_value(value) + }, + _ => {} + } + Ok(self) + } + + pub fn map_as(&mut self, func: F) -> result::Result<&mut Self, String> + where F: FnOnce(D) -> Option, + 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 { + match &self.value { + Some(value) => Ok(value.into()), + _ => Err(SelectorErrorMessage::EmptyValue.to_string()) + } + } + + pub fn get_as(&self) -> result::Result { + 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"), + } + } +} diff --git a/tests/filter.rs b/tests/filter.rs index b47e241..b9f22a3 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -10,23 +10,24 @@ use serde_json::Value; use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter}; use jsonpath::parser::parser::Parser; +use jsonpath::Selector; fn setup() { let _ = env_logger::try_init(); } -fn new_value_filter(file: &str) -> ValueFilter { - let string = read_json(file); - let json: Value = serde_json::from_str(string.as_str()).unwrap(); - ValueFilter::new((&json).into(), false, false) -} +//fn new_value_filter(file: &str) -> ValueFilter { +// let string = read_json(file); +// let json: Value = serde_json::from_str(string.as_str()).unwrap(); +// 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 mut jf = JsonValueFilter::new(string.as_str()).unwrap(); - let mut parser = Parser::new(path); - parser.parse(&mut jf).unwrap(); - jf + let mut s = Selector::new(); + let _ = s.path(path); + let _ = s.value_from_str(&string); + s } fn read_json(path: &str) -> String { @@ -36,53 +37,53 @@ fn read_json(path: &str) -> String { contents } -#[test] -fn step_in() { - setup(); - - let mut jf = new_value_filter("./benches/data_obj.json"); - { - let current = jf.step_in_str("friends"); - assert_eq!(current.is_array(), true); - } - - let mut jf = new_value_filter("./benches/data_array.json"); - { - let current = jf.step_in_num(&1.0); - assert_eq!(current.get_val().is_object(), true); - } - { - let current = jf.step_in_str("friends"); - assert_eq!(current.is_array(), true); - } - let mut jf = new_value_filter("./benches/data_obj.json"); - { - jf.step_in_str("school"); - jf.step_in_str("friends"); - jf.step_in_all(); - let current = jf.step_in_str("name"); - let friends = json!([ - "Millicent Norman", - "Vincent Cannon", - "Gray Berry" - ]); - - assert_eq!(friends, current.into_value()); - } - let mut jf = new_value_filter("./benches/data_obj.json"); - { - let current = jf.step_leaves_str("name"); - let names = json!([ - "Leonor Herman", - "Millicent Norman", - "Vincent Cannon", - "Gray Berry", - "Vincent Cannon", - "Gray Berry" - ]); - assert_eq!(names, current.into_value()); - } -} +//#[test] +//fn step_in() { +// setup(); +// +// let mut jf = new_value_filter("./benches/data_obj.json"); +// { +// let current = jf.step_in_str("friends"); +// assert_eq!(current.is_array(), true); +// } +// +// let mut jf = new_value_filter("./benches/data_array.json"); +// { +// let current = jf.step_in_num(&1.0); +// assert_eq!(current.get_val().is_object(), true); +// } +// { +// let current = jf.step_in_str("friends"); +// assert_eq!(current.is_array(), true); +// } +// let mut jf = new_value_filter("./benches/data_obj.json"); +// { +// jf.step_in_str("school"); +// jf.step_in_str("friends"); +// jf.step_in_all(); +// let current = jf.step_in_str("name"); +// let friends = json!([ +// "Millicent Norman", +// "Vincent Cannon", +// "Gray Berry" +// ]); +// +// assert_eq!(friends, current.into_value()); +// } +// let mut jf = new_value_filter("./benches/data_obj.json"); +// { +// let current = jf.step_leaves_str("name"); +// let names = json!([ +// "Leonor Herman", +// "Millicent Norman", +// "Vincent Cannon", +// "Gray Berry", +// "Vincent Cannon", +// "Gray Berry" +// ]); +// assert_eq!(names, current.into_value()); +// } +//} #[test] fn array() { @@ -93,33 +94,33 @@ fn array() { {"id": 2, "name": "Gray Berry"} ]); - let jf = do_filter("$.school.friends[1, 2]", "./benches/data_obj.json"); - assert_eq!(friends, jf.into_value()); + let s = selector("$.school.friends[1, 2]", "./benches/data_obj.json"); + assert_eq!(friends, s.select_as_value().unwrap()); - let jf = do_filter("$.school.friends[1:]", "./benches/data_obj.json"); - assert_eq!(friends, jf.into_value()); + let s = selector("$.school.friends[1:]", "./benches/data_obj.json"); + 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!([ {"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"]); - 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"]); - 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"]); - 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"); - assert_eq!(friends, jf.into_value()); + assert_eq!(friends, s.select_as_value().unwrap()); } #[test] @@ -134,32 +135,32 @@ fn return_type() { ] }); - let jf = do_filter("$.school", "./benches/data_obj.json"); - assert_eq!(friends, jf.into_value()); + let s = selector("$.school", "./benches/data_obj.json"); + assert_eq!(friends, s.select_as_value().unwrap()); - let jf = do_filter("$.school[?(@.friends[0])]", "./benches/data_obj.json"); - assert_eq!(friends, jf.into_value()); + let s = selector("$.school[?(@.friends[0])]", "./benches/data_obj.json"); + assert_eq!(friends, s.select_as_value().unwrap()); - let jf = do_filter("$.school[?(@.friends[10])]", "./benches/data_obj.json"); - assert_eq!(Value::Null, jf.into_value()); + let s = selector("$.school[?(@.friends[10])]", "./benches/data_obj.json"); + assert_eq!(Value::Null, s.select_as_value().unwrap()); - let jf = do_filter("$.school[?(1==1)]", "./benches/data_obj.json"); - assert_eq!(friends, jf.into_value()); + let s = selector("$.school[?(1==1)]", "./benches/data_obj.json"); + 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!([ {"id": 0, "name": "Millicent Norman"}, {"id": 1, "name": "Vincent Cannon" }, {"id": 2, "name": "Gray Berry"} ]); - assert_eq!(friends, jf.into_value()); + assert_eq!(friends, s.select_as_value().unwrap()); } #[test] fn op_default() { 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!({ "friends": [ {"id": 0, "name": "Millicent Norman"}, @@ -167,54 +168,55 @@ fn op_default() { {"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!([ { "id" : 1, "name" : "Vincent Cannon" }, { "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!([ { "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!([ { "id" : 2, "name" : "Gray Berry" }, { "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"); - assert_eq!(Value::Null, jf.into_value()); + let s = selector("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json"); + 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]); - 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]); - 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]); - assert_eq!(friends, jf.into_value()); + assert_eq!(friends, s.select_as_value().unwrap()); let ref value = json!([ { "name": "이름1", "age": 40, "phone": "+33 12341234" }, { "name": "이름2", "age": 42, "phone": "++44 12341234" } ]); - let mut jf = JsonValueFilter::new_from_value(value.into()); - let mut parser = Parser::new("$..[?(@.age > 40)]"); - parser.parse(&mut jf).unwrap(); + + let mut s = Selector::new(); + let _ = s.path("$..[?(@.age > 40)]"); + let _ = s.value(value); let friends = json!([ { "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!({ "school": { @@ -227,11 +229,11 @@ fn op_default() { {"name": "친구3", "age": 30}, {"name": "친구4"} ]}); - let mut jf = JsonValueFilter::new_from_value(value.into()); - let mut parser = Parser::new("$..[?(@.age >= 30)]"); - parser.parse(&mut jf).unwrap(); + let mut s = Selector::new(); + let _ = s.path("$..[?(@.age >= 30)]"); + let _ = s.value(value); let friends = json!([{ "name" : "친구3", "age" : 30 }]); - assert_eq!(friends, jf.into_value()); + assert_eq!(friends, s.select_as_value().unwrap()); } #[test] @@ -314,14 +316,14 @@ fn op_complex() { fn example() { 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"]); - assert_eq!(ret, jf.into_value()); + assert_eq!(ret, s.select_as_value().unwrap()); - let jf = do_filter("$..author", "./benches/example.json"); - assert_eq!(ret, jf.into_value()); + let s = selector("$..author", "./benches/example.json"); + 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!([ [ {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, @@ -331,13 +333,13 @@ fn example() { ], {"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]); - 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!([{ "category" : "fiction", "author" : "Herman Melville", @@ -345,9 +347,9 @@ fn example() { "isbn" : "0-553-21311-3", "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!([{ "category" : "fiction", "author" : "Herman Melville", @@ -355,9 +357,9 @@ fn example() { "isbn" : "0-553-21311-3", "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!([ { "category" : "reference", @@ -372,9 +374,9 @@ fn example() { "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!([ { "category" : "reference", @@ -389,9 +391,9 @@ fn example() { "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!([ { "category" : "fiction", @@ -408,9 +410,9 @@ fn example() { "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!([ { "category" : "fiction", @@ -427,9 +429,9 @@ fn example() { "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!([ { "category" : "reference", @@ -445,28 +447,27 @@ fn example() { "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(); - assert_eq!(json, jf.into_value()); + assert_eq!(json, s.select_as_value().unwrap()); } #[test] fn filer_same_obj() { 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, "b" : {"a": 1}, "c" : {"a": 1} } - "#).unwrap(); - let mut parser = Parser::new("$..[?(@.a == 1)]"); - parser.parse(&mut jf).unwrap(); - let ret = jf.into_value(); - assert_eq!(ret, json!([ + "#); + assert_eq!(s.select_as_value().unwrap(), json!([ {"a": 1}, {"a": 1} ])); diff --git a/tests/modifiable.rs b/tests/modifiable.rs new file mode 100644 index 0000000..85ac548 --- /dev/null +++ b/tests/modifiable.rs @@ -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 +//} diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index a495d24..fbf78ad 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -12,7 +12,7 @@ use std::collections::HashMap; use std::ops::Deref; use std::result; use std::result::Result; -use std::sync::Mutex; +use std::sync::{Mutex, Arc}; use cfg_if::cfg_if; use jsonpath::filter::value_filter::JsonValueFilter; @@ -23,6 +23,8 @@ use serde_json::Value; use wasm_bindgen::*; use wasm_bindgen::prelude::*; use web_sys::console; +use std::cell::RefCell; +use jsonpath::select::path_map::PathMap; cfg_if! { if #[cfg(feature = "wee_alloc")] { @@ -43,13 +45,14 @@ cfg_if! { } fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue { - let mut jf = JsonValueFilter::new_from_value(json); - jf.visit(node); - let taken = &jf.take_value(); - match JsValue::from_serde(taken.deref()) { - Ok(js_value) => js_value, - Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e)) - } +// let mut jf = JsonValueFilter::new(json, Arc::new(RefCell::new(PathMap::new()))); +// jf.visit(node); +// let taken = &jf.clone_value(); +// match JsValue::from_serde(taken.deref()) { +// Ok(js_value) => js_value, +// Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e)) +// } + JsValue::from_str("") } fn into_serde_json(js_value: &JsValue) -> Result @@ -77,48 +80,51 @@ fn into_ref_value(js_value: &JsValue, node: Node) -> JsValue { } fn get_ref_value(js_value: JsValue, node: Node) -> JsValue { - match js_value.as_f64() { - Some(val) => { - match CACHE_JSON.lock().unwrap().get(&(val as usize)) { - Some(json) => filter_ref_value(json.clone(), node), - _ => JsValue::from_str("Invalid pointer") - } - } - _ => into_ref_value(&js_value, node) - } +// match js_value.as_f64() { +// Some(val) => { +// match CACHE_JSON.lock().unwrap().get(&(val as usize)) { +// Some(json) => filter_ref_value(json.clone(), node), +// _ => JsValue::from_str("Invalid pointer") +// } +// } +// _ => into_ref_value(&js_value, node) +// } + JsValue::from_str("") } -lazy_static! { - static ref CACHE_JSON: Mutex> = Mutex::new(HashMap::new()); - static ref CACHE_JSON_IDX: Mutex = Mutex::new(0); -} +//lazy_static! { +// static ref CACHE_JSON: Mutex> = Mutex::new(HashMap::new()); +// static ref CACHE_JSON_IDX: Mutex = Mutex::new(0); +//} #[wasm_bindgen(js_name = allocJson)] pub extern fn alloc_json(js_value: JsValue) -> usize { - let result: result::Result = into_serde_json(&js_value); - match result { - Ok(json) => { - let mut map = CACHE_JSON.lock().unwrap(); - if map.len() >= std::u8::MAX as usize { - return 0; - } - - let mut idx = CACHE_JSON_IDX.lock().unwrap(); - *idx += 1; - map.insert(*idx, json.into()); - *idx - } - Err(e) => { - console::error_1(&e.into()); - 0 - } - } +// let result: result::Result = into_serde_json(&js_value); +// match result { +// Ok(json) => { +// let mut map = CACHE_JSON.lock().unwrap(); +// if map.len() >= std::u8::MAX as usize { +// return 0; +// } +// +// let mut idx = CACHE_JSON_IDX.lock().unwrap(); +// *idx += 1; +// map.insert(*idx, json.into()); +// *idx +// } +// Err(e) => { +// console::error_1(&e.into()); +// 0 +// } +// } + 0 } #[wasm_bindgen(js_name = deallocJson)] pub extern fn dealloc_json(ptr: usize) -> bool { - let mut map = CACHE_JSON.lock().unwrap(); - map.remove(&ptr).is_some() +// let mut map = CACHE_JSON.lock().unwrap(); +// map.remove(&ptr).is_some() + false } #[wasm_bindgen] @@ -139,32 +145,35 @@ pub fn compile(path: &str) -> JsValue { #[wasm_bindgen] pub fn selector(js_value: JsValue) -> JsValue { - let json = match js_value.as_f64() { - Some(val) => { - match CACHE_JSON.lock().unwrap().get(&(val as usize)) { - Some(json) => json.clone(), - _ => return JsValue::from_str("Invalid pointer") - } - } - _ => { - match into_serde_json::(&js_value) { - Ok(json) => json.into(), - Err(e) => return JsValue::from_str(e.as_str()) - } - } - }; +// let json = match js_value.as_f64() { +// Some(val) => { +// match CACHE_JSON.lock().unwrap().get(&(val as usize)) { +// Some(json) => json.clone(), +// _ => return JsValue::from_str("Invalid pointer") +// } +// } +// _ => { +// match into_serde_json::(&js_value) { +// Ok(json) => json.into(), +// 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 JsValue>); +// }; - let ret = cb.as_ref().clone(); - cb.forget(); - ret +// 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 JsValue>); +// +// let ret = cb.as_ref().clone(); +// cb.forget(); +// ret + + JsValue::from_str("") } #[wasm_bindgen]