use std::{
backtrace::Backtrace,
ops::{ControlFlow, Deref, DerefMut, FromResidual, Try},
};
use crate::print_backtrace;
pub struct Result<T, E> {
inner: std::result::Result<T, E>,
backtrace: Backtrace,
}
impl<T, E> Result<T, E> {
pub fn backtrace(&self) {
print_backtrace(&self.backtrace);
}
}
impl<T, E> FromResidual for Result<T, E> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
Result {
inner: Err(residual.0),
backtrace: residual.1,
}
}
}
impl<T, E> Try for Result<T, E> {
type Output = T;
type Residual = (E, Backtrace);
fn from_output(output: Self::Output) -> Self {
Result {
inner: Ok(output),
backtrace: Backtrace::capture(),
}
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self.inner {
Ok(x) => ControlFlow::Continue(x),
Err(e) => ControlFlow::Break((e, self.backtrace)),
}
}
}
impl<T, E> Deref for Result<T, E> {
type Target = std::result::Result<T, E>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T, E> DerefMut for Result<T, E> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T, E> From<std::result::Result<T, E>> for Result<T, E> {
fn from(value: std::result::Result<T, E>) -> Self {
Self {
inner: value,
backtrace: Backtrace::capture(),
}
}
}