use std::fmt::{self, Display};
use std::io;
use failure::{Fail, Context, Backtrace};
use internals::error::EncodingError;
use headers::error::{
BuildInValidationError,
HeaderTypeError, ComponentCreationError,
HeaderValidationError
};
use ::IRI;
#[derive(Debug, Fail)]
pub enum ResourceError {
#[fail(display = "{}", _0)]
Loading(ResourceLoadingError),
#[fail(display = "{}", _0)]
Encoding(EncodingError)
}
impl From<EncodingError> for ResourceError {
fn from(err: EncodingError) -> Self {
ResourceError::Encoding(err)
}
}
impl From<ResourceLoadingError> for ResourceError {
fn from(err: ResourceLoadingError) -> Self {
ResourceError::Loading(err)
}
}
#[derive(Copy, Clone, Debug, Fail, PartialEq, Eq, Hash)]
pub enum ResourceLoadingErrorKind {
#[fail(display = "resource not found")]
NotFound,
#[fail(display = "loading failed")]
LoadingFailed,
#[fail(display = "automatically detecting the media type failed")]
MediaTypeDetectionFailed
}
#[derive(Debug)]
pub struct ResourceLoadingError {
inner: Context<ResourceLoadingErrorKind>,
iri: Option<IRI>
}
impl Display for ResourceLoadingError {
fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.inner, fter)
}
}
impl Fail for ResourceLoadingError {
fn cause(&self) -> Option<&Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl ResourceLoadingError {
pub fn kind(&self) -> ResourceLoadingErrorKind {
*self.inner.get_context()
}
pub fn source_iri(&self) -> Option<&IRI> {
self.iri.as_ref()
}
pub fn with_source_iri_or_else<F>(mut self, func: F) -> Self
where F: FnOnce() -> Option<IRI>
{
if self.iri.is_none() {
self.iri = func();
}
self
}
}
impl From<ResourceLoadingErrorKind> for ResourceLoadingError {
fn from(err: ResourceLoadingErrorKind) -> Self {
ResourceLoadingError::from((None, err))
}
}
impl From<Context<ResourceLoadingErrorKind>> for ResourceLoadingError {
fn from(inner: Context<ResourceLoadingErrorKind>) -> Self {
ResourceLoadingError::from((None, inner))
}
}
impl From<(IRI, ResourceLoadingErrorKind)> for ResourceLoadingError {
fn from((iri, error_kind): (IRI, ResourceLoadingErrorKind)) -> Self {
ResourceLoadingError::from((Some(iri), error_kind))
}
}
impl From<(IRI, Context<ResourceLoadingErrorKind>)> for ResourceLoadingError {
fn from((iri, inner): (IRI, Context<ResourceLoadingErrorKind>)) -> Self {
ResourceLoadingError::from((Some(iri), inner))
}
}
impl From<(Option<IRI>, ResourceLoadingErrorKind)> for ResourceLoadingError {
fn from((iri, error_kind): (Option<IRI>, ResourceLoadingErrorKind)) -> Self {
ResourceLoadingError::from((iri, Context::new(error_kind)))
}
}
impl From<(Option<IRI>, Context<ResourceLoadingErrorKind>)> for ResourceLoadingError {
fn from((iri, inner): (Option<IRI>, Context<ResourceLoadingErrorKind>)) -> Self {
ResourceLoadingError {
inner, iri
}
}
}
impl From<io::Error> for ResourceLoadingError {
fn from(err: io::Error) -> Self {
err.context(ResourceLoadingErrorKind::LoadingFailed).into()
}
}
#[derive(Debug, Fail)]
pub enum OtherValidationError {
#[fail(display = "Content-Type header given for non multipart mail")]
ContentTypeHeaderGiven,
#[fail(display = "Content-Transfer-Encoding header given")]
ContentTransferEncodingHeaderGiven,
#[fail(display = "found non multipart content type in multipart mail")]
SingleMultipartMixup,
#[fail(display = "inserting Content-Type for singlepart body is not allowed")]
InsertSinglepartContentTypeHeader,
#[fail(display = "multipart mail does not contain a content type header")]
MissingContentTypeHeader,
#[fail(display = "mail did not contain a From header")]
NoFrom
}
impl From<OtherValidationError> for HeaderValidationError {
fn from(oe: OtherValidationError) -> Self {
let err: ::failure::Error = oe.into();
HeaderValidationError::Custom(err)
}
}
impl From<OtherValidationError> for MailError {
fn from(oe: OtherValidationError) -> Self {
let val_err = HeaderValidationError::from(oe);
MailError::from(val_err)
}
}
#[derive(Debug, Fail)]
pub enum MailError {
#[fail(display = "{}", _0)]
Encoding(EncodingError),
#[fail(display = "{}", _0)]
Type(HeaderTypeError),
#[fail(display = "{}", _0)]
Component(ComponentCreationError),
#[fail(display = "{}", _0)]
Validation(HeaderValidationError),
#[fail(display = "{}", _0)]
ResourceLoading(ResourceLoadingError)
}
impl From<BuildInValidationError> for MailError {
fn from(err: BuildInValidationError) -> Self {
MailError::Validation(err.into())
}
}
impl From<HeaderTypeError> for MailError {
fn from(err: HeaderTypeError) -> Self {
MailError::Type(err)
}
}
impl From<EncodingError> for MailError {
fn from(err: EncodingError) -> Self {
MailError::Encoding(err)
}
}
impl From<HeaderValidationError> for MailError {
fn from(err: HeaderValidationError) -> Self {
MailError::Validation(err)
}
}
impl From<ResourceLoadingError> for MailError {
fn from(err: ResourceLoadingError) -> Self {
MailError::ResourceLoading(err)
}
}
impl From<ResourceError> for MailError {
fn from(err: ResourceError) -> Self {
match err {
ResourceError::Loading(err) => MailError::ResourceLoading(err),
ResourceError::Encoding(err) => MailError::Encoding(err)
}
}
}
impl From<ComponentCreationError> for MailError {
fn from(err: ComponentCreationError) -> Self {
MailError::Component(err)
}
}
#[derive(Copy, Clone, Debug, Fail)]
pub enum ResourceNotUnloadableError {
#[fail(display = "resource is in use, can't unload it")]
InUse,
#[fail(display = "resource has no source, can't unload it")]
NoSource
}