enum_table/
intrinsics.rs

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