1#[macro_export]
2macro_rules! dowhile {
3 ($($label:lifetime:)? $body:block $(,)? $cond:expr) => ({
4 $($label:)? loop {
5 $body
6 if !$cond {
7 break $($label)?;
8 }
9 }
10 });
11 ($($label:lifetime:)? $body:block let $pattern:pat = $value:expr $(=> $cond:expr)?) => ({
12 $($label:)? loop {
13 $body
14 if let $pattern = $value {
15 $(if !$cond {
16 break;
17 })?
18 } else {
19 break $($label)?;
20 }
21 }
22 });
23 ($($label:lifetime:)? $body:block let $pattern:pat = $value:expr $(=> $cond:expr)?) => ({
24 $($label:)? loop {
25 $body
26 if let $pattern = $value {
27 $(if !$cond {
28 break;
29 })?
30 } else {
31 break $($label)?;
32 }
33 }
34 });
35 ($cond:expr, $($label:lifetime:)? $body:block) => ({
37 $($label:)? loop {
38 $body
39 if !$cond {
40 break $($label)?;
41 }
42 }
43 });
44 (let $pattern:pat = $value:expr$ (=> $cond:expr)?, $($label:lifetime:)? $body:block) => ({
45 $($label:)? loop {
46 $body
47 if let $pattern = $value {
48 $(if !$cond {
49 break;
50 })?
51 } else {
52 break $($label)?;
53 }
54 }
55 });
56}
57
58#[cfg(test)]
59mod tests {
60 #[test]
61 fn nested_with_label() {
62 let mut v = vec![];
63 let mut x = 10;
64 dowhile!(x < 6, 'main: {
65 v.push(('x', x));
66 if x > 6 {
67 x = 0;
68 continue;
69 }
70 let mut y = x;
71 dowhile!({
72 v.push(('y', y));
73 if y > 3 {
74 break 'main;
75 }
76 y += 1;
77 } y < x);
78 x += 1;
79 });
80 assert_eq!(v, vec![
81 ('x', 10), ('x', 0), ('y', 0), ('x', 1), ('y', 1), ('x', 2),
82 ('y', 2), ('x', 3), ('y', 3), ('x', 4), ('y', 4)
83 ]);
84 }
85
86 #[test]
87 fn while_true() {
88 let mut x = 0;
89 dowhile!({
90 if x > 3 {
91 break;
92 }
93 x += 1;
94 }, true);
95 assert_eq!(x, 4);
96 }
97
98 #[test]
99 fn while_let() {
100 let mut x = Some(10);
101 let mut v = vec![];
102 dowhile!({
103 v.push(x);
104 x = Some(x.unwrap_or(0) - 1);
105 } let Some(8..) = x);
106 let vv = vec![Some(10), Some(9), Some(8)];
107 assert_eq!(v, vv);
108 }
109
110 #[test]
111 fn while_let_val() {
112 let mut x = Some(10);
113 let mut v = vec![];
114 dowhile!({
115 v.push(x);
116 x = Some(x.unwrap_or(0) - 1);
117 } let Some(val) = x => val > 8);
118 let vv = vec![Some(10), Some(9)];
119 assert_eq!(v, vv);
120 }
121
122 #[test]
123 fn while_let_alter() {
124 let mut x = Some(10);
125 let mut v = vec![];
126 dowhile!(let Some(val) = x => val > 8, {
127 v.push(x);
128 x = Some(x.unwrap_or(0) - 1);
129 });
130 let vv = vec![Some(10), Some(9)];
131 assert_eq!(v, vv);
132 }
133}