C-style Enums reference conversion


#1

Hello,

I am using “C-style” enum like the following:

#[repr(u8)]
enum TheEnum {
    Off = 0,
    On = 42,
}

Here https://doc.rust-lang.org/nomicon/other-reprs.html the following said:

Adding a repr causes it to be treated exactly like the specified integer size for ABI purposes.

Well, my question is how could I cast &TheEnum to &u8? I really need just a numeric value to dump the enum state to external representation. I believe that casting &TheEnum to &u8 is safe operation due to the following two facts: 1) TheEnum is guaranteed to have specified binary representation which is exactly as u8 has (see the link above) 2) the reference is immutable, so as no modifications could be performed on variable, and we cannot break the enum by setting it wrong value (say 63).


#2
let e = &TheEnum::On;
let v = unsafe { std::mem::transmute::<_, &u8>(e) };

I wouldn’t recommend this :slight_smile:

Do you control TheEnum? If so, you probably want to impl Copy and Clone for it and then an Into<u8> or From<TheEnum> for u8 so you can safely go between a u8 and the enum. Then you can drop the repr (unless you need this for FFI or something).


#3

Thank you for the reply.

My question is rather why Info, From and AsRef traits are not implemented automatically by the compiler? #repr(u8) makes it safe to use std::mem::transmute here from runtime point of view. But then, if somebody removes #repr(u8) from the specific definition we even don’t get compile error. I would not like to rely on transmute here.


#4

I agree on the transmute part - hence suggesting to avoid that approach.

You can cast this enum to u8, if you have a value - but you have a reference to the enum. So if you impl (or derive) Copy for it, you can do *theEnum as u8. That’s better than transmute but still leaves code open to subtle bugs (eg someone changes to repr(u16) later).

Rust doesn’t implement those conversion traits or AsRef automatically. You have to opt-in to them by doing that yourself (pretty trivial to do).