Skip to content

Commit 0eaa748

Browse files
committed
add slice
1 parent 7259ac6 commit 0eaa748

File tree

4 files changed

+83
-4
lines changed

4 files changed

+83
-4
lines changed

src/parser/grammar/json_path_9535.pest

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ root = _{"$"}
1111
name_selector = {string}
1212
wildcard_selector = _{"*"}
1313
index_selector = {int}
14-
int = _{ "0" | ("-"? ~ DIGIT1 ~ DIGIT*) }
15-
slice_selector = { int? ~ S ~ ":" ~ S ~ int? ~ S ~ (":" ~ S ~ int?)? }
14+
int = { "0" | ("-"? ~ DIGIT1 ~ DIGIT*) }
15+
step = {":" ~ S ~ int?}
16+
start = {int}
17+
end = {int}
18+
slice_selector = { start? ~ S ~ ":" ~ S ~ end? ~ S ~ step? }
1619
filter_selector = {"?"~ S ~ logical_expr_or}
1720
logical_expr_or = {logical_expr_and ~ S ~ ("||" ~ S ~ logical_expr_and)*}
1821
logical_expr_and = {atom_expr ~ S ~ ("&&" ~ S ~ atom_expr)*}

src/parser/macros2.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,32 @@ macro_rules! singular_query {
3636
($($segment:tt)*) => {
3737
SingularQuery::Root(q_segments!($($segment)*))
3838
};
39+
}
40+
41+
#[macro_export]
42+
macro_rules! slice {
43+
() => {
44+
(None, None, None)
45+
};
46+
($start:expr) => {
47+
(Some($start), None, None)
48+
};
49+
($start:expr, $end:expr) => {
50+
(Some($start), Some($end), None)
51+
};
52+
($start:expr,, $step:expr) => {
53+
(Some($start), None, Some($step))
54+
};
55+
(,, $step:expr) => {
56+
(None, None, Some($step))
57+
};
58+
(, $end:expr) => {
59+
(None, Some($end), None)
60+
};
61+
(, $end:expr,$step:expr ) => {
62+
(None, Some($end), Some($step))
63+
};
64+
($start:expr, $end:expr, $step:expr) => {
65+
(Some($start), Some($end), Some($step))
66+
}
3967
}

src/parser/parser2.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ pub fn singular_query_segments(rule:Pair<Rule>) -> Parsed<Vec<SingularQuerySegme
4747
}
4848
Ok(segments)
4949
}
50+
fn validate_range(val: i64) -> Result<i64, JsonPathParserError> {
51+
if val > MAX_VAL || val < MIN_VAL {
52+
Err(JsonPathParserError::InvalidJsonPath(format!("Value {} is out of range", val)))
53+
} else {
54+
Ok(val)
55+
}
56+
}
57+
pub fn slice_selector(rule:Pair<Rule>) -> Parsed<(Option<i64>, Option<i64>, Option<i64>)> {
58+
let mut start = None;
59+
let mut end = None;
60+
let mut step = None;
61+
let get_int = |r:Pair<Rule>| r.as_str().parse::<i64>().map_err(|e|(e,"int"));
62+
63+
for r in rule.into_inner(){
64+
match r.as_rule(){
65+
Rule::start => start = Some(validate_range(get_int(r)?)?),
66+
Rule::end => end = Some(validate_range(get_int(r)?)?),
67+
Rule::step => step ={
68+
if let Some(int) = r.into_inner().next(){
69+
Some(validate_range(get_int(int)?)?)
70+
} else {
71+
None
72+
}
73+
},
74+
75+
_ => return Err(r.into())
76+
}
77+
}
78+
Ok((start,end,step))
79+
}
5080

5181
pub fn singular_query(rule:Pair<Rule>) -> Parsed<SingularQuery>{
5282
let query = child(rule)?;
@@ -91,6 +121,7 @@ fn child(rule:Pair<Rule>) -> Parsed<Pair<Rule>> {
91121
let rule_as_str = rule.as_str().to_string();
92122
rule.into_inner().next().ok_or(JsonPathParserError::EmptyInner(rule_as_str))
93123
}
124+
94125
fn children(rule:Pair<Rule>) -> Pairs<Rule> {
95126
rule.into_inner()
96127
}

src/parser/tests.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::fmt::Debug;
55
use pest::error::Error;
66
use pest::iterators::Pair;
77
use pest::Parser;
8-
use crate::{lit, q_segments, q_segment, singular_query};
9-
use crate::parser::parser2::{literal, singular_query, singular_query_segments, Rule};
8+
use crate::{lit, q_segments, q_segment, singular_query, slice};
9+
use crate::parser::parser2::{literal, singular_query, singular_query_segments, slice_selector, Rule};
1010
use std::panic;
1111

1212
struct TestPair<T> {
@@ -111,5 +111,22 @@ fn singular_query_test(){
111111
.assert("$.a.b.c",singular_query!(a b c))
112112
.assert("$[\"a\"].b[3]",singular_query!([a] b [3]))
113113

114+
;
115+
}
116+
117+
#[test]
118+
fn slice_selector_test(){
119+
TestPair::new(Rule::slice_selector, slice_selector)
120+
.assert(":",slice!())
121+
.assert("::",slice!())
122+
.assert("1:",slice!(1))
123+
.assert("1:1",slice!(1,1))
124+
.assert("1:1:1",slice!(1,1,1))
125+
.assert(":1:1",slice!(,1,1))
126+
.assert("::1",slice!(,,1))
127+
.assert("1::1",slice!(1,,1))
128+
.assert_fail("-0:")
129+
.assert_fail("9007199254740995")
130+
114131
;
115132
}

0 commit comments

Comments
 (0)