From d3840798420ff1e1c4805fc259823dc50c5d847d Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 23 Jun 2019 17:22:58 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Leaves=20=EC=B2=98=EB=A6=AC=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/select/mod.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/select/mod.rs b/src/select/mod.rs index 122337d..9d39006 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -470,12 +470,12 @@ 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) -where - F: Fn(&Value) -> Option>, -{ - fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option>, +{ + fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) + where + F: Fn(&Value) -> Option>, { if let Some(mut ret) = fun(v) { tmp.append(&mut ret); @@ -896,17 +896,17 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> { } } 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::In | ParseToken::Leaves => { - self.tokens.push(token.clone()); - } - ParseToken::Array => { - if let Some(ParseToken::Leaves) = self.tokens.last() { - self.tokens.pop(); - self.all_from_current(); - } - + ParseToken::In | ParseToken::Leaves | ParseToken::Array => { self.tokens.push(token.clone()); } ParseToken::ArrayEof => { From 053be432f2eb738ad42d08a0dd167376a7d154cc Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 23 Jun 2019 18:21:59 +0900 Subject: [PATCH 2/2] fix wildcard filter --- src/select/mod.rs | 102 ++++++++++++++++++++-------------------------- tests/filter.rs | 44 ++++++++++++++++++++ 2 files changed, 89 insertions(+), 57 deletions(-) diff --git a/src/select/mod.rs b/src/select/mod.rs index 9d39006..bb94745 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -470,12 +470,12 @@ 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) - where - F: Fn(&Value) -> Option>, +where + F: Fn(&Value) -> Option>, { fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) - where - F: Fn(&Value) -> Option>, + where + F: Fn(&Value) -> Option>, { if let Some(mut ret) = fun(v) { tmp.append(&mut ret); @@ -758,38 +758,19 @@ impl<'a, 'b> Selector<'a, 'b> { } fn next_from_current_with_str(&mut self, keys: &Vec) { - fn _collect<'a>( - v: &'a Value, - tmp: &mut Vec<&'a Value>, - keys: &Vec, - visited: &mut HashSet<*const Value>, - ) { - match v { - Value::Object(map) => { - for key in keys { - if let Some(v) = map.get(key) { - let ptr = v as *const Value; - if !visited.contains(&ptr) { - visited.insert(ptr); + 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) } } } + _ => {} } - Value::Array(vec) => { - for v in vec { - _collect(v, tmp, keys, visited); - } - } - _ => {} - } - } - - if let Some(current) = self.current.take() { - let mut tmp = Vec::new(); - let mut visited = HashSet::new(); - for c in current { - _collect(c, &mut tmp, keys, &mut visited); } self.current = Some(tmp); } @@ -801,26 +782,22 @@ impl<'a, 'b> Selector<'a, 'b> { } fn next_all_from_current(&mut self) { - fn _collect<'a>(v: &'a Value, tmp: &mut Vec<&'a Value>) { - match v { - Value::Object(map) => { - for (_, v) in map { - tmp.push(v) - } - } - Value::Array(vec) => { - for v in vec { - _collect(v, tmp); - } - } - _ => {} - } - } - if let Some(current) = self.current.take() { let mut tmp = Vec::new(); for c in current { - _collect(c, &mut tmp); + match c { + Value::Object(map) => { + for (_, v) in map { + tmp.push(v) + } + } + Value::Array(vec) => { + for v in vec { + tmp.push(v); + } + } + _ => {} + } } self.current = Some(tmp); } @@ -934,17 +911,28 @@ 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(); + ParseToken::All => { + match self.tokens.last() { + Some(ParseToken::Array) => { + self.tokens.pop(); + } + _ => {} } - Some(ParseToken::In) => { - self.tokens.pop(); - self.next_all_from_current(); + + 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::Bool(b) => { self.terms.push(Some(ExprTerm::Bool(*b))); } diff --git a/tests/filter.rs b/tests/filter.rs index dcb0eb8..0928c02 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -619,3 +619,47 @@ fn quote() { json!(["value"]), ); } + +#[test] +fn all_filter() { + setup(); + + for path in vec![r#"$.*"#, r#"$[*]"#] { + select_and_then_compare( + path, + json!(["string", 42, { "key": "value" }, [0, 1]]), + json!(["string", 42, { "key": "value" }, [0, 1]]), + ); + } + + for path in vec![r#"$..*"#, r#"$..[*]"#] { + select_and_then_compare( + path, + json!(["string", 42, { "key": "value" }, [0, 1]]), + json!([ "string", 42, { "key" : "value" }, [ 0, 1 ], "value", 0, 1 ]), + ); + } + + for path in vec![r#"$.*.*"#, r#"$[*].*"#, r#"$.*[*]"#, r#"$[*][*]"#] { + select_and_then_compare( + path, + json!(["string", 42, { "key": "value" }, [0, 1]]), + json!(["value", 0, 1]), + ); + } + + for path in vec![r#"$..friends.*"#, r#"$[*].friends.*"#] { + select_and_then_compare( + path, + read_json("./benches/data_array.json"), + json!([ + { "id" : 0, "name" : "Millicent Norman" }, + { "id" : 1, "name" : "Vincent Cannon" }, + { "id" : 2, "name" : "Gray Berry" }, + { "id" : 0, "name" : "Tillman Mckay" }, + { "id" : 1, "name" : "Rivera Berg" }, + { "id" : 2, "name" : "Rosetta Erickson" } + ]), + ); + } +}