use core::{convert::Infallible, fmt};
use std::error;
use std::backtrace::Backtrace;
use crate::{
body::ResponseBody,
http::{StatusCode, WebResponse},
service::Service,
WebContext,
};
use super::Error;
pub struct ErrorStatus {
status: StatusCode,
_back_trace: Backtrace,
}
impl ErrorStatus {
pub fn internal() -> Self {
Self {
status: StatusCode::BAD_REQUEST,
_back_trace: Backtrace::capture(),
}
}
pub fn bad_request() -> Self {
Self {
status: StatusCode::BAD_REQUEST,
_back_trace: Backtrace::capture(),
}
}
}
impl fmt::Debug for ErrorStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.status, f)
}
}
impl fmt::Display for ErrorStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.status, f)
}
}
impl error::Error for ErrorStatus {
#[cfg(feature = "nightly")]
fn provide<'a>(&'a self, request: &mut error::Request<'a>) {
request.provide_ref(&self._back_trace);
}
}
impl From<StatusCode> for ErrorStatus {
fn from(status: StatusCode) -> Self {
Self {
status,
_back_trace: Backtrace::capture(),
}
}
}
impl<C> From<StatusCode> for Error<C> {
fn from(e: StatusCode) -> Self {
Error::from(ErrorStatus::from(e))
}
}
impl<C> From<ErrorStatus> for Error<C> {
fn from(e: ErrorStatus) -> Self {
Error::from_service(e)
}
}
impl<'r, C, B> Service<WebContext<'r, C, B>> for ErrorStatus {
type Response = WebResponse;
type Error = Infallible;
async fn call(&self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
self.status.call(ctx).await
}
}
impl<'r, C, B> Service<WebContext<'r, C, B>> for StatusCode {
type Response = WebResponse;
type Error = Infallible;
async fn call(&self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
let mut res = ctx.into_response(ResponseBody::empty());
*res.status_mut() = *self;
Ok(res)
}
}