use std::fmt;
pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = std::result::Result<T, BoxError>;
#[derive(Debug, Default, Copy, Clone)]
pub struct BadVersion;
impl fmt::Display for BadVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Unknown HTTP version")
}
}
impl std::error::Error for BadVersion {}
#[derive(Debug, Default, Copy, Clone)]
pub struct BadHeader;
impl fmt::Display for BadHeader {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Error parsing header value")
}
}
impl std::error::Error for BadHeader {}
#[derive(Debug, Default, Copy, Clone)]
pub struct BadRequest;
impl fmt::Display for BadRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Request object is not cloneable. Are you passing a streaming body?")
}
}
impl std::error::Error for BadRequest {}
#[derive(Debug)]
pub enum HttpCacheError {
Client(BoxError),
Cache(String),
BadRequest(BadRequest),
Http(BoxError),
Body(BoxError),
Streaming(StreamingError),
Other(BoxError),
}
impl HttpCacheError {
pub fn cache<S: Into<String>>(message: S) -> Self {
Self::Cache(message.into())
}
pub fn http<E: Into<BoxError>>(error: E) -> Self {
Self::Http(error.into())
}
pub fn body<E: Into<BoxError>>(error: E) -> Self {
Self::Body(error.into())
}
pub fn client<E: Into<BoxError>>(error: E) -> Self {
Self::Client(error.into())
}
pub fn other<E: Into<BoxError>>(error: E) -> Self {
Self::Other(error.into())
}
pub fn is_cache_error(&self) -> bool {
matches!(self, Self::Cache(_))
}
pub fn is_client_error(&self) -> bool {
matches!(self, Self::Client(_))
}
pub fn is_streaming_error(&self) -> bool {
matches!(self, Self::Streaming(_))
}
pub fn is_bad_request(&self) -> bool {
matches!(self, Self::BadRequest(_))
}
}
impl fmt::Display for HttpCacheError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Client(e) => write!(f, "HTTP client error: {e}"),
Self::Cache(msg) => write!(f, "Cache error: {msg}"),
Self::BadRequest(e) => write!(f, "Request error: {e}"),
Self::Http(e) => write!(f, "HTTP error: {e}"),
Self::Body(e) => write!(f, "Body processing error: {e}"),
Self::Streaming(e) => write!(f, "Streaming error: {e}"),
Self::Other(e) => write!(f, "Other error: {e}"),
}
}
}
impl std::error::Error for HttpCacheError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Client(e) => Some(e.as_ref()),
Self::Cache(_) => None,
Self::BadRequest(e) => Some(e),
Self::Http(e) => Some(e.as_ref()),
Self::Body(e) => Some(e.as_ref()),
Self::Streaming(e) => Some(e),
Self::Other(e) => Some(e.as_ref()),
}
}
}
impl From<BadRequest> for HttpCacheError {
fn from(error: BadRequest) -> Self {
Self::BadRequest(error)
}
}
impl From<BadHeader> for HttpCacheError {
fn from(error: BadHeader) -> Self {
Self::Http(Box::new(error))
}
}
impl From<BadVersion> for HttpCacheError {
fn from(error: BadVersion) -> Self {
Self::Http(Box::new(error))
}
}
impl From<StreamingError> for HttpCacheError {
fn from(error: StreamingError) -> Self {
Self::Streaming(error)
}
}
impl From<BoxError> for HttpCacheError {
fn from(error: BoxError) -> Self {
Self::Other(error)
}
}
impl From<std::io::Error> for HttpCacheError {
fn from(error: std::io::Error) -> Self {
Self::Other(Box::new(error))
}
}
impl From<http::Error> for HttpCacheError {
fn from(error: http::Error) -> Self {
Self::Http(Box::new(error))
}
}
impl From<http::header::InvalidHeaderValue> for HttpCacheError {
fn from(error: http::header::InvalidHeaderValue) -> Self {
Self::Http(Box::new(error))
}
}
impl From<http::header::InvalidHeaderName> for HttpCacheError {
fn from(error: http::header::InvalidHeaderName) -> Self {
Self::Http(Box::new(error))
}
}
impl From<http::uri::InvalidUri> for HttpCacheError {
fn from(error: http::uri::InvalidUri) -> Self {
Self::Http(Box::new(error))
}
}
impl From<http::method::InvalidMethod> for HttpCacheError {
fn from(error: http::method::InvalidMethod) -> Self {
Self::Http(Box::new(error))
}
}
impl From<http::status::InvalidStatusCode> for HttpCacheError {
fn from(error: http::status::InvalidStatusCode) -> Self {
Self::Http(Box::new(error))
}
}
impl From<url::ParseError> for HttpCacheError {
fn from(error: url::ParseError) -> Self {
Self::Http(Box::new(error))
}
}
pub type HttpCacheResult<T> = std::result::Result<T, HttpCacheError>;
#[derive(Debug)]
pub struct StreamingError {
inner: BoxError,
kind: StreamingErrorKind,
}
#[derive(Debug, Clone, Copy)]
pub enum StreamingErrorKind {
Io,
Serialization,
Concurrency,
Consistency,
TempFile,
ContentAddressing,
Client,
Other,
}
impl StreamingError {
pub fn new<E: Into<BoxError>>(error: E) -> Self {
Self { inner: error.into(), kind: StreamingErrorKind::Other }
}
pub fn with_kind<E: Into<BoxError>>(
error: E,
kind: StreamingErrorKind,
) -> Self {
Self { inner: error.into(), kind }
}
pub fn io<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::Io)
}
pub fn serialization<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::Serialization)
}
pub fn concurrency<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::Concurrency)
}
pub fn consistency<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::Consistency)
}
pub fn temp_file<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::TempFile)
}
pub fn content_addressing<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::ContentAddressing)
}
pub fn client<E: Into<BoxError>>(error: E) -> Self {
Self::with_kind(error, StreamingErrorKind::Client)
}
pub fn kind(&self) -> &StreamingErrorKind {
&self.kind
}
}
impl fmt::Display for StreamingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Streaming error: {}", self.inner)
}
}
impl std::error::Error for StreamingError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.inner)
}
}
impl From<BoxError> for StreamingError {
fn from(error: BoxError) -> Self {
Self::new(error)
}
}
impl From<std::convert::Infallible> for StreamingError {
fn from(never: std::convert::Infallible) -> Self {
match never {}
}
}
impl From<std::io::Error> for StreamingError {
fn from(error: std::io::Error) -> Self {
Self::new(error)
}
}
impl From<HttpCacheError> for StreamingError {
fn from(error: HttpCacheError) -> Self {
match error {
HttpCacheError::Streaming(streaming_err) => streaming_err,
_ => Self::new(Box::new(error)),
}
}
}
#[derive(Debug)]
pub enum ClientStreamingError {
Client {
client: String,
error: BoxError,
},
HttpCache(StreamingError),
Other(BoxError),
}
impl ClientStreamingError {
pub fn client<C, E>(client: C, error: E) -> Self
where
C: Into<String>,
E: Into<BoxError>,
{
Self::Client { client: client.into(), error: error.into() }
}
pub fn http_cache(error: StreamingError) -> Self {
Self::HttpCache(error)
}
pub fn other<E: Into<BoxError>>(error: E) -> Self {
Self::Other(error.into())
}
}
impl fmt::Display for ClientStreamingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Client { client, error } => {
write!(f, "{} streaming error: {}", client, error)
}
Self::HttpCache(e) => {
write!(f, "HTTP cache streaming error: {}", e)
}
Self::Other(e) => write!(f, "Streaming error: {}", e),
}
}
}
impl std::error::Error for ClientStreamingError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Client { error, .. } => Some(error.as_ref()),
Self::HttpCache(e) => Some(e),
Self::Other(e) => Some(e.as_ref()),
}
}
}
impl From<StreamingError> for ClientStreamingError {
fn from(error: StreamingError) -> Self {
Self::HttpCache(error)
}
}
impl From<BoxError> for ClientStreamingError {
fn from(error: BoxError) -> Self {
Self::Other(error)
}
}
impl From<ClientStreamingError> for HttpCacheError {
fn from(error: ClientStreamingError) -> Self {
match error {
ClientStreamingError::HttpCache(streaming_err) => {
Self::Streaming(streaming_err)
}
ClientStreamingError::Client { error, .. } => Self::Client(error),
ClientStreamingError::Other(error) => Self::Other(error),
}
}
}
impl From<ClientStreamingError> for StreamingError {
fn from(error: ClientStreamingError) -> Self {
match error {
ClientStreamingError::HttpCache(streaming_err) => streaming_err,
ClientStreamingError::Client { client, error } => {
let client_error =
format!("Client '{}' error: {}", client, error);
Self::client(client_error)
}
ClientStreamingError::Other(error) => Self::new(error),
}
}
}