use std::fmt::Display; use poem::{ error::{ParseMultipartError, ResponseError}, http::StatusCode, }; use sqlx::postgres::PgDatabaseError; #[derive(Debug)] pub enum Error { IOError(std::io::Error), TOMLError(toml::de::Error), SQLError(String), DatabaseError(sqlx::Error), NotFound, MissingField, Unauthorized, MultipartError, BadRequest, UnsupportedFileType(String), UploadDirectory(String), } impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::SQLError(error) => write!(f, "SQL Error: {}", error), Error::IOError(error) => write!(f, "IO Error: {}", error), Error::TOMLError(error) => write!(f, "TOML deserialization error: {}", error), Error::DatabaseError(error) => write!(f, "database error: {}", error), Error::NotFound => write!(f, "not found"), Error::MissingField => write!(f, "missing field in row"), Error::Unauthorized => write!(f, "user unauthorized"), Error::MultipartError => write!(f, "error parsing multipart form data"), Error::BadRequest => write!(f, "bad request"), Error::UnsupportedFileType(filetype) => { write!(f, "unsupported file upload type: {}", filetype) } Error::UploadDirectory(directory) => { write!(f, "invalid uploads directory: {}", directory) } } } } impl std::error::Error for Error {} impl ResponseError for Error { fn status(&self) -> poem::http::StatusCode { match self { Error::IOError(_) => StatusCode::INTERNAL_SERVER_ERROR, Error::TOMLError(_) => StatusCode::INTERNAL_SERVER_ERROR, Error::DatabaseError(_) => StatusCode::INTERNAL_SERVER_ERROR, Error::NotFound => StatusCode::NOT_FOUND, Error::SQLError(_) => StatusCode::INTERNAL_SERVER_ERROR, Error::MissingField => StatusCode::INTERNAL_SERVER_ERROR, Error::Unauthorized => StatusCode::UNAUTHORIZED, Error::MultipartError => StatusCode::BAD_REQUEST, Error::BadRequest => StatusCode::BAD_REQUEST, Error::UnsupportedFileType(_) => StatusCode::BAD_REQUEST, Error::UploadDirectory(_) => StatusCode::INTERNAL_SERVER_ERROR, } } } impl From for Error { fn from(e: std::io::Error) -> Self { Self::IOError(e) } } impl From for Error { fn from(e: toml::de::Error) -> Self { Self::TOMLError(e) } } impl From for Error { fn from(e: sqlx::Error) -> Self { match e { sqlx::Error::Database(database_error) => { let error = database_error.downcast::(); match error.code() { code => Error::SQLError(code.to_string()), } } sqlx::Error::RowNotFound => Error::NotFound, _ => Self::DatabaseError(e), } } } impl From for Error { fn from(e: ParseMultipartError) -> Self { Error::MultipartError } }