|
1 | 1 | //! IMAP error types.
|
2 | 2 |
|
3 |
| -use std::error::Error as StdError; |
4 |
| -use std::fmt; |
5 | 3 | use std::io::Error as IoError;
|
6 | 4 | use std::result;
|
7 | 5 | use std::str::Utf8Error;
|
8 | 6 |
|
9 | 7 | use base64::DecodeError;
|
10 |
| -use imap_proto::Response; |
11 | 8 |
|
12 | 9 | /// A convenience wrapper around `Result` for `imap::Error`.
|
13 | 10 | pub type Result<T> = result::Result<T, Error>;
|
14 | 11 |
|
15 | 12 | /// A set of errors that can occur in the IMAP client
|
16 |
| -#[derive(Debug)] |
| 13 | +#[derive(thiserror::Error, Debug)] |
17 | 14 | pub enum Error {
|
18 | 15 | /// An `io::Error` that occurred while trying to read or write to a network stream.
|
19 |
| - Io(IoError), |
| 16 | + #[error("io: {0}")] |
| 17 | + Io(#[from] IoError), |
20 | 18 | /// A BAD response from the IMAP server.
|
| 19 | + #[error("bad response: {0}")] |
21 | 20 | Bad(String),
|
22 | 21 | /// A NO response from the IMAP server.
|
| 22 | + #[error("no response: {0}")] |
23 | 23 | No(String),
|
24 | 24 | /// The connection was terminated unexpectedly.
|
| 25 | + #[error("connection lost")] |
25 | 26 | ConnectionLost,
|
26 | 27 | /// Error parsing a server response.
|
27 |
| - Parse(ParseError), |
| 28 | + #[error("parse: {0}")] |
| 29 | + Parse(#[from] ParseError), |
28 | 30 | /// Command inputs were not valid [IMAP
|
29 | 31 | /// strings](https://tools.ietf.org/html/rfc3501#section-4.3).
|
30 |
| - Validate(ValidateError), |
31 |
| - /// `native_tls` error |
32 |
| - NativeTlsError(async_native_tls::Error), |
| 32 | + #[error("validate: {0}")] |
| 33 | + Validate(#[from] ValidateError), |
| 34 | + /// `async_native_tls` error |
| 35 | + #[error("async_native_tls: {0}")] |
| 36 | + NativeTlsError(#[from] async_native_tls::Error), |
33 | 37 | /// Error appending an e-mail.
|
| 38 | + #[error("could not append mail to mailbox")] |
34 | 39 | Append,
|
35 | 40 | #[doc(hidden)]
|
| 41 | + #[error("unknown")] |
36 | 42 | __Nonexhaustive,
|
37 | 43 | }
|
38 | 44 |
|
39 |
| -impl From<IoError> for Error { |
40 |
| - fn from(err: IoError) -> Error { |
41 |
| - Error::Io(err) |
42 |
| - } |
43 |
| -} |
44 |
| - |
45 |
| -impl From<ParseError> for Error { |
46 |
| - fn from(err: ParseError) -> Error { |
47 |
| - Error::Parse(err) |
48 |
| - } |
49 |
| -} |
50 |
| - |
51 |
| -impl<'a> From<&'a Response<'a>> for Error { |
52 |
| - fn from(err: &'a Response<'a>) -> Error { |
53 |
| - Error::Parse(ParseError::Unexpected(format!("{:?}", err))) |
54 |
| - } |
55 |
| -} |
56 |
| - |
57 |
| -impl From<async_native_tls::Error> for Error { |
58 |
| - fn from(err: async_native_tls::Error) -> Error { |
59 |
| - Error::NativeTlsError(err) |
60 |
| - } |
61 |
| -} |
62 |
| - |
63 |
| -impl fmt::Display for Error { |
64 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
65 |
| - match *self { |
66 |
| - Error::Io(ref e) => fmt::Display::fmt(e, f), |
67 |
| - Error::Validate(ref e) => fmt::Display::fmt(e, f), |
68 |
| - Error::No(ref data) | Error::Bad(ref data) => { |
69 |
| - write!(f, "{}: {}", &String::from(self.description()), data) |
70 |
| - } |
71 |
| - ref e => f.write_str(e.description()), |
72 |
| - } |
73 |
| - } |
74 |
| -} |
75 |
| - |
76 |
| -impl StdError for Error { |
77 |
| - fn description(&self) -> &str { |
78 |
| - match *self { |
79 |
| - Error::Io(ref e) => e.description(), |
80 |
| - Error::Parse(ref e) => e.description(), |
81 |
| - Error::Validate(ref e) => e.description(), |
82 |
| - Error::NativeTlsError(ref e) => e.description(), |
83 |
| - Error::Bad(_) => "Bad Response", |
84 |
| - Error::No(_) => "No Response", |
85 |
| - Error::ConnectionLost => "Connection lost", |
86 |
| - Error::Append => "Could not append mail to mailbox", |
87 |
| - Error::__Nonexhaustive => "Unknown", |
88 |
| - } |
89 |
| - } |
90 |
| - |
91 |
| - fn cause(&self) -> Option<&dyn StdError> { |
92 |
| - match *self { |
93 |
| - Error::Io(ref e) => Some(e), |
94 |
| - Error::Parse(ParseError::DataNotUtf8(_, ref e)) => Some(e), |
95 |
| - _ => None, |
96 |
| - } |
97 |
| - } |
98 |
| -} |
99 |
| - |
100 | 45 | /// An error occured while trying to parse a server response.
|
101 |
| -#[derive(Debug)] |
| 46 | +#[derive(thiserror::Error, Debug)] |
102 | 47 | pub enum ParseError {
|
103 | 48 | /// Indicates an error parsing the status response. Such as OK, NO, and BAD.
|
| 49 | + #[error("unable to parse status response")] |
104 | 50 | Invalid(Vec<u8>),
|
105 | 51 | /// An unexpected response was encountered.
|
| 52 | + #[error("encountered unexpected parsed response: {0}")] |
106 | 53 | Unexpected(String),
|
107 | 54 | /// The client could not find or decode the server's authentication challenge.
|
| 55 | + #[error("unable to parse authentication response: {0} - {1:?}")] |
108 | 56 | Authentication(String, Option<DecodeError>),
|
109 | 57 | /// The client received data that was not UTF-8 encoded.
|
110 |
| - DataNotUtf8(Vec<u8>, Utf8Error), |
111 |
| -} |
112 |
| - |
113 |
| -impl fmt::Display for ParseError { |
114 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
115 |
| - match *self { |
116 |
| - ref e => f.write_str(e.description()), |
117 |
| - } |
118 |
| - } |
119 |
| -} |
120 |
| - |
121 |
| -impl StdError for ParseError { |
122 |
| - fn description(&self) -> &str { |
123 |
| - match *self { |
124 |
| - ParseError::Invalid(_) => "Unable to parse status response", |
125 |
| - ParseError::Unexpected(_) => "Encountered unexpected parsed response", |
126 |
| - ParseError::Authentication(_, _) => "Unable to parse authentication response", |
127 |
| - ParseError::DataNotUtf8(_, _) => "Unable to parse data as UTF-8 text", |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - fn cause(&self) -> Option<&dyn StdError> { |
132 |
| - match *self { |
133 |
| - ParseError::Authentication(_, Some(ref e)) => Some(e), |
134 |
| - _ => None, |
135 |
| - } |
136 |
| - } |
| 58 | + #[error("unable to parse data ({0:?}) as UTF-8 text: {1:?}")] |
| 59 | + DataNotUtf8(Vec<u8>, #[source] Utf8Error), |
137 | 60 | }
|
138 | 61 |
|
139 | 62 | /// An [invalid character](https://tools.ietf.org/html/rfc3501#section-4.3) was found in an input
|
140 | 63 | /// string.
|
141 |
| -#[derive(Debug)] |
| 64 | +#[derive(thiserror::Error, Debug)] |
| 65 | +#[error("invalid character in input: '{0}'")] |
142 | 66 | pub struct ValidateError(pub char);
|
143 |
| - |
144 |
| -impl fmt::Display for ValidateError { |
145 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
146 |
| - // print character in debug form because invalid ones are often whitespaces |
147 |
| - write!(f, "{}: {:?}", self.description(), self.0) |
148 |
| - } |
149 |
| -} |
150 |
| - |
151 |
| -impl StdError for ValidateError { |
152 |
| - fn description(&self) -> &str { |
153 |
| - "Invalid character in input" |
154 |
| - } |
155 |
| - |
156 |
| - fn cause(&self) -> Option<&dyn StdError> { |
157 |
| - None |
158 |
| - } |
159 |
| -} |
0 commit comments