1use std::error::Error;
11use std::fmt::{self};
12use std::io::{self};
13use std::num::{self};
14
15#[cfg(doc)]
17use super::Target;
18
19pub type ErrorMessage = &'static str;
21
22#[derive(Debug)]
24pub enum ParseTargetError {
25 Message(ErrorMessage),
27 ParseIntError(ErrorMessage, num::ParseIntError),
29 GenericError(ErrorMessage, Box<dyn Error>),
31}
32
33impl Error for ParseTargetError {
34 fn source(&self) -> Option<&(dyn Error + 'static)> {
35 match self {
36 ParseTargetError::Message(_) => None,
37 ParseTargetError::ParseIntError(_, ref error) => Some(error),
38 ParseTargetError::GenericError(_, ref error) => Some(error.as_ref()),
39 }
40 }
41}
42
43impl fmt::Display for ParseTargetError {
44 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
45 let error_message = match self {
46 ParseTargetError::Message(error_message)
47 | ParseTargetError::ParseIntError(error_message, _)
48 | ParseTargetError::GenericError(error_message, _) => error_message,
49 };
50
51 match self.source() {
52 None => write!(formatter, "{}", error_message),
53 Some(error) => write!(formatter, "{} caused by: {}", error_message, error),
54 }
55 }
56}
57
58impl From<ErrorMessage> for ParseTargetError {
59 fn from(message: ErrorMessage) -> Self {
60 ParseTargetError::Message(message)
61 }
62}
63
64impl From<(ErrorMessage, num::ParseIntError)> for ParseTargetError {
65 fn from(pieces: (ErrorMessage, num::ParseIntError)) -> Self {
66 let (msg, error) = pieces;
67 ParseTargetError::ParseIntError(msg, error)
68 }
69}
70
71impl From<(ErrorMessage, Box<dyn Error>)> for ParseTargetError {
72 fn from(pieces: (ErrorMessage, Box<dyn Error>)) -> Self {
73 let (msg, error) = pieces;
74 ParseTargetError::GenericError(msg, error)
75 }
76}
77
78impl From<Box<dyn Error>> for ParseTargetError {
79 fn from(error: Box<dyn Error>) -> Self {
80 ParseTargetError::from(("GenericError", error))
81 }
82}
83
84#[derive(Debug)]
86pub enum ResolveTargetError {
87 Message(ErrorMessage),
89 IoError(ErrorMessage, io::Error),
91 GenericError(ErrorMessage, Box<dyn Error>),
93}
94
95impl Error for ResolveTargetError {
96 fn source(&self) -> Option<&(dyn Error + 'static)> {
97 match self {
98 ResolveTargetError::Message(_) => None,
99 ResolveTargetError::IoError(_, ref error) => Some(error),
100 ResolveTargetError::GenericError(_, ref error) => Some(error.as_ref()),
101 }
102 }
103}
104
105impl fmt::Display for ResolveTargetError {
106 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107 let error_message = match self {
108 ResolveTargetError::Message(error_message)
109 | ResolveTargetError::IoError(error_message, _)
110 | ResolveTargetError::GenericError(error_message, _) => error_message,
111 };
112
113 match self.source() {
114 None => write!(formatter, "{}", error_message),
115 Some(error) => write!(formatter, "{} caused by: {}", error_message, error),
116 }
117 }
118}
119
120impl From<ErrorMessage> for ResolveTargetError {
121 fn from(message: ErrorMessage) -> Self {
122 ResolveTargetError::Message(message)
123 }
124}
125
126impl From<(ErrorMessage, io::Error)> for ResolveTargetError {
127 fn from(pieces: (ErrorMessage, io::Error)) -> Self {
128 let (msg, error) = pieces;
129 ResolveTargetError::IoError(msg, error)
130 }
131}
132
133impl From<io::Error> for ResolveTargetError {
134 fn from(error: io::Error) -> Self {
135 ResolveTargetError::from(("IoError", error))
136 }
137}
138
139impl From<(ErrorMessage, Box<dyn Error>)> for ResolveTargetError {
140 fn from(pieces: (ErrorMessage, Box<dyn Error>)) -> Self {
141 let (msg, error) = pieces;
142 ResolveTargetError::GenericError(msg, error)
143 }
144}
145
146impl From<Box<dyn Error>> for ResolveTargetError {
147 fn from(error: Box<dyn Error>) -> Self {
148 ResolveTargetError::from(("GenericError", error))
149 }
150}
151
152#[derive(Debug)]
154pub enum CheckTargetError {
155 Message(ErrorMessage),
157 ResolveTargetError(ErrorMessage, ResolveTargetError),
159 GenericError(ErrorMessage, Box<dyn Error>),
161}
162
163impl Error for CheckTargetError {
164 fn source(&self) -> Option<&(dyn Error + 'static)> {
165 match self {
166 CheckTargetError::Message(_) => None,
167 CheckTargetError::ResolveTargetError(_, ref error) => Some(error),
168 CheckTargetError::GenericError(_, ref error) => Some(error.as_ref()),
169 }
170 }
171}
172
173impl fmt::Display for CheckTargetError {
174 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
175 let error_message = match self {
176 CheckTargetError::Message(error_message)
177 | CheckTargetError::ResolveTargetError(error_message, _)
178 | CheckTargetError::GenericError(error_message, _) => error_message,
179 };
180
181 match self.source() {
182 None => write!(formatter, "{}", error_message),
183 Some(error) => write!(formatter, "{} caused by: {}", error_message, error),
184 }
185 }
186}
187
188impl From<ErrorMessage> for CheckTargetError {
189 fn from(message: ErrorMessage) -> Self {
190 CheckTargetError::Message(message)
191 }
192}
193
194impl From<(ErrorMessage, ResolveTargetError)> for CheckTargetError {
195 fn from(pieces: (ErrorMessage, ResolveTargetError)) -> Self {
196 let (msg, error) = pieces;
197 CheckTargetError::ResolveTargetError(msg, error)
198 }
199}
200
201impl From<ResolveTargetError> for CheckTargetError {
202 fn from(error: ResolveTargetError) -> Self {
203 CheckTargetError::from(("ResolveTargetError", error))
204 }
205}
206
207impl From<(ErrorMessage, Box<dyn Error>)> for CheckTargetError {
208 fn from(pieces: (ErrorMessage, Box<dyn Error>)) -> Self {
209 let (msg, error) = pieces;
210 CheckTargetError::GenericError(msg, error)
211 }
212}
213
214impl From<Box<dyn Error>> for CheckTargetError {
215 fn from(error: Box<dyn Error>) -> Self {
216 CheckTargetError::from(("GenericError", error))
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223
224 #[test]
226 fn parse_target_error_from_str() {
227 assert_eq!(
229 format!("{}", ParseTargetError::from("Error Message!")),
230 "Error Message!"
231 );
232 }
233
234 #[test]
235 fn parse_target_error_from_parse_int_error() {
236 let error = i32::from_str_radix("invalid", 10).unwrap_err();
239 assert_eq!(
240 format!("{}", ParseTargetError::from(("ParseIntError!", error))),
241 "ParseIntError! caused by: invalid digit found in string"
242 );
243 }
244
245 #[test]
246 fn parse_target_error_from_boxed_error_trait_object() {
247 let boxed_error: Box<dyn Error> = Box::new(io::Error::from(io::ErrorKind::AddrNotAvailable));
250 assert_eq!(
251 format!("{}", ParseTargetError::from(boxed_error)),
252 "GenericError caused by: address not available"
253 );
254 }
255
256 #[test]
257 fn parse_target_error_chain_multiple_errors() {
258 let error1: Box<dyn Error> = Box::new(ParseTargetError::from("Layer1!"));
261 let error2: Box<dyn Error> = Box::new(ParseTargetError::from(("Layer2!", error1)));
262 assert_eq!(
263 format!("{}", ParseTargetError::from(("Layer3!", error2))),
264 "Layer3! caused by: Layer2! caused by: Layer1!"
265 );
266 }
267
268 #[test]
270 fn resolve_target_error_from_str() {
271 assert_eq!(
273 format!("{}", ResolveTargetError::from("Error Message!")),
274 "Error Message!"
275 );
276 }
277
278 #[test]
279 fn resolve_target_error_from_parse_int_error() {
280 assert_eq!(
283 format!("{}", ResolveTargetError::from(io::Error::from(io::ErrorKind::Other))),
284 "IoError caused by: other error"
285 );
286 }
287
288 #[test]
289 fn resolve_target_error_from_boxed_error_trait_object() {
290 let boxed_error: Box<dyn Error> = Box::new(ParseTargetError::from("ParseTargetError"));
293 assert_eq!(
294 format!("{}", ResolveTargetError::from(boxed_error)),
295 "GenericError caused by: ParseTargetError"
296 );
297 }
298
299 #[test]
301 fn check_target_error_from_str() {
302 assert_eq!(
304 format!("{}", CheckTargetError::from("Error Message!")),
305 "Error Message!"
306 );
307 }
308
309 #[test]
310 fn check_target_error_from_resolve_target_error() {
311 let resolve_target_error = ResolveTargetError::from(io::Error::from(io::ErrorKind::AddrNotAvailable));
314 assert_eq!(
315 format!("{}", CheckTargetError::from(resolve_target_error)),
316 "ResolveTargetError caused by: IoError caused by: address not available"
317 );
318 }
319
320 #[test]
321 fn check_target_error_from_boxed_error_trait_object() {
322 let boxed_error: Box<dyn Error> = Box::new(io::Error::from(io::ErrorKind::AddrNotAvailable));
325 assert_eq!(
326 format!("{}", CheckTargetError::from(boxed_error)),
327 "GenericError caused by: address not available"
328 );
329 }
330
331 #[test]
332 fn check_target_error_via_questionmark_operator() {
333 fn returns_io_error() -> Result<u32, io::Error> {
336 Err(io::Error::from(io::ErrorKind::TimedOut))
337 }
338 fn returns_resolve_target_error() -> Result<u32, ResolveTargetError> {
339 Ok(returns_io_error()?)
340 }
341 fn returns_check_target_error() -> Result<u32, CheckTargetError> {
342 Ok(returns_resolve_target_error()?)
343 }
344 assert_eq!(
345 format!("{}", returns_check_target_error().unwrap_err()),
346 "ResolveTargetError caused by: IoError caused by: timed out"
347 );
348 }
349}