use bytes::Bytes;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Http(#[from] CanopyHttpError),
#[error("decoding the response of {path}: {source}")]
Decode {
path: String,
source: serde_json::Error,
},
#[error("encoding the request body for {path}: {source}")]
Encode {
path: String,
source: serde_json::Error,
},
#[error("building the request for {path}: {source}")]
Request {
path: String,
source: http::Error,
},
#[error("compressing the request body for {path}: {source}")]
Compress {
path: String,
source: std::io::Error,
},
#[error("reaching canopy: {0}")]
Transport(#[source] Box<dyn std::error::Error + Send + Sync>),
}
impl Error {
pub fn transport<E: std::error::Error + Send + Sync + 'static>(err: E) -> Self {
Self::Transport(Box::new(err))
}
pub fn http(&self) -> Option<&CanopyHttpError> {
match self {
Self::Http(err) => Some(err),
_ => None,
}
}
pub fn status(&self) -> Option<http::StatusCode> {
self.http().map(|err| err.status)
}
}
#[derive(Debug, thiserror::Error)]
#[error("canopy returned {status} for {path}")]
pub struct CanopyHttpError {
pub status: http::StatusCode,
pub path: String,
pub body: Bytes,
}
impl CanopyHttpError {
pub fn body_text(&self) -> std::borrow::Cow<'_, str> {
String::from_utf8_lossy(&self.body)
}
}