use crate::controller::extract::Json;
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use serde::Serialize;
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
NotFound,
Conflict,
Internal,
}
impl Error {
const fn status_code(self) -> StatusCode {
match self {
Self::NotFound => StatusCode::NOT_FOUND,
Self::Conflict => StatusCode::CONFLICT,
Self::Internal => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
impl From<sqlx::Error> for Error {
fn from(error: sqlx::Error) -> Self {
match error {
sqlx::Error::Database(error) => {
eprintln!("sql database error: {error:?}");
Self::Conflict
}
error => {
eprintln!("sql error: {error:?}");
Self::Internal
}
}
}
}
impl IntoResponse for Error {
fn into_response(self) -> axum::response::Response {
self.status_code().into_response()
}
}
#[derive(Debug)]
pub enum AuthError {
Unauthenticated,
Unauthorized,
}
impl AuthError {
const fn status_code(self) -> StatusCode {
match self {
Self::Unauthenticated => StatusCode::UNAUTHORIZED,
Self::Unauthorized => StatusCode::FORBIDDEN,
}
}
}
impl IntoResponse for AuthError {
fn into_response(self) -> axum::response::Response {
self.status_code().into_response()
}
}
#[derive(Debug)]
pub enum ModelError<UnprocessableEntity> {
UnprocessableEntity(UnprocessableEntity),
Other(Error),
}
impl<UnprocessableEntity, E> From<E> for ModelError<UnprocessableEntity>
where
E: Into<Error>,
{
fn from(other: E) -> Self {
Self::Other(other.into())
}
}
impl From<()> for ModelError<()> {
fn from(value: ()) -> Self {
Self::UnprocessableEntity(value)
}
}
impl From<core::convert::Infallible> for ModelError<core::convert::Infallible> {
fn from(value: core::convert::Infallible) -> Self {
Self::UnprocessableEntity(value)
}
}
impl<UnprocessableEntity> IntoResponse for ModelError<UnprocessableEntity>
where
UnprocessableEntity: Serialize,
{
fn into_response(self) -> Response {
match self {
Self::UnprocessableEntity(err) => {
(StatusCode::UNPROCESSABLE_ENTITY, Json(err)).into_response()
}
Self::Other(err) => err.status_code().into_response(),
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum AppError {
#[error("{0}")]
Io(
#[from]
#[source]
std::io::Error,
),
#[error("{0}")]
Sql(
#[from]
#[source]
sqlx::Error,
),
}