use serde_json::Value;
use std::fmt;
#[derive(Debug, Clone)]
pub enum DataForSeoError {
Api(DataForSeoApiError),
Http(DataForSeoHttpError),
System(DataForSeoSystemError),
}
impl DataForSeoError {
pub fn http_status(&self) -> u16 {
match self {
DataForSeoError::Api(e) => e.http_status,
DataForSeoError::Http(e) => e.http_status,
DataForSeoError::System(_) => 0,
}
}
pub fn api_status_code(&self) -> Option<i32> {
match self {
DataForSeoError::Api(e) => Some(e.status_code),
_ => None,
}
}
}
impl fmt::Display for DataForSeoError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DataForSeoError::Api(e) => write!(
f,
"DataForSEO API error (http {}): {} {}",
e.http_status, e.status_code, e.status_message
),
DataForSeoError::Http(e) => write!(f, "HTTP error {}", e.http_status),
DataForSeoError::System(e) => write!(f, "client error: {}", e.message),
}
}
}
impl std::error::Error for DataForSeoError {}
impl From<DataForSeoApiError> for DataForSeoError {
fn from(value: DataForSeoApiError) -> Self {
DataForSeoError::Api(value)
}
}
impl From<DataForSeoHttpError> for DataForSeoError {
fn from(value: DataForSeoHttpError) -> Self {
DataForSeoError::Http(value)
}
}
impl From<DataForSeoSystemError> for DataForSeoError {
fn from(value: DataForSeoSystemError) -> Self {
DataForSeoError::System(value)
}
}
#[derive(Debug, Clone)]
pub struct DataForSeoApiError {
pub http_status: u16,
pub status_code: i32,
pub status_message: String,
pub response_body: String,
}
impl DataForSeoApiError {
pub(crate) fn from_envelope(http_status: u16, value: &Value, body: String) -> Self {
DataForSeoApiError {
http_status,
status_code: value
.get("status_code")
.and_then(Value::as_i64)
.unwrap_or_default() as i32,
status_message: value
.get("status_message")
.and_then(Value::as_str)
.unwrap_or_default()
.to_string(),
response_body: body,
}
}
}
#[derive(Debug, Clone)]
pub struct DataForSeoHttpError {
pub http_status: u16,
pub response_body: String,
}
impl DataForSeoHttpError {
pub fn new(http_status: u16, response_body: String) -> DataForSeoHttpError {
DataForSeoHttpError {
http_status,
response_body,
}
}
}
#[derive(Debug, Clone)]
pub struct DataForSeoSystemError {
pub message: String,
}
impl DataForSeoSystemError {
pub fn new<T: Into<String>>(message: T) -> DataForSeoSystemError {
DataForSeoSystemError {
message: message.into(),
}
}
}