diff --git a/Cargo.toml b/Cargo.toml index 80354a4..3daccb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath_lib" -version = "0.1.13" +version = "0.2.0" authors = ["Changseok Han "] description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript also. - Webassembly Demo: https://freestrings.github.io/jsonpath" @@ -23,6 +23,7 @@ env_logger = "0.6.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["preserve_order"] } indexmap = "1.0.2" +array_tool = "~1.0.3" [dev-dependencies] bencher = "0.1.5" @@ -32,5 +33,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 de51826..9a7f78c 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,6 +1,5 @@ #![feature(test)] extern crate bencher; -extern crate indexmap; extern crate jsonpath_lib as jsonpath; extern crate serde; extern crate serde_json; @@ -8,13 +7,10 @@ extern crate test; use std::io::Read; -use serde::Serialize; use serde::Deserialize; use serde_json::Value; use self::test::Bencher; -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(); @@ -103,71 +99,7 @@ fn bench_select_as(b: &mut Bencher) { b.iter(move || { for _ in 1..100 { - let _: Book = jsonpath::select_as(&json, r#"$..book[?(@.price<30 && @.category=="fiction")][0]"#).unwrap(); - } - }); -} - -#[bench] -fn refval_de(b: &mut Bencher) { - let json = get_json(); - b.iter(move || { - for _ in 1..100 { - let _ = RefValue::deserialize(&json).unwrap(); - } - }); -} - -#[bench] -fn refval_se(b: &mut Bencher) { - let json = get_json(); - b.iter(move || { - for _ in 1..100 { - let _ = &json.serialize(RefValueSerializer).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(); - } - } - }); -} - -#[bench] -fn value_clone(b: &mut Bencher) { - let json = get_json(); - b.iter(move || { - for _ in 1..100 { - let _ = json.clone(); + let _: Vec = jsonpath::select_as(&json, r#"$..book[?(@.price<30 && @.category=="fiction")][0]"#).unwrap(); } }); } \ No newline at end of file diff --git a/benches/bench_example.rs b/benches/bench_example.rs index 1acf867..ad2ba62 100644 --- a/benches/bench_example.rs +++ b/benches/bench_example.rs @@ -1,7 +1,6 @@ #![feature(test)] extern crate bencher; -extern crate indexmap; extern crate jsonpath_lib as jsonpath; extern crate serde; extern crate serde_json; @@ -12,7 +11,6 @@ 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(); @@ -44,77 +42,46 @@ fn get_path(i: usize) -> &'static str { "$..book[-2:]", //9 "$..book[2:]", //10 "$..book[?(@.isbn)]", //11 - "$.store.book[?(@.price < 10)]", //12 + "$.store.book[?(@.price == 10)]", //12 "$..*", //13 - "$..book[ ?( (@.price < 13 || $.store.bicycle.price < @.price) && @.price <=10 ) ]" //14 + "$..book[ ?( (@.price < 13 || $.store.bicycle.price < @.price) && @.price <=10 ) ]", //14 + "$.store.book[?( (@.price < 10 || @.price > 10) && @.price > 10 )]" ]; paths[i] } -fn _as_value(b: &mut Bencher, index: usize) { +fn _selector(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(); + selector.value(&json); + let _ = selector.select(); } }); } -macro_rules! example_val { +macro_rules! selector { ($name:ident, $i:expr) => { #[bench] - fn $name(b: &mut Bencher) { _as_value(b, $i); } + fn $name(b: &mut Bencher) { _selector(b, $i); } }; } -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 +selector!(example0_1, 0); +selector!(example1_1, 1); +selector!(example2_1, 2); +selector!(example3_1, 3); +selector!(example4_1, 4); +selector!(example5_1, 5); +selector!(example6_1, 6); +selector!(example7_1, 7); +selector!(example8_1, 8); +selector!(example9_1, 9); +selector!(example_10_1, 10); +selector!(example_11_1, 11); +selector!(example_12_1, 12); +selector!(example_13_1, 13); +selector!(example_14_1, 14); +selector!(example_15_1, 15); \ No newline at end of file diff --git a/src/filter/cmp.rs b/src/filter/cmp.rs deleted file mode 100644 index a83ee16..0000000 --- a/src/filter/cmp.rs +++ /dev/null @@ -1,191 +0,0 @@ -#[derive(Debug)] -pub enum CmpType { - Eq, - Ne, - Gt, - Ge, - Lt, - Le, -} - -#[derive(Debug)] -pub enum CmpCondType { - And, - Or, -} - -pub trait PrivCmp { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool; - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool; - - fn cmp_string(&self, v1: &String, v2: &String) -> bool; -} - -pub trait IntoType { - fn into_type(&self) -> CmpType; -} - -pub struct CmpEq; - -impl PrivCmp for CmpEq { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 == v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 == v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 == v2 - } -} - -impl IntoType for CmpEq { - fn into_type(&self) -> CmpType { - CmpType::Eq - } -} - -pub struct CmpNe; - -impl PrivCmp for CmpNe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 != v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 != v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 != v2 - } -} - -impl IntoType for CmpNe { - fn into_type(&self) -> CmpType { - CmpType::Ne - } -} - -pub struct CmpGt; - -impl PrivCmp for CmpGt { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 > v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 > v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 > v2 - } -} - -impl IntoType for CmpGt { - fn into_type(&self) -> CmpType { - CmpType::Gt - } -} - -pub struct CmpGe; - -impl PrivCmp for CmpGe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 >= v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 >= v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 >= v2 - } -} - -impl IntoType for CmpGe { - fn into_type(&self) -> CmpType { - CmpType::Ge - } -} - -pub struct CmpLt; - -impl PrivCmp for CmpLt { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 < v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 < v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 < v2 - } -} - -impl IntoType for CmpLt { - fn into_type(&self) -> CmpType { - CmpType::Lt - } -} - -pub struct CmpLe; - -impl PrivCmp for CmpLe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - v1 <= v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 <= v2 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 <= v2 - } -} - -impl IntoType for CmpLe { - fn into_type(&self) -> CmpType { - CmpType::Le - } -} - -pub struct CmpAnd; - -impl PrivCmp for CmpAnd { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - *v1 && *v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 > &0_f64 && v2 > &0_f64 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - !v1.is_empty() && !v2.is_empty() - } -} - -pub struct CmpOr; - -impl PrivCmp for CmpOr { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - *v1 || *v2 - } - - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 > &0_f64 || v2 > &0_f64 - } - - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - !v1.is_empty() || !v2.is_empty() - } -} \ No newline at end of file diff --git a/src/filter/mod.rs b/src/filter/mod.rs deleted file mode 100644 index 472c2b9..0000000 --- a/src/filter/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod cmp; -mod term; -pub mod value_filter; -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 deleted file mode 100644 index 476e29f..0000000 --- a/src/filter/term.rs +++ /dev/null @@ -1,154 +0,0 @@ -use super::cmp::*; -use super::value_filter::ValueFilterKey; -use super::value_manager::*; - -#[derive(Debug)] -pub enum TermContext { - Constants(ExprTerm), - Json(Option, ValueManager), -} - -impl TermContext { - fn cmp(&mut self, other: &mut TermContext, cmp_fn: F, default: bool) -> TermContext { - match self { - TermContext::Constants(et) => { - match other { - TermContext::Constants(oet) => { - trace!("const-const"); - TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default))) - } - TermContext::Json(ref mut key, ref mut v) => { - trace!("const-json"); - TermContext::Json(None, v.get_compare_with(key, et, cmp_fn, true)) - } - } - } - TermContext::Json(key, v) => { - match other { - TermContext::Json(key_other, ov) => { - trace!("json-json"); - - fn is_json(t: &TermContext) -> bool { - match t { - TermContext::Json(_, _) => true, - _ => false - } - } - - let mut c = v.into_term(key); - let mut oc = ov.into_term(key_other); - if is_json(&c) && is_json(&oc) { - v.cmp(&ov, cmp_fn.into_type()) - } else { - c.cmp(&mut oc, cmp_fn, default) - } - } - TermContext::Constants(et) => { - trace!("json-const"); - TermContext::Json(None, v.get_compare_with(key, et, cmp_fn, false)) - } - } - } - } - } - - fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext { - match self { - TermContext::Constants(et) => { - match other { - TermContext::Constants(oet) => { - match cmp_cond_type { - CmpCondType::Or => { - TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpOr, false))) - } - CmpCondType::And => { - TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpAnd, false))) - } - } - } - TermContext::Json(_, v) => { - TermContext::Json(None, ValueManager::new(v.get_val().clone(), false)) - } - } - } - TermContext::Json(_, v) => { - match other { - TermContext::Json(_, ov) => { - match cmp_cond_type { - CmpCondType::Or => TermContext::Json(None, v.union(ov)), - CmpCondType::And => TermContext::Json(None, v.intersect(ov)), - } - } - _ => { - TermContext::Json(None, ValueManager::new(v.get_val().clone(), false)) - } - } - } - } - } - - pub fn eq(&mut self, other: &mut TermContext) -> TermContext { - trace!("eq"); - self.cmp(other, CmpEq, false) - } - - pub fn ne(&mut self, other: &mut TermContext) -> TermContext { - trace!("ne"); - self.cmp(other, CmpNe, true) - } - - pub fn gt(&mut self, other: &mut TermContext) -> TermContext { - trace!("gt"); - self.cmp(other, CmpGt, false) - } - - pub fn ge(&mut self, other: &mut TermContext) -> TermContext { - trace!("ge"); - self.cmp(other, CmpGe, false) - } - - pub fn lt(&mut self, other: &mut TermContext) -> TermContext { - trace!("lt"); - self.cmp(other, CmpLt, false) - } - - pub fn le(&mut self, other: &mut TermContext) -> TermContext { - trace!("le"); - self.cmp(other, CmpLe, false) - } - - pub fn and(&mut self, other: &mut TermContext) -> TermContext { - self.cmp_cond(other, CmpCondType::And) - } - - pub fn or(&mut self, other: &mut TermContext) -> TermContext { - self.cmp_cond(other, CmpCondType::Or) - } -} - - -#[derive(Debug)] -pub enum ExprTerm { - String(String), - Number(f64), - Bool(bool), -} - -impl ExprTerm { - fn cmp(&self, other: &ExprTerm, cmp_fn: F, default: bool) -> bool { - match self { - ExprTerm::Bool(v1) => match other { - ExprTerm::Bool(v2) => cmp_fn.cmp_bool(v1, v2), - _ => default - } - ExprTerm::Number(v1) => match other { - ExprTerm::Number(v2) => cmp_fn.cmp_f64(v1, v2), - _ => default - } - ExprTerm::String(v1) => match other { - ExprTerm::String(v2) => cmp_fn.cmp_string(v1, v2), - _ => default - } - } - } -} diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs deleted file mode 100644 index 33564f0..0000000 --- a/src/filter/value_filter.rs +++ /dev/null @@ -1,442 +0,0 @@ -use std::ops::Deref; - -use serde_json::Value; - -use filter::term::*; -use filter::value_manager::*; -use parser::parser::{FilterToken, NodeVisitor, ParseToken}; -use ref_value::model::*; - -#[derive(Debug, Clone)] -pub enum ValueFilterKey { - Num(usize), - String(String), - All, -} - -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.iter() { - buf.push(v.clone()); - } - } - - for v in vec { - collect_all(key, v, buf); - } - } - 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 map { - collect_all(key, v, buf); - } - } - _ => {} - } -} - -#[derive(Debug)] -pub struct ValueFilter { - value_mgr: ValueManager, - last_key: Option, - is_relative: bool, -} - -impl ValueFilter { - pub fn new(v: RefValueWrapper, is_leaves: bool, is_relative: bool) -> Self { - ValueFilter { - value_mgr: ValueManager::new(v, is_leaves), - last_key: None, - is_relative, - } - } - - fn step_leaves(&mut self, key: Option<&String>) { - 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); - } - - pub fn step_leaves_all(&mut self) -> &ValueManager { - debug!("step_leaves_all"); - self.step_leaves(None); - self.last_key = Some(ValueFilterKey::All); - &self.value_mgr - } - - 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) -> &ValueManager { - debug!("step_leaves_string"); - self.step_leaves(Some(key)); - self.last_key = Some(ValueFilterKey::String(key.clone())); - &self.value_mgr - } - - pub fn step_in_all(&mut self) -> &ValueManager { - debug!("step_in_all"); - self.last_key = Some(ValueFilterKey::All); - 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) -> &ValueManager { - debug!("step_in_num"); - trace!("step_in_num - before: leaves {}, filterMode {} - {:?}" - , self.value_mgr.is_leaves() - , self.is_relative - , self.value_mgr.get_val()); - - - 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) -> &ValueManager { - self.step_in_string(&key.to_string()) - } - - pub fn step_in_string(&mut self, key: &String) -> &ValueManager { - debug!("step_in_string"); - trace!("step_in_string - before: {},{},{:?}" - , self.value_mgr.is_leaves() - , self.is_relative - , self.value_mgr.get_val()); - - self.last_key = Some(ValueFilterKey::String(key.clone())); - self.value_mgr.replace(self.value_mgr.get_with_str(key, self.is_relative)); - trace!("step_in_string - after: {},{},{:?}" - , self.value_mgr.is_leaves() - , self.is_relative - , self.value_mgr.get_val()); - &self.value_mgr - } -} - -pub struct JsonValueFilter { - json: RefValueWrapper, - filter_stack: Vec, - token_stack: Vec, - term_stack: Vec, -} - -impl JsonValueFilter { - pub fn new(json: RefValueWrapper) -> Self { - JsonValueFilter { - json, - filter_stack: Vec::new(), - token_stack: Vec::new(), - term_stack: Vec::new(), - } - } - - fn is_peek_token_array(&self) -> bool { - if let Some(ParseToken::Array) = self.token_stack.last() { true } else { false } - } - - fn create_new_filter(&mut self, is_relative: bool) { - if is_relative { - self.filter_stack.last() - .map(|vf| { - ValueFilter::new(vf.value_mgr.get_val().clone(), - vf.value_mgr.is_leaves(), - is_relative, - ) - }) - .and_then(|vf| { - Some(self.filter_stack.push(vf)) - }); - } else { - let vf = ValueFilter::new( - self.json.clone(), - false, - is_relative, - ); - self.filter_stack.push(vf); - } - } - - 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, - )); - 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.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 { - 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) { - self.token_stack.pop(); - - match self.filter_stack.last_mut() { - Some(vf) => { - if let Some(vec) = vf.value_mgr.pick_with_nums(indices) { - vf.value_mgr.replace(vec); - } - } - _ => {} - } - } - - fn token_range(&mut self, from: Option, to: Option) { - self.token_stack.pop(); - - match self.filter_stack.last_mut() { - Some(ref mut vf) => { - if let Some(vec) = vf.value_mgr.range_with(from, to) { - vf.value_mgr.replace(vec); - } - } - _ => {} - } - } - - fn token_key(&mut self, key: String) { - match self.filter_stack.last_mut() { - Some(vf) => { - match self.token_stack.pop() { - Some(ParseToken::In) | Some(ParseToken::Array) => { - vf.step_in_string(&key); - } - Some(ParseToken::Leaves) => { - vf.step_leaves_string(&key); - } - _ => { - self.term_stack.push(TermContext::Constants(ExprTerm::String(key))); - } - } - } - _ => {} - } - } - - fn token_all(&mut self) { - match self.filter_stack.last_mut() { - Some(vf) => { - match self.token_stack.pop() { - Some(ParseToken::In) => { - vf.step_in_all(); - } - Some(ParseToken::Leaves) => { - vf.step_leaves_all(); - } - _ => {} - } - } - _ => {} - } - } - - fn token_end_array(&mut self) { - trace!("array_eof - term_stack: {:?}", self.term_stack); - trace!("array_eof - filter_stack: {:?}", self.filter_stack); - - match self.term_stack.pop() { - Some(TermContext::Constants(ExprTerm::Number(v))) => { - match self.filter_stack.last_mut() { - Some(vf) => { - vf.step_in_num(&v); - } - _ => {} - } - } - Some(TermContext::Constants(ExprTerm::Bool(false))) => { - self.append_to_current_filter(RefValue::Null.into(), false); - } - Some(TermContext::Json(_, vw)) => { - 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) => { - match vf.value_mgr.get_val().deref() { - RefValue::Null | RefValue::Bool(false) => { - self.append_to_current_filter(RefValue::Null.into(), vf.value_mgr.is_leaves()); - } - _ => { - self.append_to_current_filter(vf.value_mgr.get_val().clone(), vf.value_mgr.is_leaves()); - } - } - } - _ => {} - } - } - } - } - - fn token_op(&mut self, ft: &FilterToken) { - let right = self.term_stack.pop(); - let left = self.term_stack.pop(); - - trace!("left {:?}", left); - trace!("right {:?}", right); - - if left.is_some() && right.is_some() { - let mut left = left.unwrap(); - let mut right = right.unwrap(); - - let tc = match ft { - 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), - FilterToken::Or => left.or(&mut right), - }; - self.term_stack.push(tc); - } - - trace!("filter - {:?}", self.term_stack) - } -} - -impl NodeVisitor for JsonValueFilter { - fn visit_token(&mut self, token: ParseToken) { - debug!("visit_token: {:?}", token); - - match token { - ParseToken::Absolute - | ParseToken::Relative => { - if self.is_peek_token_array() { - self.token_stack.pop(); - } - self.create_new_filter(ParseToken::Relative == token); - } - ParseToken::In - | ParseToken::Leaves => { - self.token_stack.push(token); - } - ParseToken::Array => { - if let Some(ParseToken::Leaves) = self.token_stack.last() { - self.token_all(); - } - self.token_stack.push(token); - } - ParseToken::ArrayEof => { - self.token_end_array(); - } - ParseToken::All => { - self.token_all(); - } - ParseToken::Key(key) => { - self.token_key(key); - } - ParseToken::Filter(ref ft) => { - self.token_op(ft); - } - ParseToken::Number(v) => { - self.term_stack.push(TermContext::Constants(ExprTerm::Number(v))) - } - ParseToken::Range(from, to) => { - self.token_range(from, to); - } - ParseToken::Union(v) => { - self.token_union(v); - } - ParseToken::Eof => { - debug!("visit_token eof"); - } - } - } - - fn end_term(&mut self) { - debug!("end_term"); - - if let Some(ParseToken::Array) = self.token_stack.last() { - self.token_stack.pop(); - } - - trace!("end_term - term_stack {:?}", self.term_stack); - trace!("end_term - token_stack {:?}", self.token_stack); - trace!("end_term - filter_stack {:?}", self.filter_stack); - - 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.value_mgr)); - } - _ => {} - } - } - - if match self.token_stack.last() { - Some(ParseToken::Key(_)) - | Some(ParseToken::Number(_)) => true, - _ => false - } { - match self.token_stack.pop() { - Some(ParseToken::Key(ref v)) if v.eq_ignore_ascii_case("true") => { - self.term_stack.push(TermContext::Constants(ExprTerm::Bool(true))) - } - Some(ParseToken::Key(ref v)) if v.eq_ignore_ascii_case("false") => { - self.term_stack.push(TermContext::Constants(ExprTerm::Bool(false))) - } - Some(ParseToken::Key(v)) => { - self.term_stack.push(TermContext::Constants(ExprTerm::String(v))) - } - Some(ParseToken::Number(v)) => { - self.term_stack.push(TermContext::Constants(ExprTerm::Number(v))) - } - _ => {} - } - } - } -} diff --git a/src/filter/value_manager.rs b/src/filter/value_manager.rs deleted file mode 100644 index 661a0dc..0000000 --- a/src/filter/value_manager.rs +++ /dev/null @@ -1,517 +0,0 @@ -use std::ops::Deref; - -use indexmap::{IndexMap, IndexSet}; -use serde_json::Value; - -use ref_value::model::*; - -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, - is_leaves: bool, -} - -impl ValueManager { - pub fn new(val: RefValueWrapper, is_leaves: bool) -> Self { - ValueManager { val, is_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: &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) - } - _ => { - if cmp_with_term(&self.val, et, &cmp, false, reverse) { - Self::new(self.val.clone(), false) - } else { - Self::new(RefValue::Null.into(), false) - } - } - } - } - - 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) - } - - 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) - } - - 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) - } - - 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)) - } - } - - 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) - } -} diff --git a/src/lib.rs b/src/lib.rs index 5121a55..a26e723 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,187 +1,146 @@ -//! JsonPath implementation for Rust +//! JsonPath implementation written in Rust. //! //! # Example //! ``` -//! extern crate jsonpath_lib as jsonpath; -//! #[macro_use] extern crate serde_json; +//! extern crate jsonpath_lib as jsonpath; +//! #[macro_use] extern crate serde_json; +//! let json_obj = json!({ +//! "store": { +//! "book": [ +//! { +//! "category": "reference", +//! "author": "Nigel Rees", +//! "title": "Sayings of the Century", +//! "price": 8.95 +//! }, +//! { +//! "category": "fiction", +//! "author": "Evelyn Waugh", +//! "title": "Sword of Honour", +//! "price": 12.99 +//! }, +//! { +//! "category": "fiction", +//! "author": "Herman Melville", +//! "title": "Moby Dick", +//! "isbn": "0-553-21311-3", +//! "price": 8.99 +//! }, +//! { +//! "category": "fiction", +//! "author": "J. R. R. Tolkien", +//! "title": "The Lord of the Rings", +//! "isbn": "0-395-19395-8", +//! "price": 22.99 +//! } +//! ], +//! "bicycle": { +//! "color": "red", +//! "price": 19.95 +//! } +//! }, +//! "expensive": 10 +//! }); //! -//! let json_obj = json!({ -//! "store": { -//! "book": [ -//! { -//! "category": "reference", -//! "author": "Nigel Rees", -//! "title": "Sayings of the Century", -//! "price": 8.95 -//! }, -//! { -//! "category": "fiction", -//! "author": "Evelyn Waugh", -//! "title": "Sword of Honour", -//! "price": 12.99 -//! }, -//! { -//! "category": "fiction", -//! "author": "Herman Melville", -//! "title": "Moby Dick", -//! "isbn": "0-553-21311-3", -//! "price": 8.99 -//! }, -//! { -//! "category": "fiction", -//! "author": "J. R. R. Tolkien", -//! "title": "The Lord of the Rings", -//! "isbn": "0-395-19395-8", -//! "price": 22.99 -//! } -//! ], -//! "bicycle": { -//! "color": "red", -//! "price": 19.95 -//! } -//! }, -//! "expensive": 10 -//! }); +//! let mut selector = jsonpath::selector(&json_obj); //! -//! let mut selector = jsonpath::selector(&json_obj); +//! assert_eq!(selector("$.store.book[*].author").unwrap(), +//! vec![ +//! "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" +//! ]); //! -//! // -//! // $.store.book[*].author -//! // -//! let json = selector("$.store.book[*].author").unwrap(); -//! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); -//! assert_eq!(json, ret); +//! assert_eq!(selector("$..author").unwrap(), +//! vec![ +//! "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" +//! ]); //! -//! // -//! // $..author -//! // -//! let json = selector("$..author").unwrap(); -//! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); -//! assert_eq!(json, ret); +//! assert_eq!(selector("$.store.*").unwrap(), +//! vec![ +//! &json!([ +//! { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, +//! { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, +//! { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, +//! { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } +//! ]), +//! &json!({ "color": "red", "price": 19.95 }) +//! ]); //! -//! // -//! // $.store.* -//! // -//! let json = selector("$.store.*").unwrap(); -//! let ret = json!([ -//! [ -//! {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, -//! {"category" : "fiction", "author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}, -//! {"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, -//! {"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} -//! ], -//! {"color" : "red","price" : 19.95}, -//! ]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$.store..price").unwrap(), +//! vec![ +//! 8.95, 12.99, 8.99, 22.99, 19.95 +//! ]); //! -//! // -//! // $.store..price -//! // -//! let json = selector("$.store..price").unwrap(); -//! let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[2]").unwrap(), +//! vec![ +//! &json!({ +//! "category" : "fiction", +//! "author" : "Herman Melville", +//! "title" : "Moby Dick", +//! "isbn" : "0-553-21311-3", +//! "price" : 8.99 +//! }) +//! ]); //! -//! // -//! // $..book[2] -//! // -//! let json = selector("$..book[2]").unwrap(); -//! let ret = json!([{ -//! "category" : "fiction", -//! "author" : "Herman Melville", -//! "title" : "Moby Dick", -//! "isbn" : "0-553-21311-3", -//! "price" : 8.99 -//! }]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[-2]").unwrap(), +//! vec![ +//! &json!({ +//! "category" : "fiction", +//! "author" : "Herman Melville", +//! "title" : "Moby Dick", +//! "isbn" : "0-553-21311-3", +//! "price" : 8.99 +//! }) +//! ]); //! -//! // -//! // $..book[-2] -//! // -//! let json = selector("$..book[-2]").unwrap(); -//! let ret = json!([{ -//! "category" : "fiction", -//! "author" : "Herman Melville", -//! "title" : "Moby Dick", -//! "isbn" : "0-553-21311-3", -//! "price" : 8.99 -//! }]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[0,1]").unwrap(), +//! vec![ +//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), +//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) +//! ]); //! -//! // -//! // $..book[0,1] -//! // -//! let json = selector("$..book[0,1]").unwrap(); -//! let ret = json!([ -//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, -//! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99} -//! ]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[:2]").unwrap(), +//! vec![ +//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), +//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) +//! ]); //! -//! // -//! // $..book[:2] -//! // -//! let json = selector("$..book[:2]").unwrap(); -//! let ret = json!([ -//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, -//! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99} -//! ]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[:2]").unwrap(), +//! vec![ +//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), +//! &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) +//! ]); //! -//! // -//! // $..book[2:] -//! // -//! let json = selector("$..book[2:]").unwrap(); -//! let ret = json!([ -//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, -//! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} -//! ]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$..book[?(@.isbn)]").unwrap(), +//! vec![ +//! &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}), +//! &json!({"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}) +//! ]); //! -//! // -//! // $..book[?(@.isbn)] -//! // -//! let json = selector("$..book[?(@.isbn)]").unwrap(); -//! let ret = json!([ -//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, -//! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} -//! ]); -//! assert_eq!(ret, json); -//! -//! // -//! // $.store.book[?(@.price < 10)] -//! // -//! let json = selector("$.store.book[?(@.price < 10)]").unwrap(); -//! let ret = json!([ -//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, -//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99} -//! ]); -//! assert_eq!(ret, json); +//! assert_eq!(selector("$.store.book[?(@.price < 10)]").unwrap(), +//! vec![ +//! &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), +//! &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}) +//! ]); //! ``` - +extern crate array_tool; extern crate core; extern crate env_logger; extern crate indexmap; #[macro_use] extern crate log; -#[macro_use] extern crate serde; extern crate serde_json; -use core::borrow::BorrowMut; -use std::result; - use serde_json::Value; -pub use select::selector::Selector; +#[doc(hidden)] +mod parser; +#[doc(hidden)] +mod select; -#[doc(hidden)] -pub mod parser; -#[doc(hidden)] -pub mod filter; -#[doc(hidden)] -pub mod ref_value; -#[doc(hidden)] -pub mod select; +pub use select::Selector; +pub use select::JsonPathError; +pub use parser::parser::Parser; /// It is a high-order function. it compile a JsonPath and then returns a function. this return-function can be reused for different JsonObjects. /// @@ -192,32 +151,34 @@ pub mod select; /// let mut template = jsonpath::compile("$..friends[0]"); /// /// let json_obj = json!({ -/// "school": { -/// "friends": [ -/// {"name": "친구1", "age": 20}, -/// {"name": "친구2", "age": 20} -/// ] -/// }, -/// "friends": [ -/// {"name": "친구3", "age": 30}, -/// {"name": "친구4"} +/// "school": { +/// "friends": [ +/// {"name": "친구1", "age": 20}, +/// {"name": "친구2", "age": 20} +/// ] +/// }, +/// "friends": [ +/// {"name": "친구3", "age": 30}, +/// {"name": "친구4"} /// ]}); /// /// let json = template(&json_obj).unwrap(); -/// let ret = json!([ -/// {"name": "친구3", "age": 30}, -/// {"name": "친구1", "age": 20} +/// +/// assert_eq!(json, vec![ +/// &json!({"name": "친구3", "age": 30}), +/// &json!({"name": "친구1", "age": 20}) /// ]); -/// assert_eq!(json, ret); /// ``` -pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> result::Result + 'a { - let mut selector = Selector::new(); - let _ = selector.path(path); - let mut selector = Box::new(selector); +pub fn compile(path: &str) -> impl FnMut(&Value) -> Result, JsonPathError> { + let mut parser = Parser::new(path); + let node = parser.compile(); move |json| { - let s: &mut Selector = selector.borrow_mut(); - let _ = s.value(&json); - s.select_as_value() + let mut selector = Selector::new(); + match &node { + Ok(node) => selector.compiled_path(node.clone()), + Err(e) => return Err(JsonPathError::Path(e.clone())) + }; + selector.value(json).select() } } @@ -228,40 +189,38 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> result::Result(json: &Value) -> impl FnMut(&'a str) -> result::Result { +pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result, JsonPathError> { let mut selector = Selector::new(); - let _ = selector.value(json.into()); - let mut selector = Box::new(selector); - move |path: &'a str| { - let s: &mut Selector = selector.borrow_mut(); - s.path(path)?.select_as_value() + let _ = selector.value(json); + move |path: &str| { + selector.path(path)?.reset_value().select() } } @@ -275,26 +234,27 @@ pub fn selector<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result, /// } /// -/// let mut selector = jsonpath::selector_as::>(&json_obj); +/// let mut selector = jsonpath::selector_as::(&json_obj); /// /// let json = selector("$..friends[0]").unwrap(); +/// /// let ret = vec!( /// Friend { name: "친구3".to_string(), age: Some(30) }, /// Friend { name: "친구1".to_string(), age: Some(20) } @@ -302,25 +262,22 @@ pub fn selector<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result(json: &Value) -> impl FnMut(&str) -> result::Result { +pub fn selector_as(json: &Value) -> impl FnMut(&str) -> Result, JsonPathError> + '_ { let mut selector = Selector::new(); - let _ = selector.value(json.into()); + let _ = selector.value(json); move |path: &str| { - selector.path(path)?.select_as() + selector.path(path)?.reset_value().select_as() } } -#[deprecated(since = "0.1.4", note = "Please use the selector function instead")] -pub fn reader<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result { - selector(json) -} - /// This function compile a jsonpath everytime and it convert `serde_json's Value` to `jsonpath's RefValue` everytime and then it return a `serde_json::value::Value`. /// /// ```rust @@ -328,38 +285,26 @@ pub fn reader<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result result::Result { - let mut selector = Selector::new(); - selector.path(path)?.value(json)?.select_as_value() -} - -#[deprecated(since = "0.1.4", note = "Please use the select function instead")] -pub fn read(json: &Value, path: &str) -> result::Result { - select(json, path) -} - -#[deprecated(since = "0.1.7", note = "Please use the select_as_str function instead")] -pub fn select_str(json: &str, path: &str) -> result::Result { - select_as_str(json, path) +pub fn select<'a>(json: &'a Value, path: &'a str) -> Result, JsonPathError> { + Selector::new().path(path)?.value(json).select() } /// This function compile a jsonpath everytime and it convert `&str` to `jsonpath's RefValue` everytime and then it return a json string. @@ -385,11 +330,10 @@ pub fn select_str(json: &str, path: &str) -> result::Result { /// /// assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#); /// ``` -pub fn select_as_str(json: &str, path: &str) -> result::Result { - Selector::new() - .path(path)? - .value_from_str(json)? - .select_as_str() +pub fn select_as_str(json_str: &str, path: &str) -> Result { + let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?; + let ret = Selector::new().path(path)?.value(&json).select()?; + serde_json::to_string(&ret).map_err(|e| JsonPathError::Serde(e.to_string())) } /// This function compile a jsonpath everytime and it convert `&str` to `jsonpath's RefValue` everytime and then it return a deserialized-instance of type `T`. @@ -408,7 +352,7 @@ pub fn select_as_str(json: &str, path: &str) -> result::Result { /// phones: Vec, /// } /// -/// let ret: Person = jsonpath::select_as(r#" +/// let ret: Vec = jsonpath::select_as(r#" /// { /// "person": /// { @@ -428,11 +372,9 @@ pub fn select_as_str(json: &str, path: &str) -> result::Result { /// phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], /// }; /// -/// assert_eq!(person, ret); +/// assert_eq!(ret[0], person); /// ``` -pub fn select_as(json: &str, path: &str) -> result::Result { - Selector::new() - .path(path)? - .value_from_str(json)? - .select_as() +pub fn select_as(json_str: &str, path: &str) -> Result, JsonPathError> { + let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?; + Selector::new().path(path)?.value(&json).select_as() } \ No newline at end of file diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 331b73a..bce22d6 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,3 +1,525 @@ mod path_reader; -pub mod tokenizer; -pub mod parser; \ No newline at end of file +pub(crate) mod tokenizer; +pub mod parser; + +#[cfg(test)] +mod parser_tests { + use parser::parser::{ParseToken, Parser, NodeVisitor, FilterToken}; + + struct NodeVisitorTestImpl<'a> { + input: &'a str, + stack: Vec, + } + + impl<'a> NodeVisitorTestImpl<'a> { + fn new(input: &'a str) -> Self { + NodeVisitorTestImpl { input, stack: Vec::new() } + } + + fn start(&mut self) -> Result, String> { + let mut parser = Parser::new(self.input); + let node = parser.compile()?; + self.visit(&node); + Ok(self.stack.split_off(0)) + } + } + + impl<'a> NodeVisitor for NodeVisitorTestImpl<'a> { + fn visit_token(&mut self, token: &ParseToken) { + self.stack.push(token.clone()); + } + } + + fn setup() { + let _ = env_logger::try_init(); + } + + fn run(input: &str) -> Result, String> { + let mut interpreter = NodeVisitorTestImpl::new(input); + interpreter.start() + } + + #[test] + fn parse_path() { + setup(); + + assert_eq!(run("$.aa"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("aa".to_owned()) + ])); + + assert_eq!(run("$.00.a"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("00".to_owned()), + ParseToken::In, + ParseToken::Key("a".to_owned()) + ])); + + assert_eq!(run("$.00.韓창.seok"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("00".to_owned()), + ParseToken::In, + ParseToken::Key("韓창".to_owned()), + ParseToken::In, + ParseToken::Key("seok".to_owned()) + ])); + + assert_eq!(run("$.*"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::All + ])); + + assert_eq!(run("$..*"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Leaves, + ParseToken::All + ])); + + assert_eq!(run("$..[0]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Leaves, + ParseToken::Array, + ParseToken::Number(0.0), + ParseToken::ArrayEof + ])); + + match run("$.") { + Ok(_) => panic!(), + _ => {} + } + + match run("$..") { + Ok(_) => panic!(), + _ => {} + } + + match run("$. a") { + Ok(_) => panic!(), + _ => {} + } + } + + #[test] + fn parse_array_sytax() { + setup(); + + assert_eq!(run("$.book[?(@.isbn)]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("book".to_string()), + ParseToken::Array, + ParseToken::Relative, + ParseToken::In, + ParseToken::Key("isbn".to_string()), + ParseToken::ArrayEof + ])); + + // + // Array도 컨텍스트 In으로 간주 할거라서 중첩되면 하나만 + // + assert_eq!(run("$.[*]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[*]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[*].가"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof, + ParseToken::In, ParseToken::Key("가".to_owned()) + ])); + + assert_eq!(run("$.a[0][1]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Number(0_f64), + ParseToken::ArrayEof, + ParseToken::Array, + ParseToken::Number(1_f64), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[1,2]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Union(vec![1, 2]), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[10:]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Range(Some(10), None), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[:11]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Range(None, Some(11)), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[-12:13]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Range(Some(-12), Some(13)), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[?(1>2)]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Greater), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[?($.b>3)]"), Ok(vec![ + ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Array, + ParseToken::Absolute, ParseToken::In, ParseToken::Key("b".to_owned()), ParseToken::Number(3_f64), ParseToken::Filter(FilterToken::Greater), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$[?($.c>@.d && 1==2)]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Absolute, ParseToken::In, ParseToken::Key("c".to_owned()), + ParseToken::Relative, ParseToken::In, ParseToken::Key("d".to_owned()), + ParseToken::Filter(FilterToken::Greater), + ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Equal), + ParseToken::Filter(FilterToken::And), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$[?($.c>@.d&&(1==2||3>=4))]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Absolute, ParseToken::In, ParseToken::Key("c".to_owned()), + ParseToken::Relative, ParseToken::In, ParseToken::Key("d".to_owned()), + ParseToken::Filter(FilterToken::Greater), + ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Equal), + ParseToken::Number(3_f64), ParseToken::Number(4_f64), ParseToken::Filter(FilterToken::GreaterOrEqual), + ParseToken::Filter(FilterToken::Or), + ParseToken::Filter(FilterToken::And), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$[?(@.a<@.b)]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Relative, ParseToken::In, ParseToken::Key("a".to_owned()), + ParseToken::Relative, ParseToken::In, ParseToken::Key("b".to_owned()), + ParseToken::Filter(FilterToken::Little), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$[*][*][*]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof, + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof, + ParseToken::Array, + ParseToken::All, + ParseToken::ArrayEof + ])); + + assert_eq!(run("$['a']['bb']"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Key("a".to_string()), + ParseToken::ArrayEof, + ParseToken::Array, + ParseToken::Key("bb".to_string()), + ParseToken::ArrayEof + ])); + + assert_eq!(run("$.a[?(@.e==true)]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("a".to_string()), + ParseToken::Array, + ParseToken::Relative, + ParseToken::In, + ParseToken::Key("e".to_string()), + ParseToken::Bool(true), + ParseToken::Filter(FilterToken::Equal), + ParseToken::ArrayEof + ])); + + match run("$[") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[a]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?($.a)]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?(@.a > @.b]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?(@.a < @.b&&(@.c < @.d)]") { + Ok(_) => panic!(), + _ => {} + } + } + + #[test] + fn parse_array_float() { + setup(); + + assert_eq!(run("$[?(1.1<2.1)]"), Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Number(1.1), ParseToken::Number(2.1), ParseToken::Filter(FilterToken::Little), + ParseToken::ArrayEof + ])); + + match run("$[1.1]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?(1.1<.2)]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?(1.1<2.)]") { + Ok(_) => panic!(), + _ => {} + } + + match run("$[?(1.1<2.a)]") { + Ok(_) => panic!(), + _ => {} + } + } +} + +#[cfg(test)] +mod tokenizer_tests { + use parser::tokenizer::{Token, TokenError, Tokenizer, PreloadedTokenizer}; + + fn collect_token(input: &str) -> (Vec, Option) { + let mut tokenizer = Tokenizer::new(input); + let mut vec = vec![]; + loop { + match tokenizer.next_token() { + Ok(t) => vec.push(t), + Err(e) => return (vec, Some(e)), + } + } + } + + fn run(input: &str, expected: (Vec, Option)) { + let (vec, err) = collect_token(input.clone()); + assert_eq!((vec, err), expected, "\"{}\"", input); + } + + #[test] + fn peek() { + let mut tokenizer = PreloadedTokenizer::new("$.a"); + match tokenizer.next_token() { + Ok(t) => assert_eq!(Token::Absolute(0), t), + _ => panic!() + } + + match tokenizer.peek_token() { + Ok(t) => assert_eq!(&Token::Dot(1), t), + _ => panic!() + } + + match tokenizer.peek_token() { + Ok(t) => assert_eq!(&Token::Dot(1), t), + _ => panic!() + } + + match tokenizer.next_token() { + Ok(t) => assert_eq!(Token::Dot(1), t), + _ => panic!() + } + } + + #[test] + fn token() { + run("$.01.a", + ( + vec![ + Token::Absolute(0), + Token::Dot(1), + Token::Key(2, "01".to_string()), + Token::Dot(4), + Token::Key(5, "a".to_string()) + ] + , Some(TokenError::Eof) + )); + + run("$. []", + ( + vec![ + Token::Absolute(0), + Token::Dot(1), + Token::Whitespace(2, 2), + Token::OpenArray(5), + Token::CloseArray(6) + ] + , Some(TokenError::Eof) + )); + + run("$..", + ( + vec![ + Token::Absolute(0), + Token::Dot(1), + Token::Dot(2), + ] + , Some(TokenError::Eof) + )); + + run("$..ab", + ( + vec![ + Token::Absolute(0), + Token::Dot(1), + Token::Dot(2), + Token::Key(3, "ab".to_string()) + ] + , Some(TokenError::Eof) + )); + + run("$..가 [", + ( + vec![ + Token::Absolute(0), + Token::Dot(1), + Token::Dot(2), + Token::Key(3, "가".to_string()), + Token::Whitespace(6, 0), + Token::OpenArray(7), + ] + , Some(TokenError::Eof) + )); + + run("[-1, 2 ]", + ( + vec![ + Token::OpenArray(0), + Token::Key(1, "-1".to_string()), + Token::Comma(3), + Token::Whitespace(4, 0), + Token::Key(5, "2".to_string()), + Token::Whitespace(6, 0), + Token::CloseArray(7), + ] + , Some(TokenError::Eof) + )); + + run("[ 1 2 , 3 \"abc\" : -10 ]", + ( + vec![ + Token::OpenArray(0), + Token::Whitespace(1, 0), + Token::Key(2, "1".to_string()), + Token::Whitespace(3, 0), + Token::Key(4, "2".to_string()), + Token::Whitespace(5, 0), + Token::Comma(6), + Token::Whitespace(7, 0), + Token::Key(8, "3".to_string()), + Token::Whitespace(9, 0), + Token::DoubleQuoted(10, "abc".to_string()), + Token::Whitespace(15, 0), + Token::Split(16), + Token::Whitespace(17, 0), + Token::Key(18, "-10".to_string()), + Token::Whitespace(21, 0), + Token::CloseArray(22), + ] + , Some(TokenError::Eof) + )); + + run("?(@.a가 <41.01)", + ( + vec![ + Token::Question(0), + Token::OpenParenthesis(1), + Token::At(2), + Token::Dot(3), + Token::Key(4, "a가".to_string()), + Token::Whitespace(8, 0), + Token::Little(9), + Token::Key(10, "41".to_string()), + Token::Dot(12), + Token::Key(13, "01".to_string()), + Token::CloseParenthesis(15), + ] + , Some(TokenError::Eof) + )); + + run("?(@.a <4a.01)", + ( + vec![ + Token::Question(0), + Token::OpenParenthesis(1), + Token::At(2), + Token::Dot(3), + Token::Key(4, "a".to_string()), + Token::Whitespace(5, 0), + Token::Little(6), + Token::Key(7, "4a".to_string()), + Token::Dot(9), + Token::Key(10, "01".to_string()), + Token::CloseParenthesis(12), + ] + , Some(TokenError::Eof) + )); + + run("?($.c>@.d)", ( + vec![ + Token::Question(0), + Token::OpenParenthesis(1), + Token::Absolute(2), + Token::Dot(3), + Token::Key(4, "c".to_string()), + Token::Greater(5), + Token::At(6), + Token::Dot(7), + Token::Key(8, "d".to_string()), + Token::CloseParenthesis(9) + ] + , Some(TokenError::Eof) + )); + } +} \ No newline at end of file diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 7b3432c..60318ce 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,5 +1,3 @@ -use std::result::Result; - use super::tokenizer::*; const DUMMY: usize = 0; @@ -7,7 +5,6 @@ const DUMMY: usize = 0; type ParseResult = Result; mod utils { - pub fn string_to_isize(string: &String, msg_handler: F) -> Result where F: Fn() -> String { match string.as_str().parse::() { @@ -52,6 +49,8 @@ pub enum ParseToken { Number(f64), + Bool(bool), + Eof, } @@ -87,12 +86,6 @@ impl<'a> Parser<'a> { Ok(self.json_path()?) } - pub fn parse(&mut self, visitor: &mut V) -> ParseResult<()> { - let node = self.json_path()?; - visitor.visit(node); - Ok(()) - } - fn json_path(&mut self) -> ParseResult { debug!("#json_path"); match self.tokenizer.next_token() { @@ -235,6 +228,18 @@ impl<'a> Parser<'a> { } } + fn boolean(&mut self) -> ParseResult { + debug!("#boolean"); + match self.tokenizer.next_token() { + Ok(Token::Key(_, v)) => { + Ok(self.node(ParseToken::Bool(v.eq_ignore_ascii_case("true")))) + } + _ => { + Err(self.tokenizer.err_msg()) + } + } + } + fn array_quota_value(&mut self) -> ParseResult { debug!("#array_quota_value"); match self.tokenizer.next_token() { @@ -554,8 +559,14 @@ impl<'a> Parser<'a> { | Ok(Token::SingleQuoted(_, _)) => { self.array_quota_value() } - Ok(Token::Key(_, _)) => { - self.term_num() + Ok(Token::Key(_, k)) => { + match k.chars().next() { + Some(ch) => match ch { + '-' | '0'...'9' => self.term_num(), + _ => self.boolean() + } + _ => Err(self.tokenizer.err_msg()) + } } _ => { Err(self.tokenizer.err_msg()) @@ -629,49 +640,81 @@ impl<'a> Parser<'a> { } pub trait NodeVisitor { - fn visit(&mut self, node: Node) { - match node.token { + fn visit(&mut self, node: &Node) { + match &node.token { ParseToken::Absolute | ParseToken::Relative | ParseToken::All - | ParseToken::Key(_) => { - self.visit_token(node.token); + | ParseToken::Key(_) + | ParseToken::Range(_, _) + | ParseToken::Union(_) + | ParseToken::Number(_) + | ParseToken::Bool(_) => { + self.visit_token(&node.token); } ParseToken::In | ParseToken::Leaves => { - node.left.map(|n| self.visit(*n)); - self.visit_token(node.token); - node.right.map(|n| self.visit(*n)); - } - | ParseToken::Range(_, _) - | ParseToken::Union(_) - | ParseToken::Number(_) => { - self.visit_token(node.token); - } + match &node.left { + Some(n) => self.visit(&*n), + _ => {} + } - | ParseToken::Array => { - node.left.map(|n| self.visit(*n)); - self.visit_token(node.token); - node.right.map(|n| self.visit(*n)); - self.visit_token(ParseToken::ArrayEof); + self.visit_token(&node.token); + + match &node.right { + Some(n) => self.visit(&*n), + _ => {} + } + } + ParseToken::Array => { + match &node.left { + Some(n) => self.visit(&*n), + _ => {} + } + + self.visit_token(&node.token); + + match &node.right { + Some(n) => self.visit(&*n), + _ => {} + } + self.visit_token(&ParseToken::ArrayEof); } ParseToken::Filter(FilterToken::And) | ParseToken::Filter(FilterToken::Or) => { - node.left.map(|n| self.visit(*n)); - node.right.map(|n| self.visit(*n)); - self.visit_token(node.token); + match &node.left { + Some(n) => self.visit(&*n), + _ => {} + } + + match &node.right { + Some(n) => self.visit(&*n), + _ => {} + } + + self.visit_token(&node.token); } ParseToken::Filter(_) => { - node.left.map(|n| self.visit(*n)); + match &node.left { + Some(n) => self.visit(&*n), + _ => {} + } + self.end_term(); - node.right.map(|n| self.visit(*n)); + + match &node.right { + Some(n) => self.visit(&*n), + _ => {} + } + self.end_term(); - self.visit_token(node.token); + + self.visit_token(&node.token); } _ => {} } } - fn visit_token(&mut self, token: ParseToken); + fn visit_token(&mut self, token: &ParseToken); fn end_term(&mut self) {} } \ No newline at end of file diff --git a/src/ref_value/de.rs b/src/ref_value/de.rs deleted file mode 100644 index a5765ca..0000000 --- a/src/ref_value/de.rs +++ /dev/null @@ -1,1058 +0,0 @@ -use std::borrow::Cow; -use std::fmt; -use std::ops::Deref; -use std::result::Result; -use std::vec; - -use indexmap::IndexMap; -use serde::{self, Deserialize, Deserializer}; -use serde::de::{DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess, Visitor}; -use serde_json::Value; - -use super::model::*; -use super::serde_error::SerdeError; - -/// -/// see `serde_json/value/de.rs` -/// - -macro_rules! deserialize_prim_number { - ($method:ident) => { - fn $method(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Number(ref n) => { - match n.deserialize_any(visitor) { - Ok(v) => Ok(v), - Err(e) => Err(SerdeError::new(format!("{:?}", e))) - } - } - _ => Err(SerdeError::from_str("invalid type")), - } - } - } -} - -impl<'de> Deserialize<'de> for RefValue { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct RefValueVisitor {} - - impl<'de> Visitor<'de> for RefValueVisitor { - type Value = RefValue; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("any valid JSON value") - } - - #[inline] - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, { - Ok(RefValue::Bool(v)) - } - - #[inline] - fn visit_i64(self, v: i64) -> Result - where - E: serde::de::Error, { - Ok(RefValue::Number(v.into())) - } - - #[inline] - fn visit_u64(self, v: u64) -> Result - where - E: serde::de::Error, { - Ok(RefValue::Number(v.into())) - } - - #[inline] - fn visit_f64(self, v: f64) -> Result - where - E: serde::de::Error, { - let n: Value = v.into(); - if let Value::Number(n) = n { - Ok(RefValue::Number(n)) - } else { - unreachable!() - } - } - - #[inline] - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, { - self.visit_string(String::from(v)) - } - - #[inline] - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, { - Ok(RefValue::String(v)) - } - - #[inline] - fn visit_none(self) -> Result - where - E: serde::de::Error, { - Ok(RefValue::Null) - } - - #[inline] - fn visit_some(self, deserializer: D) -> Result where - D: Deserializer<'de>, { - Deserialize::deserialize(deserializer) - } - - #[inline] - fn visit_unit(self) -> Result - where - E: serde::de::Error, { - Ok(RefValue::Null) - } - - #[inline] - fn visit_seq(self, mut visitor: A) -> Result - where - A: SeqAccess<'de>, { - let mut vec = Vec::new(); - - while let Some(elem) = visitor.next_element()? { - let e: RefValue = elem; - let v: RefValueWrapper = e.into(); - vec.push(v); - } - - Ok(RefValue::Array(vec)) - } - - fn visit_map(self, mut visitor: A) -> Result - where - A: MapAccess<'de>, { - let mut values = IndexMap::new(); - match visitor.next_key() { - Ok(Some(first_key)) => { - let next: RefValue = visitor.next_value()?; - values.insert(first_key, next.into()); - while let Some((k, v)) = visitor.next_entry()? { - let value: RefValue = v; - values.insert(k, value.into()); - } - Ok(RefValue::Object(values)) - } - _ => Ok(RefValue::Object(IndexMap::new())), - } - } - } - - deserializer.deserialize_any(RefValueVisitor {}) - } -} - -fn visit_array<'de, V>(array: Vec, visitor: V) -> Result - where - V: Visitor<'de>, -{ - let mut deserializer = SeqDeserializer::new(array); - let seq = visitor.visit_seq(&mut deserializer)?; - let remaining = deserializer.iter.len(); - if remaining == 0 { - Ok(seq) - } else { - Err(SerdeError::from_str("fewer elements in array")) - } -} - -fn visit_object<'de, V>(object: IndexMap, visitor: V) -> Result - where - V: Visitor<'de>, -{ - let mut deserializer = MapDeserializer::new(object); - let map = visitor.visit_map(&mut deserializer)?; - let remaining = deserializer.iter.len(); - if remaining == 0 { - Ok(map) - } else { - Err(SerdeError::from_str("fewer elements in map")) - } -} - -fn to_vec(vec: &Vec) -> Vec { - vec.iter().map(|v| v.clone()).collect() -} - -fn to_map(object: &IndexMap) -> IndexMap { - let mut map = IndexMap::new(); - for (k, v) in object { - map.insert(k.to_string(), v.clone()); - } - map -} - -impl<'de> serde::Deserializer<'de> for RefValue { - type Error = SerdeError; - - #[inline] - fn deserialize_any(self, visitor: V) -> Result where - V: Visitor<'de> { - match self { - RefValue::Null => visitor.visit_unit(), - RefValue::Bool(v) => visitor.visit_bool(v), - RefValue::Number(n) => { - n.deserialize_any(visitor).map_err(|e| SerdeError::new(format!("{:?}", e))) - } - RefValue::String(v) => visitor.visit_string(v), - RefValue::Array(array) => visit_array(array, visitor), - RefValue::Object(object) => visit_object(object, visitor) - } - } - - deserialize_prim_number!(deserialize_i8); - deserialize_prim_number!(deserialize_i16); - deserialize_prim_number!(deserialize_i32); - deserialize_prim_number!(deserialize_i64); - deserialize_prim_number!(deserialize_u8); - deserialize_prim_number!(deserialize_u16); - deserialize_prim_number!(deserialize_u32); - deserialize_prim_number!(deserialize_u64); - deserialize_prim_number!(deserialize_f32); - deserialize_prim_number!(deserialize_f64); - - #[inline] - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Null => visitor.visit_none(), - _ => visitor.visit_some(self), - } - } - - #[inline] - fn deserialize_enum( - self, - _name: &str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let (variant, value) = match self { - RefValue::Object(value) => { - let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(SerdeError::from_str("map with a single key")); - } - }; - if iter.next().is_some() { - return Err(SerdeError::from_str("map with a single key")); - } - (variant, Some(value)) - } - RefValue::String(variant) => (variant, None), - _ => { - return Err(SerdeError::from_str("string or map")); - } - }; - - visitor.visit_enum(EnumDeserializer { - variant: variant, - value: value, - }) - } - - #[inline] - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let _ = name; - visitor.visit_newtype_struct(self) - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Bool(v) => visitor.visit_bool(v), - _ => Err(SerdeError::from_str("invalid type: bool")), - } - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::String(v) => visitor.visit_string(v), - _ => Err(SerdeError::from_str("invalid type: string")), - } - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_byte_buf(visitor) - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::String(v) => visitor.visit_string(v), - RefValue::Array(v) => visit_array(v, visitor), - _ => Err(SerdeError::from_str("invalid type: string or array")), - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Null => visitor.visit_unit(), - _ => Err(SerdeError::from_str("invalid type: null")), - } - } - - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_unit(visitor) - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Array(v) => visit_array(v, visitor), - _ => Err(SerdeError::from_str("invalid type: array")), - } - } - - fn deserialize_tuple(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Object(v) => visit_object(v, visitor), - _ => Err(SerdeError::from_str("invalid type: object")) - } - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Array(v) => visit_array(v, visitor), - RefValue::Object(v) => visit_object(v, visitor), - _ => Err(SerdeError::from_str("invalid type: array, object")) - } - } - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - drop(self); - visitor.visit_unit() - } -} - -impl<'de> serde::Deserializer<'de> for &RefValue { - type Error = SerdeError; - - #[inline] - fn deserialize_any(self, visitor: V) -> Result where - V: Visitor<'de> { - match self { - RefValue::Null => visitor.visit_unit(), - RefValue::Bool(v) => visitor.visit_bool(*v), - RefValue::Number(n) => { - n.deserialize_any(visitor).map_err(|e| SerdeError::new(format!("{:?}", e))) - } - RefValue::String(v) => visitor.visit_string(v.to_string()), - RefValue::Array(array) => visit_array(to_vec(array), visitor), - RefValue::Object(object) => { - visit_object(to_map(object), visitor) - } - } - } - - deserialize_prim_number!(deserialize_i8); - deserialize_prim_number!(deserialize_i16); - deserialize_prim_number!(deserialize_i32); - deserialize_prim_number!(deserialize_i64); - deserialize_prim_number!(deserialize_u8); - deserialize_prim_number!(deserialize_u16); - deserialize_prim_number!(deserialize_u32); - deserialize_prim_number!(deserialize_u64); - deserialize_prim_number!(deserialize_f32); - deserialize_prim_number!(deserialize_f64); - - #[inline] - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Null => visitor.visit_none(), - _ => visitor.visit_some(self), - } - } - - #[inline] - fn deserialize_enum( - self, - _name: &str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let (variant, value) = match self { - RefValue::Object(value) => { - let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(SerdeError::from_str("map with a single key")); - } - }; - if iter.next().is_some() { - return Err(SerdeError::from_str("map with a single key")); - } - (variant, Some(value)) - } - RefValue::String(variant) => (variant, None), - _ => { - return Err(SerdeError::from_str("string or map")); - } - }; - - visitor.visit_enum(EnumDeserializer { - variant: variant.to_string(), - value: match value { - Some(v) => Some(v.clone()), - _ => None - }, - }) - } - - #[inline] - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let _ = name; - visitor.visit_newtype_struct(self) - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Bool(v) => visitor.visit_bool(*v), - _ => Err(SerdeError::from_str("invalid type: bool")), - } - } - - fn deserialize_char(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::String(v) => visitor.visit_string(v.to_string()), - _ => Err(SerdeError::from_str("invalid type: string")), - } - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_byte_buf(visitor) - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::String(v) => visitor.visit_string(v.to_string()), - RefValue::Array(vec) => visit_array(to_vec(vec), visitor), - _ => Err(SerdeError::from_str("invalid type: string or array")), - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Null => visitor.visit_unit(), - _ => Err(SerdeError::from_str("invalid type: null")), - } - } - - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_unit(visitor) - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Array(vec) => visit_array(to_vec(vec), visitor), - _ => Err(SerdeError::from_str("invalid type: array")), - } - } - - fn deserialize_tuple(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Object(object) => { - visit_object(to_map(object), visitor) - } - _ => Err(SerdeError::from_str("invalid type: object")) - } - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self { - RefValue::Array(vec) => visit_array(to_vec(vec), visitor), - RefValue::Object(object) => { - visit_object(to_map(object), visitor) - } - _ => Err(SerdeError::from_str("invalid type: array, object")) - } - } - - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_string(visitor) - } - - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - drop(self); - visitor.visit_unit() - } -} - - -struct SeqDeserializer { - iter: vec::IntoIter, -} - -impl SeqDeserializer { - fn new(vec: Vec) -> Self { - SeqDeserializer { - iter: vec.into_iter(), - } - } -} - -impl<'de> serde::Deserializer<'de> for SeqDeserializer { - type Error = SerdeError; - - #[inline] - fn deserialize_any(mut self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let len = self.iter.len(); - if len == 0 { - visitor.visit_unit() - } else { - let ret = visitor.visit_seq(&mut self)?; - let remaining = self.iter.len(); - if remaining == 0 { - Ok(ret) - } else { - Err(SerdeError::from_str("fewer elements in array")) - } - } - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } -} - -impl<'de> SeqAccess<'de> for SeqDeserializer { - type Error = SerdeError; - - fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: serde::de::DeserializeSeed<'de>, - { - match self.iter.next() { - Some(value) => seed.deserialize(value.deref()).map(Some), - None => Ok(None), - } - } - - fn size_hint(&self) -> Option { - match self.iter.size_hint() { - (lower, Some(upper)) if lower == upper => Some(upper), - _ => None, - } - } -} - -struct MapDeserializer { - iter: as IntoIterator>::IntoIter, - value: Option, -} - -impl MapDeserializer { - fn new(map: IndexMap) -> Self { - MapDeserializer { - iter: map.into_iter(), - value: None, - } - } -} - -impl<'de> MapAccess<'de> for MapDeserializer { - type Error = SerdeError; - - fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: DeserializeSeed<'de>, - { - match self.iter.next() { - Some((key, value)) => { - self.value = Some(value); - let key_de = MapKeyDeserializer { - key: Cow::Owned(key), - }; - seed.deserialize(key_de).map(Some) - } - None => Ok(None), - } - } - - fn next_value_seed(&mut self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - match self.value.take() { - Some(value) => seed.deserialize(value.deref()), - None => Err(serde::de::Error::custom("value is missing")), - } - } - - fn size_hint(&self) -> Option { - match self.iter.size_hint() { - (lower, Some(upper)) if lower == upper => Some(upper), - _ => None, - } - } -} - -impl<'de> serde::Deserializer<'de> for MapDeserializer { - type Error = SerdeError; - - #[inline] - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_map(self) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } -} - -struct MapKeyDeserializer<'de> { - key: Cow<'de, str>, -} - -macro_rules! deserialize_integer_key { - ($method:ident => $visit:ident) => { - fn $method(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match (self.key.parse(), self.key) { - (Ok(integer), _) => visitor.$visit(integer), - (Err(_), Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), - (Err(_), Cow::Owned(s)) => visitor.visit_string(s), - } - } - } -} - -impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> { - type Error = SerdeError; - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor) - } - - deserialize_integer_key!(deserialize_i8 => visit_i8); - deserialize_integer_key!(deserialize_i16 => visit_i16); - deserialize_integer_key!(deserialize_i32 => visit_i32); - deserialize_integer_key!(deserialize_i64 => visit_i64); - deserialize_integer_key!(deserialize_u8 => visit_u8); - deserialize_integer_key!(deserialize_u16 => visit_u16); - deserialize_integer_key!(deserialize_u32 => visit_u32); - deserialize_integer_key!(deserialize_u64 => visit_u64); - - serde_if_integer128! { - deserialize_integer_key!(deserialize_i128 => visit_i128); - deserialize_integer_key!(deserialize_u128 => visit_u128); - } - - #[inline] - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - // Map keys cannot be null. - visitor.visit_some(self) - } - - #[inline] - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.key - .into_deserializer() - .deserialize_enum(name, variants, visitor) - } - - forward_to_deserialize_any! { - bool f32 f64 char str string bytes byte_buf unit unit_struct seq tuple - tuple_struct map struct identifier ignored_any - } -} - -struct BorrowedCowStrDeserializer<'de> { - value: Cow<'de, str>, -} - -impl<'de> BorrowedCowStrDeserializer<'de> { - fn new(value: Cow<'de, str>) -> Self { - BorrowedCowStrDeserializer { value: value } - } -} - -impl<'de> serde::Deserializer<'de> for BorrowedCowStrDeserializer<'de> { - type Error = SerdeError; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - match self.value { - Cow::Borrowed(string) => visitor.visit_borrowed_str(string), - Cow::Owned(string) => visitor.visit_string(string), - } - } - - fn deserialize_enum( - self, - _name: &str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_enum(self) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct identifier ignored_any - } -} - -impl<'de> serde::de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> { - type Error = SerdeError; - type Variant = UnitOnly; - - fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> - where - T: serde::de::DeserializeSeed<'de>, - { - let value = seed.deserialize(self)?; - Ok((value, UnitOnly)) - } -} - -struct UnitOnly; - -impl<'de> serde::de::VariantAccess<'de> for UnitOnly { - type Error = SerdeError; - - fn unit_variant(self) -> Result<(), Self::Error> { - Ok(()) - } - - fn newtype_variant_seed(self, _seed: T) -> Result - where - T: serde::de::DeserializeSeed<'de>, - { - Err(SerdeError::from_str("newtype variant")) - } - - fn tuple_variant(self, _len: usize, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(SerdeError::from_str("tuple variant")) - } - - fn struct_variant( - self, - _fields: &'static [&'static str], - _visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(SerdeError::from_str("struct variant")) - } -} - -struct EnumDeserializer { - variant: String, - value: Option, -} - -impl<'de> EnumAccess<'de> for EnumDeserializer { - type Error = SerdeError; - type Variant = VariantDeserializer; - - fn variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer), Self::Error> - where - V: DeserializeSeed<'de>, - { - let variant = self.variant.into_deserializer(); - let visitor = VariantDeserializer { value: self.value }; - seed.deserialize(variant).map(|v| (v, visitor)) - } -} - -struct VariantDeserializer { - value: Option, -} - -impl<'de> VariantAccess<'de> for VariantDeserializer { - type Error = SerdeError; - - fn unit_variant(self) -> Result<(), Self::Error> { - match self.value { - Some(value) => Deserialize::deserialize(value.deref()), - None => Ok(()), - } - } - - fn newtype_variant_seed(self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - match self.value { - Some(value) => seed.deserialize(value.deref()), - None => Err(SerdeError::from_str("newtype variant")), - } - } - - fn tuple_variant(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.value { - Some(ref_value) => { - match ref_value.deref() { - RefValue::Array(vec) => { - serde::Deserializer::deserialize_any(SeqDeserializer::new(to_vec(vec)), visitor) - } - _ => Err(SerdeError::from_str("tuple variant")) - } - } - None => Err(SerdeError::from_str("tuple variant")), - } - } - - fn struct_variant( - self, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.value { - Some(ref_value) => { - match ref_value.deref() { - RefValue::Object(vec) => { - serde::Deserializer::deserialize_any(MapDeserializer::new(to_map(vec)), visitor) - } - _ => Err(SerdeError::from_str("struct variant")) - } - } - _ => Err(SerdeError::from_str("struct variant")), - } - } -} \ No newline at end of file diff --git a/src/ref_value/mod.rs b/src/ref_value/mod.rs deleted file mode 100644 index 05dec5f..0000000 --- a/src/ref_value/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod model; -pub mod de; -pub mod ser; -pub mod serde_error; \ No newline at end of file diff --git a/src/ref_value/model.rs b/src/ref_value/model.rs deleted file mode 100644 index 5c6e76a..0000000 --- a/src/ref_value/model.rs +++ /dev/null @@ -1,290 +0,0 @@ -use std::cell::RefCell; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; -use std::ops::Deref; -use std::sync::Arc; - -use indexmap::map::IndexMap; -use serde::ser::Serialize; -use serde_json::{Number, Value}; -use std::fmt; - -type TypeRefValue = Arc>; - -pub struct RefValueWrapper { - 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 { - fn eq(&self, other: &RefValueWrapper) -> bool { - Arc::ptr_eq(&self.data, &other.data) - } -} - -impl Eq for RefValueWrapper {} - -impl Deref for RefValueWrapper { - type Target = RefValue; - - fn deref(&self) -> &Self::Target { - 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) - } -} - -impl Clone for RefValueWrapper { - fn clone(&self) -> Self { - RefValueWrapper { - data: self.data.clone() - } - } -} - -/// -/// serde_json::Value 참고 -/// -pub trait RefIndex { - fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper>; - fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper>; - fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper; -} - -impl RefIndex for usize { - fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper> { - match *v { - RefValue::Array(ref vec) => vec.get(*self), - _ => None, - } - } - fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> { - match *v { - RefValue::Array(ref mut vec) => vec.get_mut(*self), - _ => None, - } - } - fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper { - match *v { - RefValue::Array(ref mut vec) => { - let len = vec.len(); - vec.get_mut(*self).unwrap_or_else(|| { - panic!( - "cannot access index {} of JSON array of length {}", - self, len - ) - }) - } - _ => panic!("cannot access index {} of JSON {:?}", self, v), - } - } -} - -impl RefIndex for str { - fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper> { - match *v { - RefValue::Object(ref map) => map.get(self), - _ => None, - } - } - fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> { - match *v { - RefValue::Object(ref mut map) => map.get_mut(self), - _ => None, - } - } - fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper { - if let RefValue::Null = *v { - *v = RefValue::Object(IndexMap::new()); - } - match *v { - RefValue::Object(ref mut map) => { - map.entry(self.to_owned()).or_insert(RefValue::Null.into()) - } - _ => panic!("cannot access key {:?} in JSON {:?}", self, v), - } - } -} - -impl RefIndex for String { - fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper> { - self[..].index_into(v) - } - fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> { - self[..].index_into_mut(v) - } - fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper { - self[..].index_or_insert(v) - } -} - -pub enum RefValue { - Null, - Bool(bool), - Number(Number), - String(String), - Array(Vec), - 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(); - let mut hasher2 = DefaultHasher::new(); - - self.hash(&mut hasher1); - other.hash(&mut hasher2); - - hasher1.finish() == hasher2.finish() - } -} - -static REF_VALUE_NULL: &'static str = "$jsonpath::ref_value::model::RefValue::Null"; - -impl Hash for RefValue { - fn hash(&self, state: &mut H) { - -// println!("###hash - RefValue - {:?}", self); - - match self { - RefValue::Null => { - REF_VALUE_NULL.hash(state) - } - RefValue::Bool(b) => { - b.hash(state) - } - RefValue::Number(n) => { - if n.is_f64() { - n.as_f64().unwrap().to_string().hash(state) - } else if n.is_i64() { - n.as_i64().unwrap().hash(state); - } else { - n.as_u64().unwrap().hash(state); - } - } - RefValue::String(s) => { - s.hash(state) - } - RefValue::Object(map) => { - for (k, v) in map { - k.hash(state); - v.hash(state); - } - } - RefValue::Array(v) => { - for i in v { - i.hash(state); - } - } - } - } -} - -impl Eq for RefValue {} - -impl RefValue { - pub fn get(&self, index: I) -> Option<&RefValueWrapper> { - index.index_into(self) - } - - pub fn is_object(&self) -> bool { - match *self { - RefValue::Object(_) => true, - _ => false, - } - } - - pub fn is_array(&self) -> bool { - match *self { - RefValue::Array(_) => true, - _ => false, - } - } - - pub fn len(&self) -> usize { - match &self { - RefValue::Object(m) => m.len(), - RefValue::Array(v) => v.len(), - _ => 0, - } - } - - 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 { - match *self { - RefValue::Null => true, - _ => false, - } - } -} - -impl Into for RefValue { - fn into(self) -> RefValueWrapper { - RefValueWrapper { - data: Arc::new(RefCell::new(self)) - } - } -} - -impl Into for &Value { - fn into(self) -> RefValue { - match self.serialize(super::ser::RefValueSerializer) { - Ok(v) => v, - Err(e) => panic!("Error Value into RefValue: {:?}", e) - } - } -} - -impl Into for &Value { - fn into(self) -> RefValueWrapper { - match self.serialize(super::ser::RefValueSerializer) { - Ok(v) => v.into(), - Err(e) => panic!("Error Value into RefValue: {:?}", e) - } - } -} - -impl Into for &RefValueWrapper { - fn into(self) -> Value { - match serde_json::to_value(self.deref()) { - Ok(v) => v, - Err(e) => panic!("Error RefValueWrapper into Value: {:?}", e) - } - } -} \ No newline at end of file diff --git a/src/ref_value/ser.rs b/src/ref_value/ser.rs deleted file mode 100644 index 22e0c68..0000000 --- a/src/ref_value/ser.rs +++ /dev/null @@ -1,624 +0,0 @@ -use std::result::Result; - -use indexmap::IndexMap; -use serde::{self, Serialize}; -use serde::ser::Impossible; - -use ref_value::model::{RefValue, RefValueWrapper}; - -use super::serde_error::SerdeError; - -/// -/// see `serde_json/value/ser.rs` -/// -impl Serialize for RefValue { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: ::serde::Serializer, - { - match *self { - RefValue::Null => serializer.serialize_unit(), - RefValue::Bool(b) => serializer.serialize_bool(b), - RefValue::Number(ref n) => n.serialize(serializer), - RefValue::String(ref s) => serializer.serialize_str(s), - RefValue::Array(ref v) => { - use std::ops::Deref; - let v: Vec<&RefValue> = v.iter().map(|v| v.deref()).collect(); - v.serialize(serializer) - } - RefValue::Object(ref m) => { - use serde::ser::SerializeMap; - use std::ops::Deref; - let mut map = try!(serializer.serialize_map(Some(m.len()))); - for (k, v) in m { - try!(map.serialize_key(k)); - try!(map.serialize_value(v.deref())); - } - map.end() - } - } - } -} - -pub struct RefValueSerializer; - -impl serde::Serializer for RefValueSerializer { - type Ok = RefValue; - type Error = SerdeError; - - type SerializeSeq = SerializeVec; - type SerializeTuple = SerializeVec; - type SerializeTupleStruct = SerializeVec; - type SerializeTupleVariant = SerializeTupleVariant; - type SerializeMap = SerializeMap; - type SerializeStruct = SerializeMap; - type SerializeStructVariant = SerializeStructVariant; - - #[inline] - fn serialize_bool(self, value: bool) -> Result { - Ok(RefValue::Bool(value)) - } - - #[inline] - fn serialize_i8(self, value: i8) -> Result { - self.serialize_i64(value as i64) - } - - #[inline] - fn serialize_i16(self, value: i16) -> Result { - self.serialize_i64(value as i64) - } - - #[inline] - fn serialize_i32(self, value: i32) -> Result { - self.serialize_i64(value as i64) - } - - fn serialize_i64(self, value: i64) -> Result { - Ok(RefValue::Number(value.into())) - } - - #[inline] - fn serialize_u8(self, value: u8) -> Result { - self.serialize_u64(value as u64) - } - - #[inline] - fn serialize_u16(self, value: u16) -> Result { - self.serialize_u64(value as u64) - } - - #[inline] - fn serialize_u32(self, value: u32) -> Result { - self.serialize_u64(value as u64) - } - - #[inline] - fn serialize_u64(self, value: u64) -> Result { - Ok(RefValue::Number(value.into())) - } - - #[inline] - fn serialize_f32(self, value: f32) -> Result { - self.serialize_f64(value as f64) - } - - #[inline] - fn serialize_f64(self, value: f64) -> Result { - Ok(serde_json::Number::from_f64(value).map_or(RefValue::Null, RefValue::Number)) - } - - #[inline] - fn serialize_char(self, value: char) -> Result { - let mut s = String::new(); - s.push(value); - self.serialize_str(&s) - } - - #[inline] - fn serialize_str(self, value: &str) -> Result { - Ok(RefValue::String(value.to_owned())) - } - - fn serialize_bytes(self, value: &[u8]) -> Result { - let vec = value.iter().map(|&b| RefValue::Number(b.into()).into()).collect(); - Ok(RefValue::Array(vec)) - } - - #[inline] - fn serialize_unit(self) -> Result { - Ok(RefValue::Null) - } - - #[inline] - fn serialize_unit_struct(self, _name: &'static str) -> Result { - self.serialize_unit() - } - - #[inline] - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result { - self.serialize_str(variant) - } - - #[inline] - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - value.serialize(self) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - let mut values: IndexMap = IndexMap::new(); - values.insert(String::from(variant), { - value.serialize(RefValueSerializer)?.into() - }); - Ok(RefValue::Object(values)) - } - - #[inline] - fn serialize_none(self) -> Result { - self.serialize_unit() - } - - #[inline] - fn serialize_some(self, value: &T) -> Result - where - T: Serialize, - { - value.serialize(self) - } - - fn serialize_seq(self, len: Option) -> Result { - Ok(SerializeVec { - vec: Vec::with_capacity(len.unwrap_or(0)), - }) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - len: usize, - ) -> Result { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - Ok(SerializeTupleVariant { - name: String::from(variant), - vec: Vec::with_capacity(len), - }) - } - - fn serialize_map(self, _len: Option) -> Result { - Ok(SerializeMap::Map { - map: IndexMap::new(), - next_key: None, - }) - } - - fn serialize_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - match name { - _ => self.serialize_map(Some(len)), - } - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - Ok(SerializeStructVariant { - name: String::from(variant), - map: IndexMap::new(), - }) - } -} - -pub struct SerializeVec { - vec: Vec, -} - -pub struct SerializeTupleVariant { - name: String, - vec: Vec, -} - -pub enum SerializeMap { - Map { - map: IndexMap, - next_key: Option, - }, -} - -pub struct SerializeStructVariant { - name: String, - map: IndexMap, -} - -impl serde::ser::SerializeSeq for SerializeVec { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - self.vec.push({ - value.serialize(RefValueSerializer)?.into() - }); - Ok(()) - } - - fn end(self) -> Result { - Ok(RefValue::Array(self.vec)) - } -} - -impl serde::ser::SerializeTuple for SerializeVec { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - serde::ser::SerializeSeq::serialize_element(self, value) - } - - fn end(self) -> Result { - serde::ser::SerializeSeq::end(self) - } -} - -impl serde::ser::SerializeTupleStruct for SerializeVec { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - serde::ser::SerializeSeq::serialize_element(self, value) - } - - fn end(self) -> Result { - serde::ser::SerializeSeq::end(self) - } -} - -impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - self.vec.push({ - let a: RefValue = value.serialize(RefValueSerializer)?; - a.into() - }); - Ok(()) - } - - fn end(self) -> Result { - let mut object: IndexMap = IndexMap::new(); - - object.insert(self.name, RefValue::Array(self.vec).into()); - - Ok(RefValue::Object(object)) - } -} - -impl serde::ser::SerializeMap for SerializeMap { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - match *self { - SerializeMap::Map { - ref mut next_key, .. - } => { - *next_key = Some(key.serialize(MapKeySerializer)?); - Ok(()) - } - } - } - - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - match *self { - SerializeMap::Map { - ref mut map, - ref mut next_key, - } => { - let key = next_key.take(); - // Panic because this indicates a bug in the program rather than an - // expected failure. - let key = key.expect("serialize_value called before serialize_key"); - map.insert(key, { - let a: RefValue = value.serialize(RefValueSerializer)?; - a.into() - }); - Ok(()) - } - } - } - - fn end(self) -> Result { - match self { - SerializeMap::Map { map, .. } => Ok(RefValue::Object(map)), - } - } -} - -struct MapKeySerializer; - -fn key_must_be_a_string() -> SerdeError { - SerdeError::from_str("key must be string") -} - -impl serde::Serializer for MapKeySerializer { - type Ok = String; - type Error = SerdeError; - - type SerializeSeq = Impossible; - type SerializeTuple = Impossible; - type SerializeTupleStruct = Impossible; - type SerializeTupleVariant = Impossible; - type SerializeMap = Impossible; - type SerializeStruct = Impossible; - type SerializeStructVariant = Impossible; - - #[inline] - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result { - Ok(variant.to_owned()) - } - - #[inline] - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - value.serialize(self) - } - - fn serialize_bool(self, _value: bool) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_i8(self, value: i8) -> Result { - Ok(value.to_string()) - } - - fn serialize_i16(self, value: i16) -> Result { - Ok(value.to_string()) - } - - fn serialize_i32(self, value: i32) -> Result { - Ok(value.to_string()) - } - - fn serialize_i64(self, value: i64) -> Result { - Ok(value.to_string()) - } - - fn serialize_u8(self, value: u8) -> Result { - Ok(value.to_string()) - } - - fn serialize_u16(self, value: u16) -> Result { - Ok(value.to_string()) - } - - fn serialize_u32(self, value: u32) -> Result { - Ok(value.to_string()) - } - - fn serialize_u64(self, value: u64) -> Result { - Ok(value.to_string()) - } - - fn serialize_f32(self, _value: f32) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_f64(self, _value: f64) -> Result { - Err(key_must_be_a_string()) - } - - #[inline] - fn serialize_char(self, value: char) -> Result { - Ok({ - let mut s = String::new(); - s.push(value); - s - }) - } - - #[inline] - fn serialize_str(self, value: &str) -> Result { - Ok(value.to_owned()) - } - - fn serialize_bytes(self, _value: &[u8]) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_unit(self) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T, - ) -> Result - where - T: Serialize, - { - Err(key_must_be_a_string()) - } - - fn serialize_none(self) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_some(self, _value: &T) -> Result - where - T: Serialize, - { - Err(key_must_be_a_string()) - } - - fn serialize_seq(self, _len: Option) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_tuple(self, _len: usize) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_map(self, _len: Option) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - Err(key_must_be_a_string()) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - Err(key_must_be_a_string()) - } -} - -impl serde::ser::SerializeStruct for SerializeMap { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - match *self { - SerializeMap::Map { .. } => { - serde::ser::SerializeMap::serialize_key(self, key)?; - serde::ser::SerializeMap::serialize_value(self, value) - } - } - } - - fn end(self) -> Result { - match self { - SerializeMap::Map { .. } => serde::ser::SerializeMap::end(self), - } - } -} - -impl serde::ser::SerializeStructVariant for SerializeStructVariant { - type Ok = RefValue; - type Error = SerdeError; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - self.map.insert(String::from(key), { - let a: RefValue = value.serialize(RefValueSerializer)?; - a.into() - }); - Ok(()) - } - - fn end(self) -> Result { - let mut object: IndexMap = IndexMap::new(); - - object.insert(self.name, RefValue::Object(self.map).into()); - - Ok(RefValue::Object(object)) - } -} diff --git a/src/ref_value/serde_error.rs b/src/ref_value/serde_error.rs deleted file mode 100644 index 7deb7f1..0000000 --- a/src/ref_value/serde_error.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::fmt; - -#[derive(Debug)] -pub struct SerdeError { - msg: String, -} - -impl<'a> SerdeError { - pub fn new(msg: String) -> Self { - SerdeError { msg: msg } - } - - pub fn from_str(msg: &str) -> Self { - SerdeError { msg: msg.to_string() } - } -} - -impl serde::de::Error for SerdeError { - #[cold] - fn custom(msg: T) -> SerdeError { - SerdeError { msg: msg.to_string() } - } -} - -impl serde::ser::Error for SerdeError { - #[cold] - fn custom(msg: T) -> SerdeError { - SerdeError { msg: msg.to_string() } - } -} - -impl std::error::Error for SerdeError {} - -impl fmt::Display for SerdeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.msg) - } -} \ No newline at end of file diff --git a/src/select/mod.rs b/src/select/mod.rs index ac0856c..07c4334 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -1,2 +1,1002 @@ -pub mod selector; -pub mod modifiable; \ No newline at end of file +use array_tool::vec::{Intersect, Union}; +use serde_json::{Number, Value}; + +use parser::parser::*; +use std::collections::HashSet; + +fn to_f64(n: &Number) -> f64 { + if n.is_i64() { + n.as_i64().unwrap() as f64 + } else if n.is_f64() { + n.as_f64().unwrap() + } else { + n.as_u64().unwrap() as f64 + } +} + +trait Cmp { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool; + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool; + + fn cmp_string(&self, v1: &String, v2: &String) -> bool; + + fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value>; + + fn default(&self) -> bool { false } +} + +struct CmpEq; + +impl Cmp for CmpEq { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 == v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 == v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 == v2 + } + + fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { + v1.intersect(v2.to_vec()) + } +} + +struct CmpNe; + +impl Cmp for CmpNe { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 != v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 != v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 != v2 + } + + fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { + v1.intersect_if(v2.to_vec(), |a, b| a != b) + } +} + +struct CmpGt; + +impl Cmp for CmpGt { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 > v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 > v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 > v2 + } + + fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + Vec::new() + } +} + +struct CmpGe; + +impl Cmp for CmpGe { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 >= v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 >= v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 >= v2 + } + + fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + Vec::new() + } +} + +struct CmpLt; + +impl Cmp for CmpLt { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 < v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 < v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 < v2 + } + + fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + Vec::new() + } +} + +struct CmpLe; + +impl Cmp for CmpLe { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + v1 <= v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 <= v2 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + v1 <= v2 + } + + fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + Vec::new() + } +} + +struct CmpAnd; + +impl Cmp for CmpAnd { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + *v1 && *v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 > &0_f64 && v2 > &0_f64 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + !v1.is_empty() && !v2.is_empty() + } + + fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { + v1.intersect(v2.to_vec()) + } +} + +struct CmpOr; + +impl Cmp for CmpOr { + fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + *v1 || *v2 + } + + fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + v1 > &0_f64 || v2 > &0_f64 + } + + fn cmp_string(&self, v1: &String, v2: &String) -> bool { + !v1.is_empty() || !v2.is_empty() + } + + fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { + v1.union(v2.to_vec()) + } +} + +#[derive(Debug)] +enum ExprTerm<'a> { + String(String), + Number(Number), + Bool(bool), + Json(Option, Vec<&'a Value>), +} + +impl<'a> ExprTerm<'a> { + fn is_string(&self) -> bool { + match &self { + ExprTerm::String(_) => true, + _ => false + } + } + + fn is_number(&self) -> bool { + match &self { + ExprTerm::Number(_) => true, + _ => false + } + } + + fn is_bool(&self) -> bool { + match &self { + ExprTerm::Bool(_) => true, + _ => false + } + } + + fn is_json(&self) -> bool { + match &self { + ExprTerm::Json(_, _) => true, + _ => false + } + } + + fn cmp(&self, other: &Self, cmp_fn: &C1, reverse_cmp_fn: &C2) -> ExprTerm<'a> { + match &self { + ExprTerm::String(s1) => match &other { + ExprTerm::String(s2) => ExprTerm::Bool(cmp_fn.cmp_string(s1, s2)), + ExprTerm::Json(_, _) => { + other.cmp(&self, reverse_cmp_fn, cmp_fn) + } + _ => ExprTerm::Bool(cmp_fn.default()) + } + ExprTerm::Number(n1) => match &other { + ExprTerm::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2))), + ExprTerm::Json(_, _) => { + other.cmp(&self, reverse_cmp_fn, cmp_fn) + } + _ => ExprTerm::Bool(cmp_fn.default()) + } + ExprTerm::Bool(b1) => match &other { + ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(b1, b2)), + ExprTerm::Json(_, _) => { + other.cmp(&self, reverse_cmp_fn, cmp_fn) + } + _ => ExprTerm::Bool(cmp_fn.default()) + } + ExprTerm::Json(fk1, vec1) if other.is_string() => { + match &other { + ExprTerm::String(s2) => { + let ret: Vec<&Value> = vec1.iter().filter(|v1| { + match v1 { + Value::String(s1) => cmp_fn.cmp_string(s1, s2), + Value::Object(map1) => { + if let Some(FilterKey::String(k)) = fk1 { + if let Some(Value::String(s1)) = map1.get(k) { + return cmp_fn.cmp_string(s1, s2); + } + } + cmp_fn.default() + } + _ => cmp_fn.default() + } + }).map(|v| *v).collect(); + + if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + } + _ => unreachable!() + } + } + ExprTerm::Json(fk1, vec1) if other.is_number() => { + match &other { + ExprTerm::Number(n2) => { + let ret: Vec<&Value> = vec1.iter().filter(|v1| { + match v1 { + Value::Number(n1) => cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2)), + Value::Object(map1) => { + if let Some(FilterKey::String(k)) = fk1 { + if let Some(Value::Number(n1)) = map1.get(k) { + return cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2)); + } + } + cmp_fn.default() + } + _ => cmp_fn.default() + } + }).map(|v| *v).collect(); + + if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + } + _ => unreachable!() + } + } + ExprTerm::Json(fk1, vec1) if other.is_bool() => { + match &other { + ExprTerm::Bool(b2) => { + let ret: Vec<&Value> = vec1.iter().filter(|v1| { + match v1 { + Value::Bool(b1) => cmp_fn.cmp_bool(b1, b2), + Value::Object(map1) => { + if let Some(FilterKey::String(k)) = fk1 { + if let Some(Value::Bool(b1)) = map1.get(k) { + return cmp_fn.cmp_bool(b1, b2); + } + } + cmp_fn.default() + } + _ => cmp_fn.default() + } + }).map(|v| *v).collect(); + + if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + } + _ => unreachable!() + } + } + ExprTerm::Json(_, vec1) if other.is_json() => { + match &other { + ExprTerm::Json(_, vec2) => { + let vec = cmp_fn.cmp_json(vec1, vec2); + if vec.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, vec) } + } + _ => unreachable!() + } + } + _ => unreachable!() + } + } + + fn eq(&self, other: &Self, ret: &mut Option>) { + debug!("eq - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpEq, &CmpEq); + debug!("eq = {:?}", tmp); + *ret = Some(tmp); + } + + fn ne(&self, other: &Self, ret: &mut Option>) { + debug!("ne - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpNe, &CmpNe); + debug!("ne = {:?}", tmp); + *ret = Some(tmp); + } + + fn gt(&self, other: &Self, ret: &mut Option>) { + debug!("gt - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpGt, &CmpLt); + debug!("gt = {:?}", tmp); + *ret = Some(tmp); + } + + fn ge(&self, other: &Self, ret: &mut Option>) { + debug!("ge - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpGe, &CmpLe); + debug!("ge = {:?}", tmp); + *ret = Some(tmp); + } + + fn lt(&self, other: &Self, ret: &mut Option>) { + debug!("lt - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpLt, &CmpGt); + debug!("lt = {:?}", tmp); + *ret = Some(tmp); + } + + fn le(&self, other: &Self, ret: &mut Option>) { + debug!("le - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpLe, &CmpGe); + debug!("le = {:?}", tmp); + *ret = Some(tmp); + } + + fn and(&self, other: &Self, ret: &mut Option>) { + debug!("and - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpAnd, &CmpAnd); + debug!("and = {:?}", tmp); + *ret = Some(tmp); + } + + fn or(&self, other: &Self, ret: &mut Option>) { + debug!("or - {:?} : {:?}", &self, &other); + let _ = ret.take(); + let tmp = self.cmp(other, &CmpOr, &CmpOr); + debug!("or = {:?}", tmp); + *ret = Some(tmp); + } +} + +fn walk_all_with_str<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { + if is_filter { + walk(vec, tmp, &|v| { + match v { + Value::Object(map) if map.contains_key(key) => { + Some(vec![v]) + } + _ => None + } + }); + } else { + walk(vec, tmp, &|v| { + match v { + Value::Object(map) => match map.get(key) { + Some(v) => Some(vec![v]), + _ => None + } + _ => None + } + }); + } +} + +fn walk_all<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>) { + walk(vec, tmp, &|v| match v { + Value::Array(vec) => { + Some(vec.iter().collect()) + } + Value::Object(map) => { + let mut tmp = Vec::new(); + for (_, v) in map { + tmp.push(v); + } + Some(tmp) + } + _ => None + }); +} + +fn walk<'a, F>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, fun: &F) + where F: Fn(&Value) -> Option> +{ + fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) + where F: Fn(&Value) -> Option> + { + if let Some(mut ret) = fun(v) { + tmp.append(&mut ret); + } + + match v { + Value::Array(vec) => { + for v in vec { + _walk(v, tmp, fun); + } + } + Value::Object(map) => { + for (_, v) in map { + _walk(&v, tmp, fun); + } + } + _ => {} + } + } + + for v in vec { + _walk(v, tmp, fun); + } +} + +fn abs_index(n: &isize, len: usize) -> usize { + if n < &0_isize { + (n + len as isize) as usize + } else { + *n as usize + } +} + +#[derive(Debug)] +enum FilterKey { + String(String), + All, +} + +#[derive(Debug)] +pub enum JsonPathError { + EmptyPath, + EmptyValue, + Path(String), + Serde(String), +} + +#[derive(Debug)] +pub struct Selector<'a> { + node: Option, + value: Option<&'a Value>, + tokens: Vec, + terms: Vec>>, + current: Option>, + selectors: Vec>, +} + +impl<'a> Selector<'a> { + pub fn new() -> Self { + Selector { + node: None, + value: None, + tokens: Vec::new(), + terms: Vec::new(), + current: None, + selectors: Vec::new(), + } + } + + pub fn path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> { + debug!("path : {}", path); + let mut parser = Parser::new(path); + self.node = Some(parser.compile().map_err(|e| JsonPathError::Path(e))?); + Ok(self) + } + + pub(crate) fn reset_value(&mut self) -> &mut Self { + self.current = None; + self + } + + pub fn compiled_path(&mut self, node: Node) -> &mut Self { + self.node = Some(node); + self + } + + pub fn value(&mut self, v: &'a Value) -> &mut Self { + self.value = Some(v); + self + } + + fn _select(&mut self) -> Result<(), JsonPathError> { + match self.node.take() { + Some(node) => { + self.visit(&node); + self.node = Some(node); + Ok(()) + } + _ => Err(JsonPathError::EmptyPath) + } + } + + pub fn select_as(&mut self) -> Result, JsonPathError> { + self._select()?; + + match &self.current { + Some(vec) => { + let mut ret = Vec::new(); + for v in vec { + match T::deserialize(*v) { + Ok(v) => ret.push(v), + Err(e) => return Err(JsonPathError::Serde(e.to_string())) + } + } + Ok(ret) + } + _ => Err(JsonPathError::EmptyValue) + } + } + + pub fn select_as_str(&mut self) -> Result { + self._select()?; + + match &self.current { + Some(r) => { + Ok(serde_json::to_string(r) + .map_err(|e| JsonPathError::Serde(e.to_string()))?) + } + _ => Err(JsonPathError::EmptyValue) + } + } + + pub fn select(&mut self) -> Result, JsonPathError> { + self._select()?; + + match &self.current { + Some(r) => Ok(r.to_vec()), + _ => Err(JsonPathError::EmptyValue) + } + } + + fn new_filter_context(&mut self) { + self.terms.push(None); + debug!("new_filter_context: {:?}", self.terms); + } + + fn in_filter, &mut Vec<&'a Value>) -> FilterKey>(&mut self, fun: F) { + match self.terms.pop() { + Some(peek) => { + match peek { + Some(v) => { + debug!("in_filter 1.: {:?}", v); + + match v { + ExprTerm::Json(_, vec) => { + let mut tmp = Vec::new(); + let filter_key = fun(&vec, &mut tmp); + self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp))); + } + _ => unreachable!() + }; + } + _ => { + debug!("in_filter 2.: {:?}", &self.current); + + if let Some(current) = &self.current { + let mut tmp = Vec::new(); + let filter_key = fun(current, &mut tmp); + self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp))); + } + } + }; + } + _ => {} + } + } + + fn all_in_filter_with_str(&mut self, key: &str) { + self.in_filter(|vec, tmp| { + walk_all_with_str(&vec, tmp, key, true); + FilterKey::All + }); + + debug!("all_in_filter_with_str : {}, {:?}", key, self.terms); + } + + fn next_in_filter_with_str(&mut self, key: &str) { + fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>, key: &str, visited: &mut HashSet<*const Value>) { + match v { + Value::Object(map) => if map.contains_key(key) { + let ptr = v as *const Value; + if !visited.contains(&ptr) { + visited.insert(ptr); + tmp.push(v) + } + }, + Value::Array(vec) => for v in vec { + _collect(v, tmp, key, visited); + } + _ => {} + } + } + + self.in_filter(|vec, tmp| { + let mut visited = HashSet::new(); + for v in vec { + _collect(v, tmp, key, &mut visited); + } + FilterKey::String(key.to_owned()) + }); + + debug!("next_in_filter_with_str : {}, {:?}", key, self.terms); + } + + fn next_from_current_with_num(&mut self, index: f64) { + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + for c in current { + if let Value::Array(vec) = c { + let index = abs_index(&(index as isize), vec.len()); + if let Some(v) = c.get(index) { + tmp.push(v); + } + } + } + self.current = Some(tmp); + } + + debug!("next_from_current_with_num : {:?}, {:?}", &index, self.current); + } + + fn next_from_current_with_str(&mut self, key: &str) { + fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>, key: &str, visited: &mut HashSet<*const Value>) { + match v { + Value::Object(map) => { + if let Some(v) = map.get(key) { + let ptr = v as *const Value; + if !visited.contains(&ptr) { + visited.insert(ptr); + tmp.push(v) + } + } + } + Value::Array(vec) => for v in vec { + _collect(v, tmp, key, visited); + } + _ => {} + } + } + + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + let mut visited = HashSet::new(); + for c in current { + _collect(c, &mut tmp, key, &mut visited); + } + self.current = Some(tmp); + } + + debug!("next_from_current_with_str : {}, {:?}", key, self.current); + } + + fn next_all_from_current(&mut self) { + fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>) { + match v { + Value::Object(map) => { + for (_, v) in map { + tmp.push(v) + } + } + Value::Array(vec) => for v in vec { + _collect(v, tmp); + } + _ => {} + } + } + + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + for c in current { + _collect(c, &mut tmp); + } + self.current = Some(tmp); + } + + debug!("next_all_from_current : {:?}", self.current); + } + + fn all_from_current(&mut self) { + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + walk_all(¤t, &mut tmp); + self.current = Some(tmp); + } + debug!("all_from_current: {:?}", self.current); + } + + fn all_from_current_with_str(&mut self, key: &str) { + if let Some(current) = self.current.take() { + let mut tmp = Vec::new(); + walk_all_with_str(¤t, &mut tmp, key, false); + self.current = Some(tmp); + } + debug!("all_from_current_with_str: {}, {:?}", key, self.current); + } +} + +impl<'a> NodeVisitor for Selector<'a> { + fn visit_token(&mut self, token: &ParseToken) { + debug!("token: {:?}, stack: {:?}", token, self.tokens); + + if !self.selectors.is_empty() { + match token { + ParseToken::Absolute | ParseToken::Relative | ParseToken::Filter(_) => { + let s = self.selectors.pop().unwrap(); + + if let Some(current) = &s.current { + let term = if current.len() == 1 { + match current[0] { + Value::Number(v) => ExprTerm::Number(v.clone()), + Value::String(v) => ExprTerm::String(v.clone()), + Value::Bool(v) => ExprTerm::Bool(*v), + _ => ExprTerm::Json(None, current.to_vec()) + } + } else { + ExprTerm::Json(None, current.to_vec()) + }; + + if let Some(s) = self.selectors.last_mut() { + s.terms.push(Some(term)); + } else { + self.terms.push(Some(term)); + } + } else { + unreachable!() + } + } + _ => {} + } + } + + if let Some(s) = self.selectors.last_mut() { + s.visit_token(token); + return; + } + + match token { + ParseToken::Absolute => { + if self.current.is_some() { + let mut s = Selector::new(); + if let Some(value) = self.value { + s.value = Some(value); + s.current = Some(vec![value]); + self.selectors.push(s); + } + return; + } + + match &self.value { + Some(v) => self.current = Some(vec![v]), + _ => {} + } + } + ParseToken::Relative => { + self.new_filter_context(); + } + ParseToken::In | ParseToken::Leaves => { + self.tokens.push(token.clone()); + } + ParseToken::Array => { + if let Some(ParseToken::Leaves) = self.tokens.last() { + self.tokens.pop(); + self.all_from_current(); + } + + self.tokens.push(token.clone()); + } + ParseToken::ArrayEof => { + if let Some(Some(e)) = self.terms.pop() { + match e { + ExprTerm::Number(n) => { + self.next_from_current_with_num(to_f64(&n)); + } + ExprTerm::String(key) => { + self.next_from_current_with_str(&key); + } + ExprTerm::Json(_, v) => { + if v.is_empty() { + self.current = Some(vec![&Value::Null]); + } else { + self.current = Some(v); + } + } + ExprTerm::Bool(false) => { + self.current = Some(vec![&Value::Null]); + } + _ => {} + } + } + + self.tokens.pop(); + } + ParseToken::All => { + match self.tokens.last() { + Some(ParseToken::Leaves) => { + self.tokens.pop(); + self.all_from_current(); + } + Some(ParseToken::In) => { + self.tokens.pop(); + self.next_all_from_current(); + } + _ => {} + } + } + ParseToken::Bool(b) => { + self.terms.push(Some(ExprTerm::Bool(*b))); + } + ParseToken::Key(key) => { + if let Some(ParseToken::Array) = self.tokens.last() { + self.terms.push(Some(ExprTerm::String(key.clone()))); + return; + } + + match self.tokens.pop() { + Some(t) => { + if self.terms.is_empty() { + match t { + ParseToken::Leaves => { + self.all_from_current_with_str(key.as_str()) + } + ParseToken::In => { + self.next_from_current_with_str(key.as_str()) + } + _ => {} + } + } else { + match t { + ParseToken::Leaves => { + self.all_in_filter_with_str(key.as_str()); + } + ParseToken::In => { + self.next_in_filter_with_str(key.as_str()); + } + _ => {} + } + } + } + _ => {} + } + } + ParseToken::Number(v) => { + self.terms.push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap()))); + } + ParseToken::Filter(ref ft) => { + if let Some(Some(ref right)) = self.terms.pop() { + if let Some(Some(left)) = self.terms.pop() { + let mut ret = None; + match ft { + FilterToken::Equal => left.eq(right, &mut ret), + FilterToken::NotEqual => left.ne(right, &mut ret), + FilterToken::Greater => left.gt(right, &mut ret), + FilterToken::GreaterOrEqual => left.ge(right, &mut ret), + FilterToken::Little => left.lt(right, &mut ret), + FilterToken::LittleOrEqual => left.le(right, &mut ret), + FilterToken::And => left.and(right, &mut ret), + FilterToken::Or => left.or(right, &mut ret), + }; + + if let Some(e) = ret { + self.terms.push(Some(e)); + } + } else { + unreachable!() + } + } else { + unreachable!() + } + } + ParseToken::Range(from, to) => { + if !self.terms.is_empty() { + unimplemented!("range syntax in filter"); + } + + if let Some(ParseToken::Array) = self.tokens.pop() { + let mut tmp = Vec::new(); + for vec in &self.current { + for v in vec { + if let Value::Array(vec) = v { + let from = if let Some(from) = from { + abs_index(from, vec.len()) + } else { + 0 + }; + + let to = if let Some(to) = to { + abs_index(to, vec.len()) + } else { + vec.len() + }; + + for i in from..to { + if let Some(v) = vec.get(i) { + tmp.push(v); + } + } + } + } + } + + self.current = Some(tmp); + } else { + unreachable!(); + } + } + ParseToken::Union(indices) => { + if !self.terms.is_empty() { + unimplemented!("union syntax in filter"); + } + + if let Some(ParseToken::Array) = self.tokens.pop() { + let mut tmp = Vec::new(); + for vec in &self.current { + for v in vec { + if let Value::Array(vec) = v { + for i in indices { + if let Some(v) = vec.get(abs_index(i, vec.len())) { + tmp.push(v); + } + } + } + } + } + + self.current = Some(tmp); + } else { + unreachable!(); + } + } + ParseToken::Eof => { + debug!("visit_token eof"); + } + } + } +} + + +//pub trait Transform<'a> { +// fn map(&mut self, mut fun: F) -> &mut Self where F: FnMut(&'a mut Value); +//} +// +//impl<'a> Transform<'a> for Selector<'a> { +// fn map(&mut self, mut fun: F) -> &mut Self where F: FnMut(&'a mut Value) { +// match &mut self.current { +// Some(current) => { +// current.iter_mut().for_each(|ref mut v| fun(v)) +// } +// _ => {} +// } +// +// self +// } +//} \ No newline at end of file diff --git a/src/select/modifiable.rs b/src/select/modifiable.rs deleted file mode 100644 index 3fca8f2..0000000 --- a/src/select/modifiable.rs +++ /dev/null @@ -1,60 +0,0 @@ -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/selector.rs b/src/select/selector.rs deleted file mode 100644 index fe759ab..0000000 --- a/src/select/selector.rs +++ /dev/null @@ -1,257 +0,0 @@ -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::*; - -/// 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 } - } - - 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())), - _ => 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_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/common.rs b/tests/common.rs new file mode 100644 index 0000000..98a04fe --- /dev/null +++ b/tests/common.rs @@ -0,0 +1,44 @@ +extern crate env_logger; +extern crate jsonpath_lib as jsonpath; +extern crate serde_json; + +use std::io::Read; + +use serde_json::Value; + +use self::jsonpath::Selector; + +pub fn setup() { + let _ = env_logger::try_init(); +} + +#[allow(dead_code)] +pub fn read_json(path: &str) -> Value { + let mut f = std::fs::File::open(path).unwrap(); + let mut contents = String::new(); + f.read_to_string(&mut contents).unwrap(); + serde_json::from_str(&contents).unwrap() +} + +#[allow(dead_code)] +pub fn read_contents(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 +} + +#[allow(dead_code)] +pub fn select_and_then_compare<'a>(path: &str, json: Value, target: Value) { + let mut s = Selector::new(); + let _ = s.path(path); + let _ = s.value(&json); + let result = serde_json::to_value(s.select().unwrap()).unwrap(); + assert_eq!(result, target, "{}", path); +} + +#[allow(dead_code)] +pub fn compare_result<'a>(result: Vec<&Value>, target: Value) { + let result = serde_json::to_value(result).unwrap(); + assert_eq!(result, target); +} diff --git a/tests/filter.rs b/tests/filter.rs index 99cee5e..101ec8e 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -1,223 +1,140 @@ -extern crate core; -extern crate env_logger; -extern crate jsonpath_lib as jsonpath; #[macro_use] extern crate serde_json; -use std::io::Read; - use serde_json::Value; -use jsonpath::Selector; -use jsonpath::filter::value_filter::ValueFilter; +use common::{read_json, select_and_then_compare, setup}; -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 selector(path: &str, file: &str) -> Selector { - let string = read_json(file); - let mut s = Selector::new(); - let _ = s.path(path); - let _ = s.value_from_str(&string); - s -} - -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 -} - -#[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()); - } -} +mod common; #[test] fn array() { setup(); - let friends = json!([ - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ]); + select_and_then_compare("$.school.friends[1, 2]", read_json("./benches/data_obj.json"), json!([ + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ])); - let s = selector("$.school.friends[1, 2]", "./benches/data_obj.json"); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$.school.friends[1: ]", read_json("./benches/data_obj.json"), json!([ + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ])); - let s = selector("$.school.friends[1:]", "./benches/data_obj.json"); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$.school.friends[:-2]", read_json("./benches/data_obj.json"), json!([ + {"id": 0, "name": "Millicent Norman"} + ])); - let s = selector("$.school.friends[:-2]", "./benches/data_obj.json"); - let friends = json!([ - {"id": 0, "name": "Millicent Norman"} - ]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$..friends[2].name", read_json("./benches/data_obj.json"), json!([ + "Gray Berry", "Gray Berry" + ])); - let s = selector("$..friends[2].name", "./benches/data_obj.json"); - let friends = json!(["Gray Berry", "Gray Berry"]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$..friends[*].name", read_json("./benches/data_obj.json"), json!([ + "Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry" + ])); - 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, s.select_as_value().unwrap()); + select_and_then_compare("$['school']['friends'][*].['name']", read_json("./benches/data_obj.json"), json!([ + "Millicent Norman","Vincent Cannon","Gray Berry" + ])); - let s = selector("$['school']['friends'][*].['name']", "./benches/data_obj.json"); - let friends = json!(["Millicent Norman","Vincent Cannon","Gray Berry"]); - assert_eq!(friends, s.select_as_value().unwrap()); - - let s = selector("$['school']['friends'][0].['name']", "./benches/data_obj.json"); - let friends = json!("Millicent Norman"); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$['school']['friends'][0].['name']", read_json("./benches/data_obj.json"), json!([ + "Millicent Norman" + ])); } #[test] fn return_type() { setup(); - let friends = json!({ - "friends": [ - {"id": 0, "name": "Millicent Norman"}, - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ] - }); - - let s = selector("$.school", "./benches/data_obj.json"); - assert_eq!(friends, s.select_as_value().unwrap()); - - let s = selector("$.school[?(@.friends[0])]", "./benches/data_obj.json"); - assert_eq!(friends, s.select_as_value().unwrap()); - - let s = selector("$.school[?(@.friends[10])]", "./benches/data_obj.json"); - assert_eq!(Value::Null, s.select_as_value().unwrap()); - - let s = selector("$.school[?(1==1)]", "./benches/data_obj.json"); - assert_eq!(friends, s.select_as_value().unwrap()); - - let s = selector("$.school.friends[?(1==1)]", "./benches/data_obj.json"); - let friends = json!([ + select_and_then_compare("$.school", read_json("./benches/data_obj.json"), json!([{ + "friends": [ {"id": 0, "name": "Millicent Norman"}, {"id": 1, "name": "Vincent Cannon" }, {"id": 2, "name": "Gray Berry"} - ]); - assert_eq!(friends, s.select_as_value().unwrap()); + ] + }])); + + select_and_then_compare("$.school[?(@.friends[0])]", read_json("./benches/data_obj.json"), json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }])); + + select_and_then_compare("$.school[?(@.friends[10])]", read_json("./benches/data_obj.json"), json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }])); + + select_and_then_compare("$.school[?(1==1)]", read_json("./benches/data_obj.json"), json!([{ + "friends": [ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ] + }])); + + select_and_then_compare("$.school.friends[?(1==1)]", read_json("./benches/data_obj.json"), json!([[ + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ]])); } #[test] fn op_default() { setup(); - let s = selector("$.school[?(@.friends == @.friends)]", "./benches/data_obj.json"); - let friends = json!({ + select_and_then_compare("$.school[?(@.friends == @.friends)]", read_json("./benches/data_obj.json"), json!([{ "friends": [ {"id": 0, "name": "Millicent Norman"}, {"id": 1, "name": "Vincent Cannon" }, {"id": 2, "name": "Gray Berry"} ] - }); - assert_eq!(friends, s.select_as_value().unwrap()); + }])); - 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, s.select_as_value().unwrap()); + select_and_then_compare("$.friends[?(@.name)]", read_json("./benches/data_obj.json"), json!([ + { "id" : 1, "name" : "Vincent Cannon" }, + { "id" : 2, "name" : "Gray Berry" } + ])); - let s = selector("$.friends[?(@.id >= 2)]", "./benches/data_obj.json"); - let friends = json!([ - { "id" : 2, "name" : "Gray Berry" } - ]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$.friends[?(@.id >= 2)]", read_json("./benches/data_obj.json"), json!([ + { "id" : 2, "name" : "Gray Berry" } + ])); - 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, s.select_as_value().unwrap()); + select_and_then_compare("$.friends[?(@.id >= 2 || @.id == 1)]", read_json("./benches/data_obj.json"), json!([ + { "id" : 2, "name" : "Gray Berry" }, + { "id" : 1, "name" : "Vincent Cannon" } + ])); - let s = selector("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json"); - assert_eq!(Value::Null, s.select_as_value().unwrap()); + select_and_then_compare("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", read_json("./benches/data_obj.json"), json!([ + Value::Null + ])); - let s = selector("$..friends[?(@.id == $.index)].id", "./benches/data_obj.json"); - let friends = json!([0, 0]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$..friends[?(@.id == $.index)].id", read_json("./benches/data_obj.json"), json!([ + 0, 0 + ])); - let s = selector("$..book[?($.store.bicycle.price < @.price)].price", "./benches/example.json"); - let friends = json!([22.99]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$..book[?($.store.bicycle.price < @.price)].price", read_json("./benches/example.json"), json!([ + 22.99 + ])); - let s = selector("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", "./benches/example.json"); - let friends = json!([12.99]); - assert_eq!(friends, s.select_as_value().unwrap()); + select_and_then_compare("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", read_json("./benches/example.json"), json!([ + 12.99 + ])); - let ref value = json!([ + select_and_then_compare("$..[?(@.age > 40)]", json!([ { "name": "이름1", "age": 40, "phone": "+33 12341234" }, { "name": "이름2", "age": 42, "phone": "++44 12341234" } - ]); - - 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, s.select_as_value().unwrap()); + ]), json!([ + { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } + ])); - let ref value = json!({ + select_and_then_compare("$..[?(@.age >= 30)]", json!({ "school": { "friends": [ {"name": "친구1", "age": 20}, @@ -227,246 +144,208 @@ fn op_default() { "friends": [ {"name": "친구3", "age": 30}, {"name": "친구4"} - ]}); - let mut s = Selector::new(); - let _ = s.path("$..[?(@.age >= 30)]"); - let _ = s.value(value); - let friends = json!([{ "name" : "친구3", "age" : 30 }]); - assert_eq!(friends, s.select_as_value().unwrap()); + ]}), json!([ + { "name" : "친구3", "age" : 30 } + ])); } #[test] fn op_number() { setup(); - let json = json!({ "a": 1 }); - let ret = jsonpath::select(&json, "$.[?(@.a == 1)]").unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, "$.[?(@.a != 2)]").unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, "$.[?(@.a < 2)]").unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, "$.[?(@.a <= 1)]").unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, "$.[?(@.a > 0)]").unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, "$.[?(@.a >= 0)]").unwrap(); - assert_eq!(json, ret); + select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); + select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); + select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }])); + select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }])); + select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); + select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }])); } #[test] fn op_string() { setup(); - let json = json!({ "a": "b" }); - let ret = jsonpath::select(&json, r#"$.[?(@.a == "b")]"#).unwrap(); - assert_eq!(json!({ "a": "b" }), ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a != "c")]"#).unwrap(); - assert_eq!(json!({ "a": "b" }), ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a < "b")]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a <= "b")]"#).unwrap(); - assert_eq!(json!({ "a": "b" }), ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a > "b")]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a >= "b")]"#).unwrap(); - assert_eq!(json!({ "a": "b" }), ret); + select_and_then_compare(r#"$.[?(@.a == "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }])); + select_and_then_compare(r#"$.[?(@.a != "c")]"#, json!({ "a": "b" }), json!([{ "a": "b" }])); + select_and_then_compare(r#"$.[?(@.a < "b")]"#, json!({ "a": "b" }), json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a <= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }])); + select_and_then_compare(r#"$.[?(@.a > "b")]"#, json!({ "a": "b" }), json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a >= "b")]"#, json!({ "a": "b" }), json!([{ "a": "b" }])); } #[test] fn op_object() { setup(); - let json = json!({ - "a": { "1": 1 }, - "b": { "2": 2 }, - "c": { "1": 1 }, - }); - let ret = jsonpath::select(&json, r#"$.[?(@.a == @.c)]"#).unwrap(); - assert_eq!(json, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a != @.c)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a < @.c)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a <= @.c)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a > @.c)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a >= @.c)]"#).unwrap(); - assert_eq!(Value::Null, ret); + select_and_then_compare(r#"$.[?(@.a == @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}])); + select_and_then_compare(r#"$.[?(@.a != @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a < @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a <= @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a > @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a >= @.c)]"#, + json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}), + json!([Value::Null])); } #[test] fn op_complex() { setup(); - let json = json!({ "a": { "b": 1 } }); - let ret = jsonpath::select(&json, r#"$.[?(1 == @.a)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?("1" != @.a)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a <= 1)]"#).unwrap(); - assert_eq!(Value::Null, ret); - let ret = jsonpath::select(&json, r#"$.[?(@.a > "1")]"#).unwrap(); - assert_eq!(Value::Null, ret); + select_and_then_compare(r#"$.[?(1 == @.a)]"#, json!({ "a": { "b": 1 } }), json!([Value::Null])); + select_and_then_compare(r#"$.[?("1" != @.a)]"#, json!({ "a": { "b": 1 } }), json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a <= 1)]"#, json!({ "a": { "b": 1 } }), json!([Value::Null])); + select_and_then_compare(r#"$.[?(@.a > "1")]"#, json!({ "a": { "b": 1 } }), json!([Value::Null])); } #[test] fn example() { setup(); - 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, s.select_as_value().unwrap()); + select_and_then_compare(r#"$.store.book[*].author"#, read_json("./benches/example.json"), json!([ + "Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien" + ])); - let s = selector("$..author", "./benches/example.json"); - assert_eq!(ret, s.select_as_value().unwrap()); + select_and_then_compare(r#"$..author"#, read_json("./benches/example.json"), json!([ + "Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien" + ])); - let s = selector("$.store.*", "./benches/example.json"); - let ret = json!([ - [ + select_and_then_compare(r#"$.store.*"#, read_json("./benches/example.json"), json!([ + [ {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, {"category" : "fiction", "author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}, {"category" : "fiction", "author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, {"category" : "fiction", "author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} ], {"color" : "red","price" : 19.95}, - ]); - assert_eq!(ret, s.select_as_value().unwrap()); + ])); - let s = selector("$.store..price", "./benches/example.json"); - let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); - assert_eq!(ret, s.select_as_value().unwrap()); + select_and_then_compare(r#"$.store..price"#, read_json("./benches/example.json"), json!([ + 8.95, 12.99, 8.99, 22.99, 19.95 + ])); - let s = selector("$..book[2]", "./benches/example.json"); - let ret = json!([{ + select_and_then_compare(r#"$..book[2]"#, read_json("./benches/example.json"), json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + } + ])); + + select_and_then_compare(r#"$..book[-2]"#, read_json("./benches/example.json"), json!([ + { "category" : "fiction", "author" : "Herman Melville", "title" : "Moby Dick", "isbn" : "0-553-21311-3", "price" : 8.99 - }]); - assert_eq!(ret, s.select_as_value().unwrap()); + } + ])); - let s = selector("$..book[-2]", "./benches/example.json"); - let ret = json!([{ + select_and_then_compare(r#"$..book[0, 1]"#, read_json("./benches/example.json"), json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Evelyn Waugh", + "title" : "Sword of Honour", + "price" : 12.99 + } + ])); + + select_and_then_compare(r#"$..book[:2]"#, read_json("./benches/example.json"), json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Evelyn Waugh", + "title" : "Sword of Honour", + "price" : 12.99 + } + ])); + + select_and_then_compare(r#"$..book[2:]"#, read_json("./benches/example.json"), json!([ + { "category" : "fiction", "author" : "Herman Melville", "title" : "Moby Dick", "isbn" : "0-553-21311-3", "price" : 8.99 - }]); - assert_eq!(ret, s.select_as_value().unwrap()); + }, + { + "category" : "fiction", + "author" : "J. R. R. Tolkien", + "title" : "The Lord of the Rings", + "isbn" : "0-395-19395-8", + "price" : 22.99 + } + ])); - let s = selector("$..book[0,1]", "./benches/example.json"); - let ret = json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Evelyn Waugh", - "title" : "Sword of Honour", - "price" : 12.99 - } - ]); - assert_eq!(ret, s.select_as_value().unwrap()); + select_and_then_compare(r#"$..book[?(@.isbn)]"#, read_json("./benches/example.json"), json!([ + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }, + { + "category" : "fiction", + "author" : "J. R. R. Tolkien", + "title" : "The Lord of the Rings", + "isbn" : "0-395-19395-8", + "price" : 22.99 + } + ])); - let s = selector("$..book[:2]", "./benches/example.json"); - let ret = json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Evelyn Waugh", - "title" : "Sword of Honour", - "price" : 12.99 - } - ]); - assert_eq!(ret, s.select_as_value().unwrap()); + select_and_then_compare(r#"$.store.book[?(@.price < 10)]"#, read_json("./benches/example.json"), json!([ + { + "category" : "reference", + "author" : "Nigel Rees", + "title" : "Sayings of the Century", + "price" : 8.95 + }, + { + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + } + ])); - let s = selector("$..book[2:]", "./benches/example.json"); - let ret = json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - }, - { - "category" : "fiction", - "author" : "J. R. R. Tolkien", - "title" : "The Lord of the Rings", - "isbn" : "0-395-19395-8", - "price" : 22.99 - } - ]); - assert_eq!(ret, s.select_as_value().unwrap()); - - let s = selector("$..book[?(@.isbn)]", "./benches/example.json"); - let ret = json!([ - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - }, - { - "category" : "fiction", - "author" : "J. R. R. Tolkien", - "title" : "The Lord of the Rings", - "isbn" : "0-395-19395-8", - "price" : 22.99 - } - ]); - assert_eq!(ret, s.select_as_value().unwrap()); - - let s = selector("$.store.book[?(@.price < 10)]", "./benches/example.json"); - let ret = json!([ - { - "category" : "reference", - "author" : "Nigel Rees", - "title" : "Sayings of the Century", - "price" : 8.95 - }, - { - "category" : "fiction", - "author" : "Herman Melville", - "title" : "Moby Dick", - "isbn" : "0-553-21311-3", - "price" : 8.99 - } - ]); - assert_eq!(ret, s.select_as_value().unwrap()); - - 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, s.select_as_value().unwrap()); + select_and_then_compare(r#"$..*"#, read_json("./benches/example.json"), + read_json("./benches/giveme_every_thing_result.json")); } #[test] fn filer_same_obj() { setup(); - let mut s = Selector::new(); - let _ = s.path("$..[?(@.a == 1)]"); - let _ = s.value_from_str(r#" - { + select_and_then_compare(r#"$..[?(@.a == 1)]"#, json!({ "a": 1, "b" : {"a": 1}, "c" : {"a": 1} - } - "#); - assert_eq!(s.select_as_value().unwrap(), json!([ + }), json!([ {"a": 1}, {"a": 1} ])); diff --git a/tests/lib.rs b/tests/lib.rs index 6fa8fb0..3ac8f24 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,31 +1,19 @@ -extern crate env_logger; extern crate jsonpath_lib as jsonpath; -extern crate log; extern crate serde; #[macro_use] extern crate serde_json; -use std::io::Read; - -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use serde_json::Value; -fn read_json(path: &str) -> Value { - let mut f = std::fs::File::open(path).unwrap(); - let mut contents = String::new(); - f.read_to_string(&mut contents).unwrap(); - serde_json::from_str(contents.as_str()).unwrap() -} +use common::{compare_result, read_contents, read_json, setup}; -fn read_contents(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 -} +mod common; #[test] fn compile() { + setup(); + let mut template = jsonpath::compile("$..friends[2]"); let json_obj = read_json("./benches/data_obj.json"); let json = template(&json_obj).unwrap(); @@ -33,7 +21,7 @@ fn compile() { {"id": 2,"name": "Gray Berry"}, {"id": 2,"name": "Gray Berry"} ]); - assert_eq!(json, ret); + compare_result(json, ret); let json_obj = read_json("./benches/data_array.json"); let json = template(&json_obj).unwrap(); @@ -41,11 +29,13 @@ fn compile() { {"id": 2,"name": "Gray Berry"}, {"id": 2,"name": "Rosetta Erickson"} ]); - assert_eq!(json, ret); + compare_result(json, ret); } #[test] fn selector() { + setup(); + let json_obj = read_json("./benches/data_obj.json"); let mut reader = jsonpath::selector(&json_obj); let json = reader("$..friends[2]").unwrap(); @@ -53,27 +43,26 @@ fn selector() { {"id": 2,"name": "Gray Berry"}, {"id": 2,"name": "Gray Berry"} ]); - assert_eq!(json, ret); + compare_result(json, ret); let json = reader("$..friends[0]").unwrap(); let ret = json!([ {"id": 0}, {"id": 0,"name": "Millicent Norman"} ]); - assert_eq!(json, ret); + compare_result(json, ret); } #[test] fn selector_as() { - let json_obj = read_json("./benches/data_obj.json"); - let mut selector = jsonpath::selector_as::>(&json_obj); - - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Deserialize, PartialEq, Debug)] struct Friend { id: u8, name: Option, } + let json_obj = read_json("./benches/data_obj.json"); + let mut selector = jsonpath::selector_as::(&json_obj); let json = selector("$..friends[2]").unwrap(); let ret = vec!( @@ -101,7 +90,7 @@ fn select() { "isbn" : "0-553-21311-3", "price" : 8.99 }]); - assert_eq!(json, ret); + compare_result(json, ret); } #[test] @@ -121,14 +110,14 @@ fn select_str() { #[test] fn test_to_struct() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Deserialize, PartialEq, Debug)] struct Person { name: String, age: u8, phones: Vec, } - let ret: Person = jsonpath::select_as(r#" + let ret: Vec = jsonpath::select_as(r#" { "person": { @@ -148,5 +137,5 @@ fn test_to_struct() { phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], }; - assert_eq!(person, ret); + assert_eq!(vec![person], ret); } \ No newline at end of file diff --git a/tests/modifiable.rs b/tests/modifiable.rs deleted file mode 100644 index 85ac548..0000000 --- a/tests/modifiable.rs +++ /dev/null @@ -1,31 +0,0 @@ -//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/tests/parser.rs b/tests/parser.rs deleted file mode 100644 index b0973fb..0000000 --- a/tests/parser.rs +++ /dev/null @@ -1,312 +0,0 @@ -extern crate env_logger; -extern crate jsonpath_lib as jsonpath; - -use std::result; -use jsonpath::parser::parser::{Parser, ParseToken, NodeVisitor, FilterToken}; - -struct NodeVisitorTestImpl<'a> { - input: &'a str, - stack: Vec, -} - -impl<'a> NodeVisitorTestImpl<'a> { - fn new(input: &'a str) -> Self { - NodeVisitorTestImpl { input, stack: Vec::new() } - } - - fn visit(&mut self) -> result::Result, String> { - let mut parser = Parser::new(self.input); - parser.parse(self)?; - Ok(self.stack.split_off(0)) - } -} - -impl<'a> NodeVisitor for NodeVisitorTestImpl<'a> { - fn visit_token(&mut self, token: ParseToken) { - self.stack.push(token); - } -} - -fn setup() { - let _ = env_logger::try_init(); -} - -fn run(input: &str) -> result::Result, String> { - let mut interpreter = NodeVisitorTestImpl::new(input); - interpreter.visit() -} - -#[test] -fn parse_path() { - setup(); - - assert_eq!(run("$.aa"), Ok(vec![ - ParseToken::Absolute, - ParseToken::In, - ParseToken::Key("aa".to_owned()) - ])); - - assert_eq!(run("$.00.a"), Ok(vec![ - ParseToken::Absolute, - ParseToken::In, - ParseToken::Key("00".to_owned()), - ParseToken::In, - ParseToken::Key("a".to_owned()) - ])); - - assert_eq!(run("$.00.韓창.seok"), Ok(vec![ - ParseToken::Absolute, - ParseToken::In, - ParseToken::Key("00".to_owned()), - ParseToken::In, - ParseToken::Key("韓창".to_owned()), - ParseToken::In, - ParseToken::Key("seok".to_owned()) - ])); - - assert_eq!(run("$.*"), Ok(vec![ - ParseToken::Absolute, - ParseToken::In, - ParseToken::All - ])); - - assert_eq!(run("$..*"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Leaves, - ParseToken::All - ])); - - assert_eq!(run("$..[0]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Leaves, - ParseToken::Array, - ParseToken::Number(0.0), - ParseToken::ArrayEof - ])); - - match run("$.") { - Ok(_) => panic!(), - _ => {} - } - - match run("$..") { - Ok(_) => panic!(), - _ => {} - } - - match run("$. a") { - Ok(_) => panic!(), - _ => {} - } -} - -#[test] -fn parse_array_sytax() { - setup(); - - assert_eq!(run("$.book[?(@.isbn)]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::In, - ParseToken::Key("book".to_string()), - ParseToken::Array, - ParseToken::Relative, - ParseToken::In, - ParseToken::Key("isbn".to_string()), - ParseToken::ArrayEof - ])); - - // - // Array도 컨텍스트 In으로 간주 할거라서 중첩되면 하나만 - // - assert_eq!(run("$.[*]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[*]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[*].가"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof, - ParseToken::In, ParseToken::Key("가".to_owned()) - ])); - - assert_eq!(run("$.a[0][1]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Number(0_f64), - ParseToken::ArrayEof, - ParseToken::Array, - ParseToken::Number(1_f64), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[1,2]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Union(vec![1, 2]), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[10:]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Range(Some(10), None), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[:11]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Range(None, Some(11)), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[-12:13]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Range(Some(-12), Some(13)), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[?(1>2)]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Greater), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$.a[?($.b>3)]"), Ok(vec![ - ParseToken::Absolute, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Array, - ParseToken::Absolute, ParseToken::In, ParseToken::Key("b".to_owned()), ParseToken::Number(3_f64), ParseToken::Filter(FilterToken::Greater), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$[?($.c>@.d && 1==2)]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Absolute, ParseToken::In, ParseToken::Key("c".to_owned()), - ParseToken::Relative, ParseToken::In, ParseToken::Key("d".to_owned()), - ParseToken::Filter(FilterToken::Greater), - ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Equal), - ParseToken::Filter(FilterToken::And), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$[?($.c>@.d&&(1==2||3>=4))]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Absolute, ParseToken::In, ParseToken::Key("c".to_owned()), - ParseToken::Relative, ParseToken::In, ParseToken::Key("d".to_owned()), - ParseToken::Filter(FilterToken::Greater), - ParseToken::Number(1_f64), ParseToken::Number(2_f64), ParseToken::Filter(FilterToken::Equal), - ParseToken::Number(3_f64), ParseToken::Number(4_f64), ParseToken::Filter(FilterToken::GreaterOrEqual), - ParseToken::Filter(FilterToken::Or), - ParseToken::Filter(FilterToken::And), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$[?(@.a<@.b)]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Relative, ParseToken::In, ParseToken::Key("a".to_owned()), - ParseToken::Relative, ParseToken::In, ParseToken::Key("b".to_owned()), - ParseToken::Filter(FilterToken::Little), - ParseToken::ArrayEof - ])); - - assert_eq!(run("$[*][*][*]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof, - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof, - ParseToken::Array, - ParseToken::All, - ParseToken::ArrayEof - ])); - - assert_eq!(run("$['a']['bb']"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Key("a".to_string()), - ParseToken::ArrayEof, - ParseToken::Array, - ParseToken::Key("bb".to_string()), - ParseToken::ArrayEof - ])); - - match run("$[") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[a]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?($.a)]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?(@.a > @.b]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?(@.a < @.b&&(@.c < @.d)]") { - Ok(_) => panic!(), - _ => {} - } -} - -#[test] -fn parse_array_float() { - setup(); - - assert_eq!(run("$[?(1.1<2.1)]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Number(1.1), ParseToken::Number(2.1), ParseToken::Filter(FilterToken::Little), - ParseToken::ArrayEof - ])); - - match run("$[1.1]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?(1.1<.2)]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?(1.1<2.)]") { - Ok(_) => panic!(), - _ => {} - } - - match run("$[?(1.1<2.a)]") { - Ok(_) => panic!(), - _ => {} - } -} \ No newline at end of file diff --git a/tests/readme.rs b/tests/readme.rs index 4243fa5..dc47853 100644 --- a/tests/readme.rs +++ b/tests/readme.rs @@ -3,14 +3,134 @@ extern crate serde; #[macro_use] extern crate serde_json; -use serde::{Deserialize, Serialize}; -use serde_json::Value; +use serde::Deserialize; use jsonpath::Selector; +#[test] +fn readme() { + let json_obj = json!({ + "store": { + "book": [ + { + "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { + "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99 + }, + { + "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + }, + { + "category": "fiction", + "author": "J. R. R. Tolkien", + "title": "The Lord of the Rings", + "isbn": "0-395-19395-8", + "price": 22.99 + } + ], + "bicycle": { + "color": "red", + "price": 19.95 + } + }, + "expensive": 10 + }); + + let mut selector = jsonpath::selector(&json_obj); + + assert_eq!(selector("$.store.book[*].author").unwrap(), + vec![ + "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" + ]); + + assert_eq!(selector("$..author").unwrap(), + vec![ + "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" + ]); + + assert_eq!(selector("$.store.*").unwrap(), + vec![ + &json!([ + { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, + { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, + { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, + { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } + ]), + &json!({ "color": "red", "price": 19.95 }) + ]); + + assert_eq!(selector("$.store..price").unwrap(), + vec![ + 8.95, 12.99, 8.99, 22.99, 19.95 + ]); + + assert_eq!(selector("$..book[2]").unwrap(), + vec![ + &json!({ + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }) + ]); + + assert_eq!(selector("$..book[-2]").unwrap(), + vec![ + &json!({ + "category" : "fiction", + "author" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }) + ]); + + assert_eq!(selector("$..book[0,1]").unwrap(), + vec![ + &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), + &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) + ]); + + assert_eq!(selector("$..book[:2]").unwrap(), + vec![ + &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), + &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) + ]); + + assert_eq!(selector("$..book[:2]").unwrap(), + vec![ + &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), + &json!({"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}) + ]); + + assert_eq!(selector("$..book[?(@.isbn)]").unwrap(), + vec![ + &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}), + &json!({"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}) + ]); + + assert_eq!(selector("$.store.book[?(@.price < 10)]").unwrap(), + vec![ + &json!({"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}), + &json!({"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}) + ]); +} + #[test] fn readme_selector() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Deserialize, PartialEq, Debug)] struct Friend { name: String, age: Option, @@ -32,42 +152,16 @@ fn readme_selector() { let result = selector .path("$..[?(@.age >= 30)]").unwrap() -// .value_from_str(&serde_json::to_string(&json_obj).unwrap() /*&str*/).unwrap() -// .value_from(&json_obj /*&impl serde::ser::Serialize*/).unwrap() - .value(&json_obj /*serde_json::value::Value*/).unwrap() - .select_as_value().unwrap(); + .value(&json_obj) + .select().unwrap(); - assert_eq!(json!([{"name": "친구3", "age": 30}]), result); + assert_eq!(vec![&json!({"name": "친구3", "age": 30})], result); let result = selector.select_as_str().unwrap(); assert_eq!(r#"[{"name":"친구3","age":30}]"#, result); - let result = selector.select_as::>().unwrap(); + let result = selector.select_as::().unwrap(); assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result); - - let _ = selector.map(|v| { - let r = match v { - Value::Array(mut vec) => { - for v in &mut vec { - v.as_object_mut().unwrap().remove("age"); - } - Value::Array(vec) - } - _ => Value::Null - }; - Some(r) - }); - assert_eq!(json!([{ "name": "친구3"}]), selector.get().unwrap()); - - let _ = selector.value(&json_obj).unwrap() - .map_as(|mut v: Vec| { - let mut f = v.pop().unwrap(); - f.name = "friend3".to_string(); - f.age = None; - Some(vec![f]) - }); - assert_eq!(vec![Friend { name: "friend3".to_string(), age: None }], - selector.get_as::>().unwrap()); } #[test] @@ -86,11 +180,10 @@ fn readme_select() { let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap(); - let ret = json!([ - {"name": "친구3", "age": 30}, - {"name": "친구1", "age": 20} + assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) ]); - assert_eq!(json, ret); } #[test] @@ -122,7 +215,7 @@ fn readme_select_as() { phones: Vec, } - let ret: Person = jsonpath::select_as(r#" + let ret: Vec = jsonpath::select_as(r#" { "person": { @@ -142,7 +235,7 @@ fn readme_select_as() { phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], }; - assert_eq!(person, ret); + assert_eq!(ret[0], person); } #[test] @@ -163,12 +256,10 @@ fn readme_compile() { let json = template(&json_obj).unwrap(); - let ret = json!([ - {"name": "친구3", "age": 30}, - {"name": "친구1", "age": 20} + assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) ]); - - assert_eq!(json, ret); } #[test] @@ -189,21 +280,17 @@ fn readme_selector_fn() { let json = selector("$..friends[0]").unwrap(); - let ret = json!([ - {"name": "친구3", "age": 30}, - {"name": "친구1", "age": 20} + assert_eq!(json, vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) ]); - assert_eq!(json, ret); - let json = selector("$..friends[1]").unwrap(); - let ret = json!([ - {"name": "친구4"}, - {"name": "친구2", "age": 20} + assert_eq!(json, vec![ + &json!({"name": "친구4"}), + &json!({"name": "친구2", "age": 20}) ]); - - assert_eq!(json, ret); } #[test] @@ -220,13 +307,13 @@ fn readme_selector_as() { {"name": "친구4"} ]}); - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Deserialize, PartialEq, Debug)] struct Friend { name: String, age: Option, } - let mut selector = jsonpath::selector_as::>(&json_obj); + let mut selector = jsonpath::selector_as::(&json_obj); let json = selector("$..friends[0]").unwrap(); diff --git a/tests/selector.rs b/tests/selector.rs deleted file mode 100644 index 464761d..0000000 --- a/tests/selector.rs +++ /dev/null @@ -1,209 +0,0 @@ -extern crate jsonpath_lib as jsonpath; -extern crate serde; -#[macro_use] -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: u8, - phone: String, -} - -fn input_str() -> &'static str { - r#"[ - { - "name": "이름1", - "age": 40, - "phone": "+33 12341234" - }, - { - "name": "이름2", - "age": 42, - "phone": "++44 12341234" - }, - { - "name": "이름3", - "age": 50, - "phone": "++55 111111" - }, - { - "name": "이름4", - "age": 51, - "phone": "++55 12341234" - } - ]"# -} - -fn input_json() -> Value { - serde_json::from_str(input_str()).unwrap() -} - -fn input_person() -> Vec { - serde_json::from_str(input_str()).unwrap() -} - -#[test] -fn selector_value_from() { - let result = Selector::new() - .path("$..[?(@.age > 40)]").unwrap() - .value_from(&input_person()).unwrap() - .select_as::>().unwrap(); - assert_eq!(input_person()[1], result[0]); -} - -#[test] -fn selector_value() { - let result = Selector::new() - .path("$..[?(@.age > 40)]").unwrap() - .value((&input_json()).into()).unwrap() - .select_as_value().unwrap(); - assert_eq!(input_json()[1], result[0]); -} - -#[test] -fn selector_value_from_str() { - let result = Selector::new() - .path("$..[?(@.age > 40)]").unwrap() - .value_from_str(input_str()).unwrap() - .select_as_value().unwrap(); - assert_eq!(input_json()[1], result[0]); -} - -#[test] -fn selector_select_to() { - 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(); - let value: Value = serde_json::from_str(&result).unwrap(); - assert_eq!(input_json()[1], value[0]); - - 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]); -} - -fn _remove_name(v: Value) -> Option { - let r = match v { - Value::Array(mut vec) => { - for v in &mut vec { - v.as_object_mut().unwrap().remove("name"); - } - Value::Array(vec) - } - _ => Value::Null - }; - Some(r) -} - -fn _change_phone_number(v: Value) -> Option { - let r = match v { - Value::Array(mut vec) => { - let mut v = vec.pop().unwrap(); - v.as_object_mut().unwrap() - .insert("phone".to_string(), Value::String("1234".to_string())); - v - } - _ => Value::Null - }; - Some(r) -} - -fn _rejuvenate(mut vec: Vec) -> Option> { - for p in &mut vec { - p.age = p.age - 10; - } - Some(vec) -} - -#[test] -fn selector_map_basic() { - let mut selector = Selector::new(); - - let result = selector - .path("$..[?(@.age > 40)]").unwrap() - .value_from_str(input_str()).unwrap() - .map(_remove_name).unwrap() - .get().unwrap(); - - assert_eq!(result, json!([ - {"phone": "++44 12341234", "age": 42}, - {"phone": "++55 111111", "age": 50}, - {"phone": "++55 12341234", "age": 51}, - ])); -} - -#[test] -fn selector_map() { - let mut selector = Selector::new(); - - let result = selector - .path("$..[?(@.age > 40)]").unwrap() - .value_from_str(input_str()).unwrap() - .map(_remove_name).unwrap() - .path("$..[?(@.age == 50)]").unwrap() - .map(_change_phone_number).unwrap() - .get().unwrap(); - - assert_eq!(result, json!({ - "phone": "1234", - "age": 50, - })); -} - -#[test] -fn selector_map_as_basic() { - let mut selector = Selector::new(); - - let result = selector - .path("$..[?(@.age > 40)]").unwrap() - .value_from_str(input_str()).unwrap() - .map_as(_rejuvenate).unwrap() - .get().unwrap(); - - assert_eq!(result, json!([ - {"name": "이름2", "phone": "++44 12341234", "age": 32}, - {"name": "이름3", "phone": "++55 111111", "age": 40}, - {"name": "이름4", "phone": "++55 12341234", "age": 41}, - ])); -} - -#[test] -fn selector_map_as() { - let mut selector = Selector::new(); - - let result = selector - .path("$..[?(@.age > 40)]").unwrap() - .value_from_str(input_str()).unwrap() - .map_as(_rejuvenate).unwrap() - .path("$..[?(@.age == 40)]").unwrap() - .map(_change_phone_number).unwrap() - .get().unwrap(); - - assert_eq!(result, json!({ - "name": "이름3", - "phone": "1234", - "age": 40, - })); -} diff --git a/tests/serde.rs b/tests/serde.rs deleted file mode 100644 index 5723ac0..0000000 --- a/tests/serde.rs +++ /dev/null @@ -1,39 +0,0 @@ -extern crate jsonpath_lib as jsonpath; -extern crate serde; -extern crate serde_json; - -use std::io::Read; - -use serde_json::Value; -use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; - -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 -} - -#[test] -fn de() { - let json_str = read_json("./benches/example.json"); - // RefValue -> Value - let ref_value: RefValue = serde_json::from_str(json_str.as_str()).unwrap(); - let ref value_wrapper: RefValueWrapper = ref_value.into(); - let value: Value = value_wrapper.into(); - - // Value - let json: Value = serde_json::from_str(json_str.as_str()).unwrap(); - assert_eq!(value, json); -} - -#[test] -fn ser() { - let json_str = read_json("./benches/example.json"); - let ref_value: RefValue = serde_json::from_str(json_str.as_str()).unwrap(); - let ref_value_str = serde_json::to_string(&ref_value).unwrap(); - - let json: Value = serde_json::from_str(json_str.as_str()).unwrap(); - let json_str = serde_json::to_string(&json).unwrap(); - assert_eq!(ref_value_str, json_str); -} \ No newline at end of file diff --git a/tests/tokenizer.rs b/tests/tokenizer.rs deleted file mode 100644 index dbd14f8..0000000 --- a/tests/tokenizer.rs +++ /dev/null @@ -1,194 +0,0 @@ -extern crate jsonpath_lib as jsonpath; - -use jsonpath::parser::tokenizer::{Tokenizer, Token, TokenError, PreloadedTokenizer}; - -fn collect_token(input: &str) -> (Vec, Option) { - let mut tokenizer = Tokenizer::new(input); - let mut vec = vec![]; - loop { - match tokenizer.next_token() { - Ok(t) => vec.push(t), - Err(e) => return (vec, Some(e)), - } - } -} - -fn run(input: &str, expected: (Vec, Option)) { - let (vec, err) = collect_token(input.clone()); - assert_eq!((vec, err), expected, "\"{}\"", input); -} - -#[test] -fn peek() { - let mut tokenizer = PreloadedTokenizer::new("$.a"); - match tokenizer.next_token() { - Ok(t) => assert_eq!(Token::Absolute(0), t), - _ => panic!() - } - - match tokenizer.peek_token() { - Ok(t) => assert_eq!(&Token::Dot(1), t), - _ => panic!() - } - - match tokenizer.peek_token() { - Ok(t) => assert_eq!(&Token::Dot(1), t), - _ => panic!() - } - - match tokenizer.next_token() { - Ok(t) => assert_eq!(Token::Dot(1), t), - _ => panic!() - } -} - -#[test] -fn token() { - run("$.01.a", - ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Key(2, "01".to_string()), - Token::Dot(4), - Token::Key(5, "a".to_string()) - ] - , Some(TokenError::Eof) - )); - - run("$. []", - ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Whitespace(2, 2), - Token::OpenArray(5), - Token::CloseArray(6) - ] - , Some(TokenError::Eof) - )); - - run("$..", - ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Dot(2), - ] - , Some(TokenError::Eof) - )); - - run("$..ab", - ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Dot(2), - Token::Key(3, "ab".to_string()) - ] - , Some(TokenError::Eof) - )); - - run("$..가 [", - ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Dot(2), - Token::Key(3, "가".to_string()), - Token::Whitespace(6, 0), - Token::OpenArray(7), - ] - , Some(TokenError::Eof) - )); - - run("[-1, 2 ]", - ( - vec![ - Token::OpenArray(0), - Token::Key(1, "-1".to_string()), - Token::Comma(3), - Token::Whitespace(4, 0), - Token::Key(5, "2".to_string()), - Token::Whitespace(6, 0), - Token::CloseArray(7), - ] - , Some(TokenError::Eof) - )); - - run("[ 1 2 , 3 \"abc\" : -10 ]", - ( - vec![ - Token::OpenArray(0), - Token::Whitespace(1, 0), - Token::Key(2, "1".to_string()), - Token::Whitespace(3, 0), - Token::Key(4, "2".to_string()), - Token::Whitespace(5, 0), - Token::Comma(6), - Token::Whitespace(7, 0), - Token::Key(8, "3".to_string()), - Token::Whitespace(9, 0), - Token::DoubleQuoted(10, "abc".to_string()), - Token::Whitespace(15, 0), - Token::Split(16), - Token::Whitespace(17, 0), - Token::Key(18, "-10".to_string()), - Token::Whitespace(21, 0), - Token::CloseArray(22), - ] - , Some(TokenError::Eof) - )); - - run("?(@.a가 <41.01)", - ( - vec![ - Token::Question(0), - Token::OpenParenthesis(1), - Token::At(2), - Token::Dot(3), - Token::Key(4, "a가".to_string()), - Token::Whitespace(8, 0), - Token::Little(9), - Token::Key(10, "41".to_string()), - Token::Dot(12), - Token::Key(13, "01".to_string()), - Token::CloseParenthesis(15), - ] - , Some(TokenError::Eof) - )); - - run("?(@.a <4a.01)", - ( - vec![ - Token::Question(0), - Token::OpenParenthesis(1), - Token::At(2), - Token::Dot(3), - Token::Key(4, "a".to_string()), - Token::Whitespace(5, 0), - Token::Little(6), - Token::Key(7, "4a".to_string()), - Token::Dot(9), - Token::Key(10, "01".to_string()), - Token::CloseParenthesis(12), - ] - , Some(TokenError::Eof) - )); - - run("?($.c>@.d)", ( - vec![ - Token::Question(0), - Token::OpenParenthesis(1), - Token::Absolute(2), - Token::Dot(3), - Token::Key(4, "c".to_string()), - Token::Greater(5), - Token::At(6), - Token::Dot(7), - Token::Key(8, "d".to_string()), - Token::CloseParenthesis(9) - ] - , Some(TokenError::Eof) - )); -} \ No newline at end of file diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index fa4bd9d..dc13ab0 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath-wasm" -version = "0.1.3" +version = "0.2.0" authors = ["Changseok Han "] description = "It is Webassembly version of jsonpath_lib that is JsonPath engine written in Rust - Demo: https://freestrings.github.io/jsonpath" keywords = ["jsonpath", "json", "webassembly", "parsing", "rust"] diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index db0d4c2..ce1eefb 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -1,4 +1,5 @@ extern crate cfg_if; +extern crate core; extern crate js_sys; extern crate jsonpath_lib as jsonpath; extern crate serde; @@ -6,19 +7,12 @@ extern crate serde_json; extern crate wasm_bindgen; extern crate web_sys; -use std::ops::Deref; -use std::result; -use std::result::Result; - use cfg_if::cfg_if; -use jsonpath::filter::value_filter::JsonValueFilter; -use jsonpath::parser::parser::{Node, NodeVisitor, Parser}; -use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; +use jsonpath::{JsonPathError, Parser}; use jsonpath::Selector as _Selector; use serde_json::Value; use wasm_bindgen::*; use wasm_bindgen::prelude::*; -use web_sys::console; cfg_if! { if #[cfg(feature = "wee_alloc")] { @@ -38,16 +32,6 @@ cfg_if! { } } -fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue { - 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 where D: for<'a> serde::de::Deserialize<'a> { @@ -64,26 +48,27 @@ fn into_serde_json(js_value: &JsValue) -> Result } } -fn into_ref_value(js_value: &JsValue, node: Node) -> JsValue { - let result: result::Result = into_serde_json::(js_value); - match result { - Ok(json) => filter_ref_value(json.into(), node), - Err(e) => JsValue::from_str(&format!("Json serialize error: {}", e)) - } -} - -fn get_ref_value(js_value: JsValue, node: Node) -> JsValue { - into_ref_value(&js_value, node) -} - #[wasm_bindgen] pub fn compile(path: &str) -> JsValue { let mut parser = Parser::new(path); let node = parser.compile(); + let cb = Closure::wrap(Box::new(move |js_value: JsValue| { + let mut selector = _Selector::new(); match &node { - Ok(node) => get_ref_value(js_value, node.clone()), - Err(e) => JsValue::from_str(&format!("Json path error: {:?}", e)) + Ok(node) => selector.compiled_path(node.clone()), + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone()))) + }; + let json = match into_serde_json(&js_value) { + Ok(json) => json, + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + }; + match selector.value(&json).select() { + Ok(ret) => match JsValue::from_serde(&ret) { + Ok(ret) => ret, + Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))) + }, + Err(e) => JsValue::from_str(&format!("{:?}", e)) } }) as Box JsValue>); @@ -94,16 +79,26 @@ pub fn compile(path: &str) -> JsValue { #[wasm_bindgen] pub fn selector(js_value: JsValue) -> JsValue { - let json: RefValueWrapper = match into_serde_json::(&js_value) { - Ok(json) => json.into(), - Err(e) => return JsValue::from_str(e.as_str()) + let json: Value = match JsValue::into_serde(&js_value) { + Ok(json) => json, + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))) }; 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()) + Ok(node) => { + let mut selector = _Selector::new(); + let _ = selector.compiled_path(node); + match selector.value(&json).select() { + Ok(ret) => match JsValue::from_serde(&ret) { + Ok(ret) => ret, + Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))) + }, + Err(e) => JsValue::from_str(&format!("{:?}", e)) + } + } + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e))) } }) as Box JsValue>); @@ -114,105 +109,76 @@ pub fn selector(js_value: JsValue) -> JsValue { #[wasm_bindgen] pub fn select(js_value: JsValue, path: &str) -> JsValue { - let mut parser = Parser::new(path); - match parser.compile() { - Ok(node) => get_ref_value(js_value, node), - Err(e) => return JsValue::from_str(e.as_str()) + let mut selector = _Selector::new(); + let _ = selector.path(path); + + let json = match into_serde_json(&js_value) { + Ok(json) => json, + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + }; + + match selector.value(&json).select() { + Ok(ret) => match JsValue::from_serde(&ret) { + Ok(ret) => ret, + Err(e) => JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))) + }, + Err(e) => JsValue::from_str(&format!("{:?}", e)) } } /// /// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다. +/// lifetime 제약으로 Selector를 사용 할 수 없다. /// #[wasm_bindgen] pub struct Selector { - selector: _Selector + path: Option, + value: Option, } #[wasm_bindgen] impl Selector { #[wasm_bindgen(constructor)] pub fn new() -> Self { - Selector { selector: _Selector::new() } + Selector { path: None, value: None } } #[wasm_bindgen(catch)] - pub fn path(&mut self, path: &str) -> result::Result<(), JsValue> { - let _ = self.selector.path(path)?; + pub fn path(&mut self, path: &str) -> Result<(), JsValue> { + self.path = Some(path.to_string()); Ok(()) } #[wasm_bindgen(catch)] - pub fn value(&mut self, value: JsValue) -> result::Result<(), JsValue> { - let ref ref_value = into_serde_json(&value)?; - let _ = self.selector.value(ref_value)?; + pub fn value(&mut self, value: JsValue) -> Result<(), JsValue> { + let json = into_serde_json(&value) + .map_err(|e| JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))))?; + self.value = Some(json); Ok(()) } - #[wasm_bindgen(catch, js_name = selectToStr)] - pub fn select_to_str(&mut self) -> result::Result { - self.select_as_str() - } + #[wasm_bindgen(catch, js_name = select)] + pub fn select(&mut self) -> Result { + let mut selector = _Selector::new(); - #[wasm_bindgen(catch, js_name = selectAsStr)] - pub fn select_as_str(&mut self) -> result::Result { - let json_str = self.selector.select_as_str()?; - Ok(JsValue::from_str(&json_str)) - } - - #[wasm_bindgen(catch, js_name = selectTo)] - pub fn select_to(&mut self) -> result::Result { - self.select_as() - } - - #[wasm_bindgen(catch, js_name = selectAs)] - pub fn select_as(&mut self) -> result::Result { - let ref_value = self.selector.select_as::() - .map_err(|e| JsValue::from_str(&e))?; - Ok(JsValue::from_serde(&ref_value) - .map_err(|e| JsValue::from_str(&e.to_string()))?) - } - - #[wasm_bindgen(catch)] - pub fn map(&mut self, func: JsValue) -> result::Result<(), JsValue> { - if !func.is_function() { - return Err(JsValue::from_str("Not a function argument")); + if let Some(path) = &self.path { + let _ = selector.path(&path).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?; + } else { + return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath))); } - let cb: &js_sys::Function = JsCast::unchecked_ref(func.as_ref()); + if let Some(value) = &self.value { + let _ = selector.value(value); + } else { + return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue))); + } - self.selector.map(|v| { - let str_value = match JsValue::from_serde(&v) { - Ok(str_value) => str_value, - Err(e) => return { - console::error_1(&JsValue::from_str(&e.to_string())); - None - } - }; - - match cb.call1(&func, &str_value) { - Ok(ret) => { - match into_serde_json::(&ret) { - Ok(value) => Some(value), - Err(e) => { - console::error_1(&JsValue::from_str(&e.to_string())); - None - } - } - } - Err(e) => { - console::error_1(&e); - None - } - } - }).map_err(|e| JsValue::from_str(&e))?; - - Ok(()) - } - - #[wasm_bindgen(catch)] - pub fn get(&mut self) -> result::Result { - 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())) + match selector.select() { + Ok(ret) => match JsValue::from_serde(&ret) { + Ok(ret) => Ok(ret), + Err(e) => Err(JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string())))) + }, + Err(e) => Err(JsValue::from_str(&format!("{:?}", e))) + } } } \ No newline at end of file diff --git a/wasm/tests/test/index.spec.js b/wasm/tests/test/index.spec.js index f64d094..8af3495 100644 --- a/wasm/tests/test/index.spec.js +++ b/wasm/tests/test/index.spec.js @@ -359,7 +359,7 @@ describe('compile test', () => { it('basic', (done) => { let template = jsonpath.compile('$.a'); let result = template({'a': 1}); - if (result === 1) { + if (result[0] === 1) { done(); } }); @@ -369,7 +369,7 @@ describe('selector test', () => { it('basic', (done) => { let selector = jsonpath.selector({'a': 1}); let result = selector('$.a'); - if (result === 1) { + if (result[0] === 1) { done(); } }); @@ -378,7 +378,7 @@ describe('selector test', () => { describe('select test', () => { it('basic', (done) => { let result = jsonpath.select({'a': 1}, '$.a'); - if (result === 1) { + if (result[0] === 1) { done(); } }); @@ -407,7 +407,7 @@ describe('filter test', () => { "b" : {"a": 1}, "c" : {"a": 1} }); - let result = selector.selectAs(); + let result = selector.select(); if (JSON.stringify(result) === JSON.stringify([ {"a": 1}, {"a": 1} ])) { done(); } @@ -415,32 +415,12 @@ describe('filter test', () => { }); describe('Selector test', () => { - it('basic selectTo', (done) => { - let selector = new jsonpath.Selector(); - selector.path('$.a'); - selector.value({'a': 1}); - let result = selector.selectAs(); - if (result === 1) { - done(); - } - }); - - it('basic selectToStr', (done) => { - let selector = new jsonpath.Selector(); - selector.path('$.a'); - selector.value({'a': 1}); - let result = selector.selectToStr(); - if (result === '1') { - done(); - } - }); - it('select', (done) => { let selector = new jsonpath.Selector(); selector.value(jsonObj); for(var i in list) { selector.path(i); - if(JSON.stringify(list[i]) !== selector.selectAsStr()) { + if(JSON.stringify(list[i]) !== JSON.stringify(selector.select())) { throw `fail: ${i}`; } } @@ -468,7 +448,7 @@ describe('README test', () => { { selector.path('$..[?(@.age >= 30)]'); - let jsonObj = selector.selectAs(); + let jsonObj = selector.select(); let resultObj = [{"name": "친구3", "age": 30}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: $..[?(@.age >= 30)]'; @@ -477,7 +457,7 @@ describe('README test', () => { { selector.path('$..[?(@.age == 20)]'); - let jsonObj = selector.selectAs(); + let jsonObj = selector.select(); let resultObj = [{"name": "친구1", "age": 20}, {"name": "친구2", "age": 20}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: $..[?(@.age >= 20)]'; @@ -486,35 +466,13 @@ describe('README test', () => { { selector.value({"friends": [ {"name": "친구5", "age": 20} ]}); - let jsonObj = selector.selectAs(); + let jsonObj = selector.select(); let resultObj = [{"name": "친구5", "age": 20}]; if(JSON.stringify(jsonObj) !== JSON.stringify(resultObj)) { throw 'jsonpath.Selector: change value'; } } - { - selector.value(jsonObj); - selector.map(function(v) { - let f1 = v[0]; - f1.age = 30; - return v; - }) - let jsonObj1 = selector.get(); - - let resultObj1 = [{"name": "친구1", "age": 30}, {"name": "친구2", "age": 20}]; - if(JSON.stringify(jsonObj1) !== JSON.stringify(resultObj1)) { - throw 'jsonpath.Selector.map'; - } - - selector.path('$..[?(@.age == 20)]'); - let jsonObj2 = selector.selectAs(); - let resultObj2 = [{"name": "친구2", "age": 20}]; - if(JSON.stringify(jsonObj2) !== JSON.stringify(resultObj2)) { - throw 'jsonpath.Selector.map and then select'; - } - } - done(); }); diff --git a/wasm/www_bench/index.js b/wasm/www_bench/index.js index 535151a..62e69a6 100644 --- a/wasm/www_bench/index.js +++ b/wasm/www_bench/index.js @@ -73,8 +73,4 @@ run('jsonpath', iterCount, function() { jp.query(json, path) }) .then(function() { return run('jsonpath-wasm- select', iterCount, function() { jpw.select(json, path) }); }) - .finally(function() { - if(!jpw.deallocJson(ptr)) { - console.error('fail to dealloc'); - } - }); + .finally(function() {});