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,
            }
        }
    }
}