use std::{error::Error, fmt};
use http::StatusCode;
use crate::{response::Response, server::IntoResponse};
#[derive(Debug)]
#[non_exhaustive]
pub enum ExtractBodyError {
Generic(GenericRejectionError),
String(simdutf8::basic::Utf8Error),
#[cfg(feature = "json")]
Json(crate::utils::json::Error),
#[cfg(feature = "form")]
Form(serde_urlencoded::de::Error),
}
impl fmt::Display for ExtractBodyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("failed to extract ")?;
match self {
Self::Generic(e) => write!(f, "data: {e}"),
Self::String(e) => write!(f, "string: {e}"),
#[cfg(feature = "json")]
Self::Json(e) => write!(f, "json: {e}"),
#[cfg(feature = "form")]
Self::Form(e) => write!(f, "form: {e}"),
}
}
}
impl Error for ExtractBodyError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Generic(e) => Some(e),
Self::String(e) => Some(e),
#[cfg(feature = "json")]
Self::Json(e) => Some(e),
#[cfg(feature = "form")]
Self::Form(e) => Some(e),
}
}
}
impl IntoResponse for ExtractBodyError {
fn into_response(self) -> Response {
let status = match self {
Self::Generic(e) => e.to_status_code(),
Self::String(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
#[cfg(feature = "json")]
Self::Json(_) => StatusCode::BAD_REQUEST,
#[cfg(feature = "form")]
Self::Form(_) => StatusCode::BAD_REQUEST,
};
status.into_response()
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum GenericRejectionError {
BodyCollectionError,
InvalidContentType,
}
impl fmt::Display for GenericRejectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BodyCollectionError => write!(f, "failed to collect the response body"),
Self::InvalidContentType => write!(f, "invalid content type"),
}
}
}
impl Error for GenericRejectionError {}
impl GenericRejectionError {
pub fn to_status_code(&self) -> StatusCode {
match self {
Self::BodyCollectionError => StatusCode::INTERNAL_SERVER_ERROR,
Self::InvalidContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
}
}
}
impl IntoResponse for GenericRejectionError {
fn into_response(self) -> Response {
self.to_status_code().into_response()
}
}
pub fn body_collection_error() -> ExtractBodyError {
ExtractBodyError::Generic(GenericRejectionError::BodyCollectionError)
}
pub fn invalid_content_type() -> ExtractBodyError {
ExtractBodyError::Generic(GenericRejectionError::InvalidContentType)
}