pub unsafe trait EnumLike: Copy {
const NUM_VARIANTS: usize;
// Required methods
fn to_discr(self) -> usize;
fn from_discr(x: usize) -> Self;
}Expand description
Not sure if this is needed
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_VARIANTSSelf::from_discr(self.to_discr()) == selfSelf::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
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.