Listing all branches of enums w/ 'unit' arms

I have an enum of the form:

pub fn Some_Enum {
  A,
  B,
  C,
  ...
  Z,
  Aa,
  Ab,
  Ac,
...
}

There are two important characteristics:

  1. there are many arms

  2. all arms have no data attached to them, i.e. basically ()

Question: is there some rust crate that will auto derive:

impl Some_Enum {
  fn all_enums() -> &'static [Some_Enum] { ... }

}

for me ? I want it to list out all the enum arms.

The main reason I want a derive macro is I am afraid if I do this manually, the two will get out of sync (something defined in the Some_Enum, but not in the all_enums() fn).

Thanks!

Not hard to write a macro for your specific case: Rust Playground

macro_rules! enum_slice {
    (
        $( #[$meta:meta] )*
        $vis:vis enum $name:ident {
            $($var:ident),* $(,)?
        }
    ) => {
        $( #[$meta] )*
        $vis enum $name {
            $($var,)*
        }
        impl $name {
            pub const ALL: &'static [Self] = {
                use $name::*;
                &[ $($var),* ]
            };
            pub const fn all_enums() -> &'static [Self] {
                use $name::*;
                &[ $($var),* ]
            }
        }
    };
}

For generic enum (with limited support), might be useful to use EnumIter in strum - Rust which yields an iterator instead of static slice (or const array).

7 Likes

I usually reach for strum for these sorts of things.

Creates a new type that iterates of the variants of an enum.

Iterate over the variants of an Enum. Any additional data on your variants will be set to Default::default(). The macro implements strum::IntoEnumIterator on your enum and creates a new type called YourEnumIter that is the iterator object. You cannot derive EnumIter on any type with a lifetime bound (<'a>) because the iterator would surely create unbounded lifetimes.

// You need to bring the trait into scope to use it!
use strum::{EnumIter, IntoEnumIterator};

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

// It's simple to iterate over the variants of an enum.
for color in Color::iter() {
    println!("My favorite color is {:?}", color);
}

let mut ci = Color::iter();
assert_eq!(Some(Color::Red), ci.next());
assert_eq!(Some(Color::Green {range: 0}), ci.next());
assert_eq!(Some(Color::Blue(0)), ci.next());
assert_eq!(Some(Color::Yellow), ci.next());
assert_eq!(None, ci.next());
4 Likes
  1. I ended up going with num-derive / num-trait. to_primitve on first/last elem, iter + from_primitive to iterate

  2. @vague : LOL. Was not aware macro_rules! could be 'abused' like that to enumerate over a type declaration

  3. @Michael-F-Bryan : will keep strum in mind for future

To support parsing attributes on variants, copy the code of attribute matcher $( #[$meta:meta] )* on the enum item Rust Playground

-$($var:ident),*
+$( $( #[$var_meta:meta] )* $var:ident),*
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.