use super::*; use std::{ error, fmt, io, }; #[derive(Debug, Clone)] pub enum Mode { Ignore, Warn, Cancel, Terminate, } impl Mode { pub fn handle(&self, err: Result) -> Result,E> { match err { Err(err) => { match self { Self::Warn => println!("[WARN]: {}", err), Self::Cancel => return Err(err), Self::Terminate => Err(err).expect("Terminating on error"), _ => (), }; Ok(None) }, Ok(ok) => Ok(Some(ok)), } } } #[derive(Debug)] pub enum Error { Unknown, Arch(Option<&'static str>), IO(io::Error), Size{expected: usize, got: usize}, ArgParse(arg::Error), Internal(Box<(dyn error::Error + std::marker::Send)>), } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(match &self { Error::IO(e) => e, _ => return None, }) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "error: ")?; match self { Self::ArgParse(arg) => write!(f, "arg: {}", arg), Self::Arch(Some(expl)) => write!(f, "bad arch: {}", expl), Self::Arch(_) => write!(f, "bad arch (this is usually an indicator of an improperly compiled binary.)"), Self::Size{expected, got} => write!(f, "size mismatch: expected {}, got {}", expected, got), Self::IO(e) => write!(f, "io: {}", e), Error::Internal(e) => write!(f, "internal: {}", e), _ => write!(f, "unknown"), } } } impl From> for Error { fn from(bx: Box<(dyn error::Error + std::marker::Send)>) -> Self { Self::Internal(bx) } } impl From for Error { fn from(er: io::Error) -> Self { Self::IO(er) } } impl From for Error { fn from(er: arg::Error) -> Self { Self::ArgParse(er) } } // Helper functions: /// Return error for size if needed #[inline] pub fn check_size(expected: usize, got: usize) -> Result<(), Error> { if expected == got { Ok(()) } else { Err(Error::Size{expected, got}) } } /// Return an `Error::Internal` if needed. #[inline] pub fn internal(from: Result) -> Result { from.or_else(move |e| Err(Error::Internal(Box::new(e)))) }