Try using thiserror to remove some boilerplate.
This commit is contained in:
175
src/errors.rs
175
src/errors.rs
@@ -1,162 +1,91 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::num::ParseIntError;
|
||||
use thiserror::Error;
|
||||
|
||||
macro_rules! convert_error {
|
||||
($type: ty, $super_type: ident, $pattern: ident) => {
|
||||
impl From<$type> for $super_type {
|
||||
fn from(x: $type) -> $super_type {
|
||||
$super_type::$pattern(x)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum TopLevelError {
|
||||
IOError(io::Error),
|
||||
#[error("IO error encountered ({source})")]
|
||||
IOError {
|
||||
#[from]
|
||||
source: io::Error,
|
||||
},
|
||||
#[error("No input found")]
|
||||
NoInputFound,
|
||||
#[error("No solution found")]
|
||||
NoSolutionFound,
|
||||
#[error("Unknown error occurred")]
|
||||
UnknownError,
|
||||
PassportParseError(PassportParseError),
|
||||
SeatParseError(SeatParseError),
|
||||
BaggageParseError(BaggageRuleParseError),
|
||||
#[error("Failed to parse passport: {source}")]
|
||||
PassportParseErrorPassport {
|
||||
#[from]
|
||||
source: PassportParseError,
|
||||
},
|
||||
#[error("Failed to parse seat: {source}")]
|
||||
SeatParseError {
|
||||
#[from]
|
||||
source: SeatParseError,
|
||||
},
|
||||
#[error("Failed to parse baggage rule: {source}")]
|
||||
BaggageParseError {
|
||||
#[from]
|
||||
source: BaggageRuleParseError,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for TopLevelError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
TopLevelError::IOError(e) => write!(f, "IO error: {}", e),
|
||||
TopLevelError::NoInputFound => write!(f, "No valid inputs found"),
|
||||
TopLevelError::NoSolutionFound => write!(f, "No solution found."),
|
||||
TopLevelError::PassportParseError(p) => write!(f, "Error parsing passport: {}", p),
|
||||
TopLevelError::SeatParseError(s) => write!(f, "Error parsing seat: {}", s),
|
||||
TopLevelError::BaggageParseError(e) => write!(f, "Error parsing baggage rule: {}", e),
|
||||
TopLevelError::UnknownError => {
|
||||
write!(f, "Unknown error occurred; this shouldn't be possible.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_error!(io::Error, TopLevelError, IOError);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum PasswordParseError {
|
||||
StringToIntError(ParseIntError),
|
||||
NomError(nom::Err<()>),
|
||||
#[error("Failed to convert string to integer: {source}")]
|
||||
StringToIntError {
|
||||
#[from]
|
||||
source: ParseIntError,
|
||||
},
|
||||
#[error("Error nomnomnoming: {source}")]
|
||||
NomError {
|
||||
#[from]
|
||||
source: nom::Err<()>,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for PasswordParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PasswordParseError::NomError(e) => write!(f, "Parse error: {}", e),
|
||||
PasswordParseError::StringToIntError(e) => {
|
||||
write!(f, "Error converting string to integer: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_error!(ParseIntError, PasswordParseError, StringToIntError);
|
||||
convert_error!(nom::Err<()>, PasswordParseError, NomError);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MapParseError {
|
||||
#[error("Unexpected character: {0}")]
|
||||
UnexpectedCharacter(char),
|
||||
#[error("Uneven width at line {0}")]
|
||||
UnevenLines(usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for MapParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
MapParseError::UnevenLines(l) => write!(f, "Map has uneven width at line {}", l),
|
||||
MapParseError::UnexpectedCharacter(c) => {
|
||||
write!(f, "Unexpected character parsing map: {}", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum PassportParseError {
|
||||
#[error("Invalid chunk in passport line: {0}")]
|
||||
InvalidChunk(String),
|
||||
#[error("Invalid field in passport: {0}")]
|
||||
InvalidField(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for PassportParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PassportParseError::InvalidChunk(s) => {
|
||||
write!(f, "Invalid chunk in passport line: {}", s)
|
||||
}
|
||||
PassportParseError::InvalidField(s) => write!(f, "Invalid field in passport: {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_error!(PassportParseError, TopLevelError, PassportParseError);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
pub enum SeatParseError {
|
||||
#[error("Invalid seat identifier: {0}")]
|
||||
InvalidSeatIdentifier(String),
|
||||
#[error("Bad row section size {0}")]
|
||||
BadSeatRowSectionSize(usize),
|
||||
#[error("Bad column section size {0}")]
|
||||
BadSeatColumnSectionSize(usize),
|
||||
#[error("Unexpected row character '{0}'")]
|
||||
UnexpectedRowCharacter(char),
|
||||
#[error("Unexpected column character '{0}'")]
|
||||
UnexpectedColumnCharacter(char),
|
||||
#[error("Wasn't able to resolve column for '{0}'")]
|
||||
DidNotResolveColumn(String),
|
||||
#[error("Wasn't able to resolve row for '{0}'")]
|
||||
DidNotResolveRow(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for SeatParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
SeatParseError::InvalidSeatIdentifier(s) => {
|
||||
write!(f, "Invalid seat identifier: {:?}", s)
|
||||
}
|
||||
SeatParseError::BadSeatRowSectionSize(x) => write!(
|
||||
f,
|
||||
"Bad identifiers for rows; expected 7 characters, got {}",
|
||||
x
|
||||
),
|
||||
SeatParseError::BadSeatColumnSectionSize(x) => write!(
|
||||
f,
|
||||
"Bad identifiers for columns; expected 3 characters, got {}",
|
||||
x
|
||||
),
|
||||
SeatParseError::UnexpectedRowCharacter(c) => {
|
||||
write!(f, "Unexpected character when parsing rows: {:?}", c)
|
||||
}
|
||||
SeatParseError::UnexpectedColumnCharacter(c) => {
|
||||
write!(f, "Unexpected character when parsing columns: {:?}", c)
|
||||
}
|
||||
SeatParseError::DidNotResolveRow(s) => {
|
||||
write!(f, "Could not resolve row with {:?}", s)
|
||||
}
|
||||
SeatParseError::DidNotResolveColumn(s) => {
|
||||
write!(f, "Could not resolve row with {:?}", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_error!(SeatParseError, TopLevelError, SeatParseError);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BaggageRuleParseError {
|
||||
#[error("Error parsing rule: {0}")]
|
||||
NomError(String),
|
||||
NumericConversionError(ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for BaggageRuleParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BaggageRuleParseError::NomError(e) => write!(f, "General parsing error: {}", e),
|
||||
BaggageRuleParseError::NumericConversionError(e) => {
|
||||
write!(f, "Error converting number to value: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_error!(BaggageRuleParseError, TopLevelError, BaggageParseError);
|
||||
convert_error!(ParseIntError, BaggageRuleParseError, NumericConversionError);
|
||||
|
||||
impl<'a> From<nom::Err<nom::error::Error<&'a str>>> for BaggageRuleParseError {
|
||||
fn from(x: nom::Err<nom::error::Error<&'a str>>) -> BaggageRuleParseError {
|
||||
match x {
|
||||
|
||||
Reference in New Issue
Block a user