diff --git a/benches/bench.rs b/benches/bench.rs index 27b1a37..b2907b8 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -109,7 +109,7 @@ fn bench_select_as(b: &mut Bencher) { #[bench] fn bench_delete(b: &mut Bencher) { let json = get_json(); - let mut selector = SelectorMut::new(); + let mut selector = SelectorMut::default(); let _ = selector.str_path(get_path()); b.iter(move || { @@ -123,13 +123,13 @@ fn bench_delete(b: &mut Bencher) { fn bench_select_to_compare_with_delete(b: &mut Bencher) { let json = &get_json(); - let mut selector = Selector::new(); + let mut selector = Selector::default(); let _ = selector.str_path(get_path()); b.iter(move || { for _ in 1..100 { let json = json.clone(); - let mut s = Selector::new(); + let mut s = Selector::default(); let _ = s.compiled_path(selector.node_ref().unwrap()).value(&json); let _ = s.select(); } diff --git a/benches/bench_example.rs b/benches/bench_example.rs index dd77bca..3cd3764 100644 --- a/benches/bench_example.rs +++ b/benches/bench_example.rs @@ -53,7 +53,7 @@ fn _selector(b: &mut Bencher, index: usize) { let json = get_json(); b.iter(move || { for _ in 1..100 { - let mut selector = jsonpath::Selector::new(); + let mut selector = jsonpath::Selector::default(); let _ = selector.str_path(get_path(index)); selector.value(&json); let r = selector.select(); diff --git a/src/lib.rs b/src/lib.rs index 7864342..bb1ff6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -172,7 +172,7 @@ pub fn compile(path: &str) -> impl FnMut(&Value) -> Result, JsonPath let node = Parser::compile(path); move |json| match &node { Ok(node) => { - let mut selector = Selector::new(); + let mut selector = Selector::default(); selector.compiled_path(node).value(json).select() } Err(e) => Err(JsonPathError::Path(e.to_string())), @@ -213,8 +213,9 @@ pub fn compile(path: &str) -> impl FnMut(&Value) -> Result, JsonPath /// &json!({"name": "친구2", "age": 20}) /// ]); /// ``` +#[allow(clippy::needless_lifetimes)] pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result, JsonPathError> { - let mut selector = Selector::new(); + let mut selector = Selector::default(); let _ = selector.value(json); move |path: &str| selector.str_path(path)?.reset_value().select() } @@ -268,7 +269,7 @@ pub fn selector<'a>(json: &'a Value) -> impl FnMut(&'a str) -> Result( json: &Value, ) -> impl FnMut(&str) -> Result, JsonPathError> + '_ { - let mut selector = Selector::new(); + let mut selector = Selector::default(); let _ = selector.value(json); move |path: &str| selector.str_path(path)?.reset_value().select_as() } @@ -299,7 +300,7 @@ pub fn selector_as( /// ]); /// ``` pub fn select<'a>(json: &'a Value, path: &'a str) -> Result, JsonPathError> { - Selector::new().str_path(path)?.value(json).select() + Selector::default().str_path(path)?.value(json).select() } /// It is the same to `select` function but it return the result as string. @@ -327,7 +328,7 @@ pub fn select<'a>(json: &'a Value, path: &'a str) -> Result, Json /// ``` pub fn select_as_str(json_str: &str, path: &str) -> Result { let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?; - let ret = Selector::new().str_path(path)?.value(&json).select()?; + let ret = Selector::default().str_path(path)?.value(&json).select()?; serde_json::to_string(&ret).map_err(|e| JsonPathError::Serde(e.to_string())) } @@ -374,7 +375,7 @@ pub fn select_as( path: &str, ) -> Result, JsonPathError> { let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?; - Selector::new().str_path(path)?.value(&json).select_as() + Selector::default().str_path(path)?.value(&json).select_as() } /// Delete(= replace with null) the JSON property using the jsonpath. @@ -410,7 +411,7 @@ pub fn select_as( /// ]})); /// ``` pub fn delete(value: Value, path: &str) -> Result { - let mut selector = SelectorMut::new(); + let mut selector = SelectorMut::default(); let ret = selector .str_path(path)? .value(value) @@ -466,7 +467,7 @@ pub fn replace_with(value: Value, path: &str, fun: &mut F) -> Result Value, { - let mut selector = SelectorMut::new(); + let mut selector = SelectorMut::default(); let ret = selector .str_path(path)? .value(value) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 3ef1a0c..27c4ce7 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -9,11 +9,11 @@ type ParseResult = Result; mod utils { use std::str::FromStr; - pub fn string_to_num(string: &String, msg_handler: F) -> Result + pub fn string_to_num(string: &str, msg_handler: F) -> Result where F: Fn() -> String, { - match string.as_str().parse() { + match string.parse() { Ok(n) => Ok(n), _ => Err(msg_handler()), } @@ -194,7 +194,7 @@ impl Parser { Ok(Token::Key(_, ref v)) if { let b = v.as_bytes(); - b.len() > 0 && (b[0] == b't' || b[0] == b'T' || b[0] == b'f' || b[0] == b'F') + !b.is_empty() && (b[0] == b't' || b[0] == b'T' || b[0] == b'f' || b[0] == b'F') } => { Ok(Self::node(ParseToken::Bool(v.eq_ignore_ascii_case("true")))) @@ -379,16 +379,12 @@ impl Parser { fn range_to(tokenizer: &mut TokenReader) -> ParseResult { debug!("#range_to"); - match Self::range_value(tokenizer)? { - Some(step) => return Ok(Self::node(ParseToken::Range(None, None, Some(step)))), - _ => {} + if let Some(step) = Self::range_value(tokenizer)? { + return Ok(Self::node(ParseToken::Range(None, None, Some(step)))); } - match tokenizer.peek_token() { - Ok(Token::CloseArray(_)) => { - return Ok(Self::node(ParseToken::Range(None, None, None))); - } - _ => {} + if let Ok(Token::CloseArray(_)) = tokenizer.peek_token() { + return Ok(Self::node(ParseToken::Range(None, None, None))); } match tokenizer.next_token() { @@ -492,7 +488,7 @@ impl Parser { } else if has_prop_candidate { Ok(node) } else { - return Err(tokenizer.err_msg()); + Err(tokenizer.err_msg()) } } @@ -510,13 +506,13 @@ impl Parser { } } - fn term_num_float(mut num: &str, tokenizer: &mut TokenReader) -> ParseResult { + fn term_num_float(num: &str, tokenizer: &mut TokenReader) -> ParseResult { debug!("#term_num_float"); Self::eat_token(tokenizer); match tokenizer.next_token() { Ok(Token::Key(pos, frac)) => { let mut f = String::new(); - f.push_str(&mut num); + f.push_str(&num); f.push('.'); f.push_str(frac.as_str()); let number = utils::string_to_num(&f, || tokenizer.err_msg_with_pos(pos))?; @@ -563,7 +559,7 @@ impl Parser { }; } - return Err(tokenizer.err_msg()); + Err(tokenizer.err_msg()) } fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult { @@ -631,56 +627,49 @@ pub trait NodeVisitor { self.visit_token(&node.token); } ParseToken::In | ParseToken::Leaves => { - match &node.left { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.left { + self.visit(&*n); } self.visit_token(&node.token); - match &node.right { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.right { + self.visit(&*n); } } ParseToken::Array => { - match &node.left { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.left { + self.visit(&*n); } self.visit_token(&node.token); - match &node.right { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.right { + self.visit(&*n); } + self.visit_token(&ParseToken::ArrayEof); } ParseToken::Filter(FilterToken::And) | ParseToken::Filter(FilterToken::Or) => { - match &node.left { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.left { + self.visit(&*n); } - match &node.right { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.right { + self.visit(&*n); } self.visit_token(&node.token); } ParseToken::Filter(_) => { - match &node.left { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.left { + self.visit(&*n); } self.end_term(); - match &node.right { - Some(n) => self.visit(&*n), - _ => {} + if let Some(n) = &node.right { + self.visit(&*n); } self.end_term(); diff --git a/src/parser/tokenizer.rs b/src/parser/tokenizer.rs index 9aa84cd..3238c5a 100644 --- a/src/parser/tokenizer.rs +++ b/src/parser/tokenizer.rs @@ -2,29 +2,29 @@ use std::result::Result; use super::path_reader::{PathReader, ReaderError}; -pub const ABSOLUTE: &'static str = "$"; -pub const DOT: &'static str = "."; -pub const AT: &'static str = "@"; -pub const OPEN_ARRAY: &'static str = "["; -pub const CLOSE_ARRAY: &'static str = "]"; -pub const ASTERISK: &'static str = "*"; -pub const QUESTION: &'static str = "?"; -pub const COMMA: &'static str = ","; -pub const SPLIT: &'static str = ":"; -pub const OPEN_PARENTHESIS: &'static str = "("; -pub const CLOSE_PARENTHESIS: &'static str = ")"; -pub const KEY: &'static str = "Key"; -pub const DOUBLE_QUOTE: &'static str = "\""; -pub const SINGLE_QUOTE: &'static str = "'"; -pub const EQUAL: &'static str = "=="; -pub const GREATER_OR_EQUAL: &'static str = ">="; -pub const GREATER: &'static str = ">"; -pub const LITTLE: &'static str = "<"; -pub const LITTLE_OR_EQUAL: &'static str = "<="; -pub const NOT_EQUAL: &'static str = "!="; -pub const AND: &'static str = "&&"; -pub const OR: &'static str = "||"; -pub const WHITESPACE: &'static str = " "; +pub const ABSOLUTE: &str = "$"; +pub const DOT: &str = "."; +pub const AT: &str = "@"; +pub const OPEN_ARRAY: &str = "["; +pub const CLOSE_ARRAY: &str = "]"; +pub const ASTERISK: &str = "*"; +pub const QUESTION: &str = "?"; +pub const COMMA: &str = ","; +pub const SPLIT: &str = ":"; +pub const OPEN_PARENTHESIS: &str = "("; +pub const CLOSE_PARENTHESIS: &str = ")"; +pub const KEY: &str = "Key"; +pub const DOUBLE_QUOTE: &str = "\""; +pub const SINGLE_QUOTE: &str = "'"; +pub const EQUAL: &str = "=="; +pub const GREATER_OR_EQUAL: &str = ">="; +pub const GREATER: &str = ">"; +pub const LITTLE: &str = "<"; +pub const LITTLE_OR_EQUAL: &str = "<="; +pub const NOT_EQUAL: &str = "!="; +pub const AND: &str = "&&"; +pub const OR: &str = "||"; +pub const WHITESPACE: &str = " "; const CH_DOLLA: char = '$'; const CH_DOT: char = '.'; @@ -321,7 +321,7 @@ impl<'a> TokenReader<'a> { } Err(e) => { return TokenReader { - origin_input: input.clone(), + origin_input: input, err: e, err_pos: tokenizer.current_pos(), tokens, diff --git a/src/select/mod.rs b/src/select/mod.rs index 44ce6fc..d180313 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -17,13 +17,13 @@ fn to_f64(n: &Number) -> f64 { } trait Cmp { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool; + fn cmp_bool(&self, v1: bool, v2: bool) -> bool; - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool; + fn cmp_f64(&self, v1: f64, v2: f64) -> bool; - fn cmp_string(&self, v1: &String, v2: &String) -> bool; + fn cmp_string(&self, v1: &str, v2: &str) -> bool; - fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value>; + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>; fn default(&self) -> bool { false @@ -33,59 +33,59 @@ trait Cmp { struct CmpEq; impl Cmp for CmpEq { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { v1 == v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + (v1 - v2).abs() == 0_f64 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 == v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 == v2 - } - - fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { - v1.intersect(v2.to_vec()) + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect(v2.to_vec()) } } struct CmpNe; impl Cmp for CmpNe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { v1 != v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + (v1 - v2).abs() != 0_f64 + } + + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 != v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 != v2 - } - - fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { - v1.intersect_if(v2.to_vec(), |a, b| a != b) + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect_if(v2.to_vec(), |a, b| a != b) } } struct CmpGt; impl Cmp for CmpGt { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 & !v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { v1 > v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 > v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 > v2 - } - - fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { Vec::new() } } @@ -93,19 +93,19 @@ impl Cmp for CmpGt { struct CmpGe; impl Cmp for CmpGe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { v1 >= v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { v1 >= v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 >= v2 } - fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { Vec::new() } } @@ -113,19 +113,19 @@ impl Cmp for CmpGe { struct CmpLt; impl Cmp for CmpLt { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + !v1 & v2 + } + + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { v1 < v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 < v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { - v1 < v2 - } - - fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { Vec::new() } } @@ -133,19 +133,19 @@ impl Cmp for CmpLt { struct CmpLe; impl Cmp for CmpLe { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { v1 <= v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { v1 <= v2 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { v1 <= v2 } - fn cmp_json<'a>(&self, _: &Vec<&'a Value>, _: &Vec<&'a Value>) -> Vec<&'a Value> { + fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> { Vec::new() } } @@ -153,40 +153,40 @@ impl Cmp for CmpLe { struct CmpAnd; impl Cmp for CmpAnd { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - *v1 && *v2 + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 && v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 > &0_f64 && v2 > &0_f64 + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 > 0_f64 && v2 > 0_f64 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { !v1.is_empty() && !v2.is_empty() } - fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { - v1.intersect(v2.to_vec()) + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().intersect(v2.to_vec()) } } struct CmpOr; impl Cmp for CmpOr { - fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool { - *v1 || *v2 + fn cmp_bool(&self, v1: bool, v2: bool) -> bool { + v1 || v2 } - fn cmp_f64(&self, v1: &f64, v2: &f64) -> bool { - v1 > &0_f64 || v2 > &0_f64 + fn cmp_f64(&self, v1: f64, v2: f64) -> bool { + v1 > 0_f64 || v2 > 0_f64 } - fn cmp_string(&self, v1: &String, v2: &String) -> bool { + fn cmp_string(&self, v1: &str, v2: &str) -> bool { !v1.is_empty() || !v2.is_empty() } - fn cmp_json<'a>(&self, v1: &Vec<&'a Value>, v2: &Vec<&'a Value>) -> Vec<&'a Value> { - v1.union(v2.to_vec()) + fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> { + v1.to_vec().union(v2.to_vec()) } } @@ -212,12 +212,12 @@ impl<'a> ExprTerm<'a> { _ => 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::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(to_f64(n1), to_f64(n2))), ExprTerm::Json(_, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn), _ => ExprTerm::Bool(cmp_fn.default()), }, ExprTerm::Bool(b1) => match &other { - ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(b1, b2)), + ExprTerm::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()), }, @@ -237,39 +237,39 @@ impl<'a> ExprTerm<'a> { } _ => cmp_fn.default(), }) - .map(|v| *v) + .cloned() .collect(), ExprTerm::Number(n2) => vec1 .iter() .filter(|v1| match v1 { - Value::Number(n1) => cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2)), + Value::Number(n1) => cmp_fn.cmp_f64(to_f64(n1), to_f64(n2)), Value::Object(map1) => { if let Some(FilterKey::String(k)) = fk1 { if let Some(Value::Number(n1)) = map1.get(k) { - return cmp_fn.cmp_f64(&to_f64(n1), &to_f64(n2)); + return cmp_fn.cmp_f64(to_f64(n1), to_f64(n2)); } } cmp_fn.default() } _ => cmp_fn.default(), }) - .map(|v| *v) + .cloned() .collect(), ExprTerm::Bool(b2) => vec1 .iter() .filter(|v1| match v1 { - Value::Bool(b1) => cmp_fn.cmp_bool(b1, b2), + Value::Bool(b1) => cmp_fn.cmp_bool(*b1, *b2), Value::Object(map1) => { if let Some(FilterKey::String(k)) = fk1 { if let Some(Value::Bool(b1)) = map1.get(k) { - return cmp_fn.cmp_bool(b1, b2); + return cmp_fn.cmp_bool(*b1, *b2); } } cmp_fn.default() } _ => cmp_fn.default(), }) - .map(|v| *v) + .cloned() .collect(), ExprTerm::Json(_, vec2) => cmp_fn.cmp_json(vec1, vec2), }; @@ -363,12 +363,7 @@ impl<'a> Into> for &Vec<&'a Value> { } } -fn walk_all_with_str<'a>( - vec: &Vec<&'a Value>, - tmp: &mut Vec<&'a Value>, - key: &str, - is_filter: bool, -) { +fn walk_all_with_str<'a>(vec: &[&'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]), @@ -385,7 +380,7 @@ fn walk_all_with_str<'a>( } } -fn walk_all<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>) { +fn walk_all<'a>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) { walk(vec, tmp, &|v| match v { Value::Array(vec) => Some(vec.iter().collect()), Value::Object(map) => { @@ -399,7 +394,7 @@ fn walk_all<'a>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>) { }); } -fn walk<'a, F>(vec: &Vec<&'a Value>, tmp: &mut Vec<&'a Value>, fun: &F) +fn walk<'a, F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option>, { @@ -431,11 +426,11 @@ where } } -fn abs_index(n: &isize, len: usize) -> usize { - if n < &0_isize { +fn abs_index(n: isize, len: usize) -> usize { + if n < 0_isize { (n + len as isize) as usize } else { - *n as usize + n as usize } } @@ -469,7 +464,7 @@ impl fmt::Display for JsonPathError { } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Selector<'a, 'b> { node: Option, node_ref: Option<&'b Node>, @@ -482,15 +477,7 @@ pub struct Selector<'a, 'b> { impl<'a, 'b> Selector<'a, 'b> { pub fn new() -> Self { - Selector { - node: None, - node_ref: None, - value: None, - tokens: Vec::new(), - terms: Vec::new(), - current: None, - selectors: Vec::new(), - } + Selector::default() } pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> { @@ -500,7 +487,7 @@ impl<'a, 'b> Selector<'a, 'b> { self.node_ref.take(); } - self.node = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?); + self.node = Some(Parser::compile(path).map_err(JsonPathError::Path)?); Ok(self) } @@ -593,8 +580,8 @@ impl<'a, 'b> Selector<'a, 'b> { } fn in_filter, &mut Vec<&'a Value>) -> FilterKey>(&mut self, fun: F) { - match self.terms.pop() { - Some(peek) => match peek { + if let Some(peek) = self.terms.pop() { + match peek { Some(v) => { debug!("in_filter 1.: {:?}", v); @@ -616,8 +603,7 @@ impl<'a, 'b> Selector<'a, 'b> { self.terms.push(Some(ExprTerm::Json(Some(filter_key), tmp))); } } - }, - _ => {} + } } } @@ -672,7 +658,7 @@ impl<'a, 'b> Selector<'a, 'b> { let mut tmp = Vec::new(); for c in current { if let Value::Array(vec) = c { - let index = abs_index(&(index as isize), vec.len()); + let index = abs_index(index as isize, vec.len()); if let Some(v) = c.get(index) { tmp.push(v); } @@ -687,19 +673,16 @@ impl<'a, 'b> Selector<'a, 'b> { ); } - fn next_from_current_with_str(&mut self, keys: &Vec) { + fn next_from_current_with_str(&mut self, keys: &[String]) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); for c in current { - match c { - Value::Object(map) => { - for key in keys { - if let Some(v) = map.get(key) { - tmp.push(v) - } + if let Value::Object(map) = c { + for key in keys { + if let Some(v) = map.get(key) { + tmp.push(v) } } - _ => {} } } self.current = Some(tmp); @@ -752,12 +735,8 @@ impl<'a, 'b> Selector<'a, 'b> { } debug!("all_from_current_with_str: {}, {:?}", key, self.current); } -} - -impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { - fn visit_token(&mut self, token: &ParseToken) { - debug!("token: {:?}, stack: {:?}", token, self.tokens); + fn compute_absolute_path_filter(&mut self, token: &ParseToken) -> bool { if !self.selectors.is_empty() { match token { ParseToken::Absolute | ParseToken::Relative | ParseToken::Filter(_) => { @@ -781,240 +760,262 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { if let Some(selector) = self.selectors.last_mut() { selector.visit_token(token); + true + } else { + false + } + } +} + +impl<'a, 'b> Selector<'a, 'b> { + fn visit_absolute(&mut self) { + if self.current.is_some() { + let mut selector = Selector::default(); + + if let Some(value) = self.value { + selector.value = Some(value); + selector.current = Some(vec![value]); + self.selectors.push(selector); + } + return; + } + + if let Some(v) = &self.value { + self.current = Some(vec![v]); + } + } + fn visit_relative(&mut self) { + if let Some(ParseToken::Array) = self.tokens.last() { + let array_token = self.tokens.pop(); + if let Some(ParseToken::Leaves) = self.tokens.last() { + self.tokens.pop(); + self.all_from_current(); + } + self.tokens.push(array_token.unwrap()); + } + self.new_filter_context(); + } + + fn visit_array_eof(&mut self) { + if let Some(Some(e)) = self.terms.pop() { + match e { + ExprTerm::Number(n) => { + self.next_from_current_with_num(to_f64(&n)); + } + ExprTerm::String(key) => { + self.next_from_current_with_str(&[key]); + } + ExprTerm::Json(_, v) => { + if v.is_empty() { + self.current = Some(vec![&Value::Null]); + } else { + self.current = Some(v); + } + } + ExprTerm::Bool(false) => { + self.current = Some(vec![&Value::Null]); + } + _ => {} + } + } + + self.tokens.pop(); + } + + fn visit_all(&mut self) { + if let Some(ParseToken::Array) = self.tokens.last() { + self.tokens.pop(); + } + + 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(); + } + _ => { + self.next_all_from_current(); + } + } + } + + fn visit_key(&mut self, key: &str) { + if let Some(ParseToken::Array) = self.tokens.last() { + self.terms.push(Some(ExprTerm::String(key.to_string()))); + return; + } + + if let Some(t) = self.tokens.pop() { + if self.terms.is_empty() { + match t { + ParseToken::Leaves => self.all_from_current_with_str(key), + ParseToken::In => self.next_from_current_with_str(&[key.to_string()]), + _ => {} + } + } else { + match t { + ParseToken::Leaves => { + self.all_in_filter_with_str(key); + } + ParseToken::In => { + self.next_in_filter_with_str(key); + } + _ => {} + } + } + } + } + + fn visit_keys(&mut self, keys: &[String]) { + if !self.terms.is_empty() { + unimplemented!("keys in filter"); + } + + if let Some(ParseToken::Array) = self.tokens.pop() { + self.next_from_current_with_str(keys); + } else { + unreachable!(); + } + } + + fn visit_filter(&mut self, ft: &FilterToken) { + let right = match self.terms.pop() { + Some(Some(right)) => right, + Some(None) => ExprTerm::Json( + None, + match &self.current { + Some(current) => current.to_vec(), + _ => unreachable!(), + }, + ), + _ => panic!("empty term right"), + }; + + let left = match self.terms.pop() { + Some(Some(left)) => left, + Some(None) => ExprTerm::Json( + None, + match &self.current { + Some(current) => current.to_vec(), + _ => unreachable!(), + }, + ), + _ => panic!("empty term left"), + }; + + let mut ret = None; + match ft { + FilterToken::Equal => left.eq(&right, &mut ret), + FilterToken::NotEqual => left.ne(&right, &mut ret), + FilterToken::Greater => left.gt(&right, &mut ret), + FilterToken::GreaterOrEqual => left.ge(&right, &mut ret), + FilterToken::Little => left.lt(&right, &mut ret), + FilterToken::LittleOrEqual => left.le(&right, &mut ret), + FilterToken::And => left.and(&right, &mut ret), + FilterToken::Or => left.or(&right, &mut ret), + }; + + if let Some(e) = ret { + self.terms.push(Some(e)); + } + } + + fn visit_range(&mut self, from: &Option, to: &Option, step: &Option) { + if !self.terms.is_empty() { + unimplemented!("range syntax in filter"); + } + + if let Some(ParseToken::Array) = self.tokens.pop() { + let mut tmp = Vec::new(); + if let Some(current) = &self.current { + for v in current { + if let Value::Array(vec) = v { + let from = if let Some(from) = from { + abs_index(*from, vec.len()) + } else { + 0 + }; + + let to = if let Some(to) = to { + abs_index(*to, vec.len()) + } else { + vec.len() + }; + + for i in (from..to).step_by(match step { + Some(step) => *step, + _ => 1, + }) { + if let Some(v) = vec.get(i) { + tmp.push(v); + } + } + } + } + } + self.current = Some(tmp); + } else { + unreachable!(); + } + } + + fn visit_union(&mut self, indices: &[isize]) { + if !self.terms.is_empty() { + unimplemented!("union syntax in filter"); + } + + if let Some(ParseToken::Array) = self.tokens.pop() { + let mut tmp = Vec::new(); + if let Some(current) = &self.current { + for v in current { + if let Value::Array(vec) = v { + for i in indices { + if let Some(v) = vec.get(abs_index(*i, vec.len())) { + tmp.push(v); + } + } + } + } + } + + self.current = Some(tmp); + } else { + unreachable!(); + } + } +} + +impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { + fn visit_token(&mut self, token: &ParseToken) { + debug!("token: {:?}, stack: {:?}", token, self.tokens); + + if self.compute_absolute_path_filter(token) { return; } match token { - ParseToken::Absolute => { - if self.current.is_some() { - let mut selector = Selector::new(); - - if let Some(value) = self.value { - selector.value = Some(value); - selector.current = Some(vec![value]); - self.selectors.push(selector); - } - return; - } - - match &self.value { - Some(v) => self.current = Some(vec![v]), - _ => {} - } - } - ParseToken::Relative => { - if let Some(ParseToken::Array) = self.tokens.last() { - let array_token = self.tokens.pop(); - if let Some(ParseToken::Leaves) = self.tokens.last() { - self.tokens.pop(); - self.all_from_current(); - } - self.tokens.push(array_token.unwrap()); - } - self.new_filter_context(); - } + ParseToken::Absolute => self.visit_absolute(), + ParseToken::Relative => self.visit_relative(), ParseToken::In | ParseToken::Leaves | ParseToken::Array => { self.tokens.push(token.clone()); } - ParseToken::ArrayEof => { - if let Some(Some(e)) = self.terms.pop() { - match e { - ExprTerm::Number(n) => { - self.next_from_current_with_num(to_f64(&n)); - } - ExprTerm::String(key) => { - self.next_from_current_with_str(&vec![key]); - } - ExprTerm::Json(_, v) => { - if v.is_empty() { - self.current = Some(vec![&Value::Null]); - } else { - self.current = Some(v); - } - } - ExprTerm::Bool(false) => { - self.current = Some(vec![&Value::Null]); - } - _ => {} - } - } - - self.tokens.pop(); - } - ParseToken::All => { - match self.tokens.last() { - Some(ParseToken::Array) => { - self.tokens.pop(); - } - _ => {} - } - - 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(); - } - _ => { - self.next_all_from_current(); - } - } - } + ParseToken::ArrayEof => self.visit_array_eof(), + ParseToken::All => self.visit_all(), ParseToken::Bool(b) => { self.terms.push(Some(ExprTerm::Bool(*b))); } - ParseToken::Key(key) => { - if let Some(ParseToken::Array) = self.tokens.last() { - self.terms.push(Some(ExprTerm::String(key.clone()))); - return; - } - - match self.tokens.pop() { - Some(t) => { - if self.terms.is_empty() { - match t { - ParseToken::Leaves => self.all_from_current_with_str(key.as_str()), - ParseToken::In => { - self.next_from_current_with_str(&vec![key.clone()]) - } - _ => {} - } - } else { - match t { - ParseToken::Leaves => { - self.all_in_filter_with_str(key.as_str()); - } - ParseToken::In => { - self.next_in_filter_with_str(key.as_str()); - } - _ => {} - } - } - } - _ => {} - } - } - ParseToken::Keys(keys) => { - if !self.terms.is_empty() { - unimplemented!("keys in filter"); - } - - if let Some(ParseToken::Array) = self.tokens.pop() { - self.next_from_current_with_str(keys); - } else { - unreachable!(); - } - } + ParseToken::Key(key) => self.visit_key(key), + ParseToken::Keys(keys) => self.visit_keys(keys), ParseToken::Number(v) => { self.terms .push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap()))); } - ParseToken::Filter(ref ft) => { - let ref right = match self.terms.pop() { - Some(Some(right)) => right, - Some(None) => ExprTerm::Json( - None, - match &self.current { - Some(current) => current.to_vec(), - _ => unreachable!(), - }, - ), - _ => panic!("empty term right"), - }; - - let left = match self.terms.pop() { - Some(Some(left)) => left, - Some(None) => ExprTerm::Json( - None, - match &self.current { - Some(current) => current.to_vec(), - _ => unreachable!(), - }, - ), - _ => panic!("empty term left"), - }; - - let mut ret = None; - match ft { - FilterToken::Equal => left.eq(right, &mut ret), - FilterToken::NotEqual => left.ne(right, &mut ret), - FilterToken::Greater => left.gt(right, &mut ret), - FilterToken::GreaterOrEqual => left.ge(right, &mut ret), - FilterToken::Little => left.lt(right, &mut ret), - FilterToken::LittleOrEqual => left.le(right, &mut ret), - FilterToken::And => left.and(right, &mut ret), - FilterToken::Or => left.or(right, &mut ret), - }; - - if let Some(e) = ret { - self.terms.push(Some(e)); - } - } - ParseToken::Range(from, to, step) => { - if !self.terms.is_empty() { - unimplemented!("range syntax in filter"); - } - - if let Some(ParseToken::Array) = self.tokens.pop() { - let mut tmp = Vec::new(); - if let Some(current) = &self.current { - for v in current { - if let Value::Array(vec) = v { - let from = if let Some(from) = from { - abs_index(from, vec.len()) - } else { - 0 - }; - - let to = if let Some(to) = to { - abs_index(to, vec.len()) - } else { - vec.len() - }; - - for i in (from..to).step_by(match step { - Some(step) => *step, - _ => 1, - }) { - if let Some(v) = vec.get(i) { - tmp.push(v); - } - } - } - } - } - self.current = Some(tmp); - } else { - unreachable!(); - } - } - ParseToken::Union(indices) => { - if !self.terms.is_empty() { - unimplemented!("union syntax in filter"); - } - - if let Some(ParseToken::Array) = self.tokens.pop() { - let mut tmp = Vec::new(); - if let Some(current) = &self.current { - for v in current { - if let Value::Array(vec) = v { - for i in indices { - if let Some(v) = vec.get(abs_index(i, vec.len())) { - tmp.push(v); - } - } - } - } - } - - self.current = Some(tmp); - } else { - unreachable!(); - } - } + ParseToken::Filter(ref ft) => self.visit_filter(ft), + ParseToken::Range(from, to, step) => self.visit_range(from, to, step), + ParseToken::Union(indices) => self.visit_union(indices), ParseToken::Eof => { debug!("visit_token eof"); } @@ -1022,6 +1023,7 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { } } +#[derive(Default)] pub struct SelectorMut { path: Option, value: Option, @@ -1072,14 +1074,11 @@ fn replace_value Value>(tokens: Vec, value: &mut Val impl SelectorMut { pub fn new() -> Self { - SelectorMut { - path: None, - value: None, - } + Self::default() } pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> { - self.path = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?); + self.path = Some(Parser::compile(path).map_err(JsonPathError::Path)?); Ok(self) } @@ -1139,7 +1138,7 @@ impl SelectorMut { _ => {} } - return false; + false } let mut visited = HashSet::new(); @@ -1165,7 +1164,7 @@ impl SelectorMut { fn select(&self) -> Result, JsonPathError> { if let Some(node) = &self.path { - let mut selector = Selector::new(); + let mut selector = Selector::default(); selector.compiled_path(&node); if let Some(value) = &self.value { diff --git a/tests/common.rs b/tests/common.rs index a51d35a..82883fd 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -31,7 +31,7 @@ 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 mut selector = Selector::default(); let result = selector .str_path(path) .unwrap() diff --git a/tests/mutable.rs b/tests/mutable.rs index 5cda740..0477a2c 100644 --- a/tests/mutable.rs +++ b/tests/mutable.rs @@ -12,7 +12,7 @@ mod common; fn selector_mut() { setup(); - let mut selector_mut = SelectorMut::new(); + let mut selector_mut = SelectorMut::default(); let mut nums = Vec::new(); let result = selector_mut @@ -37,7 +37,7 @@ fn selector_mut() { vec![8.95_f64, 12.99_f64, 8.99_f64, 22.99_f64, 19.95_f64] ); - let mut selector = Selector::new(); + let mut selector = Selector::default(); let result = selector .str_path(r#"$.store..price"#) .unwrap() diff --git a/tests/readme.rs b/tests/readme.rs index 03f590d..2ca2274 100644 --- a/tests/readme.rs +++ b/tests/readme.rs @@ -173,7 +173,7 @@ fn readme_selector() { {"name": "친구4"} ]}); - let mut selector = Selector::new(); + let mut selector = Selector::default(); let result = selector .str_path("$..[?(@.age >= 30)]") @@ -211,7 +211,7 @@ fn readme_selector_mut() { {"name": "친구4"} ]}); - let mut selector_mut = SelectorMut::new(); + let mut selector_mut = SelectorMut::default(); let result = selector_mut .str_path("$..[?(@.age == 20)].age")