1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103

//! An error handling / bubbling macro to reduce error handling boilerplate.
//! 
//! For a given fallible expression (expression returning a result), such as:
//! 
//! ```no_run
//! # type E = ();
//! #
//! fn do_something() -> Result<(), E> {
//!     // ....
//! # Ok(())
//! }
//! ```
//! 
//! This can be used as follows:
//! 
//! ```no_run
//! #[macro_use]
//! extern crate log;
//! 
//! #[macro_use]
//! extern crate handle_error;
//! 
//! # type E = ();
//! #
//! # fn do_something() -> Result<(), E> {
//! #     unimplemented!()
//! # }
//! #
//! fn main() -> Result<(), E> {
//!   let v = handle_error!(do_something(), "Failed to do something");
//!   Ok(())
//! }
//! ```
//! 
//! Replacing the common patterns:
//! 
//! ```no_run
//! #[macro_use]
//! extern crate log;
//! 
//! #[macro_use]
//! extern crate handle_error;
//! 
//! # type E = ();
//! # fn do_something() -> Result<(), E> {
//! #     unimplemented!()
//! # }
//! #
//! // Match case where we care about the ok value
//! fn example_one() -> Result<(), E> {
//!   let v = match do_something() {
//!     Ok(v) => v,
//!     Err(e) => {
//!       error!("Failed to do something");
//!       return Err(e);
//!     }
//!   };
//! 
//!   Ok(())
//! }
//! 
//! // If let where we do not care about the ok value
//! fn example_two() -> Result<(), E> {
//!   if let Err(e) = do_something() {
//!     error!("Failed to do something");
//!     return Err(e);
//!   }
//! 
//!   Ok(())
//! }
//! 
//! # fn main() {}
//! ```


/// Log and propagate the error result from a given expression
///
/// This logs the provided message and exits the function scope on error, and returns
/// the unpacked Ok(value) on success.
#[macro_export]
macro_rules! handle_error {
    ($call:expr, $msg:expr, $($params:tt)*) => (
        match $call {
            Ok(v) => v,
            Err(e) => {
                error!($msg, $($params)*);
                return Err(e).into();
            },
        };
    );
    ($call:expr, $msg:expr) => (
        match $call {
            Ok(v) => v,
            Err(e) => {
                error!($msg);
                return Err(e).into();
            },
        };
    );
}