use core::cmp::Ordering;
use core::convert::Infallible;
pub trait Enum: Sized {
type Array<V>: Array<Value = V>;
fn from_usize(value: usize) -> Self;
fn into_usize(self) -> usize;
}
pub trait Array: Sealed {
const LENGTH: usize;
type Value;
}
impl<V, const N: usize> Array for [V; N] {
const LENGTH: usize = N;
type Value = V;
}
pub trait Sealed {}
impl<V, const N: usize> Sealed for [V; N] {}
#[doc(hidden)]
#[inline]
pub fn out_of_bounds() -> ! {
panic!("index out of range for Enum::from_usize");
}
impl Enum for bool {
type Array<V> = [V; 2];
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => false,
1 => true,
_ => out_of_bounds(),
}
}
#[inline]
fn into_usize(self) -> usize {
usize::from(self)
}
}
impl Enum for () {
type Array<V> = [V; 1];
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => (),
_ => out_of_bounds(),
}
}
#[inline]
fn into_usize(self) -> usize {
0
}
}
impl Enum for u8 {
type Array<V> = [V; 256];
#[inline]
fn from_usize(value: usize) -> Self {
value.try_into().unwrap_or_else(|_| out_of_bounds())
}
#[inline]
fn into_usize(self) -> usize {
usize::from(self)
}
}
impl Enum for Infallible {
type Array<V> = [V; 0];
#[inline]
fn from_usize(_: usize) -> Self {
out_of_bounds();
}
#[inline]
fn into_usize(self) -> usize {
match self {}
}
}
impl Enum for Ordering {
type Array<V> = [V; 3];
#[inline]
fn from_usize(value: usize) -> Self {
match value {
0 => Ordering::Less,
1 => Ordering::Equal,
2 => Ordering::Greater,
_ => out_of_bounds(),
}
}
#[inline]
fn into_usize(self) -> usize {
match self {
Ordering::Less => 0,
Ordering::Equal => 1,
Ordering::Greater => 2,
}
}
}