enum_each_variant_derive/
lib.rs1extern crate proc_macro;
39extern crate syn;
40
41#[macro_use]
42extern crate quote;
43
44use proc_macro::TokenStream;
45use syn::*;
46
47#[doc(hidden)]
48#[proc_macro_derive(EachVariant)]
49pub fn each_variant(input: TokenStream) -> TokenStream {
50 let input: DeriveInput = parse(input).unwrap();
51 let expanded = impl_enum_each(input);
52 expanded.into()
53}
54
55fn impl_enum_each(ast: DeriveInput) -> quote::Tokens {
56 let name: &Ident = &ast.ident;
57
58 let enum_data: DataEnum = match ast.data {
59 Data::Enum(data) => data,
60 _ => panic!("#[derive(EachVariant)] is only defined for enums"),
61 };
62
63 let variants = enum_data.variants;
64 let variant_names = variants.iter().map(|ref variant| {
65 match variant.fields {
66 Fields::Unit => {}
67 _ => {
68 panic!("#[derive(EachVariant)] is only defined on enums where all the variants have no associated values");
69 }
70 };
71
72 variant.ident
73 });
74
75 let push_variants = variant_names
76 .map(|variant_name| {
77 quote! { acc.push(#name::#variant_name); }
78 });
79
80 quote! {
81 impl #name {
82 pub fn all_variants() -> Vec<Self> {
84 let mut acc: Vec<Self> = vec![];
85 #(#push_variants);*
86 acc
87 }
88 }
89 }
90}