Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit 086a428

Browse files
committed
Move error_chain! to own file.
1 parent 8868c26 commit 086a428

File tree

2 files changed

+381
-381
lines changed

2 files changed

+381
-381
lines changed

src/error_chain.rs

Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
#[macro_export]
2+
macro_rules! error_chain {
3+
(
4+
types {
5+
$error_name:ident, $error_kind_name:ident, $result_name:ident;
6+
}
7+
8+
links {
9+
$( $link_error_path:path, $link_variant:ident $(, #[$meta_links:meta])*; ) *
10+
}
11+
12+
foreign_links {
13+
$( $foreign_link_error_path:path, $foreign_link_variant:ident $(, #[$meta_foreign_links:meta])*; )*
14+
}
15+
16+
errors {
17+
$( $error_chunks:tt ) *
18+
}
19+
20+
) => {
21+
22+
23+
/// The Error type
24+
///
25+
/// This has a simple structure to support pattern matching
26+
/// during error handling. The second field is internal state
27+
/// that is mostly irrelevant for error handling purposes.
28+
#[derive(Debug)]
29+
pub struct $error_name {
30+
pub kind: $error_kind_name,
31+
pub state: $crate::State,
32+
}
33+
34+
impl_error!($error_name $error_kind_name $($link_error_path)*);
35+
36+
impl $error_name {
37+
/// Constructs an error from a kind.
38+
pub fn from_kind(kind: $error_kind_name) -> $error_name {
39+
$error_name {
40+
kind: kind,
41+
state: $crate::State::default(),
42+
}
43+
}
44+
45+
/// Returns the kind of the error.
46+
pub fn kind(&self) -> &$error_kind_name {
47+
&self.kind
48+
}
49+
50+
/// Iterates over the error chain.
51+
pub fn iter(&self) -> $crate::ErrorChainIter {
52+
$crate::ErrorChainIter(Some(self))
53+
}
54+
}
55+
56+
impl ::std::error::Error for $error_name {
57+
fn description(&self) -> &str {
58+
self.kind.description()
59+
}
60+
61+
fn cause(&self) -> Option<&::std::error::Error> {
62+
match self.state.next_error {
63+
Some(ref c) => Some(&**c),
64+
None => {
65+
match self.kind {
66+
$(
67+
$(#[$meta_foreign_links])*
68+
$error_kind_name::$foreign_link_variant(ref foreign_err) => {
69+
foreign_err.cause()
70+
}
71+
) *
72+
_ => None
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
impl ::std::fmt::Display for $error_name {
80+
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
81+
::std::fmt::Display::fmt(&self.kind, f)
82+
}
83+
}
84+
85+
$(
86+
$(#[$meta_links])*
87+
impl From<$link_error_path> for $error_name {
88+
fn from(e: $link_error_path) -> Self {
89+
$error_name {
90+
kind: $error_kind_name::$link_variant(e.kind),
91+
state: e.state,
92+
}
93+
}
94+
}
95+
) *
96+
97+
$(
98+
$(#[$meta_foreign_links])*
99+
impl From<$foreign_link_error_path> for $error_name {
100+
fn from(e: $foreign_link_error_path) -> Self {
101+
$error_name::from_kind(
102+
$error_kind_name::$foreign_link_variant(e)
103+
)
104+
}
105+
}
106+
) *
107+
108+
impl From<$error_kind_name> for $error_name {
109+
fn from(e: $error_kind_name) -> Self {
110+
$error_name::from_kind(e)
111+
}
112+
}
113+
114+
impl<'a> From<&'a str> for $error_name {
115+
fn from(s: &'a str) -> Self {
116+
$error_name::from_kind(s.into())
117+
}
118+
}
119+
120+
impl From<String> for $error_name {
121+
fn from(s: String) -> Self {
122+
$error_name::from_kind(s.into())
123+
}
124+
}
125+
126+
impl ::std::ops::Deref for $error_name {
127+
type Target = $error_kind_name;
128+
129+
fn deref(&self) -> &Self::Target {
130+
&self.kind
131+
}
132+
}
133+
134+
135+
// The ErrorKind type
136+
// --------------
137+
138+
quick_error! {
139+
/// The kind of an error
140+
#[derive(Debug)]
141+
pub enum $error_kind_name {
142+
143+
Msg(s: String) {
144+
description(&s)
145+
display("{}", s)
146+
}
147+
148+
$(
149+
$(#[$meta_links])*
150+
$link_variant(e: <$link_error_path as $crate::ChainedError>::ErrorKind) {
151+
description(e.description())
152+
display("{}", e)
153+
}
154+
) *
155+
156+
$(
157+
$(#[$meta_foreign_links])*
158+
$foreign_link_variant(err: $foreign_link_error_path) {
159+
description(::std::error::Error::description(err))
160+
display("{}", err)
161+
}
162+
) *
163+
164+
$($error_chunks)*
165+
}
166+
}
167+
168+
$(
169+
$(#[$meta_links])*
170+
impl From<<$link_error_path as $crate::ChainedError>::ErrorKind> for $error_kind_name {
171+
fn from(e: <$link_error_path as $crate::ChainedError>::ErrorKind) -> Self {
172+
$error_kind_name::$link_variant(e)
173+
}
174+
}
175+
) *
176+
177+
impl<'a> From<&'a str> for $error_kind_name {
178+
fn from(s: &'a str) -> Self {
179+
$error_kind_name::Msg(s.to_string())
180+
}
181+
}
182+
183+
impl From<String> for $error_kind_name {
184+
fn from(s: String) -> Self {
185+
$error_kind_name::Msg(s)
186+
}
187+
}
188+
189+
impl From<$error_name> for $error_kind_name {
190+
fn from(e: $error_name) -> Self {
191+
e.kind
192+
}
193+
}
194+
195+
// The Result type
196+
// ---------------
197+
198+
/// Convenient wrapper around std::Result.
199+
pub type $result_name<T> = ::std::result::Result<T, $error_name>;
200+
};
201+
202+
// Handle missing sections, or missing type names in types { }
203+
//
204+
// Macros cannot specify "zero or one repetitions" at the moment, so we allow
205+
// repeating sections. Only for the `types` section this makes no sense, which
206+
// is the reason for the three separate cases.
207+
//
208+
// Case 1: types fully specified
209+
(
210+
types {
211+
$error_name:ident, $error_kind_name:ident, $result_name:ident;
212+
}
213+
214+
$( links {
215+
$( $link_chunks:tt ) *
216+
} ) *
217+
218+
$( foreign_links {
219+
$( $foreign_link_chunks:tt ) *
220+
} ) *
221+
222+
$( errors {
223+
$( $error_chunks:tt ) *
224+
} ) *
225+
) => (
226+
error_chain! {
227+
types {
228+
$error_name, $error_kind_name, $result_name;
229+
}
230+
231+
links {
232+
$( $( $link_chunks ) * ) *
233+
}
234+
235+
foreign_links {
236+
$( $( $foreign_link_chunks ) * ) *
237+
}
238+
239+
errors {
240+
$( $( $error_chunks ) * ) *
241+
}
242+
}
243+
);
244+
// Case 2: types section present, but empty
245+
(
246+
types { }
247+
248+
$( links {
249+
$( $link_chunks:tt ) *
250+
} ) *
251+
252+
$( foreign_links {
253+
$( $foreign_link_chunks:tt ) *
254+
} ) *
255+
256+
$( errors {
257+
$( $error_chunks:tt ) *
258+
} ) *
259+
) => (
260+
error_chain! {
261+
types {
262+
Error, ErrorKind, Result;
263+
}
264+
265+
links {
266+
$( $( $link_chunks ) * ) *
267+
}
268+
269+
foreign_links {
270+
$( $( $foreign_link_chunks ) * ) *
271+
}
272+
273+
errors {
274+
$( $( $error_chunks ) * ) *
275+
}
276+
}
277+
);
278+
// Case 3: types section not present
279+
(
280+
$( links {
281+
$( $link_chunks:tt ) *
282+
} ) *
283+
284+
$( foreign_links {
285+
$( $foreign_link_chunks:tt ) *
286+
} ) *
287+
288+
$( errors {
289+
$( $error_chunks:tt ) *
290+
} ) *
291+
) => (
292+
error_chain! {
293+
types { }
294+
295+
links {
296+
$( $( $link_chunks ) * ) *
297+
}
298+
299+
foreign_links {
300+
$( $( $foreign_link_chunks ) * ) *
301+
}
302+
303+
errors {
304+
$( $( $error_chunks ) * ) *
305+
}
306+
}
307+
);
308+
}
309+
310+
/// Macro used to manage the `backtrace` feature.
311+
///
312+
/// See
313+
/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
314+
/// for more details.
315+
#[macro_export]
316+
#[doc(hidden)]
317+
#[cfg(feature = "backtrace")]
318+
macro_rules! impl_error {
319+
($error_name: ident
320+
$error_kind_name: ident
321+
$($link_error_path: path)*) => {
322+
impl $error_name {
323+
/// Returns the backtrace associated with this error.
324+
pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
325+
self.state.backtrace.as_ref().map(|v| &**v)
326+
}
327+
}
328+
329+
impl $crate::ChainedError for $error_name {
330+
type ErrorKind = $error_kind_name;
331+
332+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
333+
$error_name {
334+
kind: kind,
335+
state: state,
336+
}
337+
}
338+
339+
fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
340+
-> Option<Option<::std::sync::Arc<$crate::Backtrace>>> {
341+
if let Some(e) = e.downcast_ref::<$error_name>() {
342+
Some(e.state.backtrace.clone())
343+
}
344+
$(
345+
else if let Some(e) = e.downcast_ref::<$link_error_path>() {
346+
Some(e.state.backtrace.clone())
347+
}
348+
) *
349+
else {
350+
None
351+
}
352+
}
353+
}
354+
}
355+
}
356+
357+
/// Macro used to manage the `backtrace` feature.
358+
///
359+
/// See
360+
/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
361+
/// for more details.
362+
#[macro_export]
363+
#[doc(hidden)]
364+
#[cfg(not(feature = "backtrace"))]
365+
macro_rules! impl_error {
366+
($error_name: ident
367+
$error_kind_name: ident
368+
$($link_error_path: path)*) => {
369+
impl $crate::ChainedError for $error_name {
370+
type ErrorKind = $error_kind_name;
371+
372+
fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
373+
$error_name {
374+
kind: kind,
375+
state: state,
376+
}
377+
}
378+
}
379+
}
380+
}

0 commit comments

Comments
 (0)