1use std::fmt::{self, Display};
3use std::io;
4
5use failure::{Fail, Context, Backtrace};
6
7use internals::error::EncodingError;
8use headers::error::{
9 BuildInValidationError,
10 HeaderTypeError, ComponentCreationError,
11 HeaderValidationError
12};
13use ::IRI;
14#[derive(Debug, Fail)]
23pub enum ResourceError {
24 #[fail(display = "{}", _0)]
26 Loading(ResourceLoadingError),
27
28 #[fail(display = "{}", _0)]
34 Encoding(EncodingError)
35}
36
37impl From<EncodingError> for ResourceError {
38 fn from(err: EncodingError) -> Self {
39 ResourceError::Encoding(err)
40 }
41}
42
43impl From<ResourceLoadingError> for ResourceError {
44 fn from(err: ResourceLoadingError) -> Self {
45 ResourceError::Loading(err)
46 }
47}
48
49#[derive(Copy, Clone, Debug, Fail, PartialEq, Eq, Hash)]
51pub enum ResourceLoadingErrorKind {
52 #[fail(display = "resource not found")]
54 NotFound,
55
56 #[fail(display = "loading failed")]
58 LoadingFailed,
59
60 #[fail(display = "automatically detecting the media type failed")]
61 MediaTypeDetectionFailed
62}
63
64#[derive(Debug)]
66pub struct ResourceLoadingError {
67 inner: Context<ResourceLoadingErrorKind>,
68 iri: Option<IRI>
69}
70
71impl Display for ResourceLoadingError {
72 fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
73 Display::fmt(&self.inner, fter)
74 }
75}
76
77impl Fail for ResourceLoadingError {
78 fn cause(&self) -> Option<&Fail> {
79 self.inner.cause()
80 }
81
82 fn backtrace(&self) -> Option<&Backtrace> {
83 self.inner.backtrace()
84 }
85}
86
87impl ResourceLoadingError {
88
89 pub fn kind(&self) -> ResourceLoadingErrorKind {
91 *self.inner.get_context()
92 }
93
94 pub fn source_iri(&self) -> Option<&IRI> {
96 self.iri.as_ref()
97 }
98
99 pub fn with_source_iri_or_else<F>(mut self, func: F) -> Self
101 where F: FnOnce() -> Option<IRI>
102 {
103 if self.iri.is_none() {
104 self.iri = func();
105 }
106 self
107 }
108}
109
110impl From<ResourceLoadingErrorKind> for ResourceLoadingError {
111 fn from(err: ResourceLoadingErrorKind) -> Self {
112 ResourceLoadingError::from((None, err))
113 }
114}
115
116impl From<Context<ResourceLoadingErrorKind>> for ResourceLoadingError {
117 fn from(inner: Context<ResourceLoadingErrorKind>) -> Self {
118 ResourceLoadingError::from((None, inner))
119 }
120}
121
122impl From<(IRI, ResourceLoadingErrorKind)> for ResourceLoadingError {
123 fn from((iri, error_kind): (IRI, ResourceLoadingErrorKind)) -> Self {
124 ResourceLoadingError::from((Some(iri), error_kind))
125 }
126}
127
128impl From<(IRI, Context<ResourceLoadingErrorKind>)> for ResourceLoadingError {
129 fn from((iri, inner): (IRI, Context<ResourceLoadingErrorKind>)) -> Self {
130 ResourceLoadingError::from((Some(iri), inner))
131 }
132}
133
134impl From<(Option<IRI>, ResourceLoadingErrorKind)> for ResourceLoadingError {
135 fn from((iri, error_kind): (Option<IRI>, ResourceLoadingErrorKind)) -> Self {
136 ResourceLoadingError::from((iri, Context::new(error_kind)))
137 }
138}
139
140impl From<(Option<IRI>, Context<ResourceLoadingErrorKind>)> for ResourceLoadingError {
141 fn from((iri, inner): (Option<IRI>, Context<ResourceLoadingErrorKind>)) -> Self {
142 ResourceLoadingError {
143 inner, iri
144 }
145 }
146}
147
148impl From<io::Error> for ResourceLoadingError {
149 fn from(err: io::Error) -> Self {
150 err.context(ResourceLoadingErrorKind::LoadingFailed).into()
151 }
152}
153
154
155#[derive(Debug, Fail)]
156pub enum OtherValidationError {
157 #[fail(display = "Content-Type header given for non multipart mail")]
161 ContentTypeHeaderGiven,
162
163 #[fail(display = "Content-Transfer-Encoding header given")]
166 ContentTransferEncodingHeaderGiven,
167
168 #[fail(display = "found non multipart content type in multipart mail")]
170 SingleMultipartMixup,
171
172 #[fail(display = "inserting Content-Type for singlepart body is not allowed")]
177 InsertSinglepartContentTypeHeader,
178
179 #[fail(display = "multipart mail does not contain a content type header")]
181 MissingContentTypeHeader,
182
183 #[fail(display = "mail did not contain a From header")]
185 NoFrom
186}
187
188impl From<OtherValidationError> for HeaderValidationError {
189 fn from(oe: OtherValidationError) -> Self {
190 let err: ::failure::Error = oe.into();
191 HeaderValidationError::Custom(err)
192 }
193}
194
195impl From<OtherValidationError> for MailError {
196 fn from(oe: OtherValidationError) -> Self {
197 let val_err = HeaderValidationError::from(oe);
198 MailError::from(val_err)
199 }
200}
201
202#[derive(Debug, Fail)]
204pub enum MailError {
205 #[fail(display = "{}", _0)]
207 Encoding(EncodingError),
208
209 #[fail(display = "{}", _0)]
211 Type(HeaderTypeError),
212
213 #[fail(display = "{}", _0)]
215 Component(ComponentCreationError),
216
217 #[fail(display = "{}", _0)]
223 Validation(HeaderValidationError),
224
225 #[fail(display = "{}", _0)]
230 ResourceLoading(ResourceLoadingError)
231}
232
233impl From<BuildInValidationError> for MailError {
234 fn from(err: BuildInValidationError) -> Self {
235 MailError::Validation(err.into())
236 }
237}
238
239impl From<HeaderTypeError> for MailError {
240 fn from(err: HeaderTypeError) -> Self {
241 MailError::Type(err)
242 }
243}
244
245impl From<EncodingError> for MailError {
246 fn from(err: EncodingError) -> Self {
247 MailError::Encoding(err)
248 }
249}
250
251
252impl From<HeaderValidationError> for MailError {
253 fn from(err: HeaderValidationError) -> Self {
254 MailError::Validation(err)
255 }
256}
257
258impl From<ResourceLoadingError> for MailError {
259 fn from(err: ResourceLoadingError) -> Self {
260 MailError::ResourceLoading(err)
261 }
262}
263
264impl From<ResourceError> for MailError {
265 fn from(err: ResourceError) -> Self {
266 match err {
267 ResourceError::Loading(err) => MailError::ResourceLoading(err),
268 ResourceError::Encoding(err) => MailError::Encoding(err)
269 }
270 }
271}
272
273impl From<ComponentCreationError> for MailError {
274 fn from(err: ComponentCreationError) -> Self {
275 MailError::Component(err)
276 }
277}
278
279
280#[derive(Copy, Clone, Debug, Fail)]
282pub enum ResourceNotUnloadableError {
283 #[fail(display = "resource is in use, can't unload it")]
285 InUse,
286 #[fail(display = "resource has no source, can't unload it")]
292 NoSource
293}