1use std::borrow::Cow;
7
8use nom::IResult;
9use nom::Parser;
10use nom::branch::alt;
11use nom::bytes::complete::tag;
12use nom::bytes::complete::tag_no_case;
13use nom::character::complete::char;
14use nom::character::complete::i32;
15use nom::character::complete::i64;
16use nom::character::complete::multispace0;
17use nom::character::complete::u8;
18use nom::character::complete::u64;
19use nom::combinator::cond;
20use nom::combinator::map;
21use nom::combinator::map_res;
22use nom::combinator::opt;
23use nom::combinator::value;
24use nom::error::Error as NomError;
25use nom::error::ErrorKind;
26use nom::multi::many0;
27use nom::multi::separated_list1;
28use nom::number::complete::double;
29use nom::sequence::delimited;
30use nom::sequence::pair;
31use nom::sequence::preceded;
32use nom::sequence::separated_pair;
33use nom::sequence::terminated;
34
35use crate::constants::UNICODE_LEN;
36use crate::error::Error;
37use crate::jsonpath::path::*;
38use crate::number::Number;
39use crate::util::parse_string;
40
41pub fn parse_json_path(input: &[u8]) -> Result<JsonPath<'_>, Error> {
43 match json_path(input) {
44 Ok((rest, json_path)) => {
45 if !rest.is_empty() {
46 return Err(Error::InvalidJsonPath);
47 }
48 Ok(json_path)
49 }
50 Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(Error::InvalidJsonPath),
51 Err(nom::Err::Incomplete(_)) => unreachable!(),
52 }
53}
54
55fn json_path(input: &[u8]) -> IResult<&[u8], JsonPath<'_>> {
56 map(
57 delimited(multispace0, expr_or_paths, multispace0),
58 |paths| JsonPath { paths },
59 )
60 .parse(input)
61}
62
63fn check_escaped(input: &[u8], i: &mut usize) -> bool {
64 if *i + 1 >= input.len() {
65 return false;
66 }
67 if input[*i + 1] == b'u' {
68 if *i + 5 >= input.len() {
69 return false;
70 }
71 if input[*i + 2] == b'{' {
72 if *i + 7 >= input.len() {
73 return false;
74 }
75 *i += UNICODE_LEN + 4;
76 } else {
77 *i += UNICODE_LEN + 2;
78 }
79 } else {
80 *i += 2;
81 }
82 true
83}
84
85pub fn raw_string(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
86 let mut i = 0;
87 let mut escapes = 0;
88 while i < input.len() {
89 let c = input[i];
90 match c {
91 b'\\' => {
92 escapes += 1;
93 if !check_escaped(input, &mut i) {
94 return Err(nom::Err::Error(NomError::new(input, ErrorKind::Char)));
95 }
96 }
97 b' ' | b',' | b'.' | b':' | b'{' | b'}' | b'[' | b']' | b'(' | b')' | b'?' | b'@'
98 | b'$' | b'|' | b'<' | b'>' | b'!' | b'=' | b'+' | b'-' | b'*' | b'/' | b'%' | b'"'
99 | b'\'' => {
100 break;
101 }
102 _ => {
103 i += 1;
104 }
105 }
106 }
107 if i > 0 {
108 if escapes == 0 {
109 if let Ok(s) = std::str::from_utf8(&input[..i]) {
110 return Ok((&input[i..], Cow::Borrowed(s)));
111 }
112 } else {
113 let data = &input[..i];
114 let len = i - escapes;
115 let mut idx = 0;
116 let s = parse_string(data, len, &mut idx)
117 .map_err(|_| nom::Err::Error(NomError::new(input, ErrorKind::Char)))?;
118 return Ok((&input[i..], Cow::Owned(s)));
119 }
120 }
121 Err(nom::Err::Error(NomError::new(input, ErrorKind::Char)))
122}
123
124pub fn string(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
125 if input.is_empty() || input[0] != b'"' {
126 return Err(nom::Err::Error(NomError::new(input, ErrorKind::Char)));
127 }
128 let mut i = 1;
129 let mut escapes = 0;
130 while i < input.len() {
131 let c = input[i];
132 match c {
133 b'\\' => {
134 escapes += 1;
135 if !check_escaped(input, &mut i) {
136 return Err(nom::Err::Error(NomError::new(input, ErrorKind::Char)));
137 }
138 }
139 b'"' => {
140 break;
141 }
142 _ => {
143 i += 1;
144 }
145 }
146 }
147 if i > 1 {
148 if escapes == 0 {
149 if let Ok(s) = std::str::from_utf8(&input[1..i]) {
150 return Ok((&input[i + 1..], Cow::Borrowed(s)));
151 }
152 } else {
153 let data = &input[1..i];
154 let len = i - 1 - escapes;
155 let mut idx = 1;
156 let s = parse_string(data, len, &mut idx)
157 .map_err(|_| nom::Err::Error(NomError::new(input, ErrorKind::Char)))?;
158 return Ok((&input[i + 1..], Cow::Owned(s)));
159 }
160 }
161 Err(nom::Err::Error(NomError::new(input, ErrorKind::Char)))
162}
163
164fn bracket_wildcard(input: &[u8]) -> IResult<&[u8], ()> {
165 value(
166 (),
167 delimited(
168 char('['),
169 delimited(multispace0, char('*'), multispace0),
170 char(']'),
171 ),
172 )
173 .parse(input)
174}
175
176fn recursive_dot_wildcard(input: &[u8]) -> IResult<&[u8], Option<RecursiveLevel>> {
177 preceded(tag(".**"), opt(recursive_level)).parse(input)
178}
179
180fn recursive_level(input: &[u8]) -> IResult<&[u8], RecursiveLevel> {
181 alt((
182 delimited(
183 char('{'),
184 delimited(multispace0, recursive_level_range, multispace0),
185 char('}'),
186 ),
187 map(
188 delimited(
189 char('{'),
190 delimited(multispace0, u8, multispace0),
191 char('}'),
192 ),
193 |s| RecursiveLevel {
194 start: s,
195 end: None,
196 },
197 ),
198 ))
199 .parse(input)
200}
201
202fn recursive_level_range(input: &[u8]) -> IResult<&[u8], RecursiveLevel> {
203 alt((
204 map(
205 separated_pair(
206 u8,
207 delimited(multispace0, tag_no_case("to"), multispace0),
208 u8,
209 ),
210 |(s, e)| RecursiveLevel {
211 start: s,
212 end: Some(RecursiveLevelEnd::Index(e)),
213 },
214 ),
215 map(
216 separated_pair(
217 u8,
218 delimited(multispace0, tag_no_case("to"), multispace0),
219 tag_no_case("last"),
220 ),
221 |(s, _)| RecursiveLevel {
222 start: s,
223 end: Some(RecursiveLevelEnd::Last),
224 },
225 ),
226 ))
227 .parse(input)
228}
229
230fn colon_field(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
231 alt((preceded(char(':'), string), preceded(char(':'), raw_string))).parse(input)
232}
233
234fn dot_field(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
235 alt((preceded(char('.'), string), preceded(char('.'), raw_string))).parse(input)
236}
237
238fn object_field(input: &[u8]) -> IResult<&[u8], Cow<'_, str>> {
239 delimited(
240 terminated(char('['), multispace0),
241 string,
242 preceded(multispace0, char(']')),
243 )
244 .parse(input)
245}
246
247fn index(input: &[u8]) -> IResult<&[u8], Index> {
248 alt((
249 map(i32, Index::Index),
250 map(
251 preceded(
252 separated_pair(tag_no_case("last"), multispace0, char('-')),
253 preceded(multispace0, i32),
254 ),
255 |v| Index::LastIndex(v.saturating_neg()),
256 ),
257 map(
258 preceded(
259 separated_pair(tag_no_case("last"), multispace0, char('+')),
260 preceded(multispace0, i32),
261 ),
262 Index::LastIndex,
263 ),
264 map(tag_no_case("last"), |_| Index::LastIndex(0)),
265 ))
266 .parse(input)
267}
268
269fn array_index(input: &[u8]) -> IResult<&[u8], ArrayIndex> {
270 alt((
271 map(
272 separated_pair(
273 index,
274 delimited(multispace0, tag_no_case("to"), multispace0),
275 index,
276 ),
277 |(s, e)| ArrayIndex::Slice((s, e)),
278 ),
279 map(index, ArrayIndex::Index),
280 ))
281 .parse(input)
282}
283
284fn array_indices(input: &[u8]) -> IResult<&[u8], Vec<ArrayIndex>> {
285 delimited(
286 char('['),
287 separated_list1(char(','), delimited(multispace0, array_index, multispace0)),
288 char(']'),
289 )
290 .parse(input)
291}
292
293fn inner_path(input: &[u8]) -> IResult<&[u8], Path<'_>> {
294 alt((
295 map(recursive_dot_wildcard, Path::RecursiveDotWildcard),
296 value(Path::DotWildcard, tag(".*")),
297 value(Path::BracketWildcard, bracket_wildcard),
298 map(colon_field, Path::ColonField),
299 map(dot_field, Path::DotField),
300 map(array_indices, Path::ArrayIndices),
301 map(object_field, Path::ObjectField),
302 ))
303 .parse(input)
304}
305
306fn pre_path(input: &[u8]) -> IResult<&[u8], Path<'_>> {
308 alt((
309 value(Path::Root, char('$')),
310 map(delimited(multispace0, raw_string, multispace0), |v| {
311 Path::DotField(v)
312 }),
313 ))
314 .parse(input)
315}
316
317fn path(input: &[u8]) -> IResult<&[u8], Path<'_>> {
318 alt((
319 map(delimited(multispace0, inner_path, multispace0), |v| v),
320 map(delimited(multispace0, filter_expr, multispace0), |v| {
321 Path::FilterExpr(Box::new(v))
322 }),
323 ))
324 .parse(input)
325}
326
327fn expr_or_paths(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
328 alt((root_expr, paths)).parse(input)
329}
330
331fn root_expr(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
332 map(
333 delimited(multispace0, |i| expr_or(i, true), multispace0),
334 |v| vec![Path::Expr(Box::new(v))],
335 )
336 .parse(input)
337}
338
339fn paths(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
340 map(
341 pair(opt(pre_path), many0(path)),
342 |(opt_pre_path, mut paths)| {
343 if let Some(pre_path) = opt_pre_path {
344 paths.insert(0, pre_path);
345 }
346 paths
347 },
348 )
349 .parse(input)
350}
351
352fn expr_paths(input: &[u8], is_root_expr: bool) -> IResult<&[u8], Vec<Path<'_>>> {
353 let parse_current = map_res(
354 cond(!is_root_expr, value(Path::Current, char('@'))),
355 |res| match res {
356 Some(v) => Ok(v),
357 None => Err(NomError::new(input, ErrorKind::Char)),
358 },
359 );
360 map(
361 pair(
362 alt((value(Path::Root, char('$')), parse_current)),
363 many0(delimited(multispace0, inner_path, multispace0)),
364 ),
365 |(pre_path, mut paths)| {
366 paths.insert(0, pre_path);
367 paths
368 },
369 )
370 .parse(input)
371}
372
373fn filter_expr(input: &[u8]) -> IResult<&[u8], Expr<'_>> {
374 map(
375 delimited(
376 delimited(char('?'), multispace0, char('(')),
377 delimited(multispace0, |i| expr_or(i, false), multispace0),
378 char(')'),
379 ),
380 |v| v,
381 )
382 .parse(input)
383}
384
385fn op(input: &[u8]) -> IResult<&[u8], BinaryOperator> {
386 alt((
387 value(BinaryOperator::Eq, tag("==")),
388 value(BinaryOperator::NotEq, tag("!=")),
389 value(BinaryOperator::NotEq, tag("<>")),
390 value(BinaryOperator::Lte, tag("<=")),
391 value(BinaryOperator::Lt, char('<')),
392 value(BinaryOperator::Gte, tag(">=")),
393 value(BinaryOperator::Gt, char('>')),
394 value(BinaryOperator::StartsWith, tag("starts with")),
395 value(BinaryOperator::Add, char('+')),
396 value(BinaryOperator::Subtract, char('-')),
397 value(BinaryOperator::Multiply, char('*')),
398 value(BinaryOperator::Divide, char('/')),
399 value(BinaryOperator::Modulo, char('%')),
400 ))
401 .parse(input)
402}
403
404fn unary_arith_op(input: &[u8]) -> IResult<&[u8], UnaryOperator> {
405 alt((
406 value(UnaryOperator::Add, char('+')),
407 value(UnaryOperator::Subtract, char('-')),
408 ))
409 .parse(input)
410}
411
412fn path_value(input: &[u8]) -> IResult<&[u8], PathValue<'_>> {
413 alt((
414 value(PathValue::Null, tag("null")),
415 value(PathValue::Boolean(true), tag("true")),
416 value(PathValue::Boolean(false), tag("false")),
417 map(u64, |v| PathValue::Number(Number::UInt64(v))),
418 map(i64, |v| PathValue::Number(Number::Int64(v))),
419 map(double, |v| PathValue::Number(Number::Float64(v))),
420 map(string, PathValue::String),
421 ))
422 .parse(input)
423}
424
425fn inner_expr(input: &[u8], is_root_expr: bool) -> IResult<&[u8], Expr<'_>> {
426 alt((
427 map(|i| expr_paths(i, is_root_expr), Expr::Paths),
428 map(path_value, |v| Expr::Value(Box::new(v))),
429 ))
430 .parse(input)
431}
432
433fn expr_atom(input: &[u8], is_root_expr: bool) -> IResult<&[u8], Expr<'_>> {
434 alt((
435 map(
436 pair(
437 unary_arith_op,
438 delimited(multispace0, |i| inner_expr(i, is_root_expr), multispace0),
439 ),
440 |(op, operand)| Expr::UnaryOp {
441 op,
442 operand: Box::new(operand),
443 },
444 ),
445 map(
446 pair(
447 pair(
448 delimited(multispace0, |i| inner_expr(i, is_root_expr), multispace0),
449 op,
450 ),
451 delimited(multispace0, |i| inner_expr(i, is_root_expr), multispace0),
452 ),
453 |((left, op), right)| Expr::BinaryOp {
454 op,
455 left: Box::new(left),
456 right: Box::new(right),
457 },
458 ),
459 map(
460 delimited(
461 terminated(char('('), multispace0),
462 |i| expr_or(i, is_root_expr),
463 preceded(multispace0, char(')')),
464 ),
465 |expr| expr,
466 ),
467 map(exists_func, Expr::ExistsFunc),
468 ))
469 .parse(input)
470}
471
472fn exists_func(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
473 preceded(
474 tag("exists"),
475 preceded(
476 multispace0,
477 delimited(
478 terminated(char('('), multispace0),
479 exists_paths,
480 preceded(multispace0, char(')')),
481 ),
482 ),
483 )
484 .parse(input)
485}
486
487fn exists_paths(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
488 map(
489 pair(
490 alt((
491 value(Path::Root, char('$')),
492 value(Path::Current, char('@')),
493 )),
494 many0(path),
495 ),
496 |(pre, mut paths)| {
497 paths.insert(0, pre);
498 paths
499 },
500 )
501 .parse(input)
502}
503
504fn expr_and(input: &[u8], is_root_expr: bool) -> IResult<&[u8], Expr<'_>> {
505 map(
506 separated_list1(delimited(multispace0, tag("&&"), multispace0), |i| {
507 expr_atom(i, is_root_expr)
508 }),
509 |exprs| {
510 let mut expr = exprs[0].clone();
511 for right in exprs.iter().skip(1) {
512 expr = Expr::BinaryOp {
513 op: BinaryOperator::And,
514 left: Box::new(expr),
515 right: Box::new(right.clone()),
516 };
517 }
518 expr
519 },
520 )
521 .parse(input)
522}
523
524fn expr_or(input: &[u8], is_root_expr: bool) -> IResult<&[u8], Expr<'_>> {
525 map(
526 separated_list1(delimited(multispace0, tag("||"), multispace0), |i| {
527 expr_and(i, is_root_expr)
528 }),
529 |exprs| {
530 let mut expr = exprs[0].clone();
531 for right in exprs.iter().skip(1) {
532 expr = Expr::BinaryOp {
533 op: BinaryOperator::Or,
534 left: Box::new(expr),
535 right: Box::new(right.clone()),
536 };
537 }
538 expr
539 },
540 )
541 .parse(input)
542}