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