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" } + ]), + ); + } +}