]>
Commit | Line | Data |
---|---|---|
7cac9316 XL |
1 | #![deny(missing_docs)] |
2 | ||
3 | //! A library for consistent and reliable error handling | |
4 | //! | |
5 | //! error-chain makes it easy to take full advantage of Rust's | |
6 | //! powerful error handling features without the overhead of | |
7 | //! maintaining boilerplate error types and conversions. It implements | |
8 | //! an opinionated strategy for defining your own error types, as well | |
9 | //! as conversions from others' error types. | |
10 | //! | |
11 | //! ## Quick start | |
12 | //! | |
13 | //! If you just want to set up your new project with error-chain, | |
14 | //! follow the [quickstart.rs] template, and read this [intro] | |
15 | //! to error-chain. | |
16 | //! | |
17 | //! [quickstart.rs]: https://github.com/brson/error-chain/blob/master/examples/quickstart.rs | |
18 | //! [intro]: http://brson.github.io/2016/11/30/starting-with-error-chain | |
19 | //! | |
20 | //! ## Why error chain? | |
21 | //! | |
22 | //! * error-chain is easy to configure. Handle errors robustly with minimal | |
23 | //! effort. | |
24 | //! * Basic error handling requires no maintenance of custom error types | |
25 | //! nor the `From` conversions that make `?` work. | |
26 | //! * error-chain scales from simple error handling strategies to more | |
27 | //! rigorous. Return formatted strings for simple errors, only | |
28 | //! introducing error variants and their strong typing as needed for | |
29 | //! advanced error recovery. | |
30 | //! * error-chain makes it trivial to correctly manage the [cause] of | |
31 | //! the errors generated by your own code. This is the "chaining" | |
32 | //! in "error-chain". | |
33 | //! | |
34 | //! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause | |
35 | //! | |
36 | //! ## Principles of error-chain | |
37 | //! | |
38 | //! error-chain is based on the following principles: | |
39 | //! | |
40 | //! * No error should ever be discarded. This library primarily | |
41 | //! makes it easy to "chain" errors with the `chain_err` method. | |
42 | //! * Introducing new errors is trivial. Simple errors can be introduced | |
43 | //! at the error site with just a string. | |
44 | //! * Handling errors is possible with pattern matching. | |
45 | //! * Conversions between error types are done in an automatic and | |
46 | //! consistent way - `From` conversion behavior is never specified | |
47 | //! explicitly. | |
48 | //! * Errors implement Send. | |
49 | //! * Errors can carry backtraces. | |
50 | //! | |
51 | //! Similar to other libraries like [error-type] and [quick-error], | |
52 | //! this library introduces the error chaining mechanism originally | |
53 | //! employed by Cargo. The `error_chain!` macro declares the types | |
54 | //! and implementation boilerplate necessary for fulfilling a | |
55 | //! particular error-handling strategy. Most importantly it defines a | |
56 | //! custom error type (called `Error` by convention) and the `From` | |
57 | //! conversions that let the `try!` macro and `?` operator work. | |
58 | //! | |
59 | //! This library differs in a few ways from previous error libs: | |
60 | //! | |
61 | //! * Instead of defining the custom `Error` type as an enum, it is a | |
62 | //! struct containing an `ErrorKind` (which defines the | |
63 | //! `description` and `display` methods for the error), an opaque, | |
64 | //! optional, boxed `std::error::Error + Send + 'static` object | |
65 | //! (which defines the `cause`, and establishes the links in the | |
66 | //! error chain), and a `Backtrace`. | |
67 | //! * The macro also defines a `ResultExt` trait that defines a | |
68 | //! `chain_err` method. This method on all `std::error::Error + Send + 'static` | |
69 | //! types extends the error chain by boxing the current | |
70 | //! error into an opaque object and putting it inside a new concrete | |
71 | //! error. | |
72 | //! * It provides automatic `From` conversions between other error types | |
73 | //! defined by the `error_chain!` that preserve type information, | |
74 | //! and facilitate seamless error composition and matching of composed | |
75 | //! errors. | |
76 | //! * It provides automatic `From` conversions between any other error | |
77 | //! type that hides the type of the other error in the `cause` box. | |
78 | //! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at | |
79 | //! the earliest opportunity and propagates it down the stack through | |
80 | //! `From` and `ResultExt` conversions. | |
81 | //! | |
82 | //! To accomplish its goals it makes some tradeoffs: | |
83 | //! | |
84 | //! * The split between the `Error` and `ErrorKind` types can make it | |
85 | //! slightly more cumbersome to instantiate new (unchained) errors, | |
86 | //! requiring an `Into` or `From` conversion; as well as slightly | |
87 | //! more cumbersome to match on errors with another layer of types | |
88 | //! to match. | |
89 | //! * Because the error type contains `std::error::Error + Send + 'static` objects, | |
90 | //! it can't implement `PartialEq` for easy comparisons. | |
91 | //! | |
92 | //! ## Declaring error types | |
93 | //! | |
94 | //! Generally, you define one family of error types per crate, though | |
95 | //! it's also perfectly fine to define error types on a finer-grained | |
96 | //! basis, such as per module. | |
97 | //! | |
98 | //! Assuming you are using crate-level error types, typically you will | |
99 | //! define an `errors` module and inside it call `error_chain!`: | |
100 | //! | |
101 | //! ``` | |
102 | //! # #[macro_use] extern crate error_chain; | |
103 | //! mod other_error { | |
104 | //! error_chain! {} | |
105 | //! } | |
106 | //! | |
107 | //! error_chain! { | |
108 | //! // The type defined for this error. These are the conventional | |
109 | //! // and recommended names, but they can be arbitrarily chosen. | |
110 | //! // | |
111 | //! // It is also possible to leave this section out entirely, or | |
112 | //! // leave it empty, and these names will be used automatically. | |
113 | //! types { | |
114 | //! Error, ErrorKind, ResultExt, Result; | |
115 | //! } | |
116 | //! | |
117 | //! // Without the `Result` wrapper: | |
118 | //! // | |
119 | //! // types { | |
120 | //! // Error, ErrorKind, ResultExt; | |
121 | //! // } | |
122 | //! | |
123 | //! // Automatic conversions between this error chain and other | |
124 | //! // error chains. In this case, it will e.g. generate an | |
125 | //! // `ErrorKind` variant called `Another` which in turn contains | |
126 | //! // the `other_error::ErrorKind`, with conversions from | |
127 | //! // `other_error::Error`. | |
128 | //! // | |
129 | //! // Optionally, some attributes can be added to a variant. | |
130 | //! // | |
131 | //! // This section can be empty. | |
132 | //! links { | |
133 | //! Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)]; | |
134 | //! } | |
135 | //! | |
136 | //! // Automatic conversions between this error chain and other | |
137 | //! // error types not defined by the `error_chain!`. These will be | |
138 | //! // wrapped in a new error with, in the first case, the | |
139 | //! // `ErrorKind::Fmt` variant. The description and cause will | |
140 | //! // forward to the description and cause of the original error. | |
141 | //! // | |
142 | //! // Optionally, some attributes can be added to a variant. | |
143 | //! // | |
144 | //! // This section can be empty. | |
145 | //! foreign_links { | |
146 | //! Fmt(::std::fmt::Error); | |
147 | //! Io(::std::io::Error) #[cfg(unix)]; | |
148 | //! } | |
149 | //! | |
150 | //! // Define additional `ErrorKind` variants. The syntax here is | |
151 | //! // the same as `quick_error!`, but the `from()` and `cause()` | |
152 | //! // syntax is not supported. | |
153 | //! errors { | |
154 | //! InvalidToolchainName(t: String) { | |
155 | //! description("invalid toolchain name") | |
156 | //! display("invalid toolchain name: '{}'", t) | |
157 | //! } | |
158 | //! } | |
159 | //! } | |
160 | //! | |
161 | //! # fn main() {} | |
162 | //! ``` | |
163 | //! | |
164 | //! Each section, `types`, `links`, `foreign_links`, and `errors` may | |
165 | //! be omitted if it is empty. | |
166 | //! | |
167 | //! This populates the module with a number of definitions, | |
168 | //! the most important of which are the `Error` type | |
169 | //! and the `ErrorKind` type. An example of generated code can be found in the | |
170 | //! [example_generated](example_generated) module. | |
171 | //! | |
172 | //! ## Returning new errors | |
173 | //! | |
174 | //! Introducing new error chains, with a string message: | |
175 | //! | |
176 | //! ``` | |
177 | //! # #[macro_use] extern crate error_chain; | |
178 | //! # fn main() {} | |
179 | //! # error_chain! {} | |
180 | //! fn foo() -> Result<()> { | |
181 | //! Err("foo error!".into()) | |
182 | //! } | |
183 | //! ``` | |
184 | //! | |
185 | //! Introducing new error chains, with an `ErrorKind`: | |
186 | //! | |
187 | //! ``` | |
188 | //! # #[macro_use] extern crate error_chain; | |
189 | //! # fn main() {} | |
190 | //! error_chain! { | |
191 | //! errors { FooError } | |
192 | //! } | |
193 | //! | |
194 | //! fn foo() -> Result<()> { | |
195 | //! Err(ErrorKind::FooError.into()) | |
196 | //! } | |
197 | //! ``` | |
198 | //! | |
199 | //! Note that the return type is the typedef `Result`, which is | |
200 | //! defined by the macro as `pub type Result<T> = | |
201 | //! ::std::result::Result<T, Error>`. Note that in both cases | |
202 | //! `.into()` is called to convert a type into the `Error` type; both | |
203 | //! strings and `ErrorKind` have `From` conversions to turn them into | |
204 | //! `Error`. | |
205 | //! | |
206 | //! When the error is emitted inside a `try!` macro or behind the | |
207 | //! `?` operator, the explicit conversion isn't needed; `try!` will | |
208 | //! automatically convert `Err(ErrorKind)` to `Err(Error)`. So the | |
209 | //! below is equivalent to the previous: | |
210 | //! | |
211 | //! ``` | |
212 | //! # #[macro_use] extern crate error_chain; | |
213 | //! # fn main() {} | |
214 | //! # error_chain! { errors { FooError } } | |
215 | //! fn foo() -> Result<()> { | |
216 | //! Ok(try!(Err(ErrorKind::FooError))) | |
217 | //! } | |
218 | //! | |
219 | //! fn bar() -> Result<()> { | |
220 | //! Ok(try!(Err("bogus!"))) | |
221 | //! } | |
222 | //! ``` | |
223 | //! | |
224 | //! ## The `bail!` macro | |
225 | //! | |
226 | //! The above method of introducing new errors works but is a little | |
227 | //! verbose. Instead we can use the `bail!` macro, which, much like `try!` | |
228 | //! and `?`, performs an early return with conversions. With `bail!` the | |
229 | //! previous examples look like: | |
230 | //! | |
231 | //! ``` | |
232 | //! # #[macro_use] extern crate error_chain; | |
233 | //! # fn main() {} | |
234 | //! # error_chain! { errors { FooError } } | |
235 | //! fn foo() -> Result<()> { | |
236 | //! if true { | |
237 | //! bail!(ErrorKind::FooError); | |
238 | //! } else { | |
239 | //! Ok(()) | |
240 | //! } | |
241 | //! } | |
242 | //! | |
243 | //! fn bar() -> Result<()> { | |
244 | //! if true { | |
245 | //! bail!("bogus!"); | |
246 | //! } else { | |
247 | //! Ok(()) | |
248 | //! } | |
249 | //! } | |
250 | //! ``` | |
251 | //! | |
252 | //! ## Chaining errors | |
253 | //! | |
254 | //! To extend the error chain: | |
255 | //! | |
256 | //! ``` | |
257 | //! # #[macro_use] extern crate error_chain; | |
258 | //! # fn main() {} | |
259 | //! # error_chain! {} | |
260 | //! # fn do_something() -> Result<()> { unimplemented!() } | |
261 | //! # fn test() -> Result<()> { | |
262 | //! let res: Result<()> = do_something().chain_err(|| "something went wrong"); | |
263 | //! # Ok(()) | |
264 | //! # } | |
265 | //! ``` | |
266 | //! | |
267 | //! `chain_err` can be called on any `Result` type where the contained | |
268 | //! error type implements `std::error::Error + Send + 'static`. If | |
269 | //! the `Result` is an `Err` then `chain_err` evaluates the closure, | |
270 | //! which returns *some type that can be converted to `ErrorKind`*, | |
271 | //! boxes the original error to store as the cause, then returns a new | |
272 | //! error containing the original error. | |
273 | //! | |
274 | //! ## Matching errors | |
275 | //! | |
276 | //! error-chain error variants are matched with simple patterns. | |
277 | //! `Error` is a tuple struct and its first field is the `ErrorKind`, | |
278 | //! making dispatching on error kinds relatively compact: | |
279 | //! | |
280 | //! ``` | |
281 | //! # #[macro_use] extern crate error_chain; | |
282 | //! # fn main() { | |
283 | //! error_chain! { | |
284 | //! errors { | |
285 | //! InvalidToolchainName(t: String) { | |
286 | //! description("invalid toolchain name") | |
287 | //! display("invalid toolchain name: '{}'", t) | |
288 | //! } | |
289 | //! } | |
290 | //! } | |
291 | //! | |
292 | //! match Error::from("error!") { | |
293 | //! Error(ErrorKind::InvalidToolchainName(_), _) => { } | |
294 | //! Error(ErrorKind::Msg(_), _) => { } | |
295 | //! } | |
296 | //! # } | |
297 | //! ``` | |
298 | //! | |
299 | //! Chained errors are also matched with (relatively) compact syntax | |
300 | //! | |
301 | //! ``` | |
302 | //! # #[macro_use] extern crate error_chain; | |
303 | //! mod utils { | |
304 | //! error_chain! { | |
305 | //! errors { | |
306 | //! BadStuff { | |
307 | //! description("bad stuff") | |
308 | //! } | |
309 | //! } | |
310 | //! } | |
311 | //! } | |
312 | //! | |
313 | //! mod app { | |
314 | //! error_chain! { | |
315 | //! links { | |
316 | //! Utils(::utils::Error, ::utils::ErrorKind); | |
317 | //! } | |
318 | //! } | |
319 | //! } | |
320 | //! | |
321 | //! | |
322 | //! # fn main() { | |
323 | //! match app::Error::from("error!") { | |
324 | //! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { } | |
325 | //! _ => { } | |
326 | //! } | |
327 | //! # } | |
328 | //! ``` | |
329 | //! | |
330 | //! ## Foreign links | |
331 | //! | |
332 | //! Errors that do not conform to the same conventions as this library | |
333 | //! can still be included in the error chain. They are considered "foreign | |
334 | //! errors", and are declared using the `foreign_links` block of the | |
335 | //! `error_chain!` macro. `Error`s are automatically created from | |
336 | //! foreign errors by the `try!` macro. | |
337 | //! | |
338 | //! Foreign links and regular links have one crucial difference: | |
339 | //! `From` conversions for regular links *do not introduce a new error | |
340 | //! into the error chain*, while conversions for foreign links *always | |
341 | //! introduce a new error into the error chain*. So for the example | |
342 | //! above all errors deriving from the `temp::Error` type will be | |
343 | //! presented to the user as a new `ErrorKind::Temp` variant, and the | |
344 | //! cause will be the original `temp::Error` error. In contrast, when | |
345 | //! `rustup_utils::Error` is converted to `Error` the two `ErrorKind`s | |
346 | //! are converted between each other to create a new `Error` but the | |
347 | //! old error is discarded; there is no "cause" created from the | |
348 | //! original error. | |
349 | //! | |
350 | //! ## Backtraces | |
351 | //! | |
352 | //! If the `RUST_BACKTRACE` environment variable is set to anything | |
353 | //! but ``0``, the earliest non-foreign error to be generated creates | |
354 | //! a single backtrace, which is passed through all `From` conversions | |
355 | //! and `chain_err` invocations of compatible types. To read the | |
356 | //! backtrace just call the `backtrace()` method. | |
357 | //! | |
358 | //! Backtrace generation can be disabled by turning off the `backtrace` feature. | |
359 | //! | |
360 | //! ## Iteration | |
361 | //! | |
362 | //! The `iter` method returns an iterator over the chain of error boxes. | |
363 | //! | |
364 | //! [error-type]: https://github.com/DanielKeep/rust-error-type | |
365 | //! [quick-error]: https://github.com/tailhook/quick-error | |
366 | ||
367 | ||
368 | #[cfg(feature = "backtrace")] | |
369 | extern crate backtrace; | |
370 | ||
371 | use std::error; | |
372 | use std::iter::Iterator; | |
373 | #[cfg(feature = "backtrace")] | |
374 | use std::sync::Arc; | |
375 | use std::fmt; | |
376 | ||
377 | #[cfg(feature = "backtrace")] | |
378 | pub use backtrace::Backtrace; | |
379 | #[cfg(not(feature = "backtrace"))] | |
380 | /// Dummy type used when the `backtrace` feature is disabled. | |
381 | pub type Backtrace = (); | |
382 | ||
383 | #[macro_use] | |
384 | mod quick_error; | |
385 | #[macro_use] | |
386 | mod error_chain; | |
387 | #[macro_use] | |
388 | mod quick_main; | |
389 | pub use quick_main::ExitCode; | |
390 | #[cfg(feature = "example_generated")] | |
391 | pub mod example_generated; | |
392 | ||
393 | /// Iterator over the error chain using the `Error::cause()` method. | |
394 | pub struct ErrorChainIter<'a>(pub Option<&'a error::Error>); | |
395 | ||
396 | impl<'a> Iterator for ErrorChainIter<'a> { | |
397 | type Item = &'a error::Error; | |
398 | ||
399 | fn next<'b>(&'b mut self) -> Option<&'a error::Error> { | |
400 | match self.0.take() { | |
401 | Some(e) => { | |
402 | self.0 = e.cause(); | |
403 | Some(e) | |
404 | } | |
405 | None => None, | |
406 | } | |
407 | } | |
408 | } | |
409 | ||
410 | /// Returns a backtrace of the current call stack if `RUST_BACKTRACE` | |
411 | /// is set to anything but ``0``, and `None` otherwise. This is used | |
412 | /// in the generated error implementations. | |
413 | #[cfg(feature = "backtrace")] | |
414 | #[doc(hidden)] | |
415 | pub fn make_backtrace() -> Option<Arc<Backtrace>> { | |
416 | match std::env::var_os("RUST_BACKTRACE") { | |
417 | Some(ref val) if val != "0" => Some(Arc::new(Backtrace::new())), | |
418 | _ => None, | |
419 | } | |
420 | } | |
421 | ||
422 | /// This trait is implemented on all the errors generated by the `error_chain` | |
423 | /// macro. | |
424 | pub trait ChainedError: error::Error + Send + 'static { | |
425 | /// Associated kind type. | |
426 | type ErrorKind; | |
427 | ||
428 | /// Constructs an error from a kind, and generates a backtrace. | |
429 | fn from_kind(kind: Self::ErrorKind) -> Self where Self: Sized; | |
430 | ||
431 | /// Constructs a chained error from another error and a kind, and generates a backtrace. | |
432 | fn with_chain<E, K>(error: E, kind: K) -> Self | |
433 | where Self: Sized, | |
434 | E: ::std::error::Error + Send + 'static, | |
435 | K: Into<Self::ErrorKind>; | |
436 | ||
437 | /// Returns the kind of the error. | |
438 | fn kind(&self) -> &Self::ErrorKind; | |
439 | ||
440 | /// Iterates over the error chain. | |
441 | fn iter(&self) -> ErrorChainIter; | |
442 | ||
443 | /// Returns the backtrace associated with this error. | |
444 | fn backtrace(&self) -> Option<&Backtrace>; | |
445 | ||
446 | /// Returns an object which implements `Display` for printing the full | |
447 | /// context of this error. | |
448 | /// | |
449 | /// The full cause chain and backtrace, if present, will be printed. | |
450 | fn display<'a>(&'a self) -> Display<'a, Self> { | |
451 | Display(self) | |
452 | } | |
453 | ||
454 | /// Creates an error from its parts. | |
455 | #[doc(hidden)] | |
456 | fn new(kind: Self::ErrorKind, state: State) -> Self where Self: Sized; | |
457 | ||
458 | /// Returns the first known backtrace, either from its State or from one | |
459 | /// of the errors from `foreign_links`. | |
460 | #[cfg(feature = "backtrace")] | |
461 | #[doc(hidden)] | |
462 | fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<Arc<Backtrace>> | |
463 | where Self: Sized; | |
464 | } | |
465 | ||
466 | /// A struct which formats an error for output. | |
467 | #[derive(Debug)] | |
468 | pub struct Display<'a, T: 'a + ?Sized>(&'a T); | |
469 | ||
470 | impl<'a, T> fmt::Display for Display<'a, T> | |
471 | where T: ChainedError | |
472 | { | |
473 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
474 | try!(writeln!(fmt, "Error: {}", self.0)); | |
475 | ||
476 | for e in self.0.iter().skip(1) { | |
477 | try!(writeln!(fmt, "Caused by: {}", e)); | |
478 | } | |
479 | ||
480 | if let Some(backtrace) = self.0.backtrace() { | |
481 | try!(writeln!(fmt, "{:?}", backtrace)); | |
482 | } | |
483 | ||
484 | Ok(()) | |
485 | } | |
486 | } | |
487 | ||
488 | /// Common state between errors. | |
489 | #[derive(Debug)] | |
490 | #[doc(hidden)] | |
491 | pub struct State { | |
492 | /// Next error in the error chain. | |
493 | pub next_error: Option<Box<error::Error + Send>>, | |
494 | /// Backtrace for the current error. | |
495 | #[cfg(feature = "backtrace")] | |
496 | pub backtrace: Option<Arc<Backtrace>>, | |
497 | } | |
498 | ||
499 | impl Default for State { | |
500 | #[cfg(feature = "backtrace")] | |
501 | fn default() -> State { | |
502 | State { | |
503 | next_error: None, | |
504 | backtrace: make_backtrace(), | |
505 | } | |
506 | } | |
507 | ||
508 | #[cfg(not(feature = "backtrace"))] | |
509 | fn default() -> State { | |
510 | State { next_error: None } | |
511 | } | |
512 | } | |
513 | ||
514 | impl State { | |
515 | /// Creates a new State type | |
516 | #[cfg(feature = "backtrace")] | |
517 | pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State { | |
518 | let backtrace = CE::extract_backtrace(&*e).or_else(make_backtrace); | |
519 | State { | |
520 | next_error: Some(e), | |
521 | backtrace: backtrace, | |
522 | } | |
523 | } | |
524 | ||
525 | /// Creates a new State type | |
526 | #[cfg(not(feature = "backtrace"))] | |
527 | pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State { | |
528 | State { next_error: Some(e) } | |
529 | } | |
530 | ||
531 | /// Returns the inner backtrace if present. | |
532 | #[cfg(feature = "backtrace")] | |
533 | pub fn backtrace(&self) -> Option<&Backtrace> { | |
534 | self.backtrace.as_ref().map(|v| &**v) | |
535 | } | |
536 | ||
537 | /// Returns the inner backtrace if present. | |
538 | #[cfg(not(feature = "backtrace"))] | |
539 | pub fn backtrace(&self) -> Option<&Backtrace> { | |
540 | None | |
541 | } | |
542 | } | |
543 | ||
544 | /// Exits a function early with an error | |
545 | /// | |
546 | /// The `bail!` macro provides an easy way to exit a function. | |
547 | /// `bail!(expr)` is equivalent to writing. | |
548 | /// | |
549 | /// ``` | |
550 | /// # #[macro_use] extern crate error_chain; | |
551 | /// # error_chain! { } | |
552 | /// # fn main() { } | |
553 | /// # fn foo() -> Result<()> { | |
554 | /// # let expr = ""; | |
555 | /// return Err(expr.into()); | |
556 | /// # } | |
557 | /// ``` | |
558 | /// | |
559 | /// And as shorthand it takes a formatting string a la `println!`: | |
560 | /// | |
561 | /// ``` | |
562 | /// # #[macro_use] extern crate error_chain; | |
563 | /// # error_chain! { } | |
564 | /// # fn main() { } | |
565 | /// # fn foo() -> Result<()> { | |
566 | /// # let n = 0; | |
567 | /// bail!("bad number: {}", n); | |
568 | /// # } | |
569 | /// ``` | |
570 | /// | |
571 | /// # Examples | |
572 | /// | |
573 | /// Bailing on a custom error: | |
574 | /// | |
575 | /// ``` | |
576 | /// # #[macro_use] extern crate error_chain; | |
577 | /// # fn main() {} | |
578 | /// error_chain! { | |
579 | /// errors { FooError } | |
580 | /// } | |
581 | /// | |
582 | /// fn foo() -> Result<()> { | |
583 | /// if bad_condition() { | |
584 | /// bail!(ErrorKind::FooError); | |
585 | /// } | |
586 | /// | |
587 | /// Ok(()) | |
588 | /// } | |
589 | /// | |
590 | /// # fn bad_condition() -> bool { true } | |
591 | /// ``` | |
592 | /// | |
593 | /// Bailing on a formatted string: | |
594 | /// | |
595 | /// ``` | |
596 | /// # #[macro_use] extern crate error_chain; | |
597 | /// # fn main() {} | |
598 | /// error_chain! { } | |
599 | /// | |
600 | /// fn foo() -> Result<()> { | |
601 | /// if let Some(bad_num) = bad_condition() { | |
602 | /// bail!("so bad: {}", bad_num); | |
603 | /// } | |
604 | /// | |
605 | /// Ok(()) | |
606 | /// } | |
607 | /// | |
608 | /// # fn bad_condition() -> Option<i8> { None } | |
609 | /// ``` | |
610 | #[macro_export] | |
611 | macro_rules! bail { | |
612 | ($e:expr) => { | |
613 | return Err($e.into()); | |
614 | }; | |
615 | ($fmt:expr, $($arg:tt)+) => { | |
616 | return Err(format!($fmt, $($arg)+).into()); | |
617 | }; | |
618 | } | |
619 | ||
620 | /// Exits a function early with an error if the condition is not satisfied | |
621 | /// | |
622 | /// The `ensure!` macro is a convenience helper that provides a way to exit | |
623 | /// a function with an error if the given condition fails. | |
624 | /// | |
625 | /// As an example, `ensure!(condition, "error code: {}", errcode)` is equivalent to | |
626 | /// | |
627 | /// ``` | |
628 | /// # #[macro_use] extern crate error_chain; | |
629 | /// # error_chain! { } | |
630 | /// # fn main() { } | |
631 | /// # fn foo() -> Result<()> { | |
632 | /// # let errcode = 0u8; | |
633 | /// # let condition = true; | |
634 | /// if !condition { | |
635 | /// bail!("error code: {}", errcode); | |
636 | /// } | |
637 | /// # Ok(()) | |
638 | /// # } | |
639 | /// ``` | |
640 | /// | |
641 | /// See documentation for `bail!` macro for further details. | |
642 | #[macro_export] | |
643 | macro_rules! ensure { | |
644 | ($cond:expr, $e:expr) => { | |
645 | if !($cond) { | |
646 | bail!($e); | |
647 | } | |
648 | }; | |
649 | ($cond:expr, $fmt:expr, $($arg:tt)+) => { | |
650 | if !($cond) { | |
651 | bail!($fmt, $($arg)+); | |
652 | } | |
653 | }; | |
654 | } | |
655 | ||
656 | #[doc(hidden)] | |
657 | pub mod mock { | |
658 | error_chain!{} | |
659 | } |