use core::fmt::{Debug, Display, Formatter, Result};
use crate::prelude::*;
pub struct BT(Box<dyn Printable + Sync + Send>);
impl BT {
#[track_caller]
pub fn capture() -> Self {
#[cfg(feature = "std")]
{
#[cfg(target_arch = "wasm32")]
return BT(Box::new(std::backtrace::Backtrace::disabled()));
#[cfg(not(target_arch = "wasm32"))]
return BT(Box::new(std::backtrace::Backtrace::capture()));
}
#[cfg(not(feature = "std"))]
{
BT(Box::new(Stub))
}
}
}
trait Printable: Debug + Display {}
impl<T> Printable for T where T: Debug + Display {}
impl Debug for BT {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
Debug::fmt(&self.0, f)
}
}
impl Display for BT {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
Display::fmt(&self.0, f)
}
}
#[allow(unused)]
struct Stub;
impl Debug for Stub {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "<disabled>")
}
}
impl Display for Stub {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "<disabled>")
}
}
macro_rules! impl_from_err {
($from:ty, $to:ty, $map:path) => {
impl From<$from> for $to {
fn from(err: $from) -> Self {
$map {
source: err,
backtrace: $crate::errors::backtrace::BT::capture(),
}
}
}
};
}
pub(crate) use impl_from_err;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bt_works_without_std() {
#[derive(Debug)]
struct BacktraceStub;
impl Display for BacktraceStub {
fn fmt(&self, _f: &mut Formatter<'_>) -> Result {
Ok(())
}
}
_ = BT(Box::new(BacktraceStub));
}
}