Try using thiserror to remove some boilerplate.
This commit is contained in:
@@ -6,3 +6,4 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nom = "6.0.1"
|
nom = "6.0.1"
|
||||||
|
thiserror = "1.0.22"
|
||||||
175
src/errors.rs
175
src/errors.rs
@@ -1,162 +1,91 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
macro_rules! convert_error {
|
#[derive(Error, Debug)]
|
||||||
($type: ty, $super_type: ident, $pattern: ident) => {
|
|
||||||
impl From<$type> for $super_type {
|
|
||||||
fn from(x: $type) -> $super_type {
|
|
||||||
$super_type::$pattern(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum TopLevelError {
|
pub enum TopLevelError {
|
||||||
IOError(io::Error),
|
#[error("IO error encountered ({source})")]
|
||||||
|
IOError {
|
||||||
|
#[from]
|
||||||
|
source: io::Error,
|
||||||
|
},
|
||||||
|
#[error("No input found")]
|
||||||
NoInputFound,
|
NoInputFound,
|
||||||
|
#[error("No solution found")]
|
||||||
NoSolutionFound,
|
NoSolutionFound,
|
||||||
|
#[error("Unknown error occurred")]
|
||||||
UnknownError,
|
UnknownError,
|
||||||
PassportParseError(PassportParseError),
|
#[error("Failed to parse passport: {source}")]
|
||||||
SeatParseError(SeatParseError),
|
PassportParseErrorPassport {
|
||||||
BaggageParseError(BaggageRuleParseError),
|
#[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 {
|
#[derive(Error, Debug)]
|
||||||
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);
|
|
||||||
|
|
||||||
pub enum PasswordParseError {
|
pub enum PasswordParseError {
|
||||||
StringToIntError(ParseIntError),
|
#[error("Failed to convert string to integer: {source}")]
|
||||||
NomError(nom::Err<()>),
|
StringToIntError {
|
||||||
|
#[from]
|
||||||
|
source: ParseIntError,
|
||||||
|
},
|
||||||
|
#[error("Error nomnomnoming: {source}")]
|
||||||
|
NomError {
|
||||||
|
#[from]
|
||||||
|
source: nom::Err<()>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PasswordParseError {
|
#[derive(Error, Debug)]
|
||||||
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);
|
|
||||||
|
|
||||||
pub enum MapParseError {
|
pub enum MapParseError {
|
||||||
|
#[error("Unexpected character: {0}")]
|
||||||
UnexpectedCharacter(char),
|
UnexpectedCharacter(char),
|
||||||
|
#[error("Uneven width at line {0}")]
|
||||||
UnevenLines(usize),
|
UnevenLines(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for MapParseError {
|
#[derive(Error, Debug)]
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PassportParseError {
|
pub enum PassportParseError {
|
||||||
|
#[error("Invalid chunk in passport line: {0}")]
|
||||||
InvalidChunk(String),
|
InvalidChunk(String),
|
||||||
|
#[error("Invalid field in passport: {0}")]
|
||||||
InvalidField(String),
|
InvalidField(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PassportParseError {
|
#[derive(Error, Debug, PartialEq)]
|
||||||
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)]
|
|
||||||
pub enum SeatParseError {
|
pub enum SeatParseError {
|
||||||
|
#[error("Invalid seat identifier: {0}")]
|
||||||
InvalidSeatIdentifier(String),
|
InvalidSeatIdentifier(String),
|
||||||
|
#[error("Bad row section size {0}")]
|
||||||
BadSeatRowSectionSize(usize),
|
BadSeatRowSectionSize(usize),
|
||||||
|
#[error("Bad column section size {0}")]
|
||||||
BadSeatColumnSectionSize(usize),
|
BadSeatColumnSectionSize(usize),
|
||||||
|
#[error("Unexpected row character '{0}'")]
|
||||||
UnexpectedRowCharacter(char),
|
UnexpectedRowCharacter(char),
|
||||||
|
#[error("Unexpected column character '{0}'")]
|
||||||
UnexpectedColumnCharacter(char),
|
UnexpectedColumnCharacter(char),
|
||||||
|
#[error("Wasn't able to resolve column for '{0}'")]
|
||||||
DidNotResolveColumn(String),
|
DidNotResolveColumn(String),
|
||||||
|
#[error("Wasn't able to resolve row for '{0}'")]
|
||||||
DidNotResolveRow(String),
|
DidNotResolveRow(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SeatParseError {
|
#[derive(Error, Debug)]
|
||||||
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);
|
|
||||||
|
|
||||||
pub enum BaggageRuleParseError {
|
pub enum BaggageRuleParseError {
|
||||||
|
#[error("Error parsing rule: {0}")]
|
||||||
NomError(String),
|
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 {
|
impl<'a> From<nom::Err<nom::error::Error<&'a str>>> for BaggageRuleParseError {
|
||||||
fn from(x: nom::Err<nom::error::Error<&'a str>>) -> BaggageRuleParseError {
|
fn from(x: nom::Err<nom::error::Error<&'a str>>) -> BaggageRuleParseError {
|
||||||
match x {
|
match x {
|
||||||
|
|||||||
Reference in New Issue
Block a user