#[doc = crate::_tags!(code)]
#[doc = crate::_doc_location!("code/util")]
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! whilst {
(
/* `while` syntax */
// label:? let pattern = expr; { pre?; post? } body
$($label:lifetime:)?
let $pat:pat = $expr:expr ; { $( $pre:expr)? ; $( $post:expr)? } $body:expr) => {
$($label:)? while let $pat = $expr { $($pre;)? $body; $($post;)? }
};
($($label:lifetime:)?
let $pat:pat = $expr:expr ; $body:expr) => {
$($label:)? while let $pat = $expr { $body; }
};
(// label:? init?; condition; { pre?; post? } body
$($label:lifetime:)?
$($var:ident $(: $var_ty:ty)? = $init:expr)? ;
$condition:expr ; { $( $pre:expr)? ; $( $post:expr)? } $body:expr
) => {
$(let mut $var $(:$var_ty)? = $init;)?
$($label:)? while $condition { $($pre;)? $body; $($post;)? }
};
( $($label:lifetime:)?
$condition:expr ; { $( $pre:expr)? ; $( $post:expr)? } $body:expr
) => {
$($label:)? while $condition { $($pre;)? $body; $($post;)? }
};
( $($label:lifetime:)?
$($var:ident $(: $var_ty:ty)? = $init:expr)? ;
$condition:expr ; $body:expr
) => {
$(let mut $var $(:$var_ty)? = $init;)?
$($label:)? while $condition { $body; }
};
( $($label:lifetime:)?
$condition:expr ; $body:expr
) => {
$($label:)? while $condition { $body; }
};
(
$($label:lifetime:)?
$var:ident in rev $min:literal .. $max:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var > $min { $var -= 1; $body; }
};
($($label:lifetime:)?
$var:ident in rev $min:literal ..= $max:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var >= $min { $body; $var -= 1; }
};
($($label:lifetime:)?
$var:ident in rev $min:expr, .. $max:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var > $min { $var -= 1; $body; }
};
($($label:lifetime:)?
$var:ident in rev $min:expr, ..= $max:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var >= $min { $body; $var -= 1; }
};
(
$($label:lifetime:)?
$var:ident in rev $min:literal .. $max:expr; $step:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var > $min { $var -= $step; $body; }
};
($($label:lifetime:)?
$var:ident in rev $min:literal ..= $max:expr; $step:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var >= $min { $body; $var -= $step; }
};
($($label:lifetime:)?
$var:ident in rev $min:expr, .. $max:expr; $step:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var > $min { $var -= $step; $body; }
};
($($label:lifetime:)?
$var:ident in rev $min:expr, ..= $max:expr; $step:expr; $body:expr) => {
let mut $var = $max;
$($label:)? while $var >= $min { $body; $var -= $step; }
};
(
$($label:lifetime:)?
$var:ident in $min:literal .. $max:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var < $max { $body; $var += 1; }
};
($($label:lifetime:)?
$var:ident in $min:literal ..= $max:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var <= $max { $body; $var += 1; }
};
($($label:lifetime:)?
$var:ident in $min:expr, .. $max:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var < $max { $body; $var += 1; }
};
($($label:lifetime:)?
$var:ident in $min:expr, ..= $max:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var <= $max { $body; $var += 1; }
};
(
$($label:lifetime:)?
$var:ident in $min:literal .. $max:expr; $step:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var < $max { $body; $var += $step; }
};
($($label:lifetime:)?
$var:ident in $min:literal ..= $max:expr; $step:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var <= $max { $body; $var += $step; }
};
($($label:lifetime:)?
$var:ident in $min:expr, .. $max:expr; $step:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var < $max { $body; $var += $step; }
};
($($label:lifetime:)?
$var:ident in $min:expr, ..= $max:expr; $step:expr; $body:expr) => {
let mut $var = $min;
$($label:)? while $var <= $max { $body; $var += $step; }
};
}
#[doc(inline)]
pub use whilst;
#[cfg(test)]
mod tests {
use crate::is;
#[test]
fn test_whilst() {
let mut b = 0;
whilst![x = 0; x < 10; {;x += 1} b+=2];
assert_eq![b, 20];
let mut b = 0;
whilst![x: u8 = 0; x < 10; {;x += 1} b+=2];
assert_eq![b, 20];
let mut b = 0;
let mut y = 0;
whilst![y < 10; {; y += 1} b+=2];
assert_eq![b, 20];
let mut b = 0;
let mut y = 0;
whilst!['outer: ; y < 10; {; y += 1} {b+=2; if b == 7 { break 'outer;}}];
assert_eq![b, 20];
let mut b = 0;
whilst![x: u8 = 0; x < 10; { b+=2; x+=1; }];
assert_eq![b, 20];
let mut b = 0;
let mut x = 0;
whilst![x < 10; { b+=2; x+=1; }];
assert_eq![b, 20];
}
#[test]
fn test_whilst_let() {
let mut val = Some(3);
let mut sum = 0;
whilst![let Some(x) = val; {
sum += x;
val = if x > 0 { Some(x - 1) } else { None };
}];
assert_eq!(sum, 6);
let mut val = Some(3);
let mut sum = 0;
let mut steps = 0;
whilst![let Some(x) = val; {steps += 1; val = is![x > 0, Some(x - 1), None]} {
sum += x;
}];
assert_eq!(steps, 4); assert_eq!(sum, 6); }
#[test]
fn test_whilst_array() {
let mut arr = [0u8; 5];
let mut i = 0;
whilst![x = 0; x < 5; {; x += 1} {
arr[i] = x;
i += 1;
}];
assert_eq!(arr, [0, 1, 2, 3, 4]);
let mut arr = [0u8; 5];
let mut i = 0;
whilst![x = 5; x > 0; {x -= 1;} {
arr[i] = x;
i += 1;
}];
assert_eq!(arr, [4, 3, 2, 1, 0]);
}
#[test]
#[rustfmt::skip]
fn test_whilst_for_syntax() {
let mut b = 0; whilst![x in 0..5; b+=1]; assert_eq![b, 5];
let mut b = 0; whilst![x in 0..=5; b+=1]; assert_eq![b, 6];
let mut b = 0; whilst![x in 0,..5; b+=1]; assert_eq![b, 5];
let mut b = 0; whilst![x in 0,..=5; b+=1]; assert_eq![b, 6];
let mut b = 0; whilst![x in 0.0..5.0; 0.5; b+=1]; assert_eq![b, 10];
let mut b = 0; whilst![x in 0.0..=5.0; 0.5; b+=1]; assert_eq![b, 11];
let mut b = 0; whilst![x in 0.0,..5.0; 0.5; b+=1]; assert_eq![b, 10];
let mut b = 0; whilst![x in 0.0,..=5.0; 0.5; b+=1]; assert_eq![b, 11];
let mut b = 0; whilst![x in rev 0..5; b+=1]; assert_eq![b, 5];
let mut b = 0; whilst![x in rev 0..=5; b+=1]; assert_eq![b, 6];
let mut b = 0; whilst![x in rev 0,..5; b+=1]; assert_eq![b, 5];
let mut b = 0; whilst![x in rev 0,..=5; b+=1]; assert_eq![b, 6];
let mut sum = 0;
whilst![x in rev 0..5; sum += x];
assert_eq!(sum, 4 + 3 + 2 + 1 + 0);
let mut sum = 0;
whilst![x in rev 0..=5; sum += x];
assert_eq!(sum, 5 + 4 + 3 + 2 + 1 + 0);
}
#[test]
#[rustfmt::skip]
#[cfg(feature = "__std")]
fn test_whilst_for_syntax_alloc() {
let mut values = vec![];
whilst![x in 0..4; values.push(x)];
assert_eq![values.as_slice(), &[0, 1, 2, 3]];
values.clear();
whilst![x in 0..=4; values.push(x)];
assert_eq![values.as_slice(), &[0, 1, 2, 3, 4]];
let mut values = vec![];
whilst![x in 0..4; 2; values.push(x)];
assert_eq![values.as_slice(), &[0, 2]];
values.clear();
whilst![x in 0..=4; 2; values.push(x)];
assert_eq![values.as_slice(), &[0, 2, 4]];
let mut values = vec![];
whilst![x in 0.0..4.0; 0.5; values.push(x)];
assert_eq![values.as_slice(), &[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5]];
let mut values = vec![];
whilst![x in rev 0..4; values.push(x)];
assert_eq![values.as_slice(), &[3, 2, 1, 0]];
values.clear();
whilst![x in rev 0..=4; values.push(x)];
assert_eq![values.as_slice(), &[4, 3, 2, 1, 0]];
let mut values = vec![];
whilst![x in rev 0..4; 2; values.push(x)];
assert_eq![values.as_slice(), &[2, 0]];
values.clear();
whilst![x in rev 0..=4; 2; values.push(x)];
assert_eq![values.as_slice(), &[4, 2, 0]];
let mut values = vec![];
whilst![x in rev 0.0..4.0; 0.5; values.push(x)];
assert_eq![values.as_slice(), &[3.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 0.0]];
}
}