Skip to content

Commit b72e40e

Browse files
committed
wildcarded dot child
1 parent 6596321 commit b72e40e

File tree

5 files changed

+39
-9
lines changed

5 files changed

+39
-9
lines changed

src/grammar.pest

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ rootSelector = { "$" }
55

66
matcher = { dotChild }
77

8-
dotChild = { ".*" }
8+
dotChild = _{ wildcardedDotChild }
9+
wildcardedDotChild = { ".*" }
910

1011
WHITESPACE = _{ " " }

src/matchers.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
use serde_json::Value;
8-
use std::iter::once;
8+
use std::iter;
99

1010
// Matcher maps a node to a list of nodes. If the input node is not matched by the matcher or
1111
// the matcher does not select any subnodes of the input node, then the result is empty.
@@ -17,6 +17,18 @@ pub struct RootSelector {}
1717

1818
impl Matcher for RootSelector {
1919
fn select<'a>(&self, node: &'a Value) -> Box<dyn Iterator<Item = &'a Value> + 'a> {
20-
Box::new(once(node))
20+
Box::new(iter::once(node))
21+
}
22+
}
23+
24+
pub struct WildcardedChild {}
25+
26+
impl Matcher for WildcardedChild {
27+
fn select<'a>(&self, node: &'a Value) -> Box<dyn Iterator<Item = &'a Value> + 'a> {
28+
if node.is_object() {
29+
Box::new(node.as_object().unwrap().into_iter().map(|(_k, v)| v))
30+
} else {
31+
Box::new(iter::empty())
32+
}
2133
}
2234
}

src/parser.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use crate::pest::Parser;
1212
#[grammar = "grammar.pest"]
1313
struct PathParser;
1414

15-
#[allow(clippy::single_match)]
1615
pub fn parse(selector: &str) -> Result<Box<dyn path::Path>, String> {
1716
let selector_rule = PathParser::parse(Rule::selector, selector)
1817
.map_err(|e| format!("{}", e))?
@@ -22,12 +21,19 @@ pub fn parse(selector: &str) -> Result<Box<dyn path::Path>, String> {
2221
let mut ms: Vec<&dyn matchers::Matcher> = Vec::new();
2322
for r in selector_rule.into_inner() {
2423
match r.as_rule() {
25-
Rule::rootSelector => {
26-
ms.push(&matchers::RootSelector {});
27-
}
24+
Rule::rootSelector => ms.push(&matchers::RootSelector {}),
25+
Rule::matcher => parse_matcher(r, &mut ms),
2826
_ => println!("r={:?}", r),
2927
}
3028
}
3129

3230
Ok(Box::new(path::new(ms)))
3331
}
32+
33+
fn parse_matcher(matcher_rule: pest::iterators::Pair<Rule>, ms: &mut Vec<&dyn matchers::Matcher>) {
34+
for r in matcher_rule.into_inner() {
35+
if let Rule::wildcardedDotChild = r.as_rule() {
36+
ms.push(&matchers::WildcardedChild {});
37+
}
38+
}
39+
}

tests/cts.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ mod tests {
6262
) {
6363
assert!(
6464
false,
65-
"incorrect result, expected: {:?}, got: {:?}",
65+
"incorrect result for {}, expected: {:?}, got: {:?}",
66+
t.name,
6667
as_json_value_array(&t.result).unwrap(),
6768
result
6869
)
@@ -140,8 +141,14 @@ mod tests {
140141

141142
serde_yaml::Value::Mapping(map) => {
142143
let object_members = map.iter().map(|(k, v)| {
144+
println!(
145+
">>>>>>>>> k={:?}, v={:?}, serde_json::to_string(k)={:?}",
146+
k,
147+
v,
148+
serde_json::to_string(k).expect("bananas")
149+
);
143150
(
144-
serde_yaml::to_string(k).expect("non-string mapping key"),
151+
serde_json::to_string(k).expect("non-string mapping key"),
145152
as_json_value(v.clone()).expect("invalid map value"),
146153
)
147154
});

tests/cts.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ tests:
33
selector: "$"
44
document: ["first", "second"]
55
result: [["first", "second"]]
6+
- name: wildcarded_child
7+
selector: "$.*"
8+
document: {"a" : "A", "b" : "B"}
9+
result: ["A", "B"]

0 commit comments

Comments
 (0)