Sure, there’s enum_primitive
using macros 1.0, and enum-primitive-derive
and num-derive
using custom derive – all targeting FromPrimitive
. I’m sure TryFrom
could be derived the same way, although automatically writing this for just the repr
type is harder, since we don’t have that type info AFAIK.
Proposed solution:
#[repr(C)]
enum Foo {
Bar = 0,
Baz = 1,
Other(i32),
}
Where Other(i32)
is virtual field only allowed for repr(C)
enums, which represents other possible variants for enum, like in C.
Here’s an idea:
unsafe trait CEnum {
type Underlying: Copy;
}
// mod std::intrinsics
fn from_discriminant<E: CEnum>(val: E::Underlying) -> Option<E> { /* filled in by compiler */ }
CEnum
is automatically implemented for #[repr(uN)]
or #[repr(C)]
enums, in “the way one expects”. The intrinsic function does what it says on the tin: eats a number and returns the corresponding variant, if it exists. The actual lookup table for whether an enum is in range is only created when from_discriminant
is monomorphized.
I put together https://crates.io/crates/num_enum which allows you to derive TryFrom
just for the repr type (by deriving TryFromPrimitive
). It also allows you to derive a TryInto
implementation which works on stable (by deriving CustomTryInto
) because TryFrom
isn’t stable yet, but it’s a little ugly/hacky. It was actually refreshingly simple to put together (and my first proc_macro)!
It currently doesn’t allow deriving #[repr(C)]
enums because the target size isn’t well-specified.
I’m very open to feedback/improvements, if anyone’s interested.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.