diff options
Diffstat (limited to 'third_party/rust/error-chain/src/lib.rs')
-rw-r--r-- | third_party/rust/error-chain/src/lib.rs | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/third_party/rust/error-chain/src/lib.rs b/third_party/rust/error-chain/src/lib.rs new file mode 100644 index 0000000000..43d2d5f479 --- /dev/null +++ b/third_party/rust/error-chain/src/lib.rs @@ -0,0 +1,824 @@ +#![deny(missing_docs)] +#![doc(html_root_url = "https://docs.rs/error-chain/0.12.4")] + +//! A library for consistent and reliable error handling +//! +//! error-chain makes it easy to take full advantage of Rust's +//! powerful error handling features without the overhead of +//! maintaining boilerplate error types and conversions. It implements +//! an opinionated strategy for defining your own error types, as well +//! as conversions from others' error types. +//! +//! ## Quick start +//! +//! If you just want to set up your new project with error-chain, +//! follow the [quickstart.rs] template, and read this [intro] +//! to error-chain. +//! +//! [quickstart.rs]: https://github.com/rust-lang-nursery/error-chain/blob/master/examples/quickstart.rs +//! [intro]: http://brson.github.io/2016/11/30/starting-with-error-chain +//! +//! ## Why error chain? +//! +//! * error-chain is easy to configure. Handle errors robustly with minimal +//! effort. +//! * Basic error handling requires no maintenance of custom error types +//! nor the [`From`] conversions that make `?` work. +//! * error-chain scales from simple error handling strategies to more +//! rigorous. Return formatted strings for simple errors, only +//! introducing error variants and their strong typing as needed for +//! advanced error recovery. +//! * error-chain makes it trivial to correctly manage the [cause] of +//! the errors generated by your own code. This is the "chaining" +//! in "error-chain". +//! +//! [cause]: https://doc.rust-lang.org/std/error/trait.Error.html#method.cause +//! +//! ## Principles of error-chain +//! +//! error-chain is based on the following principles: +//! +//! * No error should ever be discarded. This library primarily +//! makes it easy to "chain" errors with the [`chain_err`] method. +//! * Introducing new errors is trivial. Simple errors can be introduced +//! at the error site with just a string. +//! * Handling errors is possible with pattern matching. +//! * Conversions between error types are done in an automatic and +//! consistent way - [`From`] conversion behavior is never specified +//! explicitly. +//! * Errors implement [`Send`]. +//! * Errors can carry backtraces. +//! +//! Similar to other libraries like [error-type] and [quick-error], +//! this library introduces the error chaining mechanism originally +//! employed by Cargo. The [`error_chain!`] macro declares the types +//! and implementation boilerplate necessary for fulfilling a +//! particular error-handling strategy. Most importantly it defines a +//! custom error type (called [`Error`] by convention) and the [`From`] +//! conversions that let the `?` operator work. +//! +//! This library differs in a few ways from previous error libs: +//! +//! * Instead of defining the custom [`Error`] type as an enum, it is a +//! struct containing an [`ErrorKind`][] (which defines the +//! [`description`] and [`display_chain`] methods for the error), an opaque, +//! optional, boxed [`std::error::Error`]` + `[`Send`]` + 'static` object +//! (which defines the [`cause`], and establishes the links in the +//! error chain), and a [`Backtrace`]. +//! * The macro also defines a [`ResultExt`] trait that defines a +//! [`chain_err`] method. This method on all [`std::error::Error`]` + `[`Send`]` + 'static` +//! types extends the error chain by boxing the current +//! error into an opaque object and putting it inside a new concrete +//! error. +//! * It provides automatic [`From`] conversions between other error types +//! defined by the [`error_chain!`] that preserve type information, +//! and facilitate seamless error composition and matching of composed +//! errors. +//! * It provides automatic [`From`] conversions between any other error +//! type that hides the type of the other error in the [`cause`] box. +//! * If `RUST_BACKTRACE` is enabled, it collects a single backtrace at +//! the earliest opportunity and propagates it down the stack through +//! [`From`] and [`ResultExt`] conversions. +//! +//! To accomplish its goals it makes some tradeoffs: +//! +//! * The split between the [`Error`] and [`ErrorKind`] types can make it +//! slightly more cumbersome to instantiate new (unchained) errors, +//! requiring an [`Into`] or [`From`] conversion; as well as slightly +//! more cumbersome to match on errors with another layer of types +//! to match. +//! * Because the error type contains [`std::error::Error`]` + `[`Send`]` + 'static` objects, +//! it can't implement [`PartialEq`] for easy comparisons. +//! +//! ## Declaring error types +//! +//! Generally, you define one family of error types per crate, though +//! it's also perfectly fine to define error types on a finer-grained +//! basis, such as per module. +//! +//! Assuming you are using crate-level error types, typically you will +//! define an `errors` module and inside it call [`error_chain!`]: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! mod other_error { +//! error_chain! {} +//! } +//! +//! error_chain! { +//! // The type defined for this error. These are the conventional +//! // and recommended names, but they can be arbitrarily chosen. +//! // +//! // It is also possible to leave this section out entirely, or +//! // leave it empty, and these names will be used automatically. +//! types { +//! Error, ErrorKind, ResultExt, Result; +//! } +//! +//! // Without the `Result` wrapper: +//! // +//! // types { +//! // Error, ErrorKind, ResultExt; +//! // } +//! +//! // Automatic conversions between this error chain and other +//! // error chains. In this case, it will e.g. generate an +//! // `ErrorKind` variant called `Another` which in turn contains +//! // the `other_error::ErrorKind`, with conversions from +//! // `other_error::Error`. +//! // +//! // Optionally, some attributes can be added to a variant. +//! // +//! // This section can be empty. +//! links { +//! Another(other_error::Error, other_error::ErrorKind) #[cfg(unix)]; +//! } +//! +//! // Automatic conversions between this error chain and other +//! // error types not defined by the `error_chain!`. These will be +//! // wrapped in a new error with, in the first case, the +//! // `ErrorKind::Fmt` variant. The description and cause will +//! // forward to the description and cause of the original error. +//! // +//! // Optionally, some attributes can be added to a variant. +//! // +//! // This section can be empty. +//! foreign_links { +//! Fmt(::std::fmt::Error); +//! Io(::std::io::Error) #[cfg(unix)]; +//! } +//! +//! // Define additional `ErrorKind` variants. Define custom responses with the +//! // `description` and `display` calls. +//! errors { +//! InvalidToolchainName(t: String) { +//! description("invalid toolchain name") +//! display("invalid toolchain name: '{}'", t) +//! } +//! +//! // You can also add commas after description/display. +//! // This may work better with some editor auto-indentation modes: +//! UnknownToolchainVersion(v: String) { +//! description("unknown toolchain version"), // note the , +//! display("unknown toolchain version: '{}'", v), // trailing comma is allowed +//! } +//! } +//! +//! // If this annotation is left off, a variant `Msg(s: String)` will be added, and `From` +//! // impls will be provided for `String` and `&str` +//! skip_msg_variant +//! } +//! +//! # fn main() {} +//! ``` +//! +//! Each section, `types`, `links`, `foreign_links`, and `errors` may +//! be omitted if it is empty. +//! +//! This populates the module with a number of definitions, +//! the most important of which are the [`Error`] type +//! and the [`ErrorKind`] type. An example of generated code can be found in the +//! [example_generated](example_generated/index.html) module. +//! +//! ## Returning new errors +//! +//! Introducing new error chains, with a string message: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # error_chain! {} +//! fn foo() -> Result<()> { +//! Err("foo error!".into()) +//! } +//! ``` +//! +//! Introducing new error chains, with an [`ErrorKind`]: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! error_chain! { +//! errors { FooError } +//! } +//! +//! fn foo() -> Result<()> { +//! Err(ErrorKind::FooError.into()) +//! } +//! ``` +//! +//! Note that the return type is the typedef [`Result`], which is +//! defined by the macro as `pub type Result<T> = +//! ::std::result::Result<T, Error>`. Note that in both cases +//! [`.into()`] is called to convert a type into the [`Error`] type; both +//! strings and [`ErrorKind`] have [`From`] conversions to turn them into +//! [`Error`]. +//! +//! When the error is emitted behind the `?` operator, the explicit conversion +//! isn't needed; `Err(ErrorKind)` will automatically be converted to `Err(Error)`. +//! So the below is equivalent to the previous: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # error_chain! { errors { FooError } } +//! fn foo() -> Result<()> { +//! Ok(Err(ErrorKind::FooError)?) +//! } +//! +//! fn bar() -> Result<()> { +//! Ok(Err("bogus!")?) +//! } +//! ``` +//! +//! ## The `bail!` macro +//! +//! The above method of introducing new errors works but is a little +//! verbose. Instead, we can use the [`bail!`] macro, which performs an early return +//! with conversions done automatically. +//! +//! With [`bail!`] the previous examples look like: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # error_chain! { errors { FooError } } +//! fn foo() -> Result<()> { +//! if true { +//! bail!(ErrorKind::FooError); +//! } else { +//! Ok(()) +//! } +//! } +//! +//! fn bar() -> Result<()> { +//! if true { +//! bail!("bogus!"); +//! } else { +//! Ok(()) +//! } +//! } +//! ``` +//! +//! ## Chaining errors +//! error-chain supports extending an error chain by appending new errors. +//! This can be done on a Result or on an existing Error. +//! +//! To extend the error chain: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # error_chain! {} +//! # fn do_something() -> Result<()> { unimplemented!() } +//! # fn test() -> Result<()> { +//! let res: Result<()> = do_something().chain_err(|| "something went wrong"); +//! # Ok(()) +//! # } +//! ``` +//! +//! [`chain_err`] can be called on any [`Result`] type where the contained +//! error type implements [`std::error::Error`]` + `[`Send`]` + 'static`, as long as +//! the [`Result`] type's corresponding [`ResultExt`] trait is in scope. If +//! the [`Result`] is an `Err` then [`chain_err`] evaluates the closure, +//! which returns *some type that can be converted to [`ErrorKind`]*, +//! boxes the original error to store as the cause, then returns a new +//! error containing the original error. +//! +//! Calling [`chain_err`][Error_chain_err] on an existing [`Error`] instance has +//! the same signature and produces the same outcome as being called on a +//! [`Result`] matching the properties described above. This is most useful when +//! partially handling errors using the [`map_err`] function. +//! +//! To chain an error directly, use [`with_chain`]: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # error_chain! {} +//! # fn do_something() -> Result<()> { unimplemented!() } +//! # fn test() -> Result<()> { +//! let res: Result<()> = +//! do_something().map_err(|e| Error::with_chain(e, "something went wrong")); +//! # Ok(()) +//! # } +//! ``` +//! +//! ## Linking errors +//! +//! To convert an error from another error chain to this error chain: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() {} +//! # mod other { error_chain! {} } +//! error_chain! { +//! links { +//! OtherError(other::Error, other::ErrorKind); +//! } +//! } +//! +//! fn do_other_thing() -> other::Result<()> { unimplemented!() } +//! +//! # fn test() -> Result<()> { +//! let res: Result<()> = do_other_thing().map_err(|e| e.into()); +//! # Ok(()) +//! # } +//! ``` +//! +//! The [`Error`] and [`ErrorKind`] types implements [`From`] for the corresponding +//! types of all linked error chains. Linked errors do not introduce a new +//! cause to the error chain. +//! +//! ## Matching errors +//! +//! error-chain error variants are matched with simple patterns. +//! [`Error`] is a tuple struct and its first field is the [`ErrorKind`], +//! making dispatching on error kinds relatively compact: +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! # fn main() { +//! error_chain! { +//! errors { +//! InvalidToolchainName(t: String) { +//! description("invalid toolchain name") +//! display("invalid toolchain name: '{}'", t) +//! } +//! } +//! } +//! +//! match Error::from("error!") { +//! Error(ErrorKind::InvalidToolchainName(_), _) => { } +//! Error(ErrorKind::Msg(_), _) => { } +//! _ => { } +//! } +//! # } +//! ``` +//! +//! Chained errors are also matched with (relatively) compact syntax +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! mod utils { +//! error_chain! { +//! errors { +//! BadStuff { +//! description("bad stuff") +//! } +//! } +//! } +//! } +//! +//! mod app { +//! error_chain! { +//! links { +//! Utils(::utils::Error, ::utils::ErrorKind); +//! } +//! } +//! } +//! +//! +//! # fn main() { +//! match app::Error::from("error!") { +//! app::Error(app::ErrorKind::Utils(utils::ErrorKind::BadStuff), _) => { } +//! _ => { } +//! } +//! # } +//! ``` +//! +//! ## Inspecting errors +//! +//! An error-chain error contains information about the error itself, a backtrace, and the chain +//! of causing errors. For reporting purposes, this information can be accessed as follows. +//! +//! ``` +//! # #[macro_use] extern crate error_chain; +//! use error_chain::ChainedError; // for e.display_chain() +//! +//! error_chain! { +//! errors { +//! InvalidToolchainName(t: String) { +//! description("invalid toolchain name") +//! display("invalid toolchain name: '{}'", t) +//! } +//! } +//! } +//! +//! # fn main() { +//! // Generate an example error to inspect: +//! let e = "xyzzy".parse::<i32>() +//! .chain_err(|| ErrorKind::InvalidToolchainName("xyzzy".to_string())) +//! .unwrap_err(); +//! +//! // Get the brief description of the error: +//! assert_eq!(e.description(), "invalid toolchain name"); +//! +//! // Get the display version of the error: +//! assert_eq!(e.to_string(), "invalid toolchain name: 'xyzzy'"); +//! +//! // Get the full cause and backtrace: +//! println!("{}", e.display_chain().to_string()); +//! // Error: invalid toolchain name: 'xyzzy' +//! // Caused by: invalid digit found in string +//! // stack backtrace: +//! // 0: 0x7fa9f684fc94 - backtrace::backtrace::libunwind::trace +//! // at src/backtrace/libunwind.rs:53 +//! // - backtrace::backtrace::trace<closure> +//! // at src/backtrace/mod.rs:42 +//! // 1: 0x7fa9f6850b0e - backtrace::capture::{{impl}}::new +//! // at out/capture.rs:79 +//! // [..] +//! # } +//! ``` +//! +//! The [`Error`] and [`ErrorKind`] types also allow programmatic access to these elements. +//! +//! ## Foreign links +//! +//! Errors that do not conform to the same conventions as this library +//! can still be included in the error chain. They are considered "foreign +//! errors", and are declared using the `foreign_links` block of the +//! [`error_chain!`] macro. [`Error`]s are automatically created from +//! foreign errors by the `?` operator. +//! +//! Foreign links and regular links have one crucial difference: +//! [`From`] conversions for regular links *do not introduce a new error +//! into the error chain*, while conversions for foreign links *always +//! introduce a new error into the error chain*. So for the example +//! above all errors deriving from the [`std::fmt::Error`] type will be +//! presented to the user as a new [`ErrorKind`] variant, and the +//! cause will be the original [`std::fmt::Error`] error. In contrast, when +//! `other_error::Error` is converted to `Error` the two `ErrorKind`s +//! are converted between each other to create a new `Error` but the +//! old error is discarded; there is no "cause" created from the +//! original error. +//! +//! ## Backtraces +//! +//! If the `RUST_BACKTRACE` environment variable is set to anything +//! but ``0``, the earliest non-foreign error to be generated creates +//! a single backtrace, which is passed through all [`From`] conversions +//! and [`chain_err`] invocations of compatible types. To read the +//! backtrace just call the [`backtrace`] method. +//! +//! Backtrace generation can be disabled by turning off the `backtrace` feature. +//! +//! The Backtrace contains a Vec of [`BacktraceFrame`]s that can be operated +//! on directly. For example, to only see the files and line numbers of code +//! within your own project. +//! +//! ``` +//! # #[macro_use] +//! # extern crate error_chain; +//! # mod errors { +//! # error_chain! { +//! # foreign_links { +//! # Io(::std::io::Error); +//! # } +//! # } +//! # } +//! # use errors::*; +//! # #[cfg(feature="backtrace")] +//! # fn main() { +//! if let Err(ref e) = open_file() { +//! if let Some(backtrace) = e.backtrace() { +//! let frames = backtrace.frames(); +//! for frame in frames.iter() { +//! for symbol in frame.symbols().iter() { +//! if let (Some(file), Some(lineno)) = (symbol.filename(), symbol.lineno()) { +//! if file.display().to_string()[0..3] == "src".to_string(){ +//! println!("{}:{}", file.display().to_string(), lineno); +//! } +//! } +//! } +//! } +//! } +//! }; +//! # } +//! # #[cfg(not(feature="backtrace"))] +//! # fn main() { } +//! +//! fn open_file() -> Result<()> { +//! std::fs::File::open("does_not_exist")?; +//! Ok(()) +//! } +//! ``` +//! +//! ## Iteration +//! +//! The [`iter`] method returns an iterator over the chain of error boxes. +//! +//! [error-type]: https://github.com/DanielKeep/rust-error-type +//! [quick-error]: https://github.com/tailhook/quick-error + +//! [`display_chain`]: trait.ChainedError.html#method.display_chain +//! [`error_chain!`]: macro.error_chain.html +//! [`bail!`]: macro.bail.html +//! [`Backtrace`]: struct.Backtrace.html + +//! [`Error`]: example_generated/struct.Error.html +//! [`with_chain`]: example_generated/struct.Error.html#method.with_chain +//! [Error_chain_err]: example_generated/struct.Error.html#method.chain_err +//! [`cause`]: example_generated/struct.Error.html#method.cause +//! [`backtrace`]: example_generated/struct.Error.html#method.backtrace +//! [`iter`]: example_generated/struct.Error.html#method.iter +//! [`ErrorKind`]: example_generated/enum.ErrorKind.html +//! [`description`]: example_generated/enum.ErrorKind.html#method.description +//! [`Result`]: example_generated/type.Result.html +//! [`ResultExt`]: example_generated/trait.ResultExt.html +//! [`chain_err`]: example_generated/trait.ResultExt.html#tymethod.chain_err + +//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html +//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +//! [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html +//! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html +//! [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html +//! [`std::fmt::Error`]: https://doc.rust-lang.org/std/fmt/struct.Error.html +//! [`.into()`]: https://doc.rust-lang.org/std/convert/trait.Into.html#tymethod.into +//! [`map_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err +//! [`BacktraceFrame`]: https://docs.rs/backtrace/0.3.2/backtrace/struct.BacktraceFrame.html + +use std::error; +use std::fmt; +use std::iter::Iterator; + +#[macro_use] +mod impl_error_chain_kind; +#[macro_use] +mod error_chain; +#[macro_use] +mod quick_main; +pub use quick_main::ExitCode; +mod backtrace; +#[cfg(feature = "example_generated")] +pub mod example_generated; +pub use backtrace::Backtrace; +#[doc(hidden)] +pub use backtrace::InternalBacktrace; + +#[derive(Debug)] +#[allow(unknown_lints, bare_trait_objects)] +/// Iterator over the error chain using the `Error::cause()` method. +pub struct Iter<'a>(Option<&'a error::Error>); + +impl<'a> Iter<'a> { + /// Returns a new iterator over the error chain using `Error::cause()`. + #[allow(unknown_lints, bare_trait_objects)] + pub fn new(err: Option<&'a error::Error>) -> Iter<'a> { + Iter(err) + } +} + +#[allow(unknown_lints, bare_trait_objects)] +impl<'a> Iterator for Iter<'a> { + type Item = &'a error::Error; + + fn next<'b>(&'b mut self) -> Option<&'a error::Error> { + match self.0.take() { + Some(e) => { + self.0 = match () { + #[cfg(not(has_error_source))] + () => e.cause(), + #[cfg(has_error_source)] + () => e.source(), + }; + Some(e) + } + None => None, + } + } +} + +/// This trait is implemented on all the errors generated by the `error_chain` +/// macro. +pub trait ChainedError: error::Error + Send + 'static { + /// Associated kind type. + type ErrorKind; + + /// Constructs an error from a kind, and generates a backtrace. + fn from_kind(kind: Self::ErrorKind) -> Self + where + Self: Sized; + + /// Constructs a chained error from another error and a kind, and generates a backtrace. + fn with_chain<E, K>(error: E, kind: K) -> Self + where + Self: Sized, + E: ::std::error::Error + Send + 'static, + K: Into<Self::ErrorKind>; + + /// Returns the kind of the error. + fn kind(&self) -> &Self::ErrorKind; + + /// Iterates over the error chain. + fn iter(&self) -> Iter; + + /// Returns the backtrace associated with this error. + fn backtrace(&self) -> Option<&Backtrace>; + + /// Returns an object which implements `Display` for printing the full + /// context of this error. + /// + /// The full cause chain and backtrace, if present, will be printed. + fn display_chain<'a>(&'a self) -> DisplayChain<'a, Self> { + DisplayChain(self) + } + + /// Extends the error chain with a new entry. + fn chain_err<F, EK>(self, error: F) -> Self + where + F: FnOnce() -> EK, + EK: Into<Self::ErrorKind>; + + /// Creates an error from its parts. + #[doc(hidden)] + fn new(kind: Self::ErrorKind, state: State) -> Self + where + Self: Sized; + + /// Returns the first known backtrace, either from its State or from one + /// of the errors from `foreign_links`. + #[doc(hidden)] + #[allow(unknown_lints, bare_trait_objects)] + fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<InternalBacktrace> + where + Self: Sized; +} + +/// A struct which formats an error for output. +#[derive(Debug)] +pub struct DisplayChain<'a, T: 'a + ?Sized>(&'a T); + +impl<'a, T> fmt::Display for DisplayChain<'a, T> +where + T: ChainedError, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + writeln!(fmt, "Error: {}", self.0)?; + + for e in self.0.iter().skip(1) { + writeln!(fmt, "Caused by: {}", e)?; + } + + if let Some(backtrace) = ChainedError::backtrace(self.0) { + writeln!(fmt, "{:?}", backtrace)?; + } + + Ok(()) + } +} + +/// Common state between errors. +#[derive(Debug)] +#[doc(hidden)] +#[allow(unknown_lints, bare_trait_objects)] +pub struct State { + /// Next error in the error chain. + pub next_error: Option<Box<error::Error + Send>>, + /// Backtrace for the current error. + pub backtrace: InternalBacktrace, +} + +impl Default for State { + fn default() -> State { + State { + next_error: None, + backtrace: InternalBacktrace::new(), + } + } +} + +impl State { + /// Creates a new State type + #[allow(unknown_lints, bare_trait_objects)] + pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State { + let backtrace = CE::extract_backtrace(&*e).unwrap_or_else(InternalBacktrace::new); + State { + next_error: Some(e), + backtrace: backtrace, + } + } + + /// Returns the inner backtrace if present. + pub fn backtrace(&self) -> Option<&Backtrace> { + self.backtrace.as_backtrace() + } +} + +/// Exits a function early with an error +/// +/// The `bail!` macro provides an easy way to exit a function. +/// `bail!(expr)` is equivalent to writing. +/// +/// ``` +/// # #[macro_use] extern crate error_chain; +/// # error_chain! { } +/// # fn main() { } +/// # fn foo() -> Result<()> { +/// # let expr = ""; +/// return Err(expr.into()); +/// # } +/// ``` +/// +/// And as shorthand it takes a formatting string a la `println!`: +/// +/// ``` +/// # #[macro_use] extern crate error_chain; +/// # error_chain! { } +/// # fn main() { } +/// # fn foo() -> Result<()> { +/// # let n = 0; +/// bail!("bad number: {}", n); +/// # } +/// ``` +/// +/// # Examples +/// +/// Bailing on a custom error: +/// +/// ``` +/// # #[macro_use] extern crate error_chain; +/// # fn main() {} +/// error_chain! { +/// errors { FooError } +/// } +/// +/// fn foo() -> Result<()> { +/// if bad_condition() { +/// bail!(ErrorKind::FooError); +/// } +/// +/// Ok(()) +/// } +/// +/// # fn bad_condition() -> bool { true } +/// ``` +/// +/// Bailing on a formatted string: +/// +/// ``` +/// # #[macro_use] extern crate error_chain; +/// # fn main() {} +/// error_chain! { } +/// +/// fn foo() -> Result<()> { +/// if let Some(bad_num) = bad_condition() { +/// bail!("so bad: {}", bad_num); +/// } +/// +/// Ok(()) +/// } +/// +/// # fn bad_condition() -> Option<i8> { None } +/// ``` +#[macro_export] +macro_rules! bail { + ($e:expr) => { + return Err($e.into()); + }; + ($fmt:expr, $($arg:tt)+) => { + return Err(format!($fmt, $($arg)+).into()); + }; +} + +/// Exits a function early with an error if the condition is not satisfied +/// +/// The `ensure!` macro is a convenience helper that provides a way to exit +/// a function with an error if the given condition fails. +/// +/// As an example, `ensure!(condition, "error code: {}", errcode)` is equivalent to +/// +/// ``` +/// # #[macro_use] extern crate error_chain; +/// # error_chain! { } +/// # fn main() { } +/// # fn foo() -> Result<()> { +/// # let errcode = 0u8; +/// # let condition = true; +/// if !condition { +/// bail!("error code: {}", errcode); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// See documentation for `bail!` macro for further details. +#[macro_export(local_inner_macros)] +macro_rules! ensure { + ($cond:expr, $e:expr) => { + if !($cond) { + bail!($e); + } + }; + ($cond:expr, $fmt:expr, $($arg:tt)+) => { + if !($cond) { + bail!($fmt, $($arg)+); + } + }; +} + +#[doc(hidden)] +pub mod mock { + error_chain! {} +} |