use failure::{Backtrace, Context, Fail};
use std::fmt;
#[derive(Debug)]
pub struct FTPError {
inner: Context<FTPErrorKind>,
}
#[derive(Eq, PartialEq, Debug, Fail)]
pub enum FTPErrorKind {
#[fail(display = "Failed to perform IO")]
IOError,
#[fail(display = "Failed to parse command")]
ParseError,
#[fail(display = "Internal Server Error")]
InternalServerError,
#[fail(display = "Something went wrong when trying to authenticate")]
AuthenticationError,
#[fail(display = "Failed to map event from data channel")]
InternalMsgError,
#[fail(display = "Non-UTF8 character in command")]
UTF8Error,
#[fail(display = "Unknown command: {}", command)]
UnknownCommand {
command: String,
},
#[fail(display = "Invalid command (invalid parameter)")]
InvalidCommand,
#[fail(display = "Encountered timer error on the control channel")]
ControlChannelTimerError,
}
impl FTPError {
#[allow(unused)]
pub fn kind(&self) -> &FTPErrorKind {
self.inner.get_context()
}
}
impl Fail for FTPError {
fn cause(&self) -> Option<&dyn Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl fmt::Display for FTPError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
impl From<FTPErrorKind> for FTPError {
fn from(kind: FTPErrorKind) -> FTPError {
FTPError { inner: Context::new(kind) }
}
}
impl From<Context<FTPErrorKind>> for FTPError {
fn from(inner: Context<FTPErrorKind>) -> FTPError {
FTPError { inner }
}
}
impl From<std::io::Error> for FTPError {
fn from(err: std::io::Error) -> FTPError {
err.context(FTPErrorKind::IOError).into()
}
}
impl From<std::str::Utf8Error> for FTPError {
fn from(err: std::str::Utf8Error) -> FTPError {
err.context(FTPErrorKind::UTF8Error).into()
}
}
impl<'a, T> From<std::sync::PoisonError<std::sync::MutexGuard<'a, T>>> for FTPError {
fn from(_err: std::sync::PoisonError<std::sync::MutexGuard<'a, T>>) -> FTPError {
FTPError {
inner: Context::new(FTPErrorKind::InternalServerError),
}
}
}