flow_control/lib.rs
1
2//! [`break`]: https://doc.rust-lang.org/std/keyword.break.html
3//! [`continue`]: https://doc.rust-lang.org/std/keyword.continue.html
4//! [`return`]: https://doc.rust-lang.org/std/keyword.return.html
5//!
6//! Declarative macros for common control-flow use cases such as [`break`], [`continue`], and [`return`].
7//!
8//! ---
9//!
10//! [`break_if!(...)`](crate::break_if)
11//!
12//! [`break`] from a loop if a given predicate evaluates to [`true`].
13//!
14//! Supports optionally providing a loop label to specify the loop from which to [`break`].
15//! ```text
16//! use flow_control::break_if;
17//!
18//! break_if!(predicate);
19//! break_if!(predicate, label);
20//! ```
21//!
22//! ---
23//!
24//! [`continue_if!(...)`](crate::continue_if)
25//!
26//! [`continue`] to the next iteration of a loop if a given predicate evaluates to [`true`].
27//!
28//! Supports optionally providing a loop label to specify the loop in which to [`continue`].
29//! ```text
30//! use flow_control::continue_if;
31//!
32//! continue_if!(predicate);
33//! continue_if!(predicate, label);
34//! ```
35//!
36//! ---
37//!
38//! [`return_if!(...)`](crate::return_if)
39//!
40//! [`return`] from a function if a given predicate evaluates to [`true`].
41//!
42//! Supports optionally providing a value to [`return`].
43//! ```text
44//! use flow_control::return_if;
45//!
46//! return_if!(predicate);
47//! return_if!(predicate, value);
48//! ```
49//!
50//! ---
51//!
52
53/// [`break`]: https://doc.rust-lang.org/std/keyword.break.html
54///
55/// [`break`] from a loop if a given predicate evaluates to [`true`].
56///
57/// Supports optionally providing a loop label to specify the loop from which to [`break`].
58///
59/// # Usage
60///
61/// [`break_if!`](crate::break_if)`(predicate)`
62///
63/// [`break_if!`](crate::break_if)`(predicate, label)`
64///
65/// # Examples
66///
67/// #### Predicate only
68/// ```
69/// use flow_control::break_if;
70///
71/// let mut v = Vec::new();
72/// for outer_n in 1..3 {
73/// for inner_n in 1..5 {
74/// break_if!(inner_n == 3);
75/// v.push((outer_n, inner_n));
76/// }
77/// }
78///
79/// assert_eq!(
80/// v,
81/// vec![
82/// (1, 1), (1, 2),
83/// (2, 1), (2, 2),
84/// ]
85/// );
86/// ```
87///
88/// #### Predicate and label
89/// ```
90/// use flow_control::break_if;
91///
92/// let mut v = Vec::new();
93/// 'outer: for outer_n in 1..3 {
94/// for inner_n in 1..5 {
95/// break_if!(inner_n == 3, 'outer);
96/// v.push((outer_n, inner_n));
97/// }
98/// }
99///
100/// assert_eq!(
101/// v,
102/// vec![(1, 1), (1, 2)],
103/// );
104/// ```
105#[macro_export]
106macro_rules! break_if {
107 ($predicate:expr $(,)?) => {
108 if $predicate {
109 break;
110 }
111 };
112 ($predicate:expr, $label:tt $(,)?) => {
113 if $predicate {
114 break $label;
115 }
116 };
117}
118
119/// [`continue`]: https://doc.rust-lang.org/std/keyword.continue.html
120///
121/// [`continue`] to the next iteration of a loop if a given predicate evaluates to [`true`].
122///
123/// Supports optionally providing a loop label to specify the loop in which to [`continue`].
124///
125/// # Usage
126///
127/// [`continue_if!`](crate::continue_if)`(predicate)`
128///
129/// [`continue_if!`](crate::continue_if)`(predicate, label)`
130///
131/// # Examples
132///
133/// #### Predicate only
134/// ```
135/// use flow_control::continue_if;
136///
137/// let mut v = Vec::new();
138/// for outer_n in 1..3 {
139/// for inner_n in 1..5 {
140/// continue_if!(inner_n == 3);
141/// v.push((outer_n, inner_n));
142/// }
143/// }
144///
145/// assert_eq!(
146/// v,
147/// vec![
148/// (1, 1), (1, 2), (1, 4),
149/// (2, 1), (2, 2), (2, 4),
150/// ]
151/// );
152/// ```
153///
154/// #### Predicate and label
155/// ```
156/// use flow_control::continue_if;
157///
158/// let mut v = Vec::new();
159/// 'outer: for outer_n in 1..3 {
160/// for inner_n in 1..5 {
161/// continue_if!(inner_n == 3, 'outer);
162/// v.push((outer_n, inner_n));
163/// }
164/// }
165///
166/// assert_eq!(
167/// v,
168/// vec![
169/// (1, 1), (1, 2),
170/// (2, 1), (2, 2),
171/// ]
172/// );
173/// ```
174#[macro_export]
175macro_rules! continue_if {
176 ($predicate:expr $(,)?) => {
177 if $predicate {
178 continue;
179 }
180 };
181 ($predicate:expr, $label:tt $(,)?) => {
182 if $predicate {
183 continue $label;
184 }
185 };
186}
187
188/// [`return`]: https://doc.rust-lang.org/std/keyword.return.html
189///
190/// [`return`] from a function if a given predicate evaluates to [`true`].
191///
192/// Supports optionally providing a value to [`return`].
193///
194/// # Usage
195///
196/// [`return_if!`](crate::return_if)`(predicate)`
197///
198/// [`return_if!`](crate::return_if)`(predicate, value)`
199///
200/// # Examples
201///
202/// #### Default return
203/// ```
204/// use flow_control::return_if;
205///
206/// let mut v = Vec::new();
207/// (|| {
208/// for n in 1..10 {
209/// return_if!(n == 5);
210/// v.push(n)
211/// }
212/// })();
213///
214/// assert_eq!(v, vec![1, 2, 3, 4]);
215/// ```
216///
217/// #### Return a specified value
218/// ```
219/// use flow_control::return_if;
220///
221/// let get_value = || {
222/// for n in 1..10 {
223/// return_if!(n == 5, "early return");
224/// }
225/// return "return after loop";
226/// };
227///
228/// assert_eq!(get_value(), "early return");
229/// ```
230#[macro_export]
231macro_rules! return_if {
232 ($predicate:expr $(,)?) => {
233 if $predicate {
234 return;
235 }
236 };
237 ($predicate:expr, $ret:expr $(,)?) => {
238 if $predicate {
239 return $ret;
240 }
241 };
242}