#[doc = crate::_tags!(code)]
#[doc = crate::_doc_meta!{location("code/util")}]
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! is {
($cond:expr, $then:expr) => {
$crate::is!(%if $cond, { $then }) };
($cond:expr, $then:expr;) => {
$crate::is!(%if $cond, { let _ = $then; }) };
($cond:expr, $then:expr, $else:expr) => {
$crate::is!(%if $cond, { $then }, { $else }) };
($cond:expr, $then:expr;, $else:expr) => {
$crate::is!(%if $cond, { let _ = $then; }, { $else }) };
($cond:expr, $then:expr, $else:expr;) => {
$crate::is!(%if $cond, { $then }, { $else; }) };
($cond:expr, $then:expr;, $else:expr;) => {
$crate::is!(%if $cond, { let _ = $then; }, { let _ = $else; }) };
($cond:expr, $then:expr,) => {
$crate::is!(%if $cond, { $then }, {}) };
($cond:expr, $then:expr; ,) => {
$crate::is!(%if $cond, { let _ = $then; }, {}) };
($cond:expr, , $else:expr) => {
$crate::is!(%if $cond, {}, { $else }) };
($cond:expr, , $else:expr;) => {
$crate::is!(%if $cond, {}, { let _ = $else; }) };
(let $pat:pat = $cond:expr, $then:expr) => {
$crate::is!(%let $pat = $cond, { $then }) };
(let $pat:pat = $cond:expr, $then:expr;) => {
$crate::is!(%let $pat = $cond, { let _ = $then; }) };
(let $pat:pat = $cond:expr, $then:expr, $else:expr) => {
$crate::is!(%let $pat = $cond, { $then }, { $else }) };
(let $pat:pat = $cond:expr, $then:expr;, $else:expr) => {
$crate::is!(%let $pat = $cond, { let _ = $then; }, { $else }) };
(let $pat:pat = $cond:expr, $then:expr, $else:expr;) => {
$crate::is!(%let $pat = $cond, { $then }, { let _ = $else; }) };
(let $pat:pat = $cond:expr, $then:expr;, $else:expr;) => {
$crate::is!(%let $pat = $cond, { let _ = $then; }, { let _ = $else; }) };
(let $pat:pat = $cond:expr, $then:expr,) => {
$crate::is!(%let $pat = $cond, { $then }, {}) };
(let $pat:pat = $cond:expr, $then:expr; ,) => {
$crate::is!(%let $pat = $cond, { let _ = $then; }, {}) };
(let $pat:pat = $cond:expr, , $else:expr) => {
$crate::is!(%let $pat = $cond, {}, { $else }) };
(let $pat:pat = $cond:expr, , $else:expr;) => {
$crate::is!(%let $pat = $cond, {}, { let _ = $else; }) };
(% if $cond:expr, $then:block) => {
#[allow(clippy::question_mark, reason = "to remain const-friendly")]
if $cond $then };
(% if $cond:expr, $then:block, $else:block) => {
if $cond $then else $else
};
(% let $pat:pat = $cond:expr, $then:block) => {
#[allow(clippy::question_mark, reason = "to remain const-friendly")]
if let $pat = $cond $then };
(% let $pat:pat = $cond:expr, $then:block, $else:block) => {
if let $pat = $cond $then else $else
};
}
#[doc(inline)]
pub use is;
#[cfg(test)]
mod tests {
#[test]
fn is_if_expr() {
assert_eq!('a', is![true, 'a', 'b']);
assert_eq!('b', is![false, 'a', 'b']);
}
#[test]
fn is_if_statement_then() {
let mut n = 0;
is![true, n += 1;];
is![false, n += 10;];
assert_eq!(1, n);
}
#[test]
fn is_if_statement_branches() {
let mut n = 0;
is![true, n += 1;, n += 10;];
assert_eq!(1, n);
is![false, n += 1;, n += 10;];
assert_eq!(11, n);
}
#[test]
fn is_if_empty_else() {
let mut n = 0;
is![true, n += 1;,];
is![false, n += 10;,];
assert_eq!(1, n);
}
#[test]
fn is_if_empty_then() {
let mut n = 0;
is![true, , n += 10;];
is![false, , n += 1;];
assert_eq!(1, n);
}
#[test]
fn is_if_empty_then_diverges() {
fn check(ok: bool) -> Result<(), &'static str> {
is![ok, , return Err("not ok");];
Ok(())
}
assert_eq!(Ok(()), check(true));
assert_eq!(Err("not ok"), check(false));
}
#[test]
fn is_let_expr() {
let somea = Some('a');
let noa: Option<char> = None;
assert_eq!('a', is![let Some(a) = somea, a, 'b']);
assert_eq!('b', is![let Some(a) = noa, a, 'b']);
}
#[test]
fn is_let_statement_then() {
let mut n = 0;
is![let Some(v) = Some(2), n += v;];
is![let Some(v) = None::<i32>, n += v;];
assert_eq!(2, n);
}
#[test]
fn is_let_statement_branches() {
let mut n = 0;
is![let Some(v) = Some(2), n += v;, n += 10;];
assert_eq!(2, n);
is![let Some(v) = None::<i32>, n += v;, n += 10;];
assert_eq!(12, n);
}
#[test]
fn is_let_empty_else() {
let mut n = 0;
is![let Some(v) = Some(3), n += v;,];
is![let Some(v) = None::<i32>, n += v;,];
assert_eq!(3, n);
}
#[test]
fn is_let_empty_then() {
let mut n = 0;
is![let Some(_) = Some(1), , n += 10;];
is![let Some(_) = None::<i32>, , n += 1;];
assert_eq!(1, n);
}
#[test]
fn is_nested_statement() {
let mut n = 2;
let is_true = Some(true);
is![let Some(b) = is_true, is![b, n += 3;]];
assert_eq!(5, n);
}
}