IntelliJ rustfmt default rule 적용

This commit is contained in:
freestrings
2019-06-19 11:34:47 +09:00
parent ebd49c2205
commit 6a270c9456
13 changed files with 1805 additions and 1246 deletions

View File

@ -18,7 +18,7 @@ fn select(mut ctx: FunctionContext) -> JsResult<JsValue> {
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<JsValue> {
let path = ctx.argument::<JsString>(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<JsValue> {
let json_val = ctx.argument::<JsString>(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::<JsString>(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<JsValue> {
let json_val = ctx.argument::<JsString>(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::<JsString>(1)?.value();
let fun = ctx.argument::<JsFunction>(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::<JsString>() {
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::<JsCompileFn>("CompileFn").expect("CompileFn class error");
m.export_class::<JsSelectorFn>("SelectorFn").expect("SelectorFn class error");
m.export_class::<JsSelector>("Selector").expect("Selector class error");
m.export_class::<JsSelectorMut>("SelectorMut").expect("SelectorMut class error");
m.export_class::<JsCompileFn>("CompileFn")
.expect("CompileFn class error");
m.export_class::<JsSelectorFn>("SelectorFn")
.expect("SelectorFn class error");
m.export_class::<JsSelector>("Selector")
.expect("Selector class error");
m.export_class::<JsSelectorMut>("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(())
});
});

View File

@ -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<Vec<&Value>, 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<Vec<&Value>, JsonPath
pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result<Vec<&Value>, 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<Vec<&Value
///
/// assert_eq!(json, ret);
/// ```
pub fn selector_as<T: serde::de::DeserializeOwned>(json: &Value) -> impl FnMut(&str) -> Result<Vec<T>, JsonPathError> + '_ {
pub fn selector_as<T: serde::de::DeserializeOwned>(
json: &Value,
) -> impl FnMut(&str) -> Result<Vec<T>, 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<String, JsonPathError
///
/// assert_eq!(ret[0], person);
/// ```
pub fn select_as<T: serde::de::DeserializeOwned>(json_str: &str, path: &str) -> Result<Vec<T>, JsonPathError> {
pub fn select_as<T: serde::de::DeserializeOwned>(
json_str: &str,
path: &str,
) -> Result<Vec<T>, 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<T: serde::de::DeserializeOwned>(json_str: &str, path: &str) ->
/// ```
pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
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<Value, JsonPathError> {
/// ]}));
/// ```
pub fn replace_with<F>(value: Value, path: &str, fun: &mut F) -> Result<Value, JsonPathError>
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)
}
}

View File

@ -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<Vec<ParseToken>, 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("$.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.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("$.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::In, ParseToken::All])
);
assert_eq!(run("$..*"), Ok(vec![
ParseToken::Absolute,
ParseToken::Leaves,
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("$..[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("$.[*]"),
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
])
);
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[*].가"),
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[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[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[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[: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("$.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#"$[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#"$[: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#"$[::]"#), 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#"$[::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(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[?(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("$.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)]"),
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("$[?($.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("$[?(@.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("$[*][*][*]"),
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']['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("$.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("$[:]"),
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("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(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)
));
Token::Key(5, "a".to_string()),
],
Some(TokenError::Eof),
),
);
run("$. []",
run(
"$. []",
(
vec![
Token::Absolute(0),
Token::Dot(1),
Token::Whitespace(2, 2),
Token::OpenArray(5),
Token::CloseArray(6)
]
, Some(TokenError::Eof)
));
Token::CloseArray(6),
],
Some(TokenError::Eof),
),
);
run("$..",
run(
"$..",
(
vec![Token::Absolute(0), Token::Dot(1), Token::Dot(2)],
Some(TokenError::Eof),
),
);
run(
"$..ab",
(
vec![
Token::Absolute(0),
Token::Dot(1),
Token::Dot(2),
]
, Some(TokenError::Eof)
));
Token::Key(3, "ab".to_string()),
],
Some(TokenError::Eof),
),
);
run("$..ab",
(
vec![
Token::Absolute(0),
Token::Dot(1),
Token::Dot(2),
Token::Key(3, "ab".to_string())
]
, Some(TokenError::Eof)
));
run("$..가 [",
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)
));
],
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(
"?($.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(
"$[:]",
(
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#"$['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)));
run(
r#"$["double\"quote"]"#,
(
vec![
Token::Absolute(0),
Token::OpenArray(1),
Token::DoubleQuoted(2, "double\"quote".to_string()),
Token::CloseArray(17),
],
Some(TokenError::Eof),
),
);
}
}
}

View File

@ -10,11 +10,12 @@ mod utils {
use std::str::FromStr;
pub fn string_to_num<F, S: FromStr>(string: &String, msg_handler: F) -> Result<S, String>
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<Node> {
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<Node> {
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<Node> {
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<S: FromStr>(tokenizer: &mut TokenReader) -> Result<Option<S>, 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<Node> {
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<Node> {
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<Node> {
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) {}
}
}

View File

@ -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<F>(&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
}
}
}

View File

@ -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<Token> {
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<String, TokenError> {
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<Token, TokenError> {
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<Token, TokenError> {
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),
}
}
}
}

View File

@ -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<C1: Cmp, C2: Cmp>(&self, other: &Self, cmp_fn: &C1, reverse_cmp_fn: &C2) -> ExprTerm<'a> {
fn cmp<C1: Cmp, C2: 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) }
}
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!()
if ret.is_empty() {
ExprTerm::Bool(cmp_fn.default())
} else {
ExprTerm::Json(None, ret)
}
}
_ => unreachable!()
ExprTerm::Json(_, vec1) if other.is_json() => match &other {
ExprTerm::Json(_, vec2) => {
let vec = cmp_fn.cmp_json(vec1, vec2);
if vec.is_empty() {
ExprTerm::Bool(cmp_fn.default())
} else {
ExprTerm::Json(None, vec)
}
}
_ => unreachable!(),
},
_ => unreachable!(),
}
}
@ -399,30 +432,31 @@ impl<'a> Into<ExprTerm<'a>> 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<Vec<&Value>>
where
F: Fn(&Value) -> Option<Vec<&Value>>,
{
fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F)
where F: Fn(&Value) -> Option<Vec<&Value>>
where
F: Fn(&Value) -> Option<Vec<&Value>>,
{
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<String>) {
fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>, keys: &Vec<String>, visited: &mut HashSet<*const Value>) {
fn _collect<'a>(
v: &'a Value,
tmp: &mut Vec<&'a Value>,
keys: &Vec<String>,
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<F: FnMut(&Value) -> Value>(tokens: Vec<String>, 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<Vec<String>> {
fn _walk(origin: &Value, target: &mut Vec<&Value>, tokens: &mut Vec<String>, visited: &mut IndexMap<*const Value, Vec<String>>) -> bool {
fn _walk(
origin: &Value,
target: &mut Vec<&Value>,
tokens: &mut Vec<String>,
visited: &mut IndexMap<*const Value, Vec<String>>,
) -> 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<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
pub fn replace_with<F: FnMut(&Value) -> 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)
}
}
}

