use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use std::error::Error; use std::fmt; use std::io; pub type Result = std::result::Result; #[derive(Debug)] pub enum ServerError { IO(io::Error), Axum(axum::Error), Db(sea_orm::DbErr), Status(StatusCode), } impl fmt::Display for ServerError { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ServerError::IO(err) => write!(fmt, "{}", err), ServerError::Axum(err) => write!(fmt, "{}", err), ServerError::Status(status) => write!(fmt, "{}", status), ServerError::Db(err) => write!(fmt, "{}", err), } } } impl Error for ServerError {} impl IntoResponse for ServerError { fn into_response(self) -> Response { tracing::error!("{:?}", self); match self { ServerError::IO(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(), ServerError::Axum(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(), ServerError::Status(status) => status.into_response(), ServerError::Db(sea_orm::DbErr::RecordNotFound(_)) => { StatusCode::NOT_FOUND.into_response() } ServerError::Db(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(), } } } impl From for ServerError { fn from(err: io::Error) -> Self { ServerError::IO(err) } } impl From for ServerError { fn from(err: axum::Error) -> Self { ServerError::Axum(err) } } impl From for ServerError { fn from(err: tokio::task::JoinError) -> Self { ServerError::IO(err.into()) } } impl From for ServerError { fn from(status: StatusCode) -> Self { Self::Status(status) } } impl From for ServerError { fn from(err: sea_orm::DbErr) -> Self { ServerError::Db(err) } }