use serde_json::Value;
use thiserror::Error;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug, Error)]
pub enum Error {
#[error("[{status}] {method}: {summary}", summary = .message.as_deref().or(.error.as_deref()).unwrap_or("no message"))]
Api {
status: u16,
method: String,
error: Option<String>,
message: Option<String>,
body: Option<Value>,
},
#[error("transport error calling {method}: {source}")]
Transport {
method: String,
#[source]
source: reqwest::Error,
},
#[error("json error in {method}: {source}")]
Json {
method: String,
#[source]
source: serde_json::Error,
},
#[error("invalid configuration: {0}")]
InvalidConfig(String),
#[error("[401] {method}: missing token — call ClientBuilder::token(...) or Client::set_token(...)")]
MissingToken { method: String },
}
impl Error {
pub fn status(&self) -> Option<u16> {
match self {
Error::Api { status, .. } => Some(*status),
Error::MissingToken { .. } => Some(401),
_ => None,
}
}
pub fn is_client_error(&self) -> bool {
matches!(self.status(), Some(s) if (400..500).contains(&s))
}
pub fn is_server_error(&self) -> bool {
matches!(self.status(), Some(s) if (500..600).contains(&s))
}
pub fn is_unauthorized(&self) -> bool {
matches!(self.status(), Some(401))
}
pub fn is_forbidden(&self) -> bool {
matches!(self.status(), Some(403))
}
pub fn is_not_found(&self) -> bool {
matches!(self.status(), Some(404))
}
pub fn is_rate_limited(&self) -> bool {
matches!(self.status(), Some(429))
}
}