linearize/impls/enums.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
macro_rules! impl_enum {
($ty:ty, $num:literal: $($name:ident => $idx:expr,)*) => {
// SAFETY: The tests below test all conditions.
unsafe impl crate::Linearize for $ty {
type Storage<T> = [T; Self::LENGTH];
type CopyStorage<T>
= [T; Self::LENGTH]
where
T: Copy;
const LENGTH: usize = $num;
#[inline]
fn linearize(&self) -> usize {
match self {
$(<$ty>::$name => $idx,)*
}
}
#[inline]
unsafe fn from_linear_unchecked(linear: usize) -> Self
where
Self: Sized,
{
match linear {
$($idx => <$ty>::$name,)*
_ => unsafe {
// SAFETY: It's a precondition that linear < Self::LENGTH,
cold_unreachable!();
},
}
}
}
impl_assert!($ty, $num);
#[test]
fn test() {
use crate::Linearize;
$(
assert_roundtrip!(<$ty>::$name, $idx);
)*
let variants = [$(<$ty>::$name),*];
assert_eq!(variants.len(), $num);
for (idx, variant) in variants.into_iter().enumerate() {
assert_eq!(variant.linearize(), idx);
}
}
};
}
mod core {
mod cmp {
mod ordering {
impl_enum! {
core::cmp::Ordering, 3:
Less => 0,
Equal => 1,
Greater => 2,
}
}
}
mod fmt {
mod alignment {
impl_enum! {
core::fmt::Alignment, 3:
Left => 0,
Right => 1,
Center => 2,
}
}
}
mod num {
mod fp_category {
impl_enum! {
core::num::FpCategory, 5:
Nan => 0,
Infinite => 1,
Zero => 2,
Subnormal => 3,
Normal => 4,
}
}
}
}
#[cfg(feature = "std")]
mod std {
mod net {
mod shutdown {
impl_enum! {
std::net::Shutdown, 3:
Read => 0,
Write => 1,
Both => 2,
}
}
}
}