use alloc::boxed::Box;
use core::panic::Location;
use thin_vec::{thin_vec, ThinVec};
use crate::ErrorKind;
pub struct Error {
pub stack: ThinVec<(ErrorKind, Option<&'static Location<'static>>)>,
}
#[derive(Debug, thiserror::Error)]
pub struct StackedError(pub Error);
impl Error {
pub fn empty() -> Self {
Self {
stack: ThinVec::new(),
}
}
#[track_caller]
pub fn new() -> Self {
Self::from_kind(ErrorKind::UnitError)
}
#[track_caller]
pub fn from_err<E: std::error::Error + Send + Sync + 'static>(e: E) -> Self {
let l = Location::caller();
Self {
stack: thin_vec![(ErrorKind::BoxedError(Box::new(e)), Some(l))],
}
}
pub fn from_err_locationless<E: std::error::Error + Send + Sync + 'static>(e: E) -> Self {
Self {
stack: thin_vec![(ErrorKind::BoxedError(Box::new(e)), None)],
}
}
#[track_caller]
pub fn from_kind<K: Into<ErrorKind>>(kind: K) -> Self {
let l = Location::caller();
Self {
stack: thin_vec![(kind.into(), Some(l))],
}
}
pub fn from_kind_locationless<K: Into<ErrorKind>>(kind: K) -> Self {
Self {
stack: thin_vec![(kind.into(), None)],
}
}
#[track_caller]
pub fn from_box(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
Self::from_kind(ErrorKind::BoxedError(e))
}
pub fn from_box_locationless(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
Self::from_kind_locationless(ErrorKind::BoxedError(e))
}
#[track_caller]
pub fn add_kind<K: Into<ErrorKind>>(mut self, kind: K) -> Self {
self.stack.push((kind.into(), Some(Location::caller())));
self
}
pub fn add_kind_locationless<K: Into<ErrorKind>>(mut self, kind: K) -> Self {
self.stack.push((kind.into(), None));
self
}
#[track_caller]
pub fn add_location(mut self) -> Self {
self.stack
.push((ErrorKind::UnitError, Some(Location::caller())));
self
}
pub fn chain_errors(mut self, mut other: Self) -> Self {
self.stack.append(&mut other.stack);
self
}
#[track_caller]
pub fn timeout() -> Self {
Self::from_kind(ErrorKind::TimeoutError)
}
#[track_caller]
pub fn probably_not_root_cause() -> Self {
Self::from_kind(ErrorKind::ProbablyNotRootCauseError)
}
pub fn is_timeout(&self) -> bool {
for (error, _) in &self.stack {
if matches!(error, ErrorKind::TimeoutError) {
return true
}
}
false
}
pub fn is_probably_not_root_cause(&self) -> bool {
for (error, _) in &self.stack {
if matches!(error, ErrorKind::ProbablyNotRootCauseError) {
return true
}
}
false
}
}
impl Default for Error {
#[track_caller]
fn default() -> Self {
Error::new()
}
}