#![no_std]
mod actix_web;
extern crate alloc;
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String};
use core::{
any::type_name,
error::Error as ErrorTrait,
fmt::{Debug, Display}, ops::Deref,
};
pub type Result<T> = core::result::Result<T, Error>;
pub struct Error(Box<ErrorImpl>);
impl Deref for Error {
type Target = ErrorImpl;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct ErrorImpl {
name: &'static str,
message: Option<String>,
location: Location,
cause: Option<Error>,
}
pub struct Location {
file: &'static str,
line: u32,
col: u32,
}
impl Location {
pub fn new(caller: &'static core::panic::Location<'static>) -> Self {
Self {
file: caller.file(),
line: caller.line(),
col: caller.column(),
}
}
}
impl Debug for Location {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}:{}:{}", self.file, self.line, self.col)
}
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<Self as Debug>::fmt(self, f)
}
}
impl Debug for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match &self.message {
None => writeln!(f, "{} in {:?}", self.name, self.location)?,
Some(msg) => writeln!(f, "{} -> `{}` in {:?}", self.name, msg, self.location)?,
}
if let Some(cause) = &self.cause {
write!(f, "Caused by: {cause}")?;
}
Ok(())
}
}
impl<E: ErrorTrait> From<E> for Error {
#[track_caller]
fn from(error: E) -> Self {
Self::new(
type_name::<E>(),
Some(format!("{error:?}")),
core::panic::Location::caller(),
error.source().map(Error::from),
)
}
}
impl Error {
pub fn new(
name: &'static str,
msg: Option<String>,
location: &'static core::panic::Location,
cause: Option<Error>,
) -> Self {
Error(Box::new(ErrorImpl {
name,
message: msg,
location: Location::new(location),
cause,
}))
}
}
pub trait ErrorExt<T> {
fn loc(self) -> Result<T>;
fn loc_msg(self, msg: &str) -> Result<T>;
}
pub trait ErrorExtTrait<T> {
fn loc(self) -> Result<T>;
fn loc_msg(self, msg: &str) -> Result<T>;
}
pub trait ErrorExtCompat<T> {
fn loc_compat(self) -> Result<T>;
fn loc_compat_msg(self, msg: &str) -> Result<T>;
}
impl<T> ErrorExt<T> for Option<T> {
#[track_caller]
fn loc(self) -> Result<T> {
match self {
Some(t) => Ok(t),
None => Err(Error::new(
type_name::<Option<T>>(),
None,
core::panic::Location::caller(),
None,
)),
}
}
#[track_caller]
fn loc_msg(self, msg: &str) -> Result<T> {
match self {
Some(t) => Ok(t),
None => Err(Error::new(
type_name::<Option<T>>(),
Some(msg.to_owned()),
core::panic::Location::caller(),
None,
)),
}
}
}
impl<T> ErrorExt<T> for Result<T> {
#[track_caller]
fn loc(self) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(err) => Err(Error::new(
type_name::<Error>(),
None,
core::panic::Location::caller(),
Some(err),
)),
}
}
#[track_caller]
fn loc_msg(self, msg: &str) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(err) => Err(Error::new(
type_name::<Error>(),
Some(msg.to_owned()),
core::panic::Location::caller(),
Some(err),
)),
}
}
}
impl<T, E> ErrorExtTrait<T> for core::result::Result<T, E>
where
E: ErrorTrait,
{
#[track_caller]
fn loc(self) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(err) => Err(Error::new(
type_name::<E>(),
None,
core::panic::Location::caller(),
Some(Error::from(err)),
)),
}
}
#[track_caller]
fn loc_msg(self, msg: &str) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(err) => Err(Error::new(
type_name::<E>(),
Some(msg.to_owned()),
core::panic::Location::caller(),
Some(Error::from(err)),
)),
}
}
}
impl<T, E> ErrorExtCompat<T> for core::result::Result<T, E> {
#[track_caller]
fn loc_compat(self) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(_) => Err(Error::new(
type_name::<E>(),
None,
core::panic::Location::caller(),
None,
)),
}
}
#[track_caller]
fn loc_compat_msg(self, msg: &str) -> Result<T> {
match self {
Ok(ok) => Ok(ok),
Err(_) => Err(Error::new(
type_name::<E>(),
Some(msg.to_owned()),
core::panic::Location::caller(),
None,
)),
}
}
}