use std::fmt::{Debug, Display, Formatter}; use actix::MailboxError; use actix_web::http::StatusCode; use actix_web::HttpResponse; use serde::ser::SerializeStruct; use serde::{Serialize, Serializer}; use crate::errors::{ApiError, DatabaseError}; use crate::types::ControllerUid; #[derive(Debug)] pub enum EmgauwaError { Api(ApiError), Uid(uuid::Error), Serialization(serde_json::Error), Database(DatabaseError), Internal(String), Connection(ControllerUid), } impl EmgauwaError { fn get_code(&self) -> StatusCode { match self { EmgauwaError::Api(err) => err.get_code(), EmgauwaError::Serialization(_) => StatusCode::INTERNAL_SERVER_ERROR, EmgauwaError::Database(err) => err.get_code(), EmgauwaError::Uid(_) => StatusCode::BAD_REQUEST, EmgauwaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR, EmgauwaError::Connection(_) => StatusCode::GATEWAY_TIMEOUT, } } } impl From<&EmgauwaError> for String { fn from(err: &EmgauwaError) -> Self { match err { EmgauwaError::Api(err) => String::from(err), EmgauwaError::Serialization(_) => String::from("error during (de-)serialization"), EmgauwaError::Database(err) => String::from(err), EmgauwaError::Uid(_) => String::from("the uid is in a bad format"), EmgauwaError::Internal(_) => String::from("general error"), EmgauwaError::Connection(_) => String::from("the target controller is not connected"), } } } impl From<ApiError> for EmgauwaError { fn from(value: ApiError) -> Self { EmgauwaError::Api(value) } } impl From<DatabaseError> for EmgauwaError { fn from(value: DatabaseError) -> Self { EmgauwaError::Database(value) } } impl From<serde_json::Error> for EmgauwaError { fn from(value: serde_json::Error) -> Self { EmgauwaError::Serialization(value) } } impl From<sqlx::Error> for EmgauwaError { fn from(value: sqlx::Error) -> Self { EmgauwaError::Database(DatabaseError::from(value)) } } impl From<uuid::Error> for EmgauwaError { fn from(value: uuid::Error) -> Self { EmgauwaError::Uid(value) } } impl From<MailboxError> for EmgauwaError { fn from(value: MailboxError) -> Self { EmgauwaError::Internal(value.to_string()) } } impl From<&EmgauwaError> for HttpResponse { fn from(err: &EmgauwaError) -> Self { HttpResponse::build(err.get_code()).json(err) } } impl Serialize for EmgauwaError { 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 Display for EmgauwaError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}: {}", self.get_code(), String::from(self)) } } impl actix_web::error::ResponseError for EmgauwaError { fn status_code(&self) -> StatusCode { self.get_code() } fn error_response(&self) -> HttpResponse { HttpResponse::from(self) } }