enum_collections_macros/
lib.rs1use proc_macro::TokenStream;
2use quote::{quote, quote_spanned};
3use syn::{parse_macro_input, spanned::Spanned, DeriveInput};
4
5#[proc_macro_derive(Enumerated)]
8pub fn derive_enum_collections(input: TokenStream) -> TokenStream {
9 let input = parse_macro_input!(input as DeriveInput);
10 let generics = &input.generics;
11 let name = &input.ident;
12 let syn::Data::Enum(en) = input.data else {
13 return quote_spanned! {
14 input.span() => compile_error!("The `Enumerated` macro only supports enums.");
15 }
16 .into();
17 };
18
19 let enum_len = en.variants.len();
20 let mut variants = proc_macro2::TokenStream::new();
21 for variant in en.variants {
22 if let Some((_, discriminant)) = variant.discriminant {
23 return quote_spanned! {
24 discriminant.span() => compile_error!("`Enumerated` doesn't support discriminants");
25 }
26 .into();
27 }
28 let variant_name = variant.ident;
29 variants.extend(quote! { Self::#variant_name, });
30 }
31
32 #[cfg(feature = "variants")]
33 return quote! {
34 impl #generics Enumerated for #name #generics {
35
36 fn position(self) -> usize {
37 self as usize
38 }
39
40 const SIZE: usize = #enum_len;
41 const VARIANTS: &'static [Self] = &[#variants];
42 }
43 }
44 .into();
45
46 #[cfg(not(feature = "variants"))]
47 return quote! {
48 impl #generics Enumerated for #name #generics {
49
50 fn position(self) -> usize {
51 self as usize
52 }
53
54 const SIZE: usize = #enum_len;
55 }
56 }
57 .into();
58}