I’m trying to write a high performance way to be able to convert between an enum variant (where none of the variants have data) and its index. Currently I am using a bunch of consts:
type: Foo = u8;
const FOO_A: Foo = 0;
const FOO_B: Foo = 1;
const FOO_C: Foo = 2;
Hopefully this gives you an idea of my goal. I really have quite a few of these kinds of structures, but I realize this is not very idiomatic. Ideally I would write something like this:
enum Foo {
A,
B,
C,
}
However, I need to be able to convert Foo to and from its inner type. For example: Foo::A as u8 -> 0
and 0 as Foo -> Foo::A
. The first one works just fine, but the second gives a justifiable (but in my case annoying) objection.
I could write a match statement, but I’m concerned about the speed. I’m doing this operation an enormous amount of times, so speed really is a concern. I could do a lookup table, but again it’s still much slower than my very un-idiomatic const method.
I think this is a rare case where transmute is my best option. I know it’s horribly unsafe, but I think something like this would work:
enum Foo {
A,
B,
C,
}
fn from_index(i: u8) -> Option<Foo> {
if i > 2 {
None
} else {
unsafe { Some(std::mem::transmute(i)) }
}
}
In my testing, this works fine, but I wanted to ask if there were any issues with this I may have missed. I see reper(C)
used with this a lot, but it doesn’t seem very obviously necessary in this particular case.
Even better, does anyone know of a way to do this without compromising on speed or using unsafe transmute?
Directly from the The Rust Reference, a discriminant can be assigned:
enum Foo {
A = 0,
B = 1,
C = 2,
}
To convert back, use casting:
assert_eq!(0, Foo::A as isize);
assert_eq!(1, Foo::B as isize);
assert_eq!(2, Foo::C as isize);