use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;
#[cfg(feature = "tls")]
use std::net::TcpStream;
use std::result;
use std::str::Utf8Error;
use base64::DecodeError;
use bufstream::IntoInnerError as BufError;
use imap_proto::Response;
#[cfg(feature = "tls")]
use native_tls::Error as TlsError;
#[cfg(feature = "tls")]
use native_tls::HandshakeError as TlsHandshakeError;
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
Io(IoError),
#[cfg(feature = "tls")]
TlsHandshake(TlsHandshakeError<TcpStream>),
#[cfg(feature = "tls")]
Tls(TlsError),
Bad(String),
No(String),
ConnectionLost,
Parse(ParseError),
Validate(ValidateError),
Append,
#[doc(hidden)]
__Nonexhaustive,
}
impl From<IoError> for Error {
fn from(err: IoError) -> Error {
Error::Io(err)
}
}
impl From<ParseError> for Error {
fn from(err: ParseError) -> Error {
Error::Parse(err)
}
}
impl<T> From<BufError<T>> for Error {
fn from(err: BufError<T>) -> Error {
Error::Io(err.into())
}
}
#[cfg(feature = "tls")]
impl From<TlsHandshakeError<TcpStream>> for Error {
fn from(err: TlsHandshakeError<TcpStream>) -> Error {
Error::TlsHandshake(err)
}
}
#[cfg(feature = "tls")]
impl From<TlsError> for Error {
fn from(err: TlsError) -> Error {
Error::Tls(err)
}
}
impl<'a> From<Response<'a>> for Error {
fn from(err: Response<'a>) -> Error {
Error::Parse(ParseError::Unexpected(format!("{:?}", err)))
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::Io(ref e) => fmt::Display::fmt(e, f),
#[cfg(feature = "tls")]
Error::Tls(ref e) => fmt::Display::fmt(e, f),
#[cfg(feature = "tls")]
Error::TlsHandshake(ref e) => fmt::Display::fmt(e, f),
Error::Validate(ref e) => fmt::Display::fmt(e, f),
Error::Parse(ref e) => fmt::Display::fmt(e, f),
Error::No(ref data) => write!(f, "No Response: {}", data),
Error::Bad(ref data) => write!(f, "Bad Response: {}", data),
Error::ConnectionLost => f.write_str("Connection Lost"),
Error::Append => f.write_str("Could not append mail to mailbox"),
Error::__Nonexhaustive => f.write_str("Unknown"),
}
}
}
impl StdError for Error {
#[allow(deprecated)]
fn description(&self) -> &str {
match *self {
Error::Io(ref e) => e.description(),
#[cfg(feature = "tls")]
Error::Tls(ref e) => e.description(),
#[cfg(feature = "tls")]
Error::TlsHandshake(ref e) => e.description(),
Error::Parse(ref e) => e.description(),
Error::Validate(ref e) => e.description(),
Error::Bad(_) => "Bad Response",
Error::No(_) => "No Response",
Error::ConnectionLost => "Connection lost",
Error::Append => "Could not append mail to mailbox",
Error::__Nonexhaustive => "Unknown",
}
}
fn cause(&self) -> Option<&dyn StdError> {
match *self {
Error::Io(ref e) => Some(e),
#[cfg(feature = "tls")]
Error::Tls(ref e) => Some(e),
#[cfg(feature = "tls")]
Error::TlsHandshake(ref e) => Some(e),
Error::Parse(ParseError::DataNotUtf8(_, ref e)) => Some(e),
_ => None,
}
}
}
#[derive(Debug)]
pub enum ParseError {
Invalid(Vec<u8>),
Unexpected(String),
Authentication(String, Option<DecodeError>),
DataNotUtf8(Vec<u8>, Utf8Error),
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ParseError::Invalid(_) => f.write_str("Unable to parse status response"),
ParseError::Unexpected(_) => f.write_str("Encountered unexpected parse response"),
ParseError::Authentication(_, _) => {
f.write_str("Unable to parse authentication response")
}
ParseError::DataNotUtf8(_, _) => f.write_str("Unable to parse data as UTF-8 text"),
}
}
}
impl StdError for ParseError {
fn description(&self) -> &str {
match *self {
ParseError::Invalid(_) => "Unable to parse status response",
ParseError::Unexpected(_) => "Encountered unexpected parsed response",
ParseError::Authentication(_, _) => "Unable to parse authentication response",
ParseError::DataNotUtf8(_, _) => "Unable to parse data as UTF-8 text",
}
}
fn cause(&self) -> Option<&dyn StdError> {
match *self {
ParseError::Authentication(_, Some(ref e)) => Some(e),
_ => None,
}
}
}
#[derive(Debug)]
pub struct ValidateError(pub char);
impl fmt::Display for ValidateError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Invalid character in input: {:?}", self.0)
}
}
impl StdError for ValidateError {
fn description(&self) -> &str {
"Invalid character in input"
}
fn cause(&self) -> Option<&dyn StdError> {
None
}
}