#[doc(hidden)]
pub mod backtrace;
#[macro_export]
macro_rules! define_error {
($name:ident) => {
pub struct $name<E> {
err: E,
desc: std::borrow::Cow<'static, str>,
backtrace: std::option::Option<$crate::backtrace::Backtrace>
}
impl<E> $name<E> {
pub fn new(err: E, desc: String) -> Self {
let backtrace = $crate::backtrace::Backtrace::capture();
let desc = std::borrow::Cow::Owned(desc);
Self::with_backtrace(err, desc, backtrace)
}
pub fn new_static(err: E, desc: &'static str) -> Self {
let backtrace = $crate::backtrace::Backtrace::capture();
let desc = std::borrow::Cow::Borrowed(desc);
Self::with_backtrace(err, desc, backtrace)
}
pub const fn with_backtrace(err: E, desc: std::borrow::Cow<'static, str>,
backtrace: Option<$crate::backtrace::Backtrace>) -> Self
{
Self { err, desc, backtrace }
}
pub const fn err(&self) -> &E {
&self.err
}
pub const fn desc(&self) -> &std::borrow::Cow<'static, str> {
&self.desc
}
pub fn backtrace(&self) -> Option<&$crate::backtrace::Backtrace> {
self.backtrace.as_ref()
}
}
impl<E> std::ops::Deref for $name<E> {
type Target = E;
fn deref(&self) -> &Self::Target {
&self.err
}
}
impl<E> std::convert::From<E> for $name<E> where E: std::fmt::Display {
fn from(error: E) -> Self {
let desc = error.to_string();
Self::new(error, desc)
}
}
impl<E> std::error::Error for $name<E> where E: std::error::Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.err.source()
}
}
impl<E> std::fmt::Debug for $name<E> where E: std::fmt::Debug {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct(std::any::type_name::<Self>())
.field("err", &self.err)
.field("desc", &self.desc)
.field("backtrace", &self.backtrace)
.finish()
}
}
impl<E> std::fmt::Display for $name<E> where E: std::fmt::Display {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", &self.err)?;
if !self.desc.is_empty() {
write!(f, " ({})", &self.desc)?;
}
if let Some(backtrace) = self.backtrace.as_ref() {
writeln!(f)?;
writeln!(f)?;
writeln!(f, "Backtrace:")?;
write!(f, "{}", backtrace)?;
}
Ok(())
}
}
impl<E> std::default::Default for $name<E> where E: std::default::Default + std::fmt::Display {
fn default() -> Self {
Self::from(E::default())
}
}
impl<E> std::clone::Clone for $name<E> where E: std::clone::Clone {
fn clone(&self) -> Self {
Self {
err: self.err.clone(),
desc: self.desc.clone(),
backtrace: self.backtrace.clone()
}
}
}
};
}