use crate::macros::impl_display_for_serialize;
use std::fmt::Display;
#[derive(Debug, thiserror::Error)]
pub enum ClientError {
#[error("HTTP request error: {0:?}")]
HttpRequestError(reqwest::Error),
#[error("Reading response text failed: {0:?}")]
ReadResponseTextFailed(reqwest::Error),
#[error("Failed to deserialize response as JSON: {error:?}, {text:?}")]
ResponseDeserializationFailed {
error: serde_json::Error,
text: String,
},
#[error(
"Failed to deserialize error response as JSON: {error:?}, {text:?}"
)]
ErrorResponseDeserializationFailed {
error: serde_json::Error,
text: String,
},
}
#[derive(Debug, thiserror::Error)]
pub struct ApiError {
pub status_code: reqwest::StatusCode,
pub error_response: ErrorResponse,
}
impl Display for ApiError {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(
f,
"API error with status code: {}, error: {}",
self.status_code, self.error_response,
)
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct ErrorResponse {
#[serde(rename = "error")]
pub error: ApiErrorBody,
}
impl_display_for_serialize!(ErrorResponse);
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct ApiErrorBody {
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub param: Option<String>,
#[serde(rename = "type")]
pub _type: String,
}
impl_display_for_serialize!(ApiErrorBody);
#[derive(Debug, thiserror::Error)]
pub struct ValidationError<T>
where
T: Display,
{
pub type_name: String,
pub reason: String,
pub value: T,
}
impl<T> Display for ValidationError<T>
where
T: Display,
{
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(
f,
"Validation error, type: {}, reason: {}, value: {}",
self.type_name, self.reason, self.value,
)
}
}