Replies: 1 comment
-
|
This is the way I'd write that code: use snafu::prelude::*;
#[derive(Snafu, Debug)]
enum ParseError {
MissingAmpersand,
Invalid { source: std::num::ParseIntError },
}
impl ParseError {
fn location(&self) -> usize {
match self {
ParseError::MissingAmpersand => 0,
ParseError::Invalid { .. } => 1,
}
}
}
/// Parse "&" followed by a number.
fn parse_it(s: &str) -> Result<usize, ParseError> {
let v = s.strip_prefix("&").context(MissingAmpersandSnafu)?;
v.parse().context(InvalidSnafu)
}
fn main() {
let _ = parse_it("&42").unwrap();
let e = parse_it("42").unwrap_err();
assert!(matches!(e, ParseError::MissingAmpersand));
assert_eq!(0, e.location());
let e = parse_it("&").unwrap_err();
assert!(matches!(e, ParseError::Invalid { .. }));
assert_eq!(1, e.location());
}A few possible changes I could see happening:
Here's the code with 2 and 3 applied: #[derive(Snafu, Debug)]
struct ParseError(ParseErrorInner);
impl ParseError {
fn location(&self) -> usize {
match self.0 {
ParseErrorInner::MissingAmpersand => 0,
ParseErrorInner::Invalid { .. } => 1,
}
}
}
#[derive(Snafu, Debug)]
enum ParseErrorInner {
MissingAmpersand,
#[snafu(transparent)]
Invalid { source: std::num::ParseIntError },
}
/// Parse "&" followed by a number.
fn parse_it(s: &str) -> Result<usize, ParseError> {
let v = s.strip_prefix("&").context(MissingAmpersandSnafu)?;
Ok(v.parse()?)
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
(This relates back to #504 How to create a custom snafu error type with an optional source field?, but explores the place such a field fills even without any "stringly" typing of errors.)
Snafu is generally focused on adding information and context to an error which allows better handling of those errors in a caller. However, another important operation on errors is hiding information that would be meaningless for a caller while still maintaining that information for logging and debugging purposes. This means that an error may or may not have a source depending on what caused it internally. For example, a parser which uses
from_strto parse numbers, but performs other parsing manually. We want to reportParseErrors to the caller simply, but also include any underlyingfrom_strerror for later debugging.I have a solution, but I want input since I'm sure others have encountered related issues.
This should work and the code can be improved with a few extension methods to make
parse_itmore readable. But the use of a fakeOptiontype and introducing another layer ofError::sourcejust to attach another error which may be needed for debugging seems messy to me.The questions are:
Thanks.
PS: This issue has hit me particularly hard because I want to gradually update an existing system to use Snafu, so I need to avoid major surgery on the error types to limit the scope of the refactor. But even after the full transition, we will still want to have errors that hide information, to make debugging easier when errors in one component pass through another before actually being handled.
Extension methods for ergonomics for the interested
Beta Was this translation helpful? Give feedback.
All reactions