Declaring array size from enum total of variants

One thing that I found useful when working in C, is that I could create an array using the last definition of an enum, such as:

enum state_name {
    STATE_NAME_0, // = 0
    STATE_NAME_1, // = 1
    STATE_NAME_2, // = 2
    STATE_NAME_3, // = 3
    STATE_NAME_TOTAL, // = 4
};
struct context {
    struct state array_of_states[STATE_NAME_TOTAL];
};

Now, we assume here that the last definition STATE_NAME_TOTAL is the correct number of definitions before it, because in C the value of the definitions start at 0 and grow each new definition, if no explicit assignment is made.

In Rust, we can also do that by doing this:

enum StateName {
    Name0,
    Name1,
    Name2,
    Name3,
    Total,
}
struct context {
    array_of_states: [State; StateName::Total as usize],
}

The problem here is that StateName::Total will also need to be taken in account in every match expression. I think it would be interesting to have some sort of expression to get the number of variants in an C-style enum in Rust.

1 Like

I believe this sort of thing is usually done with external macro crates, e.g. with https://docs.rs/enum_derive/0.1.7/enum_derive/ iiuc it'd be StateName::iter_variants().count().

But array length needs to be a (guaranteed) compile-time constant. So maybe what we need here is a const fn-ification of enum_derive or some similar crate. I can't think of any reason why it wouldn't be straightforward to const-ify things like iter_variants().

4 Likes

Use EnumMap instead.

5 Likes

Maybe I'm missing something, but it doesn't look like any of EnumMap is const-ified either? Are they planning to do that soon?

You don't need to use an array with enum-map, so that's not relevant. You can just do

use enum_map::{enum_map, Enum, EnumMap};

#[derive(Enum)]
enum StateName {
    Name0,
    Name1,
    Name2,
    Name3,
}

struct context {
    array_of_states: EnumMap<StateName, State>,
}
3 Likes

I know I've seen a macro to generate just an associated const VARIANTS: [Self; N] before. I've definitely used a manual version of it to implement TryFrom<reprN> before.

That said, if you really want an enum associative array, EnumMap is probably the way to go.

1 Like