macro_rules! debug_assert_match {
($pattern:pat, $value:expr) => {
if cfg!(debug_assertions) {
let value = $value;
#[allow(unreachable_patterns)]
match value {
$pattern => {}
_ => panic!(
"assertion failed: `(value matches pattern)`
pattern: `{}`,
value: `{:?}`",
stringify!($pattern),
value
),
}
}
};
}
macro_rules! parse_pairs_as {
($pair:expr, ($($rules:pat),*)) => {
parse_pairs_as!($pair, ($($rules),*,))
};
($pair:expr, ($($rules:pat),*), ..) => {
parse_pairs_as!($pair, ($($rules),*,), ..)
};
($pair:expr, ($($rules:pat),*,)) => {
{
let iter = &mut $pair;
let out = parse_pairs_as!(@recur iter, (), ($($rules),*,));
debug_assert_match!(Option::None, iter.next());
out
}
};
($pair:expr, ($($rules:pat),*,), ..) => {
{
let iter = &mut $pair;
parse_pairs_as!(@recur iter, (), ($($rules),*,))
}
};
(@recur
$iter:ident,
(),
($head_rule:pat, $($remaining_rules:pat),*,)
) => {
parse_pairs_as!(@recur
$iter,
(
{
let tmp = $iter.next().unwrap();
debug_assert_match!($head_rule, tmp.as_rule());
tmp
},
),
($($remaining_rules),*,)
)
};
(@recur
$iter:ident,
($($processed:expr),*,),
($head_rule:pat, $($remaining_rules:pat),*,)
) => {
parse_pairs_as!(@recur
$iter,
(
$($processed),*,
{
let tmp = $iter.next().unwrap();
debug_assert_match!($head_rule, tmp.as_rule());
tmp
},
),
($($remaining_rules),*,)
)
};
(@recur $iter:ident, (), ($head_rule:pat,)) => {
(
{
let tmp = $iter.next().unwrap();
debug_assert_match!($head_rule, tmp.as_rule());
tmp
},
)
};
(@recur $iter:ident, ($($processed:expr),*,), ($head_rule:pat,)) => {
(
$($processed),*,
{
let tmp = $iter.next().unwrap();
debug_assert_match!($head_rule, tmp.as_rule());
tmp
},
)
};
}