migra/migra-cli/src/error.rs

102 lines
2.2 KiB
Rust
Raw Normal View History

2021-02-10 01:13:27 +03:00
use std::error::Error as StdError;
use std::fmt;
use std::mem;
use std::result;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub struct Error {
repr: Repr,
}
enum Repr {
Simple(ErrorKind),
Custom(Box<Custom>),
}
#[derive(Debug)]
struct Custom {
kind: ErrorKind,
error: Box<dyn StdError + Send + Sync>,
}
#[derive(Debug, Clone)]
pub enum ErrorKind {
MissedEnvVar(String),
}
impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ErrorKind::MissedEnvVar(ref name) => {
write!(fmt, r#"Missed "{}" environment variable"#, name)
}
}
}
}
impl PartialEq for ErrorKind {
fn eq(&self, other: &Self) -> bool {
mem::discriminant(self) == mem::discriminant(other)
}
}
impl From<ErrorKind> for Error {
#[inline]
fn from(kind: ErrorKind) -> Error {
Error {
repr: Repr::Simple(kind),
}
}
}
impl Error {
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where
E: Into<Box<dyn StdError + Send + Sync>>,
{
Self::_new(kind, error.into())
}
fn _new(kind: ErrorKind, error: Box<dyn StdError + Send + Sync>) -> Error {
Error {
repr: Repr::Custom(Box::new(Custom { kind, error })),
}
}
pub fn kind(&self) -> &ErrorKind {
match &self.repr {
Repr::Custom(ref c) => &c.kind,
Repr::Simple(kind) => &kind,
}
}
}
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.repr {
Repr::Custom(ref c) => c.error.fmt(fmt),
Repr::Simple(kind) => write!(fmt, "{}", kind),
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self.repr {
Repr::Simple(..) => None,
Repr::Custom(ref c) => c.error.source(),
}
}
}