#![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) }
}
}
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(SimpleError::with($str.as_ref(), err));
},
})
}
#[macro_export]
macro_rules! require_with {
($expr: expr, $str: expr) => (match $expr {
Some(val) => val,
None => {
return Err(SimpleError::new($str.as_ref()));
},
})
}
#[macro_export]
macro_rules! bail {
($e:expr) => {
return Err($e.into());
};
($fmt:expr, $($arg:tt)+) => {
return Err(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))
}
#[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"));
}
fn require_block(option: Option<()>, s: &str) -> Result<(), SimpleError> {
Ok(require_with!(option, 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"));
}
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);
}
#[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"));
}
}