enum_values_derive/
lib.rs1#![doc = include_str!("../README.md")]
2
3use proc_macro::TokenStream;
4use syn::{Data, DeriveInput, Expr, ExprLit, Lit, parse_macro_input};
5
6use quote::quote;
7
8#[proc_macro_derive(EnumValues)]
10pub fn generate_enum_values_impl(input: TokenStream) -> TokenStream {
11 let input = parse_macro_input!(input as DeriveInput);
12 let name = &input.ident;
13
14 let Data::Enum(data_enum) = &input.data else {
15 return syn::Error::new_spanned(name, "EnumReflect only works on enums")
16 .to_compile_error()
17 .into();
18 };
19
20 let get_fields_arms = data_enum
21 .variants
22 .iter()
23 .map(|v| {
24 let variant_ident = &v.ident;
25 let doc = v
26 .attrs
27 .iter()
28 .filter(|a| a.path().is_ident("doc"))
29 .filter_map(|a| {
30 let expr = if let Ok(nv) = &a.meta.require_name_value() {
31 &nv.value
32 } else {
33 return None;
34 };
35 if let Expr::Lit(ExprLit { lit, .. }) = expr
36 && let Lit::Str(str) = lit
37 {
38 return Some(str.value().clone());
39 }
40 None
41 })
42 .collect::<String>();
43
44 let Some(discriminant) = v.discriminant.as_ref() else {
45 return syn::Error::new_spanned(name, "No discriminant for enum variant")
46 .to_compile_error();
47 };
48
49 let value = if let Expr::Lit(lit) = &discriminant.1 {
50 if let Lit::Int(int) = &lit.lit {
51 if let Ok(value) = int.base10_parse::<u16>() {
52 value
53 } else {
54 return syn::Error::new_spanned(name, "Cannot parse int literal as u16")
55 .to_compile_error();
56 }
57 } else {
58 return syn::Error::new_spanned(name, "Cannot parse int literal")
59 .to_compile_error();
60 }
61 } else {
62 return syn::Error::new_spanned(name, "Enum discriminant should be a literal")
63 .to_compile_error();
64 };
65
66 quote! { enum_values::VariantInfo {
67 name: stringify!(#variant_ident),
68 value: #value,
69 doc: #doc.trim()
70 } }
71 })
72 .collect::<Vec<_>>();
73
74 quote! {
75 impl enum_values::EnumValues for #name {
76 fn variants() -> impl Iterator<Item = enum_values::VariantInfo> {
77 [ #(#get_fields_arms),* ].into_iter()
78 }
79 }
80 }
81 .into()
82}