1use std::io;
24use std::fmt;
25use std::net;
26use std::num;
27use std::error::Error as StdError;
28use std::sync::mpsc;
29use std::sync;
30use std::result::Result as StdResult;
31
32use serde_json;
33use ansi_term::Colour;
34
35
36pub type Result<T> = StdResult<T, Error>;
40
41
42#[derive(Debug)]
46pub enum ErrorKind {
47 ProviderNotFound(String),
50
51 InvalidInput(String),
54
55 NotBehindProxy,
59
60 WrongRequestKind,
62
63 InvalidHexChar(char),
66
67 InvalidHexLength,
69
70 BrokenChannel,
72
73 PoisonedLock,
75
76 ThreadCrashed,
78
79 IoError(io::Error),
82
83 JsonError(serde_json::Error),
86
87 AddrParseError(net::AddrParseError),
90
91 ParseIntError(num::ParseIntError),
94
95 GenericError(Box<StdError + Send + Sync>),
97
98 #[doc(hidden)]
99 Dummy,
100}
101
102impl fmt::Display for ErrorKind {
103
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 write!(f, "{}", match *self {
106
107 ErrorKind::ProviderNotFound(ref provider) =>
108 format!("Provider {} not found", provider),
109
110 ErrorKind::InvalidInput(ref error) =>
111 format!("invalid input: {}", error),
112
113 ErrorKind::NotBehindProxy =>
114 "not behind the proxies".into(),
115
116 ErrorKind::WrongRequestKind =>
117 "wrong request kind".into(),
118
119 ErrorKind::InvalidHexChar(chr) =>
120 format!("{} is not valid hex", chr),
121
122 ErrorKind::InvalidHexLength =>
123 "invalid length of the hex".into(),
124
125 ErrorKind::BrokenChannel =>
126 "an internal communication channel crashed".into(),
127
128 ErrorKind::PoisonedLock =>
129 "an internal lock was poisoned".into(),
130
131 ErrorKind::ThreadCrashed =>
132 "an internal thread crashed".into(),
133
134 ErrorKind::IoError(ref error) =>
135 format!("{}", error),
136
137 ErrorKind::JsonError(ref error) =>
138 format!("{}", error),
139
140 ErrorKind::AddrParseError(ref error) =>
141 format!("{}", error),
142
143 ErrorKind::ParseIntError(..) =>
144 "you didn't provide a valid number".into(),
145
146 ErrorKind::GenericError(ref error) =>
147 format!("{}", error),
148
149 ErrorKind::Dummy =>
150 "dummy_error".into(),
151 })
152 }
153}
154
155
156
157
158#[derive(Debug, PartialEq, Eq)]
161pub enum ErrorLocation {
162 File(String, Option<u32>),
166
167 HookProcessing(String),
170
171 Unknown,
173
174 #[doc(hidden)]
175 __NonExaustiveMatch,
176}
177
178impl fmt::Display for ErrorLocation {
179
180 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181 match *self {
182
183 ErrorLocation::File(ref path, line) => {
184 write!(f, "file {}", path)?;
185 if let Some(num) = line {
186 write!(f, ", on line {}", num)?;
187 }
188
189 Ok(())
190 },
191
192 ErrorLocation::HookProcessing(ref name) => {
193 write!(f, "while processing {}", name)
194 },
195
196 ErrorLocation::Unknown => {
197 write!(f, "")
198 },
199
200 ErrorLocation::__NonExaustiveMatch => {
201 panic!("You shouldn't use this.");
202 },
203 }
204 }
205}
206
207
208#[derive(Debug)]
216pub struct Error {
217 kind: ErrorKind,
218 location: ErrorLocation,
219}
220
221impl Error {
222
223 pub fn new(kind: ErrorKind) -> Self {
238 Error {
239 kind: kind,
240 location: ErrorLocation::Unknown,
241 }
242 }
243
244 pub fn set_location(&mut self, location: ErrorLocation) {
246 self.location = location;
247 }
248
249 pub fn location(&self) -> &ErrorLocation {
252 &self.location
253 }
254
255 pub fn kind(&self) -> &ErrorKind {
258 &self.kind
259 }
260
261 pub fn pretty_print(&self) {
274 println!("{} {}",
275 Colour::Red.bold().paint("Error:"),
276 self
277 );
278 if self.location != ErrorLocation::Unknown {
279 println!("{} {}",
280 Colour::Yellow.bold().paint("Location:"),
281 self.location
282 );
283 }
284 }
285}
286
287impl fmt::Display for Error {
288
289 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
290 write!(f, "{}", self.kind)
291 }
292}
293
294impl StdError for Error {
295
296 fn description(&self) -> &str {
297 match self.kind {
298 ErrorKind::ProviderNotFound(..) =>
299 "provider not found",
300 ErrorKind::InvalidInput(..) =>
301 "invalid input",
302 ErrorKind::NotBehindProxy =>
303 "not behind the proxies",
304 ErrorKind::WrongRequestKind =>
305 "wrong request kind",
306 ErrorKind::InvalidHexChar(..) =>
307 "invalid character in hex",
308 ErrorKind::InvalidHexLength =>
309 "invalid length of the hex",
310 ErrorKind::BrokenChannel =>
311 "internal communication channel crashed",
312 ErrorKind::PoisonedLock =>
313 "poisoned lock",
314 ErrorKind::ThreadCrashed =>
315 "thread crashed",
316 ErrorKind::IoError(ref error) =>
317 error.description(),
318 ErrorKind::JsonError(ref error) =>
319 error.description(),
320 ErrorKind::AddrParseError(ref error) =>
321 error.description(),
322 ErrorKind::ParseIntError(..) =>
323 "invalid number",
324 ErrorKind::GenericError(ref error) =>
325 error.description(),
326 ErrorKind::Dummy =>
327 "dummy error",
328 }
329 }
330
331 fn cause(&self) -> Option<&StdError> {
332 match self.kind {
333 ErrorKind::IoError(ref error) => Some(error as &StdError),
334 ErrorKind::JsonError(ref error) => Some(error as &StdError),
335 ErrorKind::AddrParseError(ref error) => Some(error as &StdError),
336 ErrorKind::ParseIntError(ref error) => Some(error as &StdError),
337 _ => None,
338 }
339 }
340}
341
342macro_rules! derive_error {
343 ($from:path, $to:path) => {
344 impl From<$from> for Error {
345
346 fn from(error: $from) -> Self {
347 Error::new($to(error))
348 }
349 }
350 };
351}
352
353impl From<ErrorKind> for Error {
354
355 fn from(error: ErrorKind) -> Self {
356 Error::new(error)
357 }
358}
359
360impl From<mpsc::RecvError> for Error {
361
362 fn from(_: mpsc::RecvError) -> Self {
363 Error::new(ErrorKind::BrokenChannel)
364 }
365}
366
367impl<T> From<mpsc::SendError<T>> for Error {
368
369 fn from(_: mpsc::SendError<T>) -> Self {
370 Error::new(ErrorKind::BrokenChannel)
371 }
372}
373
374impl<T> From<sync::PoisonError<T>> for Error {
375
376 fn from(_: sync::PoisonError<T>) -> Self {
377 Error::new(ErrorKind::PoisonedLock)
378 }
379}
380
381derive_error!(io::Error, ErrorKind::IoError);
382derive_error!(serde_json::Error, ErrorKind::JsonError);
383derive_error!(net::AddrParseError, ErrorKind::AddrParseError);
384derive_error!(num::ParseIntError, ErrorKind::ParseIntError);
385derive_error!(Box<StdError + Send + Sync>, ErrorKind::GenericError);