#[macro_export]
macro_rules! Const {
( $($rest:tt)* ) => {
$crate::__const_block_inner!(@idx 0usize; @prev (0i64); $($rest)*);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! const_block {
( $($rest:tt)* ) => { $crate::Const!{ $($rest)* } };
}
#[doc(hidden)]
#[macro_export]
macro_rules! __const_block_inner {
(@idx $idx:expr; @prev ($prev:expr); ) => {};
(@idx $idx:expr; @prev ($prev:expr); $name:ident : $ty:ty = $val:expr; $($rest:tt)*) => {
#[allow(dead_code, non_upper_case_globals)]
pub const $name: $ty = {
#[allow(non_upper_case_globals, unused)]
const iota: $ty = $idx as $ty;
$val
};
$crate::__const_block_inner!(@idx $idx + 1usize; @prev ($val); $($rest)*);
};
(@idx $idx:expr; @prev ($prev:expr); $name:ident = $val:expr; $($rest:tt)*) => {
#[allow(dead_code, non_upper_case_globals)]
pub const $name: i64 = {
#[allow(non_upper_case_globals, unused)]
const iota: i64 = $idx as i64;
$val
};
$crate::__const_block_inner!(@idx $idx + 1usize; @prev ($val); $($rest)*);
};
(@idx $idx:expr; @prev ($prev:expr); $name:ident : $ty:ty ; $($rest:tt)*) => {
#[allow(dead_code, non_upper_case_globals)]
pub const $name: $ty = {
#[allow(non_upper_case_globals, unused)]
const iota: $ty = $idx as $ty;
$prev as $ty
};
$crate::__const_block_inner!(@idx $idx + 1usize; @prev ($prev); $($rest)*);
};
(@idx $idx:expr; @prev ($prev:expr); $name:ident ; $($rest:tt)*) => {
#[allow(dead_code, non_upper_case_globals)]
pub const $name: i64 = {
#[allow(non_upper_case_globals, unused)]
const iota: i64 = $idx as i64;
$prev
};
$crate::__const_block_inner!(@idx $idx + 1usize; @prev ($prev); $($rest)*);
};
}
#[cfg(test)]
mod tests {
crate::Const! {
Sunday = iota;
Monday;
Tuesday;
Wednesday;
Thursday;
Friday;
Saturday;
}
#[test]
fn weekday_iota() {
assert_eq!(Sunday, 0);
assert_eq!(Monday, 1);
assert_eq!(Tuesday, 2);
assert_eq!(Saturday, 6);
}
crate::Const! {
_ignored = 1 << (10 * iota);
KB;
MB;
GB;
TB;
}
#[test]
fn storage_units() {
assert_eq!(KB, 1 << 10);
assert_eq!(MB, 1 << 20);
assert_eq!(GB, 1 << 30);
assert_eq!(TB, 1i64 << 40);
}
crate::Const! {
ReadPerm: u32 = 1 << iota;
WritePerm: u32;
ExecPerm: u32;
}
#[test]
fn permissions_typed() {
assert_eq!(ReadPerm, 1u32);
assert_eq!(WritePerm, 2u32);
assert_eq!(ExecPerm, 4u32);
}
}