From 6a270c9456b62f71c4bef0c44b87e7fb74927382 Mon Sep 17 00:00:00 2001 From: freestrings Date: Wed, 19 Jun 2019 11:34:47 +0900 Subject: [PATCH] =?UTF-8?q?IntelliJ=20rustfmt=20default=20rule=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nodejs/native/src/lib.rs | 77 ++-- src/lib.rs | 50 ++- src/parser/mod.rs | 890 +++++++++++++++++++++++--------------- src/parser/parser.rs | 248 ++++------- src/parser/path_reader.rs | 11 +- src/parser/tokenizer.rs | 90 ++-- src/select/mod.rs | 309 ++++++++----- tests/common.rs | 21 +- tests/filter.rs | 799 ++++++++++++++++++++++------------ tests/lib.rs | 81 ++-- tests/mutable.rs | 38 +- tests/readme.rs | 416 ++++++++++-------- wasm/src/lib.rs | 143 +++--- 13 files changed, 1866 insertions(+), 1307 deletions(-) diff --git a/nodejs/native/src/lib.rs b/nodejs/native/src/lib.rs index eb778639..7a5eed52 100644 --- a/nodejs/native/src/lib.rs +++ b/nodejs/native/src/lib.rs @@ -18,7 +18,7 @@ fn select(mut ctx: FunctionContext) -> JsResult { match jsonpath::select(&json, path.as_str()) { Ok(value) => Ok(neon_serde::to_value(&mut ctx, &value)?), - Err(e) => panic!("{:?}", e) + Err(e) => panic!("{:?}", e), } } @@ -27,7 +27,7 @@ fn select_str(mut ctx: FunctionContext) -> JsResult { let path = ctx.argument::(1)?.value(); match jsonpath::select_as_str(&json_val, path.as_str()) { Ok(value) => Ok(JsString::new(&mut ctx, &value).upcast()), - Err(e) => panic!("{:?}", e) + Err(e) => panic!("{:?}", e), } } @@ -35,15 +35,19 @@ fn delete(mut ctx: FunctionContext) -> JsResult { let json_val = ctx.argument::(0)?.value(); let json: Value = match serde_json::from_str(&json_val) { Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), }; let path = ctx.argument::(1)?.value(); match jsonpath::delete(json, &path) { - Ok(value) => Ok(JsString::new(&mut ctx, match serde_json::to_string(&value) { - Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) - }).upcast()), - Err(e) => panic!("{:?}", e) + Ok(value) => Ok(JsString::new( + &mut ctx, + match serde_json::to_string(&value) { + Ok(value) => value, + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), + }, + ) + .upcast()), + Err(e) => panic!("{:?}", e), } } @@ -51,36 +55,43 @@ fn replace_with(mut ctx: FunctionContext) -> JsResult { let json_val = ctx.argument::(0)?.value(); let json: Value = match serde_json::from_str(&json_val) { Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), }; let path = ctx.argument::(1)?.value(); let fun = ctx.argument::(2)?; match jsonpath::replace_with(json, &path, &mut |v| { - let json_str = JsString::new(&mut ctx, match serde_json::to_string(v) { - Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) - }); + let json_str = JsString::new( + &mut ctx, + match serde_json::to_string(v) { + Ok(value) => value, + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), + }, + ); let null = ctx.null(); let args = vec![ctx.string(json_str.value())]; let result = match fun.call(&mut ctx, null, args) { Ok(result) => result, - Err(e) => panic!("{:?}", e) + Err(e) => panic!("{:?}", e), }; let json_str = match result.downcast::() { Ok(v) => v.value(), - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), }; match serde_json::from_str(&json_str) { Ok(v) => v, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), } }) { - Ok(value) => Ok(JsString::new(&mut ctx, match serde_json::to_string(&value) { - Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) - }).upcast()), - Err(e) => panic!("{:?}", e) + Ok(value) => Ok(JsString::new( + &mut ctx, + match serde_json::to_string(&value) { + Ok(value) => value, + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), + }, + ) + .upcast()), + Err(e) => panic!("{:?}", e), } } @@ -93,7 +104,7 @@ impl SelectorCls { fn path(&mut self, path: &str) { let node = match Parser::compile(path) { Ok(node) => node, - Err(e) => panic!("{:?}", e) + Err(e) => panic!("{:?}", e), }; self.node = Some(node); @@ -102,7 +113,7 @@ impl SelectorCls { fn value(&mut self, json_str: &str) { let value: Value = match serde_json::from_str(&json_str) { Ok(value) => value, - Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())) + Err(e) => panic!("{:?}", JsonPathError::Serde(e.to_string())), }; self.value = Some(value); @@ -111,12 +122,12 @@ impl SelectorCls { fn select(&self) -> String { let node = match &self.node { Some(node) => node, - None => panic!("{:?}", JsonPathError::EmptyPath) + None => panic!("{:?}", JsonPathError::EmptyPath), }; let value = match &self.value { Some(value) => value, - None => panic!("{:?}", JsonPathError::EmptyValue) + None => panic!("{:?}", JsonPathError::EmptyValue), }; let mut selector = Selector::new(); @@ -124,7 +135,7 @@ impl SelectorCls { selector.value(&value); match selector.select_as_str() { Ok(ret) => ret, - Err(e) => panic!("{:?}", e) + Err(e) => panic!("{:?}", e), } } } @@ -257,13 +268,17 @@ declare_types! { } } register_module!(mut m, { - m.export_class::("CompileFn").expect("CompileFn class error"); - m.export_class::("SelectorFn").expect("SelectorFn class error"); - m.export_class::("Selector").expect("Selector class error"); - m.export_class::("SelectorMut").expect("SelectorMut class error"); + m.export_class::("CompileFn") + .expect("CompileFn class error"); + m.export_class::("SelectorFn") + .expect("SelectorFn class error"); + m.export_class::("Selector") + .expect("Selector class error"); + m.export_class::("SelectorMut") + .expect("SelectorMut class error"); m.export_function("select", select)?; m.export_function("deleteValue", delete)?; m.export_function("replaceWith", replace_with)?; m.export_function("selectStr", select_str)?; Ok(()) -}); \ No newline at end of file +}); diff --git a/src/lib.rs b/src/lib.rs index 7b5c5b21..57826921 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,8 +134,8 @@ extern crate serde_json; use serde_json::Value; pub use parser::parser::{Node, Parser}; -pub use select::{Selector, SelectorMut}; pub use select::JsonPathError; +pub use select::{Selector, SelectorMut}; #[doc(hidden)] mod parser; @@ -171,14 +171,12 @@ mod select; /// ``` pub fn compile(path: &str) -> impl FnMut(&Value) -> Result, JsonPathError> { let node = Parser::compile(path); - move |json| { - match &node { - Ok(node) => { - let mut selector = Selector::new(); - selector.compiled_path(node).value(json).select() - } - Err(e) => Err(JsonPathError::Path(e.to_string())) + move |json| match &node { + Ok(node) => { + let mut selector = Selector::new(); + selector.compiled_path(node).value(json).select() } + Err(e) => Err(JsonPathError::Path(e.to_string())), } } @@ -219,9 +217,7 @@ pub fn compile(path: &str) -> impl FnMut(&Value) -> Result, JsonPath pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result, JsonPathError> { let mut selector = Selector::new(); let _ = selector.value(json); - move |path: &str| { - selector.str_path(path)?.reset_value().select() - } + move |path: &str| selector.str_path(path)?.reset_value().select() } /// It is the same to `selector` function. but it deserialize the result as given type `T`. @@ -270,12 +266,12 @@ pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result(json: &Value) -> impl FnMut(&str) -> Result, JsonPathError> + '_ { +pub fn selector_as( + json: &Value, +) -> impl FnMut(&str) -> Result, JsonPathError> + '_ { let mut selector = Selector::new(); let _ = selector.value(json); - move |path: &str| { - selector.str_path(path)?.reset_value().select_as() - } + move |path: &str| selector.str_path(path)?.reset_value().select_as() } /// It is a simple select function. but it compile the jsonpath argument every time. @@ -374,7 +370,10 @@ pub fn select_as_str(json_str: &str, path: &str) -> Result(json_str: &str, path: &str) -> Result, JsonPathError> { +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().str_path(path)?.value(&json).select_as() } @@ -413,7 +412,12 @@ pub fn select_as(json_str: &str, path: &str) -> /// ``` pub fn delete(value: Value, path: &str) -> Result { let mut selector = SelectorMut::new(); - let ret = selector.str_path(path)?.value(value).delete()?.take().unwrap_or(Value::Null); + let ret = selector + .str_path(path)? + .value(value) + .delete()? + .take() + .unwrap_or(Value::Null); Ok(ret) } @@ -460,9 +464,15 @@ pub fn delete(value: Value, path: &str) -> Result { /// ]})); /// ``` pub fn replace_with(value: Value, path: &str, fun: &mut F) -> Result - where F: FnMut(&Value) -> Value +where + F: FnMut(&Value) -> Value, { let mut selector = SelectorMut::new(); - let ret = selector.str_path(path)?.value(value).replace_with(fun)?.take().unwrap_or(Value::Null); + let ret = selector + .str_path(path)? + .value(value) + .replace_with(fun)? + .take() + .unwrap_or(Value::Null); Ok(ret) -} \ No newline at end of file +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index f3b5c171..bda8b4fd 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,10 +1,10 @@ +pub mod parser; mod path_reader; pub(crate) mod tokenizer; -pub mod parser; #[cfg(test)] mod parser_tests { - use parser::parser::{FilterToken, NodeVisitor, Parser, ParseToken}; + use parser::parser::{FilterToken, NodeVisitor, ParseToken, Parser}; struct NodeVisitorTestImpl<'a> { input: &'a str, @@ -13,7 +13,10 @@ mod parser_tests { impl<'a> NodeVisitorTestImpl<'a> { fn new(input: &'a str) -> Self { - NodeVisitorTestImpl { input, stack: Vec::new() } + NodeVisitorTestImpl { + input, + stack: Vec::new(), + } } fn start(&mut self) -> Result, String> { @@ -42,49 +45,63 @@ mod parser_tests { 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 - ])); + 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!(), @@ -106,225 +123,346 @@ mod parser_tests { 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 - ])); + 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, 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), None), - 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), None), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$[0:3:2]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(Some(0), Some(3), Some(2)), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$[:3:2]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(None, Some(3), Some(2)), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$[:]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(None, None, None), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$[::]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(None, None, None), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$[::2]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(None, None, Some(2)), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$["a", 'b']"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Keys(vec!["a".to_string(), "b".to_string()]), - 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 - ])); - - assert_eq!(run("$[:]"), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Range(None, None, None), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$['single\'quote']"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Key("single'quote".to_string()), - ParseToken::ArrayEof - ])); - - assert_eq!(run(r#"$["single\"quote"]"#), Ok(vec![ - ParseToken::Absolute, - ParseToken::Array, - ParseToken::Key(r#"single"quote"#.to_string()), - ParseToken::ArrayEof - ])); + 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, 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), None), + 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), None), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$[0:3:2]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(Some(0), Some(3), Some(2)), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$[:3:2]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(None, Some(3), Some(2)), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$[:]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(None, None, None), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$[::]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(None, None, None), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$[::2]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(None, None, Some(2)), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$["a", 'b']"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Keys(vec!["a".to_string(), "b".to_string()]), + 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 + ]) + ); + + assert_eq!( + run("$[:]"), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Range(None, None, None), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$['single\'quote']"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Key("single'quote".to_string()), + ParseToken::ArrayEof + ]) + ); + + assert_eq!( + run(r#"$["single\"quote"]"#), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Key(r#"single"quote"#.to_string()), + ParseToken::ArrayEof + ]) + ); match run("$[") { Ok(_) => panic!(), @@ -361,12 +499,17 @@ mod parser_tests { 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 - ])); + 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!(), @@ -392,7 +535,7 @@ mod parser_tests { #[cfg(test)] mod tokenizer_tests { - use parser::tokenizer::{Token, TokenError, Tokenizer, TokenReader}; + use parser::tokenizer::{Token, TokenError, TokenReader, Tokenizer}; fn setup() { let _ = env_logger::try_init(); @@ -419,22 +562,22 @@ mod tokenizer_tests { let mut tokenizer = TokenReader::new("$.a"); match tokenizer.next_token() { Ok(t) => assert_eq!(Token::Absolute(0), t), - _ => panic!() + _ => panic!(), } match tokenizer.peek_token() { Ok(t) => assert_eq!(&Token::Dot(1), t), - _ => panic!() + _ => panic!(), } match tokenizer.peek_token() { Ok(t) => assert_eq!(&Token::Dot(1), t), - _ => panic!() + _ => panic!(), } match tokenizer.next_token() { Ok(t) => assert_eq!(Token::Dot(1), t), - _ => panic!() + _ => panic!(), } } @@ -442,52 +585,57 @@ mod tokenizer_tests { fn token() { setup(); - run("$.01.a", + 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("$. []", + 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("$..", + Token::CloseArray(6), + ], + Some(TokenError::Eof), + ), + ); + + run( + "$..", ( - vec![ - Token::Absolute(0), - Token::Dot(1), - Token::Dot(2), - ] - , Some(TokenError::Eof) - )); + vec![Token::Absolute(0), Token::Dot(1), Token::Dot(2)], + Some(TokenError::Eof), + ), + ); - run("$..ab", + run( + "$..ab", ( vec![ Token::Absolute(0), Token::Dot(1), Token::Dot(2), - Token::Key(3, "ab".to_string()) - ] - , Some(TokenError::Eof) - )); - - run("$..가 [", + Token::Key(3, "ab".to_string()), + ], + Some(TokenError::Eof), + ), + ); + + run( + "$..가 [", ( vec![ Token::Absolute(0), @@ -496,11 +644,13 @@ mod tokenizer_tests { Token::Key(3, "가".to_string()), Token::Whitespace(6, 0), Token::OpenArray(7), - ] - , Some(TokenError::Eof) - )); + ], + Some(TokenError::Eof), + ), + ); - run("[-1, 2 ]", + run( + "[-1, 2 ]", ( vec![ Token::OpenArray(0), @@ -510,11 +660,13 @@ mod tokenizer_tests { Token::Key(5, "2".to_string()), Token::Whitespace(6, 0), Token::CloseArray(7), - ] - , Some(TokenError::Eof) - )); + ], + Some(TokenError::Eof), + ), + ); - run("[ 1 2 , 3 \"abc\" : -10 ]", + run( + "[ 1 2 , 3 \"abc\" : -10 ]", ( vec![ Token::OpenArray(0), @@ -534,11 +686,13 @@ mod tokenizer_tests { Token::Key(18, "-10".to_string()), Token::Whitespace(21, 0), Token::CloseArray(22), - ] - , Some(TokenError::Eof) - )); + ], + Some(TokenError::Eof), + ), + ); - run("?(@.a가 <41.01)", + run( + "?(@.a가 <41.01)", ( vec![ Token::Question(0), @@ -552,11 +706,13 @@ mod tokenizer_tests { Token::Dot(12), Token::Key(13, "01".to_string()), Token::CloseParenthesis(15), - ] - , Some(TokenError::Eof) - )); + ], + Some(TokenError::Eof), + ), + ); - run("?(@.a <4a.01)", + run( + "?(@.a <4a.01)", ( vec![ Token::Question(0), @@ -570,45 +726,67 @@ mod tokenizer_tests { 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) - )); - - run("$[:]", (vec![ - Token::Absolute(0), - Token::OpenArray(1), - Token::Split(2), - Token::CloseArray(3) - ], Some(TokenError::Eof))); - - run(r#"$['single\'quote']"#, (vec![ - Token::Absolute(0), - Token::OpenArray(1), - Token::SingleQuoted(2, "single\'quote".to_string()), - Token::CloseArray(17) - ], Some(TokenError::Eof))); - - run(r#"$["double\"quote"]"#, (vec![ - Token::Absolute(0), - Token::OpenArray(1), - Token::DoubleQuoted(2, "double\"quote".to_string()), - Token::CloseArray(17) - ], Some(TokenError::Eof))); + ], + 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), + ), + ); + + run( + "$[:]", + ( + vec![ + Token::Absolute(0), + Token::OpenArray(1), + Token::Split(2), + Token::CloseArray(3), + ], + Some(TokenError::Eof), + ), + ); + + run( + r#"$['single\'quote']"#, + ( + vec![ + Token::Absolute(0), + Token::OpenArray(1), + Token::SingleQuoted(2, "single\'quote".to_string()), + Token::CloseArray(17), + ], + Some(TokenError::Eof), + ), + ); + + run( + r#"$["double\"quote"]"#, + ( + vec![ + Token::Absolute(0), + Token::OpenArray(1), + Token::DoubleQuoted(2, "double\"quote".to_string()), + Token::CloseArray(17), + ], + Some(TokenError::Eof), + ), + ); } -} \ No newline at end of file +} diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 3258dec9..65eaa569 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -10,11 +10,12 @@ mod utils { use std::str::FromStr; pub fn string_to_num(string: &String, msg_handler: F) -> Result - where F: Fn() -> String + where + F: Fn() -> String, { match string.as_str().parse() { Ok(n) => Ok(n), - _ => Err(msg_handler()) + _ => Err(msg_handler()), } } } @@ -86,9 +87,7 @@ impl Parser { let node = Self::node(ParseToken::Absolute); Self::paths(node, tokenizer) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -105,9 +104,7 @@ impl Parser { let node = Self::array(prev, tokenizer)?; Self::paths(node, tokenizer) } - _ => { - Ok(prev) - } + _ => Ok(prev), } } @@ -122,34 +119,22 @@ impl Parser { | Ok(Token::Greater(_)) | Ok(Token::GreaterOrEqual(_)) | Ok(Token::And(_)) - | Ok(Token::Or(_)) => { - Ok(node) - } - _ => { - Self::paths(node, tokenizer) - } + | Ok(Token::Or(_)) => Ok(node), + _ => Self::paths(node, tokenizer), } } fn path(prev: Node, tokenizer: &mut TokenReader) -> ParseResult { debug!("#path"); match tokenizer.peek_token() { - Ok(Token::Dot(_)) => { - Self::path_leaves(prev, tokenizer) - } - Ok(Token::Asterisk(_)) => { - Self::path_in_all(prev, tokenizer) - } - Ok(Token::Key(_, _)) => { - Self::path_in_key(prev, tokenizer) - } + Ok(Token::Dot(_)) => Self::path_leaves(prev, tokenizer), + Ok(Token::Asterisk(_)) => Self::path_in_all(prev, tokenizer), + Ok(Token::Key(_, _)) => Self::path_in_key(prev, tokenizer), Ok(Token::OpenArray(_)) => { Self::eat_token(tokenizer); Self::array(prev, tokenizer) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -157,17 +142,13 @@ impl Parser { debug!("#path_leaves"); Self::eat_token(tokenizer); match tokenizer.peek_token() { - Ok(Token::Asterisk(_)) => { - Self::path_leaves_all(prev, tokenizer) - } + Ok(Token::Asterisk(_)) => Self::path_leaves_all(prev, tokenizer), Ok(Token::OpenArray(_)) => { let mut leaves_node = Self::node(ParseToken::Leaves); leaves_node.left = Some(Box::new(prev)); Ok(Self::paths(leaves_node, tokenizer)?) } - _ => { - Self::path_leaves_key(prev, tokenizer) - } + _ => Self::path_leaves_key(prev, tokenizer), } } @@ -212,12 +193,8 @@ impl Parser { fn key(tokenizer: &mut TokenReader) -> ParseResult { debug!("#key"); match tokenizer.next_token() { - Ok(Token::Key(_, v)) => { - Ok(Self::node(ParseToken::Key(v))) - } - _ => { - Err(tokenizer.err_msg()) - } + Ok(Token::Key(_, v)) => Ok(Self::node(ParseToken::Key(v))), + _ => Err(tokenizer.err_msg()), } } @@ -227,9 +204,7 @@ impl Parser { Ok(Token::Key(_, v)) => { Ok(Self::node(ParseToken::Bool(v.eq_ignore_ascii_case("true")))) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -244,8 +219,7 @@ impl Parser { } match tokenizer.next_token() { - Ok(Token::SingleQuoted(_, val)) - | Ok(Token::DoubleQuoted(_, val)) => { + Ok(Token::SingleQuoted(_, val)) | Ok(Token::DoubleQuoted(_, val)) => { keys.push(val); } _ => {} @@ -267,12 +241,8 @@ impl Parser { Self::array_keys(tokenizer, val) } } - Err(TokenError::Eof) => { - Ok(Self::node(ParseToken::Eof)) - } - _ => { - Err(tokenizer.err_msg()) - } + Err(TokenError::Eof) => Ok(Self::node(ParseToken::Eof)), + _ => Err(tokenizer.err_msg()), } } @@ -295,13 +265,11 @@ impl Parser { right: Some(Box::new(Self::node(ParseToken::All))), }) } - _ => { - Ok(Node { - token: ParseToken::Array, - left: Some(Box::new(prev)), - right: Some(Box::new(Self::array_value(tokenizer)?)), - }) - } + _ => Ok(Node { + token: ParseToken::Array, + left: Some(Box::new(prev)), + right: Some(Box::new(Self::array_value(tokenizer)?)), + }), } } @@ -320,41 +288,27 @@ impl Parser { Self::eat_whitespace(tokenizer); match tokenizer.peek_token() { - Ok(Token::Comma(_)) => { - Self::union(digit, tokenizer) - } - Ok(Token::Split(_)) => { - Self::range_from(digit, tokenizer) - } - _ => { - Ok(Self::node(ParseToken::Number(digit as f64))) - } + Ok(Token::Comma(_)) => Self::union(digit, tokenizer), + Ok(Token::Split(_)) => Self::range_from(digit, tokenizer), + _ => Ok(Self::node(ParseToken::Number(digit as f64))), } } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } - fn array_value(tokenizer: &mut TokenReader) -> ParseResult { debug!("#array_value"); match tokenizer.peek_token() { - Ok(Token::Key(_, _)) => { - Self::array_value_key(tokenizer) - } + Ok(Token::Key(_, _)) => Self::array_value_key(tokenizer), Ok(Token::Split(_)) => { Self::eat_token(tokenizer); Self::range_to(tokenizer) } - Ok(Token::DoubleQuoted(_, _)) - | Ok(Token::SingleQuoted(_, _)) => { + Ok(Token::DoubleQuoted(_, _)) | Ok(Token::SingleQuoted(_, _)) => { Self::array_quote_value(tokenizer) } - Err(TokenError::Eof) => { - Ok(Self::node(ParseToken::Eof)) - } + Err(TokenError::Eof) => Ok(Self::node(ParseToken::Eof)), _ => { Self::eat_token(tokenizer); Err(tokenizer.err_msg()) @@ -367,7 +321,7 @@ impl Parser { let mut values = vec![num]; while match tokenizer.peek_token() { Ok(Token::Comma(_)) => true, - _ => false + _ => false, } { Self::eat_token(tokenizer); Self::eat_whitespace(tokenizer); @@ -385,6 +339,8 @@ impl Parser { } fn range_value(tokenizer: &mut TokenReader) -> Result, String> { + Self::eat_whitespace(tokenizer); + if tokenizer.peek_is(SPLIT) { Self::eat_token(tokenizer); Self::eat_whitespace(tokenizer); @@ -394,10 +350,10 @@ impl Parser { Ok(Token::Key(pos, str_step)) => { match utils::string_to_num(&str_step, || tokenizer.err_msg_with_pos(pos)) { Ok(step) => Ok(Some(step)), - Err(e) => Err(e) + Err(e) => Err(e), } } - _ => Ok(None) + _ => Ok(None), } } else { Ok(None) @@ -413,18 +369,12 @@ impl Parser { Self::eat_whitespace(tokenizer); match tokenizer.peek_token() { - Ok(Token::Key(_, _)) => { - Self::range(from, tokenizer) - } - Ok(Token::Split(_)) => { - match Self::range_value(tokenizer)? { - Some(step) => Ok(Self::node(ParseToken::Range(Some(from), None, Some(step)))), - _ => Ok(Self::node(ParseToken::Range(Some(from), None, None))) - } - } - _ => { - Ok(Self::node(ParseToken::Range(Some(from), None, None))) - } + Ok(Token::Key(_, _)) => Self::range(from, tokenizer), + Ok(Token::Split(_)) => match Self::range_value(tokenizer)? { + Some(step) => Ok(Self::node(ParseToken::Range(Some(from), None, Some(step)))), + _ => Ok(Self::node(ParseToken::Range(Some(from), None, None))), + }, + _ => Ok(Self::node(ParseToken::Range(Some(from), None, None))), } } @@ -449,9 +399,7 @@ impl Parser { let step = Self::range_value(tokenizer)?; Ok(Self::node(ParseToken::Range(None, Some(to), step))) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -463,9 +411,7 @@ impl Parser { let step = Self::range_value(tokenizer)?; Ok(Self::node(ParseToken::Range(Some(from), Some(to), step))) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -477,12 +423,8 @@ impl Parser { Self::eat_whitespace(tokenizer); Self::close_token(ret, Token::CloseParenthesis(DUMMY), tokenizer) } - Err(TokenError::Eof) => { - Ok(Self::node(ParseToken::Eof)) - } - _ => { - Err(tokenizer.err_msg()) - } + Err(TokenError::Eof) => Ok(Self::node(ParseToken::Eof)), + _ => Err(tokenizer.err_msg()), } } @@ -525,9 +467,7 @@ impl Parser { right: Some(Box::new(Self::exprs(tokenizer)?)), }) } - _ => { - Ok(prev) - } + _ => Ok(prev), } } @@ -536,7 +476,7 @@ impl Parser { let has_prop_candidate = match tokenizer.peek_token() { Ok(Token::At(_)) => true, - _ => false + _ => false, }; let node = Self::term(tokenizer)?; @@ -549,7 +489,7 @@ impl Parser { | Ok(Token::LittleOrEqual(_)) | Ok(Token::Greater(_)) | Ok(Token::GreaterOrEqual(_)) => true, - _ => false + _ => false, } { Self::op(node, tokenizer) } else if has_prop_candidate { @@ -562,23 +502,15 @@ impl Parser { fn term_num(tokenizer: &mut TokenReader) -> ParseResult { debug!("#term_num"); match tokenizer.next_token() { - Ok(Token::Key(pos, val)) => { - match tokenizer.peek_token() { - Ok(Token::Dot(_)) => { - Self::term_num_float(val.as_str(), tokenizer) - } - _ => { - let number = utils::string_to_num(&val, || tokenizer.err_msg_with_pos(pos))?; - Ok(Self::node(ParseToken::Number(number))) - } + Ok(Token::Key(pos, val)) => match tokenizer.peek_token() { + Ok(Token::Dot(_)) => Self::term_num_float(val.as_str(), tokenizer), + _ => { + let number = utils::string_to_num(&val, || tokenizer.err_msg_with_pos(pos))?; + Ok(Self::node(ParseToken::Number(number))) } - } - Err(TokenError::Eof) => { - Ok(Self::node(ParseToken::Eof)) - } - _ => { - Err(tokenizer.err_msg()) - } + }, + Err(TokenError::Eof) => Ok(Self::node(ParseToken::Eof)), + _ => Err(tokenizer.err_msg()), } } @@ -594,9 +526,7 @@ impl Parser { let number = utils::string_to_num(&f, || tokenizer.err_msg_with_pos(pos))?; Ok(Self::node(ParseToken::Number(number))) } - _ => { - Err(tokenizer.err_msg()) - } + _ => Err(tokenizer.err_msg()), } } @@ -620,9 +550,7 @@ impl Parser { Self::eat_whitespace(tokenizer); Ok(node) } - _ => { - Self::paths(node, tokenizer) - } + _ => Self::paths(node, tokenizer), }; } @@ -639,11 +567,11 @@ impl Parser { Some(key) => match key.chars().next() { Some(ch) => match ch { '-' | '0'...'9' => Self::term_num(tokenizer), - _ => Self::boolean(tokenizer) - } - _ => Err(tokenizer.err_msg()) + _ => Self::boolean(tokenizer), + }, + _ => Err(tokenizer.err_msg()), }, - _ => Err(tokenizer.err_msg()) + _ => Err(tokenizer.err_msg()), }; } @@ -653,27 +581,13 @@ impl Parser { fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult { debug!("#op"); let token = match tokenizer.next_token() { - Ok(Token::Equal(_)) => { - ParseToken::Filter(FilterToken::Equal) - } - Ok(Token::NotEqual(_)) => { - ParseToken::Filter(FilterToken::NotEqual) - } - Ok(Token::Little(_)) => { - ParseToken::Filter(FilterToken::Little) - } - Ok(Token::LittleOrEqual(_)) => { - ParseToken::Filter(FilterToken::LittleOrEqual) - } - Ok(Token::Greater(_)) => { - ParseToken::Filter(FilterToken::Greater) - } - Ok(Token::GreaterOrEqual(_)) => { - ParseToken::Filter(FilterToken::GreaterOrEqual) - } - Err(TokenError::Eof) => { - ParseToken::Eof - } + Ok(Token::Equal(_)) => ParseToken::Filter(FilterToken::Equal), + Ok(Token::NotEqual(_)) => ParseToken::Filter(FilterToken::NotEqual), + Ok(Token::Little(_)) => ParseToken::Filter(FilterToken::Little), + Ok(Token::LittleOrEqual(_)) => ParseToken::Filter(FilterToken::LittleOrEqual), + Ok(Token::Greater(_)) => ParseToken::Filter(FilterToken::Greater), + Ok(Token::GreaterOrEqual(_)) => ParseToken::Filter(FilterToken::GreaterOrEqual), + Err(TokenError::Eof) => ParseToken::Eof, _ => { return Err(tokenizer.err_msg()); } @@ -699,18 +613,18 @@ impl Parser { } fn node(token: ParseToken) -> Node { - Node { left: None, right: None, token } + Node { + left: None, + right: None, + token, + } } fn close_token(ret: Node, token: Token, tokenizer: &mut TokenReader) -> ParseResult { debug!("#close_token"); match tokenizer.next_token() { - Ok(ref t) if t.partial_eq(token) => { - Ok(ret) - } - _ => { - Err(tokenizer.err_msg()) - } + Ok(ref t) if t.partial_eq(token) => Ok(ret), + _ => Err(tokenizer.err_msg()), } } } @@ -729,8 +643,7 @@ pub trait NodeVisitor { | ParseToken::Bool(_) => { self.visit_token(&node.token); } - ParseToken::In - | ParseToken::Leaves => { + ParseToken::In | ParseToken::Leaves => { match &node.left { Some(n) => self.visit(&*n), _ => {} @@ -757,8 +670,7 @@ pub trait NodeVisitor { } self.visit_token(&ParseToken::ArrayEof); } - ParseToken::Filter(FilterToken::And) - | ParseToken::Filter(FilterToken::Or) => { + ParseToken::Filter(FilterToken::And) | ParseToken::Filter(FilterToken::Or) => { match &node.left { Some(n) => self.visit(&*n), _ => {} @@ -794,4 +706,4 @@ pub trait NodeVisitor { fn visit_token(&mut self, token: &ParseToken); fn end_term(&mut self) {} -} \ No newline at end of file +} diff --git a/src/parser/path_reader.rs b/src/parser/path_reader.rs index 297821e8..8147f554 100644 --- a/src/parser/path_reader.rs +++ b/src/parser/path_reader.rs @@ -12,10 +12,7 @@ pub struct PathReader<'a> { impl<'a> PathReader<'a> { pub fn new(input: &'a str) -> Self { - PathReader { - input, - pos: 0, - } + PathReader { input, pos: 0 } } pub fn peek_char(&self) -> Result<(usize, char), ReaderError> { @@ -24,8 +21,8 @@ impl<'a> PathReader<'a> { } pub fn take_while(&mut self, fun: F) -> Result<(usize, String), ReaderError> - where - F: Fn(&char) -> bool + where + F: Fn(&char) -> bool, { let mut char_len: usize = 0; let mut ret = String::new(); @@ -53,4 +50,4 @@ impl<'a> PathReader<'a> { pub fn current_pos(&self) -> usize { self.pos } -} \ No newline at end of file +} diff --git a/src/parser/tokenizer.rs b/src/parser/tokenizer.rs index 638f1666..eee93656 100644 --- a/src/parser/tokenizer.rs +++ b/src/parser/tokenizer.rs @@ -55,7 +55,7 @@ pub enum TokenError { fn to_token_error(read_err: ReaderError) -> TokenError { match read_err { - ReaderError::Eof => TokenError::Eof + ReaderError::Eof => TokenError::Eof, } } @@ -119,7 +119,7 @@ impl Token { Token::NotEqual(_) => NOT_EQUAL, Token::And(_) => AND, Token::Or(_) => OR, - Token::Whitespace(_, _) => WHITESPACE + Token::Whitespace(_, _) => WHITESPACE, } } } @@ -137,7 +137,7 @@ fn simple_matched_token(ch: char, pos: usize) -> Option { CH_QUESTION => Some(Token::Question(pos)), CH_COMMA => Some(Token::Comma(pos)), CH_SEMICOLON => Some(Token::Split(pos)), - _ => None + _ => None, } } @@ -154,12 +154,18 @@ impl<'a> Tokenizer<'a> { } fn quote(&mut self, ch: char) -> Result { - let (_, mut val) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; + let (_, mut val) = self + .input + .take_while(|c| *c != ch) + .map_err(to_token_error)?; if let Some('\\') = val.chars().last() { self.input.next_char().map_err(to_token_error)?; let _ = val.pop(); - let (_, mut val_remain) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; + let (_, mut val_remain) = self + .input + .take_while(|c| *c != ch) + .map_err(to_token_error)?; self.input.next_char().map_err(to_token_error)?; val.push(ch); val.push_str(val_remain.as_str()); @@ -187,7 +193,7 @@ impl<'a> Tokenizer<'a> { self.input.next_char().map_err(to_token_error)?; Ok(Token::Equal(pos)) } - _ => Err(TokenError::Position(pos)) + _ => Err(TokenError::Position(pos)), } } @@ -198,7 +204,7 @@ impl<'a> Tokenizer<'a> { self.input.next_char().map_err(to_token_error)?; Ok(Token::NotEqual(pos)) } - _ => Err(TokenError::Position(pos)) + _ => Err(TokenError::Position(pos)), } } @@ -231,7 +237,7 @@ impl<'a> Tokenizer<'a> { let _ = self.input.next_char().map_err(to_token_error); Ok(Token::And(pos)) } - _ => Err(TokenError::Position(pos)) + _ => Err(TokenError::Position(pos)), } } @@ -242,27 +248,31 @@ impl<'a> Tokenizer<'a> { self.input.next_char().map_err(to_token_error)?; Ok(Token::Or(pos)) } - _ => Err(TokenError::Position(pos)) + _ => Err(TokenError::Position(pos)), } } fn whitespace(&mut self, pos: usize, _: char) -> Result { - let (_, vec) = self.input.take_while(|c| c.is_whitespace()).map_err(to_token_error)?; + let (_, vec) = self + .input + .take_while(|c| c.is_whitespace()) + .map_err(to_token_error)?; Ok(Token::Whitespace(pos, vec.len())) } fn other(&mut self, pos: usize, ch: char) -> Result { - let fun = |c: &char| { - match simple_matched_token(*c, pos) { - Some(_) => false, - _ if c == &CH_LITTLE - || c == &CH_GREATER - || c == &CH_EQUAL - || c == &CH_AMPERSAND - || c == &CH_PIPE - || c == &CH_EXCLAMATION => false, - _ => !c.is_whitespace() + let fun = |c: &char| match simple_matched_token(*c, pos) { + Some(_) => false, + _ if c == &CH_LITTLE + || c == &CH_GREATER + || c == &CH_EQUAL + || c == &CH_AMPERSAND + || c == &CH_PIPE + || c == &CH_EXCLAMATION => + { + false } + _ => !c.is_whitespace(), }; let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?; vec.insert(0, ch); @@ -273,20 +283,18 @@ impl<'a> Tokenizer<'a> { let (pos, ch) = self.input.next_char().map_err(to_token_error)?; match simple_matched_token(ch, pos) { Some(t) => Ok(t), - None => { - match ch { - CH_SINGLE_QUOTE => self.single_quote(pos, ch), - CH_DOUBLE_QUOTE => self.double_quote(pos, ch), - CH_EQUAL => self.equal(pos, ch), - CH_GREATER => self.greater(pos, ch), - CH_LITTLE => self.little(pos, ch), - CH_AMPERSAND => self.and(pos, ch), - CH_PIPE => self.or(pos, ch), - CH_EXCLAMATION => self.not_equal(pos, ch), - _ if ch.is_whitespace() => self.whitespace(pos, ch), - _ => self.other(pos, ch), - } - } + None => match ch { + CH_SINGLE_QUOTE => self.single_quote(pos, ch), + CH_DOUBLE_QUOTE => self.double_quote(pos, ch), + CH_EQUAL => self.equal(pos, ch), + CH_GREATER => self.greater(pos, ch), + CH_LITTLE => self.little(pos, ch), + CH_AMPERSAND => self.and(pos, ch), + CH_PIPE => self.or(pos, ch), + CH_EXCLAMATION => self.not_equal(pos, ch), + _ if ch.is_whitespace() => self.whitespace(pos, ch), + _ => self.other(pos, ch), + }, } } @@ -328,7 +336,7 @@ impl<'a> TokenReader<'a> { pub fn peek_is(&self, simple_token: &str) -> bool { match self.peek_token() { Ok(t) => t.simple_eq(simple_token), - _ => false + _ => false, } } @@ -365,18 +373,14 @@ impl<'a> TokenReader<'a> { writeln!(&mut w, "{}", "^".repeat(pos)).unwrap(); match std::str::from_utf8(&w[..]) { Ok(s) => s.to_owned(), - Err(_) => panic!("Invalid UTF-8") + Err(_) => panic!("Invalid UTF-8"), } } pub fn err_msg(&self) -> String { match self.curr_pos { - Some(pos) => { - self.err_msg_with_pos(pos) - } - _ => { - self.err_msg_with_pos(self.err_pos) - } + Some(pos) => self.err_msg_with_pos(pos), + _ => self.err_msg_with_pos(self.err_pos), } } -} \ No newline at end of file +} diff --git a/src/select/mod.rs b/src/select/mod.rs index ffce0d76..c2d09156 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -25,7 +25,9 @@ trait Cmp { fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value>; - fn default(&self) -> bool { false } + fn default(&self) -> bool { + false + } } struct CmpEq; @@ -200,59 +202,63 @@ impl<'a> ExprTerm<'a> { fn is_string(&self) -> bool { match &self { ExprTerm::String(_) => true, - _ => false + _ => false, } } fn is_number(&self) -> bool { match &self { ExprTerm::Number(_) => true, - _ => false + _ => false, } } fn is_bool(&self) -> bool { match &self { ExprTerm::Bool(_) => true, - _ => false + _ => false, } } fn is_json(&self) -> bool { match &self { ExprTerm::Json(_, _) => true, - _ => false + _ => false, } } - fn cmp(&self, other: &Self, cmp_fn: &C1, reverse_cmp_fn: &C2) -> ExprTerm<'a> { + 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::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::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(_, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn), + _ => ExprTerm::Bool(cmp_fn.default()), + }, ExprTerm::Json(fk1, vec1) if other.is_string() => { - let s2 = if let ExprTerm::String(s2) = &other { s2 } else { unreachable!() }; + let s2 = if let ExprTerm::String(s2) = &other { + s2 + } else { + unreachable!() + }; - let ret: Vec<&Value> = vec1.iter().filter(|v1| { - match v1 { + 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 { @@ -262,16 +268,26 @@ impl<'a> ExprTerm<'a> { } cmp_fn.default() } - _ => cmp_fn.default() - } - }).map(|v| *v).collect(); + _ => cmp_fn.default(), + }) + .map(|v| *v) + .collect(); - if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + if ret.is_empty() { + ExprTerm::Bool(cmp_fn.default()) + } else { + ExprTerm::Json(None, ret) + } } ExprTerm::Json(fk1, vec1) if other.is_number() => { - let n2 = if let ExprTerm::Number(n2) = &other { n2 } else { unreachable!() }; - let ret: Vec<&Value> = vec1.iter().filter(|v1| { - match v1 { + let n2 = if let ExprTerm::Number(n2) = &other { + n2 + } else { + unreachable!() + }; + 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 { @@ -281,16 +297,26 @@ impl<'a> ExprTerm<'a> { } cmp_fn.default() } - _ => cmp_fn.default() - } - }).map(|v| *v).collect(); + _ => cmp_fn.default(), + }) + .map(|v| *v) + .collect(); - if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + if ret.is_empty() { + ExprTerm::Bool(cmp_fn.default()) + } else { + ExprTerm::Json(None, ret) + } } ExprTerm::Json(fk1, vec1) if other.is_bool() => { - let b2 = if let ExprTerm::Bool(b2) = &other { b2 } else { unreachable!() }; - let ret: Vec<&Value> = vec1.iter().filter(|v1| { - match v1 { + let b2 = if let ExprTerm::Bool(b2) = &other { + b2 + } else { + unreachable!() + }; + 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 { @@ -300,22 +326,29 @@ impl<'a> ExprTerm<'a> { } cmp_fn.default() } - _ => cmp_fn.default() - } - }).map(|v| *v).collect(); + _ => cmp_fn.default(), + }) + .map(|v| *v) + .collect(); - if ret.is_empty() { ExprTerm::Bool(cmp_fn.default()) } else { ExprTerm::Json(None, ret) } + if ret.is_empty() { + ExprTerm::Bool(cmp_fn.default()) + } else { + ExprTerm::Json(None, ret) + } } - 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) } + 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!() + _ => unreachable!(), + }, + _ => unreachable!(), } } @@ -399,30 +432,31 @@ impl<'a> Into> for &Vec<&'a Value> { } } -fn walk_all_with_str<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { +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 + 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 + _ => 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::Array(vec) => Some(vec.iter().collect()), Value::Object(map) => { let mut tmp = Vec::new(); for (_, v) in map { @@ -430,15 +464,17 @@ fn walk_all<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>) { } Some(tmp) } - _ => None + _ => None, }); } fn walk<'a, F>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, fun: &F) - where F: Fn(&Value) -> Option> +where + F: Fn(&Value) -> Option>, { fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) - where F: Fn(&Value) -> Option> + where + F: Fn(&Value) -> Option>, { if let Some(mut ret) = fun(v) { tmp.append(&mut ret); @@ -575,12 +611,12 @@ impl<'a, 'b> Selector<'a, 'b> { for v in vec { match T::deserialize(*v) { Ok(v) => ret.push(v), - Err(e) => return Err(JsonPathError::Serde(e.to_string())) + Err(e) => return Err(JsonPathError::Serde(e.to_string())), } } Ok(ret) } - _ => Err(JsonPathError::EmptyValue) + _ => Err(JsonPathError::EmptyValue), } } @@ -589,10 +625,9 @@ impl<'a, 'b> Selector<'a, 'b> { match &self.current { Some(r) => { - Ok(serde_json::to_string(r) - .map_err(|e| JsonPathError::Serde(e.to_string()))?) + Ok(serde_json::to_string(r).map_err(|e| JsonPathError::Serde(e.to_string()))?) } - _ => Err(JsonPathError::EmptyValue) + _ => Err(JsonPathError::EmptyValue), } } @@ -601,7 +636,7 @@ impl<'a, 'b> Selector<'a, 'b> { match &self.current { Some(r) => Ok(r.to_vec()), - _ => Err(JsonPathError::EmptyValue) + _ => Err(JsonPathError::EmptyValue), } } @@ -622,7 +657,7 @@ impl<'a, 'b> Selector<'a, 'b> { let filter_key = fun(&vec, &mut tmp); self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp))); } - _ => unreachable!() + _ => unreachable!(), }; } _ => { @@ -649,17 +684,26 @@ impl<'a, 'b> Selector<'a, 'b> { } 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>) { + 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::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); } - }, - Value::Array(vec) => for v in vec { - _collect(v, tmp, key, visited); } _ => {} } @@ -690,11 +734,19 @@ impl<'a, 'b> Selector<'a, 'b> { self.current = Some(tmp); } - debug!("next_from_current_with_num : {:?}, {:?}", &index, self.current); + debug!( + "next_from_current_with_num : {:?}, {:?}", + &index, self.current + ); } fn next_from_current_with_str(&mut self, keys: &Vec) { - fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>, keys: &Vec, visited: &mut HashSet<*const Value>) { + fn _collect<'a>( + v: &'a Value, + tmp: &mut Vec<&'a Value>, + keys: &Vec, + visited: &mut HashSet<*const Value>, + ) { match v { Value::Object(map) => { for key in keys { @@ -707,8 +759,10 @@ impl<'a, 'b> Selector<'a, 'b> { } } } - Value::Array(vec) => for v in vec { - _collect(v, tmp, keys, visited); + Value::Array(vec) => { + for v in vec { + _collect(v, tmp, keys, visited); + } } _ => {} } @@ -723,7 +777,10 @@ impl<'a, 'b> Selector<'a, 'b> { self.current = Some(tmp); } - debug!("next_from_current_with_str : {:?}, {:?}", keys, self.current); + debug!( + "next_from_current_with_str : {:?}, {:?}", + keys, self.current + ); } fn next_all_from_current(&mut self) { @@ -734,8 +791,10 @@ impl<'a, 'b> Selector<'a, 'b> { tmp.push(v) } } - Value::Array(vec) => for v in vec { - _collect(v, tmp); + Value::Array(vec) => { + for v in vec { + _collect(v, tmp); + } } _ => {} } @@ -858,19 +917,17 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { 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::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))); } @@ -884,9 +941,7 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { Some(t) => { if self.terms.is_empty() { match t { - ParseToken::Leaves => { - self.all_from_current_with_str(key.as_str()) - } + ParseToken::Leaves => self.all_from_current_with_str(key.as_str()), ParseToken::In => { self.next_from_current_with_str(&vec![key.clone()]) } @@ -919,7 +974,8 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { } } ParseToken::Number(v) => { - self.terms.push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap()))); + self.terms + .push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap()))); } ParseToken::Filter(ref ft) => { if let Some(Some(ref right)) = self.terms.pop() { @@ -970,7 +1026,7 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { for i in (from..to).step_by(match step { Some(step) => *step, - _ => 1 + _ => 1, }) { if let Some(v) = vec.get(i) { tmp.push(v); @@ -1065,7 +1121,10 @@ fn replace_value Value>(tokens: Vec, value: &mut Val impl SelectorMut { pub fn new() -> Self { - SelectorMut { path: None, value: None } + SelectorMut { + path: None, + value: None, + } } pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> { @@ -1083,7 +1142,12 @@ impl SelectorMut { } fn compute_paths(&self, mut result: Vec<&Value>) -> Vec> { - fn _walk(origin: &Value, target: &mut Vec<&Value>, tokens: &mut Vec, visited: &mut IndexMap<*const Value, Vec>) -> bool { + fn _walk( + origin: &Value, + target: &mut Vec<&Value>, + tokens: &mut Vec, + visited: &mut IndexMap<*const Value, Vec>, + ) -> bool { trace!("{:?}, {:?}", target, tokens); if target.is_empty() { @@ -1100,19 +1164,23 @@ impl SelectorMut { }); match origin { - Value::Array(vec) => for (i, v) in vec.iter().enumerate() { - tokens.push(i.to_string()); - if _walk(v, target, tokens, visited) { - return true; + Value::Array(vec) => { + for (i, v) in vec.iter().enumerate() { + tokens.push(i.to_string()); + if _walk(v, target, tokens, visited) { + return true; + } + tokens.pop(); } - tokens.pop(); - }, - Value::Object(map) => for (k, v) in map { - tokens.push(k.clone()); - if _walk(v, target, tokens, visited) { - return true; + } + Value::Object(map) => { + for (k, v) in map { + tokens.push(k.clone()); + if _walk(v, target, tokens, visited) { + return true; + } + tokens.pop(); } - tokens.pop(); } _ => {} } @@ -1149,7 +1217,10 @@ impl SelectorMut { } } - pub fn replace_with Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> { + pub fn replace_with Value>( + &mut self, + fun: &mut F, + ) -> Result<&mut Self, JsonPathError> { let paths = { let result = self.select()?; self.compute_paths(result) @@ -1163,4 +1234,4 @@ impl SelectorMut { Ok(self) } -} \ No newline at end of file +} diff --git a/tests/common.rs b/tests/common.rs index acd29258..a51d35a4 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -32,14 +32,21 @@ pub fn read_contents(path: &str) -> String { #[allow(dead_code)] pub fn select_and_then_compare<'a>(path: &str, json: Value, target: Value) { let mut selector = Selector::new(); - let result = selector.str_path(path).unwrap() + let result = selector + .str_path(path) + .unwrap() .value(&json) - .select_as::().unwrap(); - - assert_eq!(result, match target { - Value::Array(vec) => vec, - _ => panic!("Give me the Array!") - }, "{}", path); + .select_as::() + .unwrap(); + assert_eq!( + result, + match target { + Value::Array(vec) => vec.clone(), + _ => panic!("Give me the Array!"), + }, + "{}", + path + ); } #[allow(dead_code)] diff --git a/tests/filter.rs b/tests/filter.rs index 9193ce47..839b3653 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -11,146 +11,226 @@ mod common; fn array() { setup(); - 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"} - ])); - - select_and_then_compare("$.school.friends[1: ]", read_json("./benches/data_obj.json"), json!([ - {"id": 1, "name": "Vincent Cannon" }, - {"id": 2, "name": "Gray Berry"} - ])); - - select_and_then_compare("$.school.friends[:-2]", read_json("./benches/data_obj.json"), json!([ - {"id": 0, "name": "Millicent Norman"} - ])); - - select_and_then_compare("$..friends[2].name", read_json("./benches/data_obj.json"), json!([ - "Gray Berry", "Gray Berry" - ])); - - select_and_then_compare("$..friends[*].name", read_json("./benches/data_obj.json"), json!([ - "Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry" - ])); - - select_and_then_compare("$['school']['friends'][*].['name']", read_json("./benches/data_obj.json"), json!([ - "Millicent Norman","Vincent Cannon","Gray Berry" - ])); - - select_and_then_compare("$['school']['friends'][0].['name']", read_json("./benches/data_obj.json"), json!([ - "Millicent Norman" - ])); - - select_and_then_compare(r#"$.["eyeColor", "name"]"#, read_json("./benches/data_obj.json"), json!([ - "blue", "Leonor Herman" - ])); + 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"} + ]), + ); + + select_and_then_compare( + "$.school.friends[1: ]", + read_json("./benches/data_obj.json"), + json!([ + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} + ]), + ); + + select_and_then_compare( + "$.school.friends[:-2]", + read_json("./benches/data_obj.json"), + json!([ + {"id": 0, "name": "Millicent Norman"} + ]), + ); + + select_and_then_compare( + "$..friends[2].name", + read_json("./benches/data_obj.json"), + json!(["Gray Berry", "Gray Berry"]), + ); + + select_and_then_compare( + "$..friends[*].name", + read_json("./benches/data_obj.json"), + json!([ + "Vincent Cannon", + "Gray Berry", + "Millicent Norman", + "Vincent Cannon", + "Gray Berry" + ]), + ); + + select_and_then_compare( + "$['school']['friends'][*].['name']", + read_json("./benches/data_obj.json"), + json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]), + ); + + select_and_then_compare( + "$['school']['friends'][0].['name']", + read_json("./benches/data_obj.json"), + json!(["Millicent Norman"]), + ); + + select_and_then_compare( + r#"$.["eyeColor", "name"]"#, + read_json("./benches/data_obj.json"), + json!(["blue", "Leonor Herman"]), + ); } #[test] fn return_type() { setup(); - 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"} - ] - }])); + 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"} + ] + }]), + ); - 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[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[?(@.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[?(1==1)]", read_json("./benches/data_obj.json"), json!([{ - "friends": [ + 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"} - ] - }])); - - 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(); - 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"} - ] - }])); - - select_and_then_compare("$.friends[?(@.name)]", read_json("./benches/data_obj.json"), json!([ - { "id" : 1, "name" : "Vincent Cannon" }, - { "id" : 2, "name" : "Gray Berry" } - ])); - - select_and_then_compare("$.friends[?(@.id >= 2)]", read_json("./benches/data_obj.json"), json!([ - { "id" : 2, "name" : "Gray Berry" } - ])); - - 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" } - ])); - - select_and_then_compare("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", read_json("./benches/data_obj.json"), json!([ - Value::Null - ])); - - select_and_then_compare("$..friends[?(@.id == $.index)].id", read_json("./benches/data_obj.json"), json!([ - 0, 0 - ])); - - select_and_then_compare("$..book[?($.store.bicycle.price < @.price)].price", read_json("./benches/example.json"), json!([ - 22.99 - ])); - - select_and_then_compare("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", read_json("./benches/example.json"), json!([ - 12.99 - ])); - - select_and_then_compare("$..[?(@.age > 40)]", json!([ - { "name": "이름1", "age": 40, "phone": "+33 12341234" }, - { "name": "이름2", "age": 42, "phone": "++44 12341234" } - ]), json!([ - { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } - ])); - - select_and_then_compare("$..[?(@.age >= 30)]", json!({ - "school": { + select_and_then_compare( + "$.school[?(@.friends == @.friends)]", + read_json("./benches/data_obj.json"), + json!([{ "friends": [ - {"name": "친구1", "age": 20}, - {"name": "친구2", "age": 20} + {"id": 0, "name": "Millicent Norman"}, + {"id": 1, "name": "Vincent Cannon" }, + {"id": 2, "name": "Gray Berry"} ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ]}), json!([ - { "name" : "친구3", "age" : 30 } - ])); + }]), + ); + + select_and_then_compare( + "$.friends[?(@.name)]", + read_json("./benches/data_obj.json"), + json!([ + { "id" : 1, "name" : "Vincent Cannon" }, + { "id" : 2, "name" : "Gray Berry" } + ]), + ); + + select_and_then_compare( + "$.friends[?(@.id >= 2)]", + read_json("./benches/data_obj.json"), + json!([ + { "id" : 2, "name" : "Gray Berry" } + ]), + ); + + 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" } + ]), + ); + + select_and_then_compare( + "$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", + read_json("./benches/data_obj.json"), + json!([Value::Null]), + ); + + select_and_then_compare( + "$..friends[?(@.id == $.index)].id", + read_json("./benches/data_obj.json"), + json!([0, 0]), + ); + + select_and_then_compare( + "$..book[?($.store.bicycle.price < @.price)].price", + read_json("./benches/example.json"), + json!([22.99]), + ); + + select_and_then_compare( + "$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", + read_json("./benches/example.json"), + json!([12.99]), + ); + + select_and_then_compare( + "$..[?(@.age > 40)]", + json!([ + { "name": "이름1", "age": 40, "phone": "+33 12341234" }, + { "name": "이름2", "age": 42, "phone": "++44 12341234" } + ]), + json!([ + { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" } + ]), + ); + + select_and_then_compare( + "$..[?(@.age >= 30)]", + json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 20}, + {"name": "친구2", "age": 20} + ] + }, + "friends": [ + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ]}), + json!([ + { "name" : "친구3", "age" : 30 } + ]), + ); } #[test] @@ -169,210 +249,357 @@ fn op_number() { fn op_string() { setup(); - 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" }])); + 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(); - 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])); + 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(); - 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])); + 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(); - select_and_then_compare(r#"$.store.book[*].author"#, read_json("./benches/example.json"), json!([ - "Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien" - ])); - - select_and_then_compare(r#"$..author"#, read_json("./benches/example.json"), json!([ - "Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien" - ])); - - 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}, - ])); - - select_and_then_compare(r#"$.store..price"#, read_json("./benches/example.json"), json!([ - 8.95, 12.99, 8.99, 22.99, 19.95 - ])); - - 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 - } - ])); - - 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 - }, - { - "category" : "fiction", - "author" : "J. R. R. Tolkien", - "title" : "The Lord of the Rings", - "isbn" : "0-395-19395-8", - "price" : 22.99 - } - ])); - - 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 - } - ])); - - 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 - }, - { + select_and_then_compare( + r#"$.store.book[*].author"#, + read_json("./benches/example.json"), + json!([ + "Nigel Rees", + "Evelyn Waugh", + "Herman Melville", + "J. R. R. Tolkien" + ]), + ); + + select_and_then_compare( + r#"$..author"#, + read_json("./benches/example.json"), + json!([ + "Nigel Rees", + "Evelyn Waugh", + "Herman Melville", + "J. R. R. Tolkien" + ]), + ); + + 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}, + ]), + ); + + select_and_then_compare( + r#"$.store..price"#, + read_json("./benches/example.json"), + json!([8.95, 12.99, 8.99, 22.99, 19.95]), + ); + + 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#"$..*"#, read_json("./benches/example.json"), - read_json("./benches/giveme_every_thing_result.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[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 + }, + { + "category" : "fiction", + "author" : "J. R. R. Tolkien", + "title" : "The Lord of the Rings", + "isbn" : "0-395-19395-8", + "price" : 22.99 + } + ]), + ); + + 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 + } + ]), + ); + + 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 + } + ]), + ); + + select_and_then_compare( + r#"$..*"#, + read_json("./benches/example.json"), + read_json("./benches/giveme_every_thing_result.json"), + ); } #[test] fn filer_same_obj() { setup(); - select_and_then_compare(r#"$..[?(@.a == 1)]"#, json!({ - "a": 1, - "b" : {"a": 1}, - "c" : {"a": 1} - }), json!([ - {"a": 1}, - {"a": 1} - ])); + select_and_then_compare( + r#"$..[?(@.a == 1)]"#, + json!({ + "a": 1, + "b" : {"a": 1}, + "c" : {"a": 1} + }), + json!([ + {"a": 1}, + {"a": 1} + ]), + ); } #[test] fn range() { setup(); - select_and_then_compare("$[:]", json!(["first", "second"]), json!(["first", "second"])); - select_and_then_compare("$[::]", json!(["first", "second", "third", "forth", "fifth"]), json!(["first", "second", "third", "forth", "fifth"])); - select_and_then_compare("$[::2]", json!(["first", "second", "third", "forth", "fifth"]), json!(["first", "third", "fifth"])); - select_and_then_compare("$[1: :]", json!(["first", "second", "third", "forth", "fifth"]), json!(["second", "third", "forth", "fifth"])); - select_and_then_compare("$[1:2:]", json!(["first", "second", "third", "forth", "fifth"]), json!(["second"])); - select_and_then_compare("$[1::2]", json!(["first", "second", "third", "forth", "fifth"]), json!(["second", "forth"])); - select_and_then_compare("$[0:3:1]", json!(["first", "second", "third", "forth", "fifth"]), json!(["first", "second", "third"])); - select_and_then_compare("$[0:3:2]", json!(["first", "second", "third", "forth", "fifth"]), json!(["first", "third"])); + select_and_then_compare( + "$[ : ]", + json!(["first", "second"]), + json!(["first", "second"]), + ); + select_and_then_compare( + "$[::]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "second", "third", "forth", "fifth"]), + ); + select_and_then_compare( + "$[::2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "third", "fifth"]), + ); + select_and_then_compare( + "$[1::]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second", "third", "forth", "fifth"]), + ); + select_and_then_compare( + "$[1:2:]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second"]), + ); + select_and_then_compare( + "$[1::2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["second", "forth"]), + ); + select_and_then_compare( + "$[0:3:1]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "second", "third"]), + ); + select_and_then_compare( + "$[0:3:2]", + json!(["first", "second", "third", "forth", "fifth"]), + json!(["first", "third"]), + ); } #[test] fn quote() { setup(); - select_and_then_compare(r#"$['single\'quote']"#, json!({"single'quote":"value"}), json!(["value"])); - select_and_then_compare(r#"$["double\"quote"]"#, json!({"double\"quote":"value"}), json!(["value"])); -} \ No newline at end of file + select_and_then_compare( + r#"$['single\'quote']"#, + json!({"single'quote":"value"}), + json!(["value"]), + ); + select_and_then_compare( + r#"$["double\"quote"]"#, + json!({"double\"quote":"value"}), + json!(["value"]), + ); +} diff --git a/tests/lib.rs b/tests/lib.rs index 3ac8f249..742980a8 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -18,17 +18,17 @@ fn compile() { let json_obj = read_json("./benches/data_obj.json"); let json = template(&json_obj).unwrap(); let ret = json!([ - {"id": 2,"name": "Gray Berry"}, - {"id": 2,"name": "Gray Berry"} - ]); + {"id": 2,"name": "Gray Berry"}, + {"id": 2,"name": "Gray Berry"} + ]); compare_result(json, ret); let json_obj = read_json("./benches/data_array.json"); let json = template(&json_obj).unwrap(); let ret = json!([ - {"id": 2,"name": "Gray Berry"}, - {"id": 2,"name": "Rosetta Erickson"} - ]); + {"id": 2,"name": "Gray Berry"}, + {"id": 2,"name": "Rosetta Erickson"} + ]); compare_result(json, ret); } @@ -40,16 +40,16 @@ fn selector() { let mut reader = jsonpath::selector(&json_obj); let json = reader("$..friends[2]").unwrap(); let ret = json!([ - {"id": 2,"name": "Gray Berry"}, - {"id": 2,"name": "Gray Berry"} - ]); + {"id": 2,"name": "Gray Berry"}, + {"id": 2,"name": "Gray Berry"} + ]); compare_result(json, ret); let json = reader("$..friends[0]").unwrap(); let ret = json!([ - {"id": 0}, - {"id": 0,"name": "Millicent Norman"} - ]); + {"id": 0}, + {"id": 0,"name": "Millicent Norman"} + ]); compare_result(json, ret); } @@ -65,17 +65,26 @@ fn selector_as() { let mut selector = jsonpath::selector_as::(&json_obj); let json = selector("$..friends[2]").unwrap(); - let ret = vec!( - Friend { id: 2, name: Some("Gray Berry".to_string()) }, - Friend { id: 2, name: Some("Gray Berry".to_string()) }, - ); + let ret = vec![ + Friend { + id: 2, + name: Some("Gray Berry".to_string()), + }, + Friend { + id: 2, + name: Some("Gray Berry".to_string()), + }, + ]; assert_eq!(json, ret); let json = selector("$..friends[0]").unwrap(); - let ret = vec!( + let ret = vec![ Friend { id: 0, name: None }, - Friend { id: 0, name: Some("Millicent Norman".to_string()) }, - ); + Friend { + id: 0, + name: Some("Millicent Norman".to_string()), + }, + ]; assert_eq!(json, ret); } @@ -84,12 +93,12 @@ fn select() { let json_obj = read_json("./benches/example.json"); let json = jsonpath::select(&json_obj, "$..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" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }]); compare_result(json, ret); } @@ -98,12 +107,12 @@ fn select_str() { let json_str = read_contents("./benches/example.json"); let result_str = jsonpath::select_as_str(&json_str, "$..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" : "Herman Melville", + "title" : "Moby Dick", + "isbn" : "0-553-21311-3", + "price" : 8.99 + }]); let json: Value = serde_json::from_str(&result_str).unwrap(); assert_eq!(json, ret); } @@ -117,7 +126,8 @@ fn test_to_struct() { phones: Vec, } - let ret: Vec = jsonpath::select_as(r#" + let ret: Vec = jsonpath::select_as( + r#" { "person": { @@ -129,7 +139,10 @@ fn test_to_struct() { ] } } - "#, "$.person").unwrap(); + "#, + "$.person", + ) + .unwrap(); let person = Person { name: "Doe John".to_string(), @@ -138,4 +151,4 @@ fn test_to_struct() { }; assert_eq!(vec![person], ret); -} \ No newline at end of file +} diff --git a/tests/mutable.rs b/tests/mutable.rs index b61fa075..5cda7409 100644 --- a/tests/mutable.rs +++ b/tests/mutable.rs @@ -3,7 +3,7 @@ extern crate jsonpath_lib as jsonpath; extern crate serde_json; use common::{read_json, setup}; -use jsonpath::{SelectorMut, Selector}; +use jsonpath::{Selector, SelectorMut}; use serde_json::Value; mod common; @@ -16,7 +16,8 @@ fn selector_mut() { let mut nums = Vec::new(); let result = selector_mut - .str_path(r#"$.store..price"#).unwrap() + .str_path(r#"$.store..price"#) + .unwrap() .value(read_json("./benches/example.json")) .replace_with(&mut |v| { match v { @@ -26,15 +27,32 @@ fn selector_mut() { _ => {} } Value::String("a".to_string()) - }).unwrap() - .take().unwrap(); + }) + .unwrap() + .take() + .unwrap(); - assert_eq!(nums, vec![8.95_f64, 12.99_f64, 8.99_f64, 22.99_f64, 19.95_f64]); + assert_eq!( + nums, + vec![8.95_f64, 12.99_f64, 8.99_f64, 22.99_f64, 19.95_f64] + ); let mut selector = Selector::new(); - let result = selector.str_path(r#"$.store..price"#).unwrap() + let result = selector + .str_path(r#"$.store..price"#) + .unwrap() .value(&result) - .select().unwrap(); - - assert_eq!(vec![&json!("a"), &json!("a"), &json!("a"), &json!("a"), &json!("a")], result); -} \ No newline at end of file + .select() + .unwrap(); + + assert_eq!( + vec![ + &json!("a"), + &json!("a"), + &json!("a"), + &json!("a"), + &json!("a") + ], + result + ); +} diff --git a/tests/readme.rs b/tests/readme.rs index ef986730..3f15f65f 100644 --- a/tests/readme.rs +++ b/tests/readme.rs @@ -52,83 +52,105 @@ fn readme() { 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}) - ]); + 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] @@ -154,9 +176,11 @@ fn readme_selector() { let mut selector = Selector::new(); let result = selector - .str_path("$..[?(@.age >= 30)]").unwrap() + .str_path("$..[?(@.age >= 30)]") + .unwrap() .value(&json_obj) - .select().unwrap(); + .select() + .unwrap(); assert_eq!(vec![&json!({"name": "친구3", "age": 30})], result); @@ -164,7 +188,13 @@ fn readme_selector() { assert_eq!(r#"[{"name":"친구3","age":30}]"#, result); let result = selector.select_as::().unwrap(); - assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result); + assert_eq!( + vec![Friend { + name: "친구3".to_string(), + age: Some(30) + }], + result + ); } #[test] @@ -184,7 +214,8 @@ fn readme_selector_mut() { let mut selector_mut = SelectorMut::new(); let result = selector_mut - .str_path("$..[?(@.age == 20)].age").unwrap() + .str_path("$..[?(@.age == 20)].age") + .unwrap() .value(json_obj) .replace_with(&mut |v| { let age = if let Value::Number(n) = v { @@ -194,20 +225,25 @@ fn readme_selector_mut() { }; json!(age) - }).unwrap() - .take().unwrap(); - - assert_eq!(result, json!({ - "school": { + }) + .unwrap() + .take() + .unwrap(); + + assert_eq!( + result, + json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 40}, + {"name": "친구2", "age": 40} + ] + }, "friends": [ - {"name": "친구1", "age": 40}, - {"name": "친구2", "age": 40} - ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ]})); + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ]}) + ); } #[test] @@ -226,15 +262,19 @@ fn readme_select() { let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap(); - assert_eq!(json, vec![ - &json!({"name": "친구3", "age": 30}), - &json!({"name": "친구1", "age": 20}) - ]); + assert_eq!( + json, + vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) + ] + ); } #[test] fn readme_select_as_str() { - let ret = jsonpath::select_as_str(r#" + let ret = jsonpath::select_as_str( + r#" { "school": { "friends": [ @@ -247,9 +287,15 @@ fn readme_select_as_str() { {"name": "친구4"} ] } - "#, "$..friends[0]").unwrap(); - - assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#); + "#, + "$..friends[0]", + ) + .unwrap(); + + assert_eq!( + ret, + r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"# + ); } #[test] @@ -261,19 +307,21 @@ fn readme_select_as() { phones: Vec, } - let ret: Vec = jsonpath::select_as(r#" - { - "person": - { - "name": "Doe John", - "age": 44, - "phones": [ - "+44 1234567", - "+44 2345678" - ] - } - } - "#, "$.person").unwrap(); + let ret: Vec = jsonpath::select_as( + r#"{ + "person": + { + "name": "Doe John", + "age": 44, + "phones": [ + "+44 1234567", + "+44 2345678" + ] + } + }"#, + "$.person", + ) + .unwrap(); let person = Person { name: "Doe John".to_string(), @@ -302,10 +350,13 @@ fn readme_compile() { let json = first_firend(&json_obj).unwrap(); - assert_eq!(json, vec![ - &json!({"name": "친구3", "age": 30}), - &json!({"name": "친구1", "age": 20}) - ]); + assert_eq!( + json, + vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) + ] + ); } #[test] @@ -326,17 +377,23 @@ fn readme_selector_fn() { let json = selector("$..friends[0]").unwrap(); - assert_eq!(json, vec![ - &json!({"name": "친구3", "age": 30}), - &json!({"name": "친구1", "age": 20}) - ]); + assert_eq!( + json, + vec![ + &json!({"name": "친구3", "age": 30}), + &json!({"name": "친구1", "age": 20}) + ] + ); let json = selector("$..friends[1]").unwrap(); - assert_eq!(json, vec![ - &json!({"name": "친구4"}), - &json!({"name": "친구2", "age": 20}) - ]); + assert_eq!( + json, + vec![ + &json!({"name": "친구4"}), + &json!({"name": "친구2", "age": 20}) + ] + ); } #[test] @@ -363,23 +420,34 @@ fn readme_selector_as() { 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) } - ); + let ret = vec![ + Friend { + name: "친구3".to_string(), + age: Some(30), + }, + Friend { + name: "친구1".to_string(), + age: Some(20), + }, + ]; assert_eq!(json, ret); let json = selector("$..friends[1]").unwrap(); - let ret = vec!( - Friend { name: "친구4".to_string(), age: None }, - Friend { name: "친구2".to_string(), age: Some(20) } - ); + let ret = vec![ + Friend { + name: "친구4".to_string(), + age: None, + }, + Friend { + name: "친구2".to_string(), + age: Some(20), + }, + ]; assert_eq!(json, ret); } - #[test] fn readme_delete() { let json_obj = json!({ @@ -396,17 +464,20 @@ fn readme_delete() { let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap(); - assert_eq!(ret, json!({ - "school": { + assert_eq!( + ret, + json!({ + "school": { + "friends": [ + null, + null + ] + }, "friends": [ - null, - null - ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ]})); + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ]}) + ); } #[test] @@ -417,16 +488,19 @@ fn readme_delete2() { println!("{:?}", ret); - assert_eq!(ret, json!({ - "store": { - "book": null, - "bicycle": { - "color": "red", - "price": 19.95 - } - }, - "expensive": 10 - })); + assert_eq!( + ret, + json!({ + "store": { + "book": null, + "bicycle": { + "color": "red", + "price": 19.95 + } + }, + "expensive": 10 + }) + ); } #[test] @@ -451,17 +525,21 @@ fn readme_replace_with() { }; json!(age) - }).unwrap(); - - assert_eq!(result, json!({ - "school": { + }) + .unwrap(); + + assert_eq!( + result, + json!({ + "school": { + "friends": [ + {"name": "친구1", "age": 40}, + {"name": "친구2", "age": 40} + ] + }, "friends": [ - {"name": "친구1", "age": 40}, - {"name": "친구2", "age": 40} - ] - }, - "friends": [ - {"name": "친구3", "age": 30}, - {"name": "친구4"} - ]})); -} \ No newline at end of file + {"name": "친구3", "age": 30}, + {"name": "친구4"} + ]}) + ); +} diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 25abf1c4..ec1b8bfa 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -5,9 +5,9 @@ extern crate serde_json; extern crate wasm_bindgen; use cfg_if::cfg_if; -use jsonpath::{JsonPathError, Parser}; use jsonpath::Selector as _Selector; use jsonpath::SelectorMut as _SelectorMut; +use jsonpath::{JsonPathError, Parser}; use serde_json::Value; use wasm_bindgen::prelude::*; @@ -40,40 +40,37 @@ macro_rules! console_error { } fn into_serde_json(js_value: &JsValue) -> Result - where D: for<'a> serde::de::Deserialize<'a> +where + D: for<'a> serde::de::Deserialize<'a>, { if js_value.is_string() { match serde_json::from_str(js_value.as_string().unwrap().as_str()) { Ok(json) => Ok(json), - Err(e) => Err(e.to_string()) + Err(e) => Err(e.to_string()), } } else { match js_value.into_serde() { Ok(json) => Ok(json), - Err(e) => Err(e.to_string()) + Err(e) => Err(e.to_string()), } } } fn replace_fun(v: &Value, fun: &js_sys::Function) -> Value { match JsValue::from_serde(v) { - Ok(js_v) => { - match fun.call1(&JsValue::NULL, &js_v) { - Ok(result) => { - match into_serde_json(&result) { - Ok(json) => json, - Err(e) => { - console_error!("replace_with - closure returned a invalid JSON: {:?}", e); - Value::Null - } - } - } + Ok(js_v) => match fun.call1(&JsValue::NULL, &js_v) { + Ok(result) => match into_serde_json(&result) { + Ok(json) => json, Err(e) => { - console_error!("replace_with - fail to call closure: {:?}", e); + console_error!("replace_with - closure returned a invalid JSON: {:?}", e); Value::Null } + }, + Err(e) => { + console_error!("replace_with - fail to call closure: {:?}", e); + Value::Null } - } + }, Err(e) => { console_error!("replace_with - invalid JSON object: {:?}", e); Value::Null @@ -88,22 +85,22 @@ pub fn compile(path: &str) -> JsValue { let cb = Closure::wrap(Box::new(move |js_value: JsValue| { let json = match into_serde_json(&js_value) { Ok(json) => json, - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))), }; let mut selector = _Selector::new(); match &node { Ok(node) => selector.compiled_path(node), - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone()))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone()))), }; 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!("{:?}", JsonPathError::Serde(e.to_string()))), }, - Err(e) => JsValue::from_str(&format!("{:?}", e)) + Err(e) => JsValue::from_str(&format!("{:?}", e)), } }) as Box JsValue>); @@ -116,25 +113,27 @@ pub fn compile(path: &str) -> JsValue { pub fn selector(js_value: JsValue) -> JsValue { let json: Value = match JsValue::into_serde(&js_value) { Ok(json) => json, - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e.to_string()))), }; - let cb = Closure::wrap(Box::new(move |path: String| { - match Parser::compile(path.as_str()) { + let cb = Closure::wrap( + Box::new(move |path: String| match Parser::compile(path.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!("{:?}", JsonPathError::Serde(e.to_string()))) + } }, - Err(e) => JsValue::from_str(&format!("{:?}", e)) + Err(e) => JsValue::from_str(&format!("{:?}", e)), } } - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e))) - } - }) as Box JsValue>); + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e))), + }) as Box JsValue>, + ); let ret = cb.as_ref().clone(); cb.forget(); @@ -145,15 +144,15 @@ pub fn selector(js_value: JsValue) -> JsValue { pub fn select(js_value: JsValue, path: &str) -> JsValue { let json = match into_serde_json(&js_value) { Ok(json) => json, - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))), }; match jsonpath::select(&json, path) { 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!("{:?}", JsonPathError::Serde(e.to_string()))), }, - Err(e) => JsValue::from_str(&format!("{:?}", e)) + Err(e) => JsValue::from_str(&format!("{:?}", e)), } } @@ -161,17 +160,15 @@ pub fn select(js_value: JsValue, path: &str) -> JsValue { pub fn delete(js_value: JsValue, path: &str) -> JsValue { let json = match into_serde_json(&js_value) { Ok(json) => json, - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))), }; match jsonpath::delete(json, path) { - 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)) + 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)), } } @@ -179,15 +176,15 @@ pub fn delete(js_value: JsValue, path: &str) -> JsValue { pub fn replace_with(js_value: JsValue, path: &str, fun: js_sys::Function) -> JsValue { let json = match into_serde_json(&js_value) { Ok(json) => json, - Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))) + Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e))), }; match jsonpath::replace_with(json, path, &mut |v| replace_fun(v, &fun)) { 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!("{:?}", JsonPathError::Serde(e.to_string()))), }, - Err(e) => JsValue::from_str(&format!("{:?}", e)) + Err(e) => JsValue::from_str(&format!("{:?}", e)), } } @@ -205,7 +202,10 @@ pub struct Selector { impl Selector { #[wasm_bindgen(constructor)] pub fn new() -> Self { - Selector { path: None, value: None } + Selector { + path: None, + value: None, + } } #[wasm_bindgen(catch)] @@ -227,23 +227,34 @@ impl Selector { let mut selector = _Selector::new(); if let Some(path) = &self.path { - let _ = selector.str_path(&path).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?; + let _ = selector + .str_path(&path) + .map_err(|e| JsValue::from_str(&format!("{:?}", e)))?; } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyPath + ))); } if let Some(value) = &self.value { let _ = selector.value(value); } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyValue + ))); } 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!( + "{:?}", + JsonPathError::Serde(e.to_string()) + ))), }, - Err(e) => Err(JsValue::from_str(&format!("{:?}", e))) + Err(e) => Err(JsValue::from_str(&format!("{:?}", e))), } } } @@ -261,7 +272,10 @@ pub struct SelectorMut { impl SelectorMut { #[wasm_bindgen(constructor)] pub fn new() -> Self { - SelectorMut { path: None, value: None } + SelectorMut { + path: None, + value: None, + } } #[wasm_bindgen(catch)] @@ -285,13 +299,19 @@ impl SelectorMut { if let Some(path) = &self.path { let _ = selector.str_path(path); } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyPath + ))); }; if let Some(value) = self.value.take() { selector.value(value); } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyValue + ))); }; match selector.delete() { @@ -310,13 +330,19 @@ impl SelectorMut { if let Some(path) = &self.path { let _ = selector.str_path(path); } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyPath))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyPath + ))); }; if let Some(value) = self.value.take() { selector.value(value); } else { - return Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue))); + return Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyValue + ))); }; match selector.replace_with(&mut |v| replace_fun(v, &fun)) { @@ -333,9 +359,12 @@ impl SelectorMut { match self.value.take() { Some(ret) => match JsValue::from_serde(&ret) { Ok(ret) => Ok(ret), - Err(e) => Err(JsValue::from_str(&format!("{:?}", e))) + Err(e) => Err(JsValue::from_str(&format!("{:?}", e))), }, - None => Err(JsValue::from_str(&format!("{:?}", JsonPathError::EmptyValue))) + None => Err(JsValue::from_str(&format!( + "{:?}", + JsonPathError::EmptyValue + ))), } } -} \ No newline at end of file +}