#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://wisagan.github.io/simple-error/simple_error/")]
#![deny(missing_docs)]
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SimpleError {
err: String,
}
impl SimpleError {
#[inline]
pub fn new<T: Into<String>>(t: T) -> SimpleError {
SimpleError{ err: t.into() }
}
#[inline]
pub fn from<T: std::error::Error>(t: T) -> SimpleError {
SimpleError{ err: format!("{}", t) }
}
#[inline]
pub fn with<T: std::error::Error>(s: &str, t: T) -> SimpleError {
SimpleError{ err: format!("{}, {}", s, t) }
}
#[inline]
pub fn as_str(&self) -> &str {
&self.err
}
}
impl<'a> From<&'a str> for SimpleError {
#[inline]
fn from(s: &str) -> SimpleError {
SimpleError{ err: s.into() }
}
}
impl fmt::Display for SimpleError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.err.fmt(f)
}
}
impl std::error::Error for SimpleError {
#[inline]
fn description(&self) -> &str {
&self.err
}
}
pub type SimpleResult<T> = Result<T, SimpleError>;
#[macro_export]
macro_rules! try_with {
($expr: expr, $str: expr) => (match $expr {
Ok(val) => val,
Err(err) => {
return Err(::std::convert::From::from($crate::SimpleError::with($str.as_ref(), err)));
},
});
($expr: expr, $fmt:expr, $($arg:tt)+) => (match $expr {
Ok(val) => val,
Err(err) => {
return Err(::std::convert::From::from($crate::SimpleError::with(&format!($fmt, $($arg)+), err)));
},
});
}
#[macro_export]
macro_rules! require_with {
($expr: expr, $str: expr) => (match $expr {
Some(val) => val,
None => {
return Err(::std::convert::From::from($crate::SimpleError::new($str.as_ref())));
},
});
($expr: expr, $fmt:expr, $($arg:tt)+) => (match $expr {
Some(val) => val,
None => {
return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt, $($arg)+))));
},
});
}
#[macro_export]
macro_rules! bail {
($e:expr) => {
return Err(::std::convert::From::from($e));
};
($fmt:expr, $($arg:tt)+) => {
return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt, $($arg)+))));
};
}
#[cfg(test)]
mod tests {
use super::SimpleError;
use std::error::Error;
use std::io;
pub struct ErrorSeed;
impl From<ErrorSeed> for SimpleError {
fn from(_: ErrorSeed) -> SimpleError {
SimpleError::new(".")
}
}
#[test]
fn new_from_string() {
let err = SimpleError::new(String::from("an error from String"));
assert_eq!("an error from String", format!("{}", err));
assert_eq!("an error from String", err.description());
}
#[test]
fn new_from_str() {
let err = SimpleError::new("an error from str");
assert_eq!("an error from str", format!("{}", err));
}
#[test]
fn from_io_error() {
let err = SimpleError::from(io::Error::new(io::ErrorKind::Other, "oh no"));
assert_eq!("oh no", format!("{}", err));
}
fn try_block(result: Result<(), SimpleError>, s: &str) -> Result<(), SimpleError> {
Ok(try_with!(result, s))
}
fn try_block_format(result: Result<(), SimpleError>, s: &str) -> Result<(), SimpleError> {
Ok(try_with!(result, "with {}", s))
}
#[test]
fn macro_try_with() {
assert_eq!(Ok(()), try_block(Ok(()), ""));
assert_eq!(Err(SimpleError::new("try block error, error foo")), try_block(Err(SimpleError::new("error foo")), "try block error"));
assert_eq!(Err(SimpleError::new("with try block error, error foo")), try_block_format(Err(SimpleError::new("error foo")), "try block error"));
}
fn require_block(option: Option<()>, s: &str) -> Result<(), SimpleError> {
Ok(require_with!(option, s))
}
fn require_block_format(maybe: Option<()>, s: &str) -> Result<(), SimpleError> {
Ok(require_with!(maybe, "with {}", s))
}
#[test]
fn macro_require_with() {
assert_eq!(Ok(()), require_block(Some(()), ""));
assert_eq!(Err(SimpleError::new("require block error")), require_block(None, "require block error"));
assert_eq!(Err(SimpleError::new("with require block error")), require_block_format(None, "require block error"));
}
fn bail_block_into(es: ErrorSeed) -> Result<(), SimpleError> {
bail!(es);
}
fn bail_block_str(s: &str) -> Result<(), SimpleError> {
bail!(s);
}
fn bail_block_format(s: &str) -> Result<(), SimpleError> {
bail!("reason: {}", s);
}
fn bail_block_format_to_box_error(s: &str) -> Result<(), Box<Error>> {
bail!("reason: {}", s);
}
#[test]
fn macro_bail() {
assert_eq!(Err(SimpleError::new(".")), bail_block_into(ErrorSeed));
assert_eq!(Err(SimpleError::new("no reason")), bail_block_str("no reason"));
assert_eq!(Err(SimpleError::new("reason: plane crashed")), bail_block_format("plane crashed"));
assert!(bail_block_format_to_box_error("plane crashed").is_err());
}
}