enum_table/
intrinsics.rs

1#[inline(always)]
2pub(crate) const fn cast_variant<T>(u: &usize) -> &T {
3    unsafe {
4        // SAFETY: This function is only called with usize values that were originally
5        // derived from valid enum discriminants via to_usize(). The transmute is safe
6        // because we maintain the invariant that the usize was created from a T of the
7        // same type and the memory layout is preserved.
8        core::mem::transmute::<&usize, &T>(u)
9    }
10}
11
12#[inline(always)]
13pub(crate) const fn into_variant<T: Copy>(u: usize) -> T {
14    *cast_variant::<T>(&u)
15}
16
17#[inline(always)]
18pub(crate) const fn to_usize<T>(t: &T) -> usize {
19    macro_rules! as_usize {
20        ($t:ident as $type:ident) => {
21            unsafe { *(t as *const T as *const $type) as usize }
22        };
23    }
24
25    match const { core::mem::size_of::<T>() } {
26        1 => as_usize!(t as u8),
27        2 => as_usize!(t as u16),
28        4 => as_usize!(t as u32),
29
30        #[cfg(target_pointer_width = "64")]
31        8 => as_usize!(t as u64),
32        #[cfg(target_pointer_width = "32")]
33        8 => panic!(
34            "enum-table: Cannot handle 64-bit enum discriminants on 32-bit architecture. Consider using smaller discriminant values or compile for 64-bit target."
35        ),
36
37        _ => panic!(
38            "enum-table: Enum discriminants larger than 64 bits are not supported. This is likely due to an extremely large enum or invalid memory layout."
39        ),
40    }
41}
42
43pub const fn sort_variants<const N: usize, T>(mut arr: [T; N]) -> [T; N] {
44    let mut i = 1;
45    while i < N {
46        let mut j = i;
47        while j > 0 && to_usize(&arr[j]) < to_usize(&arr[j - 1]) {
48            arr.swap(j, j - 1);
49            j -= 1;
50        }
51        i += 1;
52    }
53    arr
54}
55
56#[cfg(debug_assertions)]
57pub(crate) const fn is_sorted<T>(arr: &[T]) -> bool {
58    let mut i = 0;
59    while i < arr.len() - 1 {
60        if to_usize(&arr[i]) > to_usize(&arr[i + 1]) {
61            return false;
62        }
63        i += 1;
64    }
65    true
66}