use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json::to_string_pretty;
use thiserror::Error as ThisError;
#[derive(Debug, Serialize, Deserialize)]
pub struct ErrorDetails {
pub provider_parser: &'static str,
pub message: &'static str,
pub status: u16,
}
impl ErrorDetails {
fn new(
provider_parser: &'static str,
err_msg: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
const DEFAULT_ERROR_STATUS: u16 = StatusCode::INTERNAL_SERVER_ERROR.as_u16();
const DEFAULT_ERROR_MESSAGE: &str = "Something went wrong";
let (status, message) = match (status, err_msg) {
(Some(s), Some(msg)) => (s.as_u16(), msg),
(Some(s), None) => (s.as_u16(), DEFAULT_ERROR_MESSAGE),
(None, Some(msg)) => (DEFAULT_ERROR_STATUS, msg),
(None, None) => (DEFAULT_ERROR_STATUS, DEFAULT_ERROR_MESSAGE),
};
let err = ErrorDetails {
provider_parser,
message,
status,
};
err.log_error();
return err;
}
fn get_json(&self) -> String {
match to_string_pretty(self) {
Ok(stringified_json) => stringified_json,
Err(_) => {
println!("error occured while serializing custom error details into json");
"{\"status\": 500}".to_string()
}
}
}
fn log_error(&self) {
const ANSI_ESC_CODE_COLOR_RED: &str = "\x1b[31m";
const ANSI_ESC_CODE_COLOR_RESET: &str = "\x1b[0m";
eprintln!(
"{}{}{}",
ANSI_ESC_CODE_COLOR_RED,
self.get_json(),
ANSI_ESC_CODE_COLOR_RESET
);
}
}
pub type EnmaResult<T> = std::result::Result<T, EnmaError>;
#[derive(Debug, ThisError)]
pub enum EnmaError {
#[error("<{}>: {} SrcFetchError", details.provider_parser, details.status)]
SrcFetchError { details: ErrorDetails },
#[error("<{}>: {} SrcParseError", details.provider_parser, details.status)]
SrcParseError { details: ErrorDetails },
#[error("<{}>: {} ParseIntError", details.provider_parser, details.status)]
ParseIntError { details: ErrorDetails },
#[error("<{}>: {} JsonSerDeError", details.provider_parser, details.status)]
JsonSerDeError { details: ErrorDetails },
#[error("<{}>: {} UnknownError", details.provider_parser, details.status)]
UnknownError { details: ErrorDetails },
}
impl EnmaError {
pub fn src_fetch_error(
provider_parser: &'static str,
err_msg: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
return Self::SrcFetchError {
details: ErrorDetails::new(
provider_parser,
err_msg.or(Some("SrcFetchError: Failed to fetch source data")),
status,
),
};
}
pub fn src_parse_error(
provider_parser: &'static str,
err_msg: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
return Self::SrcParseError {
details: ErrorDetails::new(
provider_parser,
err_msg.or(Some("SrcParseError: Failed to parse fetched source data")),
status,
),
};
}
pub fn parse_int_error(
provider_parser: &'static str,
err_msg: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
return Self::ParseIntError {
details: ErrorDetails::new(
provider_parser,
err_msg.or(Some("ParseIntError: Failed to parse integer value")),
status,
),
};
}
pub fn json_serde_error(
provider_parser: &'static str,
err_msg: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
return Self::JsonSerDeError {
details: ErrorDetails::new(
provider_parser,
err_msg.or(Some(
"JsonSerDeError: Failed to serialize or deserialize json",
)),
status,
),
};
}
pub fn unknown_error(
provider_parser: &'static str,
err_message: Option<&'static str>,
status: Option<StatusCode>,
) -> Self {
return Self::UnknownError {
details: ErrorDetails::new(provider_parser, err_message, status),
};
}
}