#[derive(Debug, Clone)]
pub struct WrappedError {
pub kind_repr: String,
pub description: String,
pub file: &'static str,
pub line: u32,
pub sub_error: Option<std::rc::Rc<WrappedError>>
}
impl<T: std::fmt::Debug + Send> From<Error<T>> for WrappedError {
fn from(error: Error<T>) -> Self {
WrappedError {
kind_repr: format!("{:?}", error.kind), description: error.description,
file: error.file, line: error.line,
sub_error: error.sub_error
}
}
}
impl ToString for WrappedError {
fn to_string(&self) -> String {
let mut string = format!("{}: {} (at {}:{})", self.kind_repr, self.description, self.file, self.line);
if let Some(ref sub_error) = self.sub_error { string += "\n - "; string += &sub_error.to_string(); }
string
}
}
unsafe impl Send for WrappedError {}
#[derive(Debug)]
pub struct Error<T: std::fmt::Debug + Send> {
pub kind: T,
pub description: String,
pub file: &'static str,
pub line: u32,
pub sub_error: Option<std::rc::Rc<WrappedError>>
}
impl<T: std::fmt::Debug + Send> Error<T> {
pub fn with_kind_desc<S: ToString>(kind: T, description: S, file: &'static str, line: u32) -> Self {
Error{ kind, description: description.to_string(), file, line, sub_error: None }
}
pub fn with_kind(kind: T, file: &'static str, line: u32) -> Self {
let description = format!("{:?}", kind);
Error::with_kind_desc(kind, description, file, line)
}
pub fn propagate_with_kind_desc<S: ToString>(kind: T, description: S, sub_error: WrappedError, file: &'static str, line: u32) -> Self {
Error{ kind, description: description.to_string(), file, line, sub_error: Some(std::rc::Rc::new(sub_error)) }
}
pub fn propagate_with_kind(kind: T, sub_error: WrappedError, file: &'static str, line: u32) -> Self {
let description = format!("{:?}", kind);
Error::propagate_with_kind_desc(kind, description, sub_error, file, line)
}
pub fn propagate(sub_error: Error<T>, file: &'static str, line: u32) -> Self where T: Clone {
Error::propagate_with_kind_desc(sub_error.kind.clone(), sub_error.description.clone(), sub_error.into(), file, line)
}
}
impl<T: std::fmt::Debug + Send> ToString for Error<T> {
fn to_string(&self) -> String {
let mut string = format!("{:?}: {} (at {}:{})", self.kind, self.description, self.file, self.line);
if let Some(ref sub_error) = self.sub_error { string += "\n - "; string += &sub_error.to_string(); }
string
}
}
unsafe impl<T: std::fmt::Debug + Send> Send for Error<T> {}
#[macro_export]
macro_rules! new_err {
($kind:expr, $description:expr) => ($crate::Error::with_kind_desc($kind, $description, file!(), line!()));
($kind:expr) => ($crate::Error::with_kind($kind, file!(), line!()));
}
#[macro_export]
macro_rules! new_err_with {
($kind:expr, $description:expr, $suberr:expr) =>
($crate::Error::propagate_with_kind_desc($kind, $description, $suberr.into(), file!(), line!()));
($kind:expr, $suberr:expr) =>
($crate::Error::propagate_with_kind($kind, $suberr.into(), file!(), line!()));
($suberr:expr) =>
($crate::Error::propagate($suberr.into(), file!(), line!()))
}
#[macro_export]
macro_rules! new_err_from {
($kind:expr, $description:expr) => (new_err!($kind.into(), $description));
($kind:expr) => (new_err!($kind.into()));
}
#[macro_export]
macro_rules! throw_err {
($kind:expr, $description:expr) => (return Err(new_err!($kind, $description)));
($kind:expr) => (return Err(new_err!($kind)));
}
#[macro_export]
macro_rules! rethrow_err {
($kind:expr, $description:expr, $suberr:expr) => (return Err(new_err_with!($kind, $description, $suberr)));
($kind:expr, $suberr:expr) => (return Err(new_err_with!($kind, $suberr)));
($suberr:expr) => (return Err(new_err_with!($suberr)));
}
#[macro_export]
macro_rules! try_err {
($code:expr, $kind:expr, $description:expr) => (match $code {
Ok(result) => result,
Err(error) => rethrow_err!($kind, $description, error)
});
($code:expr, $kind:expr) => (match $code {
Ok(result) => result,
Err(error) => rethrow_err!($kind, error)
});
($code:expr) => (match $code {
Ok(result) => result,
Err(error) => rethrow_err!(error)
});
}
#[macro_export]
macro_rules! try_err_from {
($code:expr, $description:expr) => (match $code {
Ok(result) => result,
Err(error) => throw_err!(error.into(), $description)
});
($code:expr) => (match $code {
Ok(result) => result,
Err(error) => throw_err!(error.into())
});
}
#[macro_export]
macro_rules! ok_or {
($code:expr, $err:ident, $or:expr) => (match $code {
Ok(result) => result,
Err($err) => $or
});
($code:expr, $or:expr) => (match $code {
Ok(result) => result,
Err(_) => $or
});
}
#[macro_export]
macro_rules! some_or {
($code:expr, $or:expr) => (match $code {
Some(result) => result,
None => $or
});
}