strum_macros

Derive Macro FromRepr

Source
#[derive(FromRepr)]
{
    // Attributes available to this derive:
    #[strum]
}
Expand description

Add a function to enum that allows accessing variants by its discriminant

This macro adds a standalone function to obtain an enum variant by its discriminant. The macro adds from_repr(discriminant: usize) -> Option<YourEnum> as a standalone function on the enum. For variants with additional data, the returned variant will use the Default trait to fill the data. The discriminant follows the same rules as rustc. The first discriminant is zero and each successive variant has a discriminant of one greater than the previous variant, except where an explicit discriminant is specified. The type of the discriminant will match the repr type if it is specified.

When the macro is applied using rustc >= 1.46 and when there is no additional data on any of the variants, the from_repr function is marked const. rustc >= 1.46 is required to allow match statements in const fn. The no additional data requirement is due to the inability to use Default::default() in a const fn.

You cannot derive FromRepr on any type with a lifetime bound (<'a>) because the function would surely create unbounded lifetimes.


use strum_macros::FromRepr;

#[derive(FromRepr, Debug, PartialEq)]
enum Color {
    Red,
    Green { range: usize },
    Blue(usize),
    Yellow,
}

assert_eq!(Some(Color::Red), Color::from_repr(0));
assert_eq!(Some(Color::Green {range: 0}), Color::from_repr(1));
assert_eq!(Some(Color::Blue(0)), Color::from_repr(2));
assert_eq!(Some(Color::Yellow), Color::from_repr(3));
assert_eq!(None, Color::from_repr(4));

// Custom discriminant tests
#[derive(FromRepr, Debug, PartialEq)]
#[repr(u8)]
enum Vehicle {
    Car = 1,
    Truck = 3,
}

assert_eq!(None, Vehicle::from_repr(0));

On versions of rust >= 1.46, the from_repr function is marked const.

use strum_macros::FromRepr;

#[derive(FromRepr, Debug, PartialEq)]
#[repr(u8)]
enum Number {
    One = 1,
    Three = 3,
}

const fn number_from_repr(d: u8) -> Option<Number> {
    Number::from_repr(d)
}

assert_eq!(None, number_from_repr(0));
assert_eq!(Some(Number::One), number_from_repr(1));
assert_eq!(None, number_from_repr(2));
assert_eq!(Some(Number::Three), number_from_repr(3));
assert_eq!(None, number_from_repr(4));