use std::{fmt, io};
#[derive(Fail, Debug)]
pub struct Error {
kind: ErrorKind,
details: Option<String>,
}
impl Error {
pub(crate) fn with_details<D>(kind: ErrorKind, details: D) -> Self
where
D: Into<String>,
{
Self {
kind,
details: Some(details.into()),
}
}
pub(crate) fn parse_err<T: Into<String>>(msg: T) -> Error {
Error::with_details(ErrorKind::ParseError, msg.into())
}
pub fn kind(&self) -> ErrorKind {
self.kind.clone()
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Error {
kind,
details: None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Self {
kind: ErrorKind::ParseError,
details: Some(err.to_string()),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match &self.details {
Some(details) => write!(fmt, "{}: {}", self.kind, details),
None => write!(fmt, "{}", self.kind),
}
}
}
#[derive(Fail, Debug, Clone)]
pub enum ErrorKind {
#[fail(display = "data could not be parsed")]
ParseError,
#[fail(display = "the signature is invalid")]
InvalidSignature,
#[fail(display = "error")]
Other,
#[doc(hidden)]
#[fail(display = "__NonExhaustive")]
__NonExhaustive,
}