loop_unwrap/lib.rs
1//! # loop_unwrap
2//! Provides utility macros for unwrapping during loops.
3
4/// Works like `.unwrap`, if it's an Err or None, it calls `continue` on the loop.
5/// Prints an error message with `println!()` if provided.
6/// Loop Label can be provided in any order besides the Result/Option being the first argument.
7/// If loop label is proivded, the specified loop will be continued.
8/// # Examples
9/// ```
10/// loop {
11/// let input = "Not a number";
12/// let parsed_input: i32 = unwrap_continue!(input.parse()); //parse returns Err for this input
13/// break; //<-- never reached, since `continue` is called.
14/// }
15/// ```
16/// ```
17/// loop {
18/// let input = "Not a number";
19/// let parsed_input: i32 = unwrap_continue!(input.parse(), "Please Enter a Number!");
20/// // "Please Enter a Number!" is printed in console with a `println!()`
21/// break;
22/// }
23/// ```
24/// ```
25/// loop {
26/// let some_value: i32 = unwrap_continue!(Some(32), "Please Enter a Number!");
27/// assert_eq!(some_value, 32_i32)
28/// }
29/// ```
30/// ```
31/// 'main: loop {
32/// loop {
33/// let n =
34/// unwrap_continue!("t".parse::<i32>(), "Couldn't parse, retrying main loop", 'main);
35/// break 'main; //<-- this line will never be reached, and main will go into an infinite loop
36/// }
37/// break; //<-- this line won't be reached, since 'main will be continued infinitely
38/// }
39/// ```
40#[macro_export]
41macro_rules! unwrap_continue {
42 ($x:expr) => {
43 match $x.to_option() {
44 Some(v) => v,
45 None => {
46 continue;
47 }
48 }
49 };
50 ($x:expr, $label:lifetime) => {
51 match $x.to_option() {
52 Some(v) => v,
53 None => {
54 continue $label;
55 }
56 }
57 };
58 ($x:expr, $label:lifetime, $err_msg:expr) => {
59 match $x.to_option() {
60 Some(v) => v,
61 None => {
62 println!("{}", $err_msg);
63 continue $label;
64 }
65 }
66 };
67 ($x:expr, $err_msg:expr) => {
68 match $x.to_option() {
69 Some(v) => v,
70 None => {
71 println!("{}", $err_msg);
72 continue;
73 }
74 }
75 };
76 ($x:expr, $err_msg:expr, $label:lifetime) => {
77 match $x.to_option() {
78 Some(v) => v,
79 None => {
80 println!("{}", $err_msg);
81 continue $label;
82 }
83 }
84 };
85
86
87
88}
89
90/// Works like `.unwrap`, if it's an Err or None, it calls `break` on the loop.
91/// Prints an error message with `println!()` if provided.
92/// Loop Label can be provided in any order besides the Result/Option being the first argument.
93/// If loop label is proivded, the specified loop will be break;-ed.
94/// # Examples
95/// ```
96/// loop {
97/// let input = "Not a number";
98/// let parsed_input: i32 = unwrap_break!(input.parse()); //parse returns Err for this input
99/// }
100/// println!("This line will be reached.");
101/// ```
102/// ```
103/// loop {
104/// let input = "Not a number";
105/// let parsed_input: i32 = unwrap_break!(input.parse(), "Please Enter a Number!");
106/// // "Please Enter a Number!" is printed in console with a `println!()`
107/// //loop breaks
108/// }
109/// ```
110/// ```
111/// loop {
112/// let some_value: i32 = unwrap_break!(Some(32), "Please Enter a Number!");
113/// assert_eq!(some_value, 32_i32)
114/// //no breakage here.
115/// }
116/// ```
117/// ```
118/// 'main: loop {
119/// loop {
120/// let n = unwrap_break!("t".parse::<i32>(), "Couldn't parse, exiting main loop", 'main);
121/// break; //<-- this line won't be reached.
122/// }
123/// println!("This line will never be reached, because 'main breaks.");
124/// }
125/// ```
126#[macro_export]
127macro_rules! unwrap_break {
128 ($x:expr) => {
129 match $x.to_option() {
130 Some(v) => v,
131 None => {
132 break;
133 }
134 }
135 };
136 ($x:expr, $label:lifetime) => {
137 match $x.to_option() {
138 Some(v) => v,
139 None => {
140 break $label;
141 }
142 }
143 };
144 ($x:expr, $label:lifetime, $err_msg:expr) => {
145 match $x.to_option() {
146 Some(v) => v,
147 None => {
148 println!("{}", $err_msg);
149 break $label;
150 }
151 }
152 };
153 ($x:expr, $err_msg:expr) => {
154 match $x.to_option() {
155 Some(v) => v,
156 None => {
157 println!("{}", $err_msg);
158 break;
159 }
160 }
161 };
162 ($x:expr, $err_msg:expr, $label:lifetime) => {
163 match $x.to_option() {
164 Some(v) => v,
165 None => {
166 println!("{}", $err_msg);
167 break $label;
168 }
169 }
170 };
171}
172
173/// Works only on Result enum. If the value is Err(e), breaks the loop returning Err(e).
174/// Otherwise, it unwraps and the code continues.
175/// Supports loop labels.
176/// # Examples
177/// ```
178/// let value = loop {
179/// let s = "not a number";
180/// let n = unwrap_break_err!(s.parse::<i32>(), "Couldn't parse number."); // breaks with error value
181/// break Ok(n + 1); //<-- this line will never be reached since the macro breaks
182/// };
183/// assert_eq!(true, value.is_err());
184/// ```
185/// ```
186/// let result = 'main: loop {
187/// loop {
188/// let n = unwrap_break_err!("t".parse::<i32>(), 'main);
189/// break 'main Ok(100);
190/// }
191/// };
192/// assert_eq!(result.is_err(), true);
193/// ```
194#[macro_export]
195macro_rules! unwrap_break_err {
196 ($x:expr) => {
197 match $x {
198 Ok(v) => v,
199 Err(e) => {
200 break Err(e);
201 }
202 }
203 };
204 ($x:expr, $label:lifetime) => {
205 match $x {
206 Ok(v) => v,
207 Err(e) => {
208 break $label Err(e);
209 }
210 }
211 };
212 ($x:expr, $label:lifetime, $err_msg:expr) => {
213 match $x {
214 Ok(v) => v,
215 Err(e) => {
216 println!("{}", $err_msg);
217 break $label Err(e);
218 }
219 }
220 };
221 ($x:expr, $err_msg:expr) => {
222 match $x {
223 Ok(v) => v,
224 Err(e) => {
225 println!("{}", $err_msg);
226 break Err(e);
227 }
228 }
229 };
230 ($x:expr, $err_msg:expr, $label:lifetime) => {
231 match $x {
232 Ok(v) => v,
233 Err(e) => {
234 println!("{}", $err_msg);
235 break $label Err(e);
236 }
237 }
238 };
239}
240
241pub trait ToOption<T> {
242 fn to_option(self) -> Option<T>;
243}
244
245impl<T> ToOption<T> for Option<T> {
246 fn to_option(self) -> Option<T> {
247 self
248 }
249}
250
251impl<T, U> ToOption<T> for Result<T, U> {
252 fn to_option(self) -> Option<T> {
253 match self {
254 Ok(v) => Some(v),
255 Err(_) => None,
256 }
257 }
258}