use std::fmt::{Display, Formatter}; use actix_web::http::StatusCode; use actix_web::HttpResponse; use emgauwa_lib::db::errors::DatabaseError; use serde::ser::SerializeStruct; use serde::{Serialize, Serializer}; #[derive(Debug)] pub enum ApiError { BadUid, ProtectedSchedule, DatabaseError(DatabaseError), InternalError(String), } impl ApiError { fn get_code(&self) -> StatusCode { match self { ApiError::BadUid => StatusCode::BAD_REQUEST, ApiError::ProtectedSchedule => StatusCode::FORBIDDEN, ApiError::DatabaseError(db_error) => db_error.get_code(), ApiError::InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR, } } } impl Serialize for ApiError { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { let mut s = serializer.serialize_struct("error", 2)?; s.serialize_field("code", &self.get_code().as_u16())?; s.serialize_field("description", &String::from(self))?; s.end() } } impl From<&ApiError> for String { fn from(err: &ApiError) -> Self { match err { ApiError::BadUid => String::from("the uid is in a bad format"), ApiError::ProtectedSchedule => String::from("the targeted schedule is protected"), ApiError::DatabaseError(db_err) => String::from(db_err), ApiError::InternalError(msg) => msg.clone(), } } } impl From<&ApiError> for HttpResponse { fn from(err: &ApiError) -> Self { HttpResponse::build(err.get_code()).json(err) } } impl Display for ApiError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}: {}", self.get_code(), String::from(self)) } } impl actix_web::error::ResponseError for ApiError { fn status_code(&self) -> StatusCode { self.get_code() } fn error_response(&self) -> HttpResponse { HttpResponse::from(self) } } impl From<sqlx::Error> for ApiError { fn from(err: sqlx::Error) -> Self { ApiError::DatabaseError(DatabaseError::from(err)) } } impl From<DatabaseError> for ApiError { fn from(err: DatabaseError) -> Self { ApiError::DatabaseError(err) } }