How to get the number of elements (options) in an enumeration as a constant value?

Is there a way to extract the number of elements in an enumeration?

A simple example (with the imaginary number_of_elements method):

 enum FooBar { A = 0, B, C, }; println!("Number of items: {}", FooBar.number_of_elements()); // "Number of items: 3" 

In C, I usually do ...

 enum FooBar { A = 0, B, C, }; #define FOOBAR_NUMBER_OF_ITEMS (C + 1) 

However, the Rust equivalent, equivalent to this, does not work:

 enum FooBar { A = 0, B, C, }; const FOOBAR_NUMBER_OF_ITEMS: usize = (C as usize) + 1; // Raises an error: // unimplemented constant expression: enum variants 

Including the last element in an enumeration is very inconvenient, because matching enumerations will be an error if all members are not taken into account.

 enum FooBar { A = 0, B, C, FOOBAR_NUMBER_OF_ITEMS, }; 

Is there a way to get the number of elements in an enumeration as a constant value?


Note: although this is not directly related to the question, the reason I wanted this function is to use the builder-pattern to build a series of actions that only make sense to run once. For this reason, I can use an array of a fixed size enumeration size.

+8
enums rust
source share
1 answer

You can use new procedural macros (stable after 2 weeks as of the date of writing this answer):

 extern crate proc_macro; extern crate syn; #[macro_use] extern crate quote; use proc_macro::TokenStream; #[proc_macro_derive(EnumVariantCount)] pub fn derive_enum_variant_count(input: TokenStream) -> TokenStream { let syn_item: syn::DeriveInput = syn::parse(input).unwrap(); let len = match syn_item.data { syn::Data::Enum(enum_item) => enum_item.variants.len(), _ => panic!("EnumVariantCount only works on Enums"), }; let expanded =quote! { const LENGTH: usize = #len; }; expanded.into() } 

This is left as an exercise for the reader to ensure that this derived macro can be used multiple times in the same module.

To use a macro, simply attach #[derive(EnumVariantCount)] to your enumeration. There should now be a global constant named LENGTH .

+9
source share

All Articles