pub unsafe trait EnumLike: Copy {
const NUM_VARIANTS: usize;
fn to_discr(self) -> usize;
fn from_discr(x: usize) -> Self;
}
Expand description
The EnumLike
trait specifies how a type will be stored inside the
EnumVec
.
It associates every possible instance of the type with a number. However
this number does not need to be the same as the result of a simple
enum as usize
cast.
This trait is unsafe because implementations must follow the contract, especially the first rule:
self.to_discr()
returns a valuex < NUM_VARIANTS
Self::from_discr(self.to_discr()) == self
Self::from_discr(x)
is only required to handle valid values ofx
Example 1
use enum_like::EnumLike;
#[derive(Copy, Clone, Debug)]
enum ExtendedBool {
True,
False,
FileNotFound,
}
unsafe impl EnumLike for ExtendedBool {
const NUM_VARIANTS: usize = 3;
fn to_discr(self) -> usize {
match self {
ExtendedBool::True => 0,
ExtendedBool::False => 1,
ExtendedBool::FileNotFound => 2,
}
}
fn from_discr(x: usize) -> Self {
match x {
0 => ExtendedBool::True,
1 => ExtendedBool::False,
2 => ExtendedBool::FileNotFound,
_ => unreachable!(),
}
}
}
Example 2
use enum_like::EnumLike;
#[derive(Copy, Clone, Debug)]
enum SomeFlags {
Read = 4,
Write = 2,
Exec = 1,
}
unsafe impl EnumLike for SomeFlags {
const NUM_VARIANTS: usize = 3;
fn to_discr(self) -> usize {
match self {
// We override the default values, because 4 is out of range,
// but we could also increase NUM_VARIANTS to 5 instead.
SomeFlags::Read => 0,
SomeFlags::Write => 1,
SomeFlags::Exec => 2,
}
}
fn from_discr(x: usize) -> Self {
match x {
0 => SomeFlags::Read,
1 => SomeFlags::Write,
2 => SomeFlags::Exec,
_ => unreachable!(),
}
}
}
Example 3
Of course, it is not limited to enums:
use enum_like::EnumLike;
#[derive(Copy, Clone, Debug)]
struct Digit {
x: u8, // x >= 0 && x <= 9
}
unsafe impl EnumLike for Digit {
const NUM_VARIANTS: usize = 10;
fn to_discr(self) -> usize {
self.x as usize
}
fn from_discr(x: usize) -> Self {
let x = x as u8;
Self { x }
}
}
Here it is important to make sure that the Digit
will always have a valid
value in the [0, 9] range. Otherwise, if self.to_discr()
returns any number
bigger than NUM_VARIANTS
, everything breaks.
Required Associated Constants
sourceconst NUM_VARIANTS: usize
const NUM_VARIANTS: usize
The number of variants of this type
Required Methods
sourcefn from_discr(x: usize) -> Self
fn from_discr(x: usize) -> Self
Get type instance from discriminant