use std::time::Duration;
mod api_error;
mod envelope;
mod retry_after;
#[cfg(test)]
mod tests;
pub use api_error::{ApiError, ApiErrorKind};
pub use retry_after::parse_retry_after;
pub(crate) use retry_after::parse_retry_after_with;
pub(crate) use retry_after::REQUEST_ID_HEADER;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("{0}")]
Api(#[from] Box<ApiError>),
#[error("connection error: {0}")]
Connection(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("request timed out after {timeout:?}")]
Timeout {
timeout: Duration,
},
#[error("response body exceeded the {limit}-byte limit")]
ResponseTooLarge {
limit: usize,
},
#[error("failed to decode response body (status {status}): {source}")]
Decode {
status: u16,
body_excerpt: String,
#[source]
source: serde_json::Error,
},
#[error("invalid response: {source}")]
InvalidResponse {
#[source]
source: openkind_core::ValidationError,
},
#[error("invalid client configuration: {0}")]
Config(String),
}
impl Error {
pub fn status(&self) -> Option<u16> {
match self {
Error::Api(api) => Some(api.status),
_ => None,
}
}
pub fn retry_after(&self) -> Option<Duration> {
match self {
Error::Api(api) => api.retry_after,
_ => None,
}
}
pub fn request_id(&self) -> Option<&str> {
match self {
Error::Api(api) => api.request_id.as_deref(),
_ => None,
}
}
pub fn kind(&self) -> Option<ApiErrorKind> {
match self {
Error::Api(api) => Some(api.kind()),
_ => None,
}
}
}