diff --git a/README.md b/README.md index 0ad07c3..71e19b1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine writte - [Javascript - jsonpath.select(json: string|object, jsonpath: string)](#javascript---jsonpathselectjson-stringobject-jsonpath-string) - [Javascript - jsonpath.compile(jsonpath: string)](#javascript---jsonpathcompilejsonpath-string) - [Javascript - jsonpath.selector(json: string|object)](#javascript---jsonpathselectorjson-stringobject) -- [Javascript - allocJson, deallocJson (Webassembly Only)](#javascript---allocjson-deallocjson-webassembly-only) - [Javascript - Other Examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples) --- @@ -532,60 +531,4 @@ console.log( ); // => true, true -``` - -#### Javascript - allocJson, deallocJson (Webassembly Only) -wasm-bindgen은 Javascript와 Webassembly간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체는 Webassembly 영역에 생성해 두면 성능에 도움이 된다. - -Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, creating frequently used JSON objects in the WebAssembly area helps performance. - -```javascript -const jsonpath = require('jsonpath-wasm'); - -let jsonObj = { - "school": { - "friends": [ - {"name": "친구1", "age": 20}, - {"name": "친구2", "age": 20} - ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ] -}; - -// allocate jsonObj in webassembly -let ptr = jsonpath.allocJson(jsonObj); - -// `0` is invalid pointer -if(ptr == 0) { - console.error('invalid ptr'); -} - -let path = '$..friends[0]'; -let template = jsonpath.compile(path); -let selector = jsonpath.selector(jsonObj); -// create selector as pointer -let ptrSelector = jsonpath.selector(ptr); - -let ret1 = selector(path) -let ret2 = ptrSelector(path) -let ret3 = template(jsonObj); -// select as pointer -let ret4 = template(ptr); -let ret5 = jsonpath.select(jsonObj, path); -// select as pointer -let ret6 = jsonpath.select(ptr, path); - -console.log( - JSON.stringify(ret1) == JSON.stringify(ret2), - JSON.stringify(ret1) == JSON.stringify(ret3), - JSON.stringify(ret1) == JSON.stringify(ret4), - JSON.stringify(ret1) == JSON.stringify(ret5), - JSON.stringify(ret1) == JSON.stringify(ret6)); - -// => true true true true true - -jsonpath.deallocJson(ptr); -``` +``` \ No newline at end of file diff --git a/benches/bench.rs b/benches/bench.rs index 55fcb58..de51826 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -160,4 +160,14 @@ fn refval_copy(b: &mut Bencher) { } } }); +} + +#[bench] +fn value_clone(b: &mut Bencher) { + let json = get_json(); + b.iter(move || { + for _ in 1..100 { + let _ = json.clone(); + } + }); } \ No newline at end of file diff --git a/benches/bench_example.rs b/benches/bench_example.rs index d2e8322..1acf867 100644 --- a/benches/bench_example.rs +++ b/benches/bench_example.rs @@ -12,6 +12,7 @@ use std::io::Read; use serde_json::Value; use self::test::Bencher; +use jsonpath::ref_value::model::RefValueWrapper; fn read_json(path: &str) -> String { let mut f = std::fs::File::open(path).unwrap(); @@ -50,32 +51,70 @@ fn get_path(i: usize) -> &'static str { paths[i] } -macro_rules! example { +fn _as_value(b: &mut Bencher, index: usize) { + let json = get_json(); + b.iter(move || { + for _ in 1..100 { + let _ = jsonpath::select(&json, get_path(index)); + } + }); +} + +fn _as_ref_value(b: &mut Bencher, index: usize) { + let ref json = get_json(); + let rv: RefValueWrapper = json.into(); + b.iter(move || { + for _ in 1..100 { + let mut selector = jsonpath::Selector::new(); + let _ = selector.path(get_path(index)); + let _ = selector.value_from_ref_value(rv.clone()); + let _ = selector.select_as_value(); + } + }); +} + +macro_rules! example_val { ($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)); - } - }); - } + fn $name(b: &mut Bencher) { _as_value(b, $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); +macro_rules! example_val_ref { + ($name:ident, $i:expr) => { + #[bench] + fn $name(b: &mut Bencher) { _as_ref_value(b, $i); } + }; +} + +example_val!(example_val_0, 0); +example_val!(example_val_1, 1); +example_val!(example_val_2, 2); +example_val!(example_val_3, 3); +example_val!(example_val_4, 4); +example_val!(example_val_5, 5); +example_val!(example_val_6, 6); +example_val!(example_val_7, 7); +example_val!(example_val_8, 8); +example_val!(example_val_9, 9); +example_val!(example_val_10, 10); +example_val!(example_val_11, 11); +example_val!(example_val_12, 12); +example_val!(example_val_13, 13); +example_val!(example_val_14, 14); + +example_val_ref!(example_val_ref_0, 0); +example_val_ref!(example_val_ref_1, 1); +example_val_ref!(example_val_ref_2, 2); +example_val_ref!(example_val_ref_3, 3); +example_val_ref!(example_val_ref_4, 4); +example_val_ref!(example_val_ref_5, 5); +example_val_ref!(example_val_ref_6, 6); +example_val_ref!(example_val_ref_7, 7); +example_val_ref!(example_val_ref_8, 8); +example_val_ref!(example_val_ref_9, 9); +example_val_ref!(example_val_ref_10, 10); +example_val_ref!(example_val_ref_11, 11); +example_val_ref!(example_val_ref_12, 12); +example_val_ref!(example_val_ref_13, 13); +example_val_ref!(example_val_ref_14, 14); \ No newline at end of file diff --git a/benches/javascript/bench.js b/benches/javascript/bench.js index a4c7a0b..6537aca 100644 --- a/benches/javascript/bench.js +++ b/benches/javascript/bench.js @@ -92,45 +92,12 @@ function wasmCompile() { } } -function wasmCompileAlloc() { - let ptr = jpw.allocJson(getJson()); - if (ptr == 0) { - console.error('Invalid pointer'); - return; - } - - try { - let template = jpw.compile(path); - for (var i = 0; i < iter; i++) { - let _ = template(ptr); - } - } finally { - jpw.deallocJson(ptr); - } -} - function wasmSelect() { for (var i = 0; i < iter; i++) { let _ = jpw.select(getJson(), path); } } -function wasmSelectAlloc() { - let ptr = jpw.allocJson(getJson()); - if (ptr == 0) { - console.error('Invalid pointer'); - return; - } - - try { - for (var i = 0; i < iter; i++) { - let _ = jpw.select(ptr, path); - } - } finally { - jpw.deallocJson(ptr); - } -} - function wasmSelectorClass() { let selector = new jpw.Selector(); for (var i = 0; i < iter; i++) { diff --git a/src/filter/term.rs b/src/filter/term.rs index a5b8d03..476e29f 100644 --- a/src/filter/term.rs +++ b/src/filter/term.rs @@ -1,9 +1,6 @@ use super::cmp::*; use super::value_filter::ValueFilterKey; use super::value_manager::*; -use std::cell::RefCell; -use select::path_map::PathMap; -use std::sync::Arc; #[derive(Debug)] pub enum TermContext { @@ -55,7 +52,7 @@ impl TermContext { } } - fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType, path_map: Arc>) -> TermContext { + fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext { match self { TermContext::Constants(et) => { match other { @@ -70,7 +67,7 @@ impl TermContext { } } TermContext::Json(_, v) => { - TermContext::Json(None, ValueManager::new(v.get_val().clone(), false, path_map)) + TermContext::Json(None, ValueManager::new(v.get_val().clone(), false)) } } } @@ -83,7 +80,7 @@ impl TermContext { } } _ => { - TermContext::Json(None, ValueManager::new(v.get_val().clone(), false, path_map)) + TermContext::Json(None, ValueManager::new(v.get_val().clone(), false)) } } } @@ -120,12 +117,12 @@ impl TermContext { self.cmp(other, CmpLe, false) } - pub fn and(&mut self, other: &mut TermContext, path_map: Arc>) -> TermContext { - self.cmp_cond(other, CmpCondType::And, path_map) + pub fn and(&mut self, other: &mut TermContext) -> TermContext { + self.cmp_cond(other, CmpCondType::And) } - pub fn or(&mut self, other: &mut TermContext, path_map: Arc>) -> TermContext { - self.cmp_cond(other, CmpCondType::Or, path_map) + pub fn or(&mut self, other: &mut TermContext) -> TermContext { + self.cmp_cond(other, CmpCondType::Or) } } diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs index 839f4b8..33564f0 100644 --- a/src/filter/value_filter.rs +++ b/src/filter/value_filter.rs @@ -1,6 +1,4 @@ -use std::cell::RefCell; use std::ops::Deref; -use std::sync::Arc; use serde_json::Value; @@ -8,7 +6,6 @@ use filter::term::*; use filter::value_manager::*; use parser::parser::{FilterToken, NodeVisitor, ParseToken}; use ref_value::model::*; -use select::path_map::PathMap; #[derive(Debug, Clone)] pub enum ValueFilterKey { @@ -52,16 +49,14 @@ pub struct ValueFilter { value_mgr: ValueManager, last_key: Option, is_relative: bool, - path_map: Arc>, } impl ValueFilter { - pub fn new(v: RefValueWrapper, is_leaves: bool, is_relative: bool, path_map: Arc>) -> Self { + pub fn new(v: RefValueWrapper, is_leaves: bool, is_relative: bool) -> Self { ValueFilter { - value_mgr: ValueManager::new(v, is_leaves, path_map.clone()), + value_mgr: ValueManager::new(v, is_leaves), last_key: None, is_relative, - path_map, } } @@ -69,7 +64,7 @@ impl ValueFilter { let mut buf = Vec::new(); collect_all(key, &self.value_mgr.get_val(), &mut buf); trace!("step_leaves - {:?}", buf); - self.value_mgr = ValueManager::new(RefValue::Array(buf).into(), true, self.path_map.clone()); + self.value_mgr = ValueManager::new(RefValue::Array(buf).into(), true); } pub fn step_leaves_all(&mut self) -> &ValueManager { @@ -136,17 +131,15 @@ impl ValueFilter { pub struct JsonValueFilter { json: RefValueWrapper, - path_map: Arc>, filter_stack: Vec, token_stack: Vec, term_stack: Vec, } impl JsonValueFilter { - pub fn new(json: RefValueWrapper, path_map: Arc>) -> Self { + pub fn new(json: RefValueWrapper) -> Self { JsonValueFilter { json, - path_map, filter_stack: Vec::new(), token_stack: Vec::new(), term_stack: Vec::new(), @@ -164,7 +157,6 @@ impl JsonValueFilter { ValueFilter::new(vf.value_mgr.get_val().clone(), vf.value_mgr.is_leaves(), is_relative, - self.path_map.clone(), ) }) .and_then(|vf| { @@ -175,7 +167,6 @@ impl JsonValueFilter { self.json.clone(), false, is_relative, - self.path_map.clone(), ); self.filter_stack.push(vf); } @@ -187,7 +178,6 @@ impl JsonValueFilter { v, is_leaves, false, - self.path_map.clone(), )); return; } @@ -348,8 +338,8 @@ impl JsonValueFilter { 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()), + FilterToken::And => left.and(&mut right), + FilterToken::Or => left.or(&mut right), }; self.term_stack.push(tc); } diff --git a/src/filter/value_manager.rs b/src/filter/value_manager.rs index e0a7690..661a0dc 100644 --- a/src/filter/value_manager.rs +++ b/src/filter/value_manager.rs @@ -1,12 +1,9 @@ -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::*; @@ -176,13 +173,12 @@ 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 new(val: RefValueWrapper, is_leaves: bool) -> Self { + ValueManager { val, is_leaves } } pub fn is_leaves(&self) -> bool { @@ -226,16 +222,13 @@ impl ValueManager { } let ret = set.into_iter().collect(); - Self::new( - RefValue::Array(ret).into(), - false, - self.path_map.clone()) + Self::new(RefValue::Array(ret).into(), false) } _ => { if cmp_with_term(&self.val, et, &cmp, false, reverse) { - Self::new(self.val.clone(), false, self.path_map.clone()) + Self::new(self.val.clone(), false) } else { - Self::new(RefValue::Null.into(), false, self.path_map.clone()) + Self::new(RefValue::Null.into(), false) } } } @@ -427,7 +420,7 @@ impl ValueManager { } let vec = ret.into_iter().map(|v| v.clone()).collect(); - ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone()) + ValueManager::new(RefValue::Array(vec).into(), false) } pub fn intersect(&self, other: &Self) -> Self { @@ -450,7 +443,7 @@ impl ValueManager { } let vec = ret.into_iter().map(|v| v.clone()).collect(); - ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone()) + ValueManager::new(RefValue::Array(vec).into(), false) } pub fn union(&self, other: &Self) -> Self { @@ -478,7 +471,7 @@ impl ValueManager { } let vec = ret.into_iter().map(|v| v.clone()).collect(); - ValueManager::new(RefValue::Array(vec).into(), false, self.path_map.clone()) + ValueManager::new(RefValue::Array(vec).into(), false) } pub fn into_term(&self, key: &Option) -> TermContext { @@ -489,7 +482,7 @@ impl ValueManager { _ => TermContext::Json(match key { Some(vk) => Some(vk.clone()), _ => None - }, ValueManager::new(self.val.clone(), false, self.path_map.clone())) + }, ValueManager::new(self.val.clone(), false)) } } @@ -519,6 +512,6 @@ impl ValueManager { _ => self.val.clone() }; - ValueManager::new(v, false, self.path_map.clone()) + ValueManager::new(v, false) } } diff --git a/src/select/mod.rs b/src/select/mod.rs index 45c77d9..ac0856c 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -1,3 +1,2 @@ pub mod selector; -pub mod modifiable; -pub mod path_map; \ No newline at end of file +pub mod modifiable; \ No newline at end of file diff --git a/src/select/path_map.rs b/src/select/path_map.rs deleted file mode 100644 index 82154a0..0000000 --- a/src/select/path_map.rs +++ /dev/null @@ -1,53 +0,0 @@ -//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 index 2447ee3..fe759ab 100644 --- a/src/select/selector.rs +++ b/src/select/selector.rs @@ -7,9 +7,6 @@ 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. /// @@ -110,12 +107,11 @@ use std::cell::RefCell; 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())) } + Selector { node: None, value: None } } fn set_value(&mut self, value: RefValueWrapper) { @@ -157,8 +153,7 @@ impl Selector { fn jf(&self) -> result::Result { match &self.value { - Some(v) => Ok(JsonValueFilter::new(v.clone(), - self.path_builder.clone())), + Some(v) => Ok(JsonValueFilter::new(v.clone())), _ => return Err(SelectorErrorMessage::EmptyValue.to_string()) } } @@ -194,10 +189,6 @@ impl Selector { 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()) } @@ -212,7 +203,7 @@ impl Selector { match func((&self.select()?).into()).map(|ref v| v.into()) { Some(value) => { self.set_value(value) - }, + } _ => {} } Ok(self) diff --git a/tests/filter.rs b/tests/filter.rs index b9f22a3..99cee5e 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -8,19 +8,18 @@ use std::io::Read; use serde_json::Value; -use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter}; -use jsonpath::parser::parser::Parser; use jsonpath::Selector; +use jsonpath::filter::value_filter::ValueFilter; 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 selector(path: &str, file: &str) -> Selector { let string = read_json(file); @@ -37,53 +36,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() { diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index fbf78ad..db0d4c2 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -1,18 +1,14 @@ extern crate cfg_if; extern crate js_sys; extern crate jsonpath_lib as jsonpath; -#[macro_use] -extern crate lazy_static; extern crate serde; extern crate serde_json; extern crate wasm_bindgen; extern crate web_sys; -use std::collections::HashMap; use std::ops::Deref; use std::result; use std::result::Result; -use std::sync::{Mutex, Arc}; use cfg_if::cfg_if; use jsonpath::filter::value_filter::JsonValueFilter; @@ -23,8 +19,6 @@ 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")] { @@ -45,14 +39,13 @@ cfg_if! { } fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue { -// 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("") + let mut jf = JsonValueFilter::new(json); + 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)) + } } fn into_serde_json(js_value: &JsValue) -> Result @@ -80,51 +73,7 @@ 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) -// } - JsValue::from_str("") -} - -//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 -// } -// } - 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() - false + into_ref_value(&js_value, node) } #[wasm_bindgen] @@ -145,35 +94,22 @@ 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: RefValueWrapper = 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 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("") + let ret = cb.as_ref().clone(); + cb.forget(); + ret } #[wasm_bindgen] @@ -279,14 +215,4 @@ impl Selector { let v = self.selector.get().map_err(|e| JsValue::from_str(&e.to_string()))?; JsValue::from_serde(&v).map_err(|e| JsValue::from_str(&e.to_string())) } -} - -#[wasm_bindgen(catch)] -pub fn testa(js_value: JsValue, path: &str, iter: usize) -> result::Result<(), JsValue> { - for _ in 0..iter { - let mut parser = Parser::new(path); - let node = parser.compile().unwrap(); - into_ref_value(&js_value, node); - } - Ok(()) } \ No newline at end of file diff --git a/wasm/tests/web.rs b/wasm/tests/web.rs index 0dac354..a8ee5df 100644 --- a/wasm/tests/web.rs +++ b/wasm/tests/web.rs @@ -95,20 +95,6 @@ fn selector() { assert_eq!(json, target_json()); } -#[wasm_bindgen_test] -fn alloc_dealloc_json() { - let ptr = jsonpath::alloc_json(JsValue::from_str(json_str())); - assert_eq!(ptr > 0, true); - - let json: Value = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").into_serde().unwrap(); - assert_eq!(json, target_json()); - - assert_eq!(jsonpath::dealloc_json(ptr), true); - - let err = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").as_string().unwrap(); - assert_eq!(err, "Invalid pointer".to_string()); -} - #[wasm_bindgen_test] fn selector_struct() { let mut selector = jsonpath::Selector::new(); diff --git a/wasm/www_bench/index.js b/wasm/www_bench/index.js index 89810ed..535151a 100644 --- a/wasm/www_bench/index.js +++ b/wasm/www_bench/index.js @@ -61,9 +61,6 @@ let path = '$..book[?(@.price<30 && @.category=="fiction")]'; let template = jpw.compile(path); let selector = jpw.selector(json); -let ptr = jpw.allocJson(json); -if(ptr == 0) console.error('invalid ptr'); - let iterCount = 2000; run('jsonpath', iterCount, function() { jp.query(json, path) }) @@ -73,15 +70,9 @@ run('jsonpath', iterCount, function() { jp.query(json, path) }) .then(function() { return run('jsonpath-wasm- compile', iterCount, function() { template(json) }); }) - .then(function() { - return run('jsonpath-wasm- compile-alloc', iterCount, function() { template(ptr) }); - }) .then(function() { return run('jsonpath-wasm- select', iterCount, function() { jpw.select(json, path) }); }) - .then(function() { - return run('jsonpath-wasm- select-alloc', iterCount, function() { jpw.select(ptr, path) }); - }) .finally(function() { if(!jpw.deallocJson(ptr)) { console.error('fail to dealloc');