View File

@ -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::<Value>().unwrap();
assert_eq!(result, match target {
Value::Array(vec) => vec,
_ => panic!("Give me the Array!")
}, "{}", path);
.select_as::<Value>()
.unwrap();
assert_eq!(
result,
match target {
Value::Array(vec) => vec.clone(),
_ => panic!("Give me the Array!"),
},
"{}",
path
);
}
#[allow(dead_code)]

View File

@ -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, 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[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(
"$.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[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(
"$..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'][*].['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(
"$['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(
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": [
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[10])]",
read_json("./benches/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school[?(1==1)]",
read_json("./benches/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school.friends[?(1==1)]",
read_json("./benches/data_obj.json"),
json!([[
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]));
select_and_then_compare("$.school[?(@.friends[0])]", read_json("./benches/data_obj.json"), json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]));
select_and_then_compare("$.school[?(@.friends[10])]", read_json("./benches/data_obj.json"), json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]));
select_and_then_compare("$.school[?(1==1)]", read_json("./benches/data_obj.json"), json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]));
select_and_then_compare("$.school.friends[?(1==1)]", read_json("./benches/data_obj.json"), json!([[
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]]));
]]),
);
}
#[test]
fn op_default() {
setup();
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#"$.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#"$..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.*"#,
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#"$.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!([
{
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" : "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" : "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[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" : "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[: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[?(@.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#"$..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#"$.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#"$..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#"$..*"#, read_json("./benches/example.json"),
read_json("./benches/giveme_every_thing_result.json"));
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"]));
}
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"]),
);
}

View File

@ -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::<Friend>(&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<String>,
}
let ret: Vec<Person> = jsonpath::select_as(r#"
let ret: Vec<Person> = 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);
}
}

View File

@ -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();
.select()
.unwrap();
assert_eq!(vec![&json!("a"), &json!("a"), &json!("a"), &json!("a"), &json!("a")], result);
}
assert_eq!(
vec![
&json!("a"),
&json!("a"),
&json!("a"),
&json!("a"),
&json!("a")
],
result
);
}

View File

@ -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("$.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("$..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.*").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("$.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[-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[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[: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("$..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[?(@.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::<Friend>().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();
})
.unwrap()
.take()
.unwrap();
assert_eq!(result, json!({
"school": {
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();
"#,
"$..friends[0]",
)
.unwrap();
assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
assert_eq!(
ret,
r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#
);
}
#[test]
@ -261,19 +307,21 @@ fn readme_select_as() {
phones: Vec<String>,
}
let ret: Vec<Person> = jsonpath::select_as(r#"
{
"person":
{
"name": "Doe John",
"age": 44,
"phones": [
"+44 1234567",
"+44 2345678"
]
}
}
"#, "$.person").unwrap();
let ret: Vec<Person> = 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();
})
.unwrap();
assert_eq!(result, json!({
"school": {
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"}
]})
);
}

View File

@ -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<D>(js_value: &JsValue) -> Result<D, String>
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<Fn(JsValue) -> 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<Fn(String) -> JsValue>);
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e))),
}) as Box<Fn(String) -> 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
))),
}
}
}
}