handle_error/
lib.rs

1
2//! An error handling / bubbling macro to reduce error handling boilerplate.
3//! 
4//! For a given fallible expression (expression returning a result), such as:
5//! 
6//! ```no_run
7//! # type E = ();
8//! #
9//! fn do_something() -> Result<(), E> {
10//!     // ....
11//! # Ok(())
12//! }
13//! ```
14//! 
15//! This can be used as follows:
16//! 
17//! ```no_run
18//! #[macro_use]
19//! extern crate log;
20//! 
21//! #[macro_use]
22//! extern crate handle_error;
23//! 
24//! # type E = ();
25//! #
26//! # fn do_something() -> Result<(), E> {
27//! #     unimplemented!()
28//! # }
29//! #
30//! fn main() -> Result<(), E> {
31//!   let v = handle_error!(do_something(), "Failed to do something");
32//!   Ok(())
33//! }
34//! ```
35//! ```no_run
36//! #[macro_use]
37//! extern crate log;
38//! 
39//! #[macro_use]
40//! extern crate handle_error;
41//! 
42//! # type E = ();
43//! #
44//! # fn do_something() -> Result<(), E> {
45//! #     unimplemented!()
46//! # }
47//! #
48//! fn main() -> Result<(), E> {
49//!   let v = retry_error!(3, do_something(), "Failed to do something");
50//!   Ok(())
51//! }
52//! ```
53//! 
54//! Replacing the common patterns:
55//! 
56//! ```no_run
57//! #[macro_use]
58//! extern crate log;
59//! 
60//! #[macro_use]
61//! extern crate handle_error;
62//! 
63//! # type E = ();
64//! # fn do_something() -> Result<(), E> {
65//! #     unimplemented!()
66//! # }
67//! #
68//! // Match case where we care about the ok value
69//! fn example_one() -> Result<(), E> {
70//!   let v = match do_something() {
71//!     Ok(v) => v,
72//!     Err(e) => {
73//!       error!("Failed to do something");
74//!       return Err(e);
75//!     }
76//!   };
77//! 
78//!   Ok(())
79//! }
80//! 
81//! // If let where we do not care about the ok value
82//! fn example_two() -> Result<(), E> {
83//!   if let Err(e) = do_something() {
84//!     error!("Failed to do something");
85//!     return Err(e);
86//!   }
87//! 
88//!   Ok(())
89//! }
90//! 
91//! # fn main() {}
92//! ```
93
94
95/// Log and propagate the error result from a given expression
96///
97/// This logs the provided message and exits the function scope on error, and returns
98/// the unpacked Ok(value) on success.
99#[macro_export]
100macro_rules! handle_error {
101    ($call:expr, $msg:expr, $($params:tt)*) => (
102        match $call {
103            Ok(v) => v,
104            Err(e) => {
105                error!($msg, $($params)*);
106                return Err(e).into();
107            },
108        };
109    );
110    ($call:expr, $msg:expr) => (
111        match $call {
112            Ok(v) => v,
113            Err(e) => {
114                error!($msg);
115                return Err(e).into();
116            },
117        };
118    );
119}
120
121/// Retry a provided fallible function N times
122///
123/// This will optionally log a message, and returns the final error if all attempts fail
124#[macro_export]
125macro_rules! retry_error {
126    ($retries:expr, $fallible:expr, $($params:tt)*) => (
127        (|| {
128            let mut i = 0;
129            loop {
130                match $fallible {
131                    Ok(v) => break Ok(v),
132                    Err(e) if i < $retries => {
133                        i += 1;
134                    },
135                    Err(e) => {
136                        error!($($params)*);
137                        break Err(e)
138                    },
139                }
140            }
141        })()
142    );
143    ($retries:expr, $fallible:expr) => (
144        (|| {
145            let mut i = 0;
146            loop {
147                match $fallible {
148                    Ok(v) => break Ok(v),
149                    Err(e) if i < $retries => {
150                        i += 1;
151                    },
152                    Err(e) => break Err(e),
153                }
154            }
155        })()
156    );
157}
158