1
0
mirror of https://github.com/danog/strum.git synced 2024-11-30 04:28:59 +01:00

Merge branch 'master' of github.com:Peternator7/strum

This commit is contained in:
Peter Glotfelty 🚀 2018-12-05 11:05:36 -08:00
commit b66f15edb5
5 changed files with 72 additions and 0 deletions

View File

@ -380,6 +380,11 @@ Strum has implemented the following macros:
} }
``` ```
8. `EnumCount`: for a given enum generates implementation of `strum::EnumCount`,
which returns number of variants via `strum::EnumCount::count` method,
also for given `enum MyEnum` generates `const MYENUM_COUNT: usize`
which gives the same value as `strum::EnumCount` (which is usefull for array sizes, etc.).
# Additional Attributes # Additional Attributes
Strum supports several custom attributes to modify the generated code. At the enum level, the Strum supports several custom attributes to modify the generated code. At the enum level, the

View File

@ -669,3 +669,8 @@ where
{ {
fn as_static(&self) -> &'static T; fn as_static(&self) -> &'static T;
} }
/// Number of variants in Enum
pub trait EnumCount {
fn count() -> usize;
}

View File

@ -0,0 +1,30 @@
use proc_macro2::{Span, TokenStream};
use syn;
pub(crate) fn enum_count_inner(ast: &syn::DeriveInput) -> TokenStream {
let n = match ast.data {
syn::Data::Enum(ref v) => v.variants.len(),
_ => panic!("EnumCount can only be used with enums"),
};
// Used in the quasi-quotation below as `#name`
let name = &ast.ident;
let const_name = &syn::Ident::new(
&format!("{}_COUNT", name.to_string().to_uppercase()),
Span::call_site(),
);
// Helper is provided for handling complex generic types correctly and effortlessly
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
quote! {
// The generated impl
impl #impl_generics ::strum::EnumCount for #name #ty_generics #where_clause {
fn count() -> usize {
#n
}
}
#[allow(dead_code)]
pub const #const_name: usize = #n;
}
}

View File

@ -20,6 +20,7 @@ extern crate proc_macro2;
mod as_ref_str; mod as_ref_str;
mod case_style; mod case_style;
mod display; mod display;
mod enum_count;
mod enum_discriminants; mod enum_discriminants;
mod enum_iter; mod enum_iter;
mod enum_messages; mod enum_messages;
@ -124,3 +125,11 @@ pub fn enum_discriminants(input: proc_macro::TokenStream) -> proc_macro::TokenSt
debug_print_generated(&ast, &toks); debug_print_generated(&ast, &toks);
toks.into() toks.into()
} }
#[proc_macro_derive(EnumCount, attributes(strum))]
pub fn enum_count(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();
let toks = enum_count::enum_count_inner(&ast);
debug_print_generated(&ast, &toks);
toks.into()
}

View File

@ -0,0 +1,23 @@
extern crate strum;
#[macro_use]
extern crate strum_macros;
use strum::{EnumCount, IntoEnumIterator};
#[derive(Debug, EnumCount, EnumIter)]
enum Week {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
#[test]
fn simple_test() {
assert_eq!(7, Week::count());
assert_eq!(Week::count(), WEEK_COUNT);
assert_eq!(Week::iter().count(), WEEK_COUNT);
}