Skip to content

Commit

Permalink
Merge pull request #52 from hanxuanliang/feat/12_filter_starts_with
Browse files Browse the repository at this point in the history
feat(expr): add filter expr [starts with]
  • Loading branch information
b41sh authored Dec 20, 2024
2 parents ace7386 + df1de53 commit e461dc8
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/jsonpath/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ fn expr_atom(input: &[u8], root_predicate: bool) -> IResult<&[u8], Expr<'_>> {
}

fn filter_func(input: &[u8]) -> IResult<&[u8], FilterFunc<'_>> {
alt((exists,))(input)
alt((exists, starts_with))(input)
}

fn exists(input: &[u8]) -> IResult<&[u8], FilterFunc<'_>> {
Expand Down Expand Up @@ -441,6 +441,13 @@ fn exists_paths(input: &[u8]) -> IResult<&[u8], Vec<Path<'_>>> {
)(input)
}

fn starts_with(input: &[u8]) -> IResult<&[u8], FilterFunc<'_>> {
preceded(
tag("starts with"),
preceded(multispace0, map(string, FilterFunc::StartsWith)),
)(input)
}

fn expr_and(input: &[u8], root_predicate: bool) -> IResult<&[u8], Expr<'_>> {
map(
separated_list1(delimited(multispace0, tag("&&"), multispace0), |i| {
Expand Down Expand Up @@ -478,3 +485,18 @@ fn expr_or(input: &[u8], root_predicate: bool) -> IResult<&[u8], Expr<'_>> {
},
)(input)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_starts_with() {
let input = r#"starts with "Nigel""#;
let res = starts_with(input.as_bytes()).unwrap();
assert_eq!(
res,
(&b""[..], FilterFunc::StartsWith(Cow::Borrowed("Nigel")))
);
}
}
5 changes: 5 additions & 0 deletions src/jsonpath/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub enum Expr<'a> {
#[derive(Debug, Clone, PartialEq)]
pub enum FilterFunc<'a> {
Exists(Vec<Path<'a>>),
StartsWith(Cow<'a, str>),
}

impl<'a> Display for JsonPath<'a> {
Expand Down Expand Up @@ -401,6 +402,10 @@ impl<'a> Display for Expr<'a> {
}
f.write_str(")")?;
}
FilterFunc::StartsWith(paths) => {
f.write_str("starts with ")?;
write!(f, "{paths}")?;
}
},
}
Ok(())
Expand Down
11 changes: 11 additions & 0 deletions src/jsonpath/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ impl<'a> Selector<'a> {
},
Expr::FilterFunc(filter_expr) => match filter_expr {
FilterFunc::Exists(paths) => self.eval_exists(root, pos, paths),
FilterFunc::StartsWith(prefix) => self.eval_starts_with(root, pos, prefix),
},
_ => todo!(),
}
Expand All @@ -506,6 +507,16 @@ impl<'a> Selector<'a> {
Ok(res)
}

fn eval_starts_with(
&'a self,
_root: &'a [u8],
_pos: &Position,
_prefix: &str,
) -> Result<bool, Error> {
// todo
Ok(false)
}

fn convert_expr_val(
&'a self,
root: &'a [u8],
Expand Down
1 change: 1 addition & 0 deletions tests/it/jsonpath_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ fn test_json_path() {
// exists expression
r#"$.store.book?(exists(@.price?(@ > 20)))"#,
r#"$.store?(exists(@.book?(exists(@.category?(@ == "fiction")))))"#,
r#"$.store.book?(starts with "Nigel")"#,
];

for case in cases {
Expand Down
25 changes: 25 additions & 0 deletions tests/it/testdata/json_path.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1219,3 +1219,28 @@ JsonPath {
}


---------- Input ----------
$.store.book?(starts with "Nigel")
---------- Output ---------
$.store.book?(starts with Nigel)
---------- AST ------------
JsonPath {
paths: [
Root,
DotField(
"store",
),
DotField(
"book",
),
FilterExpr(
FilterFunc(
StartsWith(
"Nigel",
),
),
),
],
}


0 comments on commit e461dc8

Please sign in to comment.