use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use crate::StatusCode;
pub type Result<T> = std::result::Result<T, Error>;
pub struct Error {
error: anyhow::Error,
status: crate::StatusCode,
}
impl Error {
pub fn new<E>(status: StatusCode, error: E) -> Self
where
E: StdError + Send + Sync + 'static,
{
Self {
status,
error: anyhow::Error::new(error),
}
}
pub fn from_str<M>(status: StatusCode, msg: M) -> Self
where
M: Display + Debug + Send + Sync + 'static,
{
Self {
status,
error: anyhow::Error::msg(msg),
}
}
pub(crate) fn new_adhoc<M>(message: M) -> Error
where
M: Display + Debug + Send + Sync + 'static,
{
Self::from_str(StatusCode::InternalServerError, message)
}
pub fn status(&self) -> StatusCode {
self.status
}
pub fn set_status(&mut self, status: StatusCode) {
self.status = status;
}
#[cfg(backtrace)]
pub fn backtrace(&self) -> &std::backtrace::Backtrace {
self.error.downcast_ref::<E>()
}
pub fn downcast<E>(self) -> std::result::Result<E, Self>
where
E: Display + Debug + Send + Sync + 'static,
{
if self.error.downcast_ref::<E>().is_some() {
Ok(self.error.downcast().unwrap())
} else {
Err(self)
}
}
pub fn downcast_ref<E>(&self) -> Option<&E>
where
E: Display + Debug + Send + Sync + 'static,
{
self.error.downcast_ref::<E>()
}
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
where
E: Display + Debug + Send + Sync + 'static,
{
self.error.downcast_mut::<E>()
}
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{}", self.error)
}
}
impl Debug for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{}", self.error)
}
}
impl<E> From<E> for Error
where
E: StdError + Send + Sync + 'static,
{
fn from(error: E) -> Self {
Self {
error: anyhow::Error::new(error),
status: StatusCode::InternalServerError,
}
}
}
impl AsRef<dyn StdError + Send + Sync> for Error {
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
self.error.as_ref()
}
}
impl AsRef<StatusCode> for Error {
fn as_ref(&self) -> &StatusCode {
&self.status
}
}
impl AsMut<StatusCode> for Error {
fn as_mut(&mut self) -> &mut StatusCode {
&mut self.status
}
}
impl AsRef<dyn StdError> for Error {
fn as_ref(&self) -> &(dyn StdError + 'static) {
self.error.as_ref()
}
}
impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
fn from(error: Error) -> Self {
error.error.into()
}
}
impl From<Error> for Box<dyn StdError + 'static> {
fn from(error: Error) -> Self {
Box::<dyn StdError + Send + Sync>::from(error.error)
}
}