-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add custom error with variants to parser
module
#50
Conversation
let mut expr: Option<FilterExpression> = None; | ||
while pairs.peek().is_some() { | ||
let next_expr = parse_logic_and(pairs.next().unwrap().into_inner()); | ||
let error_message = format!("Failed to parse logical expression: {:?}", pairs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error_message
has to be constructed before the call to pair.into_inner()
as into_inner()
takes ownership and moves the value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, sure
src/parser/parser.rs
Outdated
Rule::logic => parse_logic(pairs.next().unwrap().into_inner()), | ||
Rule::atom => { | ||
let left: Operand = parse_atom(pairs.next().unwrap())?; | ||
if pairs.peek().is_none() { | ||
Ok(FilterExpression::exists(left)) | ||
} else { | ||
let sign: FilterSign = FilterSign::new(pairs.next().unwrap().as_str()); | ||
let right: Operand = parse_atom(pairs.next().unwrap())?; | ||
Ok(FilterExpression::Atom(left, sign, right)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're still using .unwrap()
here but it should be safe as we're peeking ahead to make sure there's a value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, no problem. But can you replace unwrap with expect("unreachable in arithmetic")
or something like that
match rule.as_rule() { | ||
Rule::path => rule | ||
Rule::path => Ok(rule | ||
.into_inner() | ||
.next() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in this case, I would suggest
next()
.ok_or(...)
.and_then(parse_internal)
instead of
next()
.map()
.unwrap_or
.unwrap_or
src/parser/parser.rs
Outdated
.unwrap_or(JsonPath::Empty), | ||
Rule::current => JsonPath::Current(Box::new( | ||
.unwrap_or(Ok(JsonPath::Empty)) | ||
.unwrap_or(JsonPath::Empty)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, since we have Result as a result we don't have to return JsonPath::Empty and can return Err instead (apparently). I would suggest replacing unwrap_or everywhere to ok_or(Err(..))
Rule::current => JsonPath::Current(Box::new( | ||
.unwrap_or(Ok(JsonPath::Empty)) | ||
.unwrap_or(JsonPath::Empty)), | ||
Rule::current => Ok(JsonPath::Current(Box::new( | ||
rule.into_inner() | ||
.next() | ||
.map(parse_internal) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is the same:
- we convert the first option into result using
ok_or
- then we use
flatmap
(and_then
) instead ofmap
src/parser/parser.rs
Outdated
_ => JsonPath::Empty, | ||
.unwrap_or(JsonPath::Empty)), | ||
Rule::index => Ok(JsonPath::Index(parse_index(rule)?)), | ||
_ => Ok(JsonPath::Empty), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here we return Error instead of JsPath::Empty
I think
src/parser/parser.rs
Outdated
Rule::logic => parse_logic(pairs.next().unwrap().into_inner()), | ||
Rule::atom => { | ||
let left: Operand = parse_atom(pairs.next().unwrap())?; | ||
if pairs.peek().is_none() { | ||
Ok(FilterExpression::exists(left)) | ||
} else { | ||
let sign: FilterSign = FilterSign::new(pairs.next().unwrap().as_str()); | ||
let right: Operand = parse_atom(pairs.next().unwrap())?; | ||
Ok(FilterExpression::Atom(left, sign, right)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, no problem. But can you replace unwrap with expect("unreachable in arithmetic")
or something like that
The PR looks very good. Nice job! I added just a couple of comments, just to correct a little.
Yeah, it seems fine, but I would ensure the new error enum has a |
@besok thank you for the feedback! I'll implement these changes in the coming week. |
.unwrap_or(JsonPath::Empty), | ||
Rule::index => JsonPath::Index(parse_index(rule)), | ||
_ => JsonPath::Empty, | ||
.unwrap_or(Ok(JsonPath::Empty))?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@besok handling the Rule::current
variant with ok_or(Err())
causes the following tests to fail:
failures:
---- parser::parser::tests::path_test stdout ----
thread 'parser::parser::tests::path_test' panicked at 'parsing error expected valid Rule::current token but found nothing', src\parser\parser.rs:273:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- parser::parser::tests::index_filter_test stdout ----
thread 'parser::parser::tests::index_filter_test' panicked at 'parsing error expected valid Rule::current token but found nothing', src\parser\parser.rs:273:17
---- tests::no_value_chain_test stdout ----
thread 'tests::no_value_chain_test' panicked at 'the path is correct: "expected valid Rule::current token but found nothing"', src\lib.rs:1141:65
---- tests::no_value_filter_from_not_arr_filter_test stdout ----
thread 'tests::no_value_filter_from_not_arr_filter_test' panicked at 'the path is correct: "expected valid Rule::current token but found nothing"', src\lib.rs:1092:68
failures:
parser::parser::tests::index_filter_test
parser::parser::tests::path_test
tests::no_value_chain_test
tests::no_value_filter_from_not_arr_filter_test
I'm not sure if this a problem with the tests or a problem with the logic of their not being a value when calling Rule::current.into_inner()
, so I've left it with the previous behavior of unwrap_or(JsonPath::Empty)
which was there before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me neither :).
No problems. Let's leave it as is. I will take a look at the weekend, hopefully.
@besok I've refactored out most of the |
@CalemRoelofs |
Ah, the build error with Clippy, you need to fix a small warning
|
Fixed now :) |
thank you very much for the PR! |
Closes #38
This PR adds the
parser::errors
submodule using thiserror to handle different variants.In the
parser::parser
module, almost all calls tounwrap()
have been replaced and functions now returnResult<T, JsonPathParserError>
instead.Changing the signature of the public method
parse_json_path
fromResult<JsonPath, pest::error::Error<Rule>>
toResult<JsonPath, JsonPathParsingError>
is considered a breaking change so I'll leave it you you @besok on how you want to handle bumping versions etc.There's a bit of extra boilerplate added to the existing functions where
Option<T>
is nowResult<Option<T>, JsonPathParserError>
but I've tried to make it as concise as possible.