use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ServerError {
pub message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub documentation_url: Option<String>,
}
#[derive(Debug, thiserror::Error)]
pub enum ApiError {
#[error("transport error: {0}")]
Transport(#[from] reqwest::Error),
#[error("server returned status {status}{}", body.as_ref().map(|b| format!(": {}", b.message)).unwrap_or_default())]
Status {
status: u16,
lfs_authenticate: Option<String>,
body: Option<ServerError>,
},
#[error("malformed response body: {0}")]
Decode(String),
#[error("url error: {0}")]
Url(#[from] url::ParseError),
}
impl ApiError {
pub fn is_unauthorized(&self) -> bool {
matches!(self, ApiError::Status { status: 401, .. })
}
pub fn is_forbidden(&self) -> bool {
matches!(self, ApiError::Status { status: 403, .. })
}
pub fn is_not_found(&self) -> bool {
matches!(self, ApiError::Status { status: 404, .. })
}
pub fn is_retryable(&self) -> bool {
matches!(
self,
ApiError::Transport(_)
| ApiError::Status { status: 408 | 429 | 500..=599, .. }
)
}
}