1#![allow(unused_macros)]
4
5#[cfg(feature = "alloc")]
6use prelude::*;
7
8#[cfg(feature = "alloc")]
9use core::{num::ParseIntError, str::Utf8Error};
10use failure::Context;
11
12#[cfg(feature = "std")]
13use std::{
14 error::Error as StdError,
15 fmt::{self, Display},
16 io,
17 string::{FromUtf8Error, String, ToString},
18};
19
20#[derive(Debug)]
22pub struct Error {
23 inner: Context<ErrorKind>,
25
26 #[cfg(feature = "alloc")]
28 description: Option<String>,
29}
30
31impl Error {
32 #[allow(unused_variables)]
34 pub fn new(kind: ErrorKind, description: Option<&str>) -> Self {
35 #[cfg_attr(not(feature = "alloc"), allow(unused_mut))]
36 let mut err = Self::from(kind);
37
38 #[cfg(feature = "alloc")]
39 {
40 err.description = description.map(|desc| desc.into());
41 }
42
43 err
44 }
45
46 pub fn kind(&self) -> ErrorKind {
48 *self.inner.get_context()
49 }
50}
51
52#[cfg(feature = "alloc")]
53impl Display for Error {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 self.description().fmt(f)
56 }
57}
58
59#[cfg(feature = "alloc")]
60impl StdError for Error {
61 fn description(&self) -> &str {
62 if let Some(ref desc) = self.description {
63 desc
64 } else {
65 "(none)"
66 }
67 }
68}
69
70impl From<ErrorKind> for Error {
71 fn from(kind: ErrorKind) -> Error {
72 Error {
73 inner: Context::new(kind),
74 #[cfg(feature = "alloc")]
75 description: None,
76 }
77 }
78}
79
80impl From<Context<ErrorKind>> for Error {
81 fn from(inner: Context<ErrorKind>) -> Self {
82 Self {
83 inner,
84 #[cfg(feature = "alloc")]
85 description: None,
86 }
87 }
88}
89
90#[derive(Copy, Clone, Debug, Fail, Eq, PartialEq)]
92pub enum ErrorKind {
93 #[fail(display = "address invalid")]
95 AddrInvalid,
96
97 #[fail(display = "I/O error")]
99 IoError,
100
101 #[fail(display = "parse error")]
103 ParseError,
104
105 #[fail(display = "request error")]
107 RequestError,
108
109 #[fail(display = "error reading response")]
111 ResponseError,
112}
113
114macro_rules! err {
116 ($variant:ident, $msg:expr) => {
117 ::error::Error::new(
118 ::error::ErrorKind::$variant,
119 Some($msg)
120 )
121 };
122 ($variant:ident, $fmt:expr, $($arg:tt)+) => {
123 err!($variant, &format!($fmt, $($arg)+))
124 };
125}
126
127macro_rules! fail {
129 ($kind:ident, $msg:expr) => {
130 return Err(err!($kind, $msg).into());
131 };
132 ($kind:ident, $fmt:expr, $($arg:tt)+) => {
133 fail!($kind, &format!($fmt, $($arg)+));
134 };
135}
136
137macro_rules! ensure {
139 ($condition: expr, $variant:ident, $msg:expr) => {
140 if !($condition) {
141 return Err(err!($variant, $msg).into());
142 }
143 };
144 ($condition: expr, $variant:ident, $fmt:expr, $($arg:tt)+) => {
145 ensure!($variant, $fmt, $($arg)+);
146 };
147}
148
149#[cfg(feature = "alloc")]
150impl From<ParseIntError> for Error {
151 fn from(err: ParseIntError) -> Self {
152 err!(ParseError, &err.to_string())
153 }
154}
155
156#[cfg(feature = "std")]
157impl From<FromUtf8Error> for Error {
158 fn from(err: FromUtf8Error) -> Self {
159 err!(ParseError, &err.to_string())
160 }
161}
162
163#[cfg(feature = "alloc")]
164impl From<Utf8Error> for Error {
165 fn from(err: Utf8Error) -> Self {
166 err!(ParseError, &err.to_string())
167 }
168}
169
170#[cfg(feature = "std")]
171impl From<fmt::Error> for Error {
172 fn from(err: fmt::Error) -> Self {
173 err!(RequestError, &err.to_string())
174 }
175}
176
177#[cfg(feature = "std")]
178impl From<io::Error> for Error {
179 fn from(err: io::Error) -> Self {
180 err!(IoError, &err.to_string())
181 }
182}