#![allow(deprecated)]
use std::error::Error as StdError;
use std::fmt;
use std::io;
#[derive(Debug)]
pub enum Error {
Aborted,
BadClientCertificate(Option<String>),
BadServerCertificate(Option<String>),
ConnectFailed,
CouldntResolveHost,
CouldntResolveProxy,
Curl(String),
InvalidContentEncoding(Option<String>),
InvalidCredentials,
InvalidHttpFormat(http::Error),
InvalidUtf8,
Io(io::Error),
NoResponse,
RangeRequestUnsupported,
RequestBodyError(Option<String>),
ResponseBodyError(Option<String>),
SSLConnectFailed(Option<String>),
SSLEngineError(Option<String>),
Timeout,
TooManyRedirects,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}: {}", self, Error::description(self))
}
}
impl StdError for Error {
fn description(&self) -> &str {
match self {
Error::Aborted => "request aborted unexpectedly",
Error::BadClientCertificate(Some(ref e)) => e,
Error::BadServerCertificate(Some(ref e)) => e,
Error::ConnectFailed => "failed to connect to the server",
Error::CouldntResolveHost => "couldn't resolve host name",
Error::CouldntResolveProxy => "couldn't resolve proxy host name",
Error::Curl(ref e) => e,
Error::InvalidContentEncoding(Some(ref e)) => e,
Error::InvalidCredentials => "credentials were rejected by the server",
Error::InvalidHttpFormat(ref e) => e.description(),
Error::InvalidUtf8 => "bytes are not valid UTF-8",
Error::Io(ref e) => e.description(),
Error::NoResponse => "server did not send a response",
Error::RangeRequestUnsupported => "server does not support or accept range requests",
Error::RequestBodyError(Some(ref e)) => e,
Error::ResponseBodyError(Some(ref e)) => e,
Error::SSLConnectFailed(Some(ref e)) => e,
Error::SSLEngineError(Some(ref e)) => e,
Error::Timeout => "request took longer than the configured timeout",
Error::TooManyRedirects => "max redirect limit exceeded",
_ => "unknown error",
}
}
fn cause(&self) -> Option<&dyn StdError> {
match self {
Error::InvalidHttpFormat(e) => Some(e),
Error::Io(e) => Some(e),
_ => None,
}
}
}
#[doc(hidden)]
impl From<curl::Error> for Error {
fn from(error: curl::Error) -> Error {
if error.is_ssl_certproblem() || error.is_ssl_cacert_badfile() {
Error::BadClientCertificate(error.extra_description().map(str::to_owned))
} else if error.is_peer_failed_verification() || error.is_ssl_cacert() {
Error::BadServerCertificate(error.extra_description().map(str::to_owned))
} else if error.is_couldnt_connect() {
Error::ConnectFailed
} else if error.is_couldnt_resolve_host() {
Error::CouldntResolveHost
} else if error.is_couldnt_resolve_proxy() {
Error::CouldntResolveProxy
} else if error.is_bad_content_encoding() || error.is_conv_failed() {
Error::InvalidContentEncoding(error.extra_description().map(str::to_owned))
} else if error.is_login_denied() {
Error::InvalidCredentials
} else if error.is_got_nothing() {
Error::NoResponse
} else if error.is_range_error() {
Error::RangeRequestUnsupported
} else if error.is_read_error() || error.is_aborted_by_callback() {
Error::RequestBodyError(error.extra_description().map(str::to_owned))
} else if error.is_write_error() || error.is_partial_file() {
Error::ResponseBodyError(error.extra_description().map(str::to_owned))
} else if error.is_ssl_connect_error() {
Error::SSLConnectFailed(error.extra_description().map(str::to_owned))
} else if error.is_ssl_engine_initfailed()
|| error.is_ssl_engine_notfound()
|| error.is_ssl_engine_setfailed()
{
Error::SSLEngineError(error.extra_description().map(str::to_owned))
} else if error.is_operation_timedout() {
Error::Timeout
} else if error.is_too_many_redirects() {
Error::TooManyRedirects
} else {
Error::Curl(error.description().to_owned())
}
}
}
#[doc(hidden)]
impl From<curl::MultiError> for Error {
fn from(error: curl::MultiError) -> Error {
Error::Curl(error.description().to_owned())
}
}
#[doc(hidden)]
impl From<http::Error> for Error {
fn from(error: http::Error) -> Error {
Error::InvalidHttpFormat(error)
}
}
#[doc(hidden)]
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
match error.kind() {
io::ErrorKind::ConnectionRefused => Error::ConnectFailed,
io::ErrorKind::TimedOut => Error::Timeout,
_ => Error::Io(error),
}
}
}
#[doc(hidden)]
impl From<Error> for io::Error {
fn from(error: Error) -> io::Error {
match error {
Error::ConnectFailed => io::ErrorKind::ConnectionRefused.into(),
Error::Io(e) => e,
Error::Timeout => io::ErrorKind::TimedOut.into(),
e => io::Error::new(io::ErrorKind::Other, e),
}
}
}
#[doc(hidden)]
impl From<std::string::FromUtf8Error> for Error {
fn from(_: std::string::FromUtf8Error) -> Error {
Error::InvalidUtf8
}
}
#[doc(hidden)]
impl From<std::str::Utf8Error> for Error {
fn from(_: std::str::Utf8Error) -> Error {
Error::InvalidUtf8
}
}