use failure::{Backtrace, Context, Fail}; use std::fmt; use std::fmt::Display; use std::io::Error as IOError; use std::path::PathBuf; // ----------------------------------------------------------------------------- #[derive(Fail, Debug)] pub enum ErrorKind { #[fail(display = "IO error")] Io, #[fail(display = "File error: {:?}", _0)] File(PathBuf), #[fail(display = "Include error")] Include, #[fail(display = "Parse error: {:?}", _0)] Parse(Option<(PathBuf, usize)>), #[fail(display = "Preprocess error")] Preprocess, #[fail(display = "Define argument not found: {}", _0)] DefineArgNotFound(String), #[fail(display = "Define text not found: {}", _0)] DefineTextNotFound(String), #[fail(display = "Define not found: {}", _0)] DefineNotFound(String), } // ----------------------------------------------------------------------------- #[derive(Debug)] pub struct Error { inner: Context, } impl Fail for Error { fn cause(&self) -> Option<&dyn Fail> { self.inner.cause() } fn backtrace(&self) -> Option<&Backtrace> { self.inner.backtrace() } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } impl Error { pub fn new(inner: Context) -> Error { Error { inner } } pub fn kind(&self) -> &ErrorKind { self.inner.get_context() } } impl From for Error { fn from(kind: ErrorKind) -> Error { Error { inner: Context::new(kind), } } } impl From> for Error { fn from(inner: Context) -> Error { Error { inner } } } // ----------------------------------------------------------------------------- impl From for Error { fn from(error: IOError) -> Error { Error { inner: error.context(ErrorKind::Io), } } }