Is there a way to extract the number of elements in an enum?
Simple example (with 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'd normally do...
enum FooBar { A = 0, B, C, };
#define FOOBAR_NUMBER_OF_ITEMS (C + 1)
However the Rust equivalent to this doesn't 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 item in the enum is very inconvenient because matching enums will error if all members aren't accounted for.
enum FooBar { A = 0, B, C, FOOBAR_NUMBER_OF_ITEMS, };
Is there a way to get the number of items in an enum as a constant value?
Note: even though this isn't directly related to the question, the reason I was wanting this feature is I'm using the builder-pattern to construct a series of actions which only make sense to run once. For this reason I can use a fixed size array the size of the enum.
Use the len() class to get the number of elements in an enum, e.g. len(Color) . The len() function returns the length (the number of items) of an object and can directly be passed an enum.
To get the length of an enum: Use the Object. keys() method to get an array containing the enum's keys. Access the length property on the array.
An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it.
You can use procedural macros:
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()
}
It is left as an excercise to the reader to ensure that this derive macro can be used multiple times within the same module.
To use the macro, just attach #[derive(EnumVariantCount)]
to your enum. There should now be a global constant named LENGTH
.
As an alternative (maybe this is newer since the original answer) you can use the strum crate and use the EnumCount macro. Here is their example:
use strum::{EnumCount, IntoEnumIterator};
use strum_macros::{EnumCount as EnumCountMacro, EnumIter};
#[derive(Debug, EnumCountMacro, EnumIter)]
enum Week {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
assert_eq!(7, Week::COUNT);
assert_eq!(Week::iter().count(), Week::COUNT);
There's a new function std::mem::variant_count in rust nightly version.
Example to use by rust docs.
use std::mem;
enum Void {}
enum Foo { A(&'static str), B(i32), C(i32) }
assert_eq!(mem::variant_count::<Void>(), 0);
assert_eq!(mem::variant_count::<Foo>(), 3);
assert_eq!(mem::variant_count::<Option<!>>(), 2);
assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With