use core::cmp::Ordering;
use core::convert::Infallible;
pub trait Enum: Sized {
const LENGTH: usize;
fn from_usize(value: usize) -> Self;
fn into_usize(self) -> usize;
}
pub trait EnumArray<V>: Enum {
type Array: Array<V>;
}
pub unsafe trait Array<V> {
const LENGTH: usize;
}
unsafe impl<V, const N: usize> Array<V> for [V; N] {
const LENGTH: usize = N;
}
impl Enum for bool {
const LENGTH: usize = 2;
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => false,
1 => true,
_ => unreachable!(),
}
}
#[inline]
fn into_usize(self) -> usize {
usize::from(self)
}
}
impl<T> EnumArray<T> for bool {
type Array = [T; Self::LENGTH];
}
impl Enum for () {
const LENGTH: usize = 1;
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => (),
_ => unreachable!(),
}
}
#[inline]
fn into_usize(self) -> usize {
0
}
}
impl<T> EnumArray<T> for () {
type Array = [T; Self::LENGTH];
}
impl Enum for u8 {
const LENGTH: usize = 256;
#[inline]
fn from_usize(value: usize) -> Self {
value.try_into().unwrap()
}
#[inline]
fn into_usize(self) -> usize {
usize::from(self)
}
}
impl<T> EnumArray<T> for u8 {
type Array = [T; Self::LENGTH];
}
impl Enum for Infallible {
const LENGTH: usize = 0;
#[inline]
fn from_usize(_: usize) -> Self {
unreachable!();
}
#[inline]
fn into_usize(self) -> usize {
match self {}
}
}
impl<T> EnumArray<T> for Infallible {
type Array = [T; Self::LENGTH];
}
impl Enum for Ordering {
const LENGTH: usize = 3;
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => Ordering::Less,
1 => Ordering::Equal,
2 => Ordering::Greater,
_ => unreachable!(),
}
}
#[inline]
fn into_usize(self) -> usize {
match self {
Ordering::Less => 0,
Ordering::Equal => 1,
Ordering::Greater => 2,
}
}
}
impl<T> EnumArray<T> for Ordering {
type Array = [T; Self::LENGTH];
}