kson_effect_param_macro/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DeriveInput};
4
5#[proc_macro_derive(Effect)]
6pub fn derive_effect_param(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
8
9 match &input.data {
10 Data::Enum(e) => {
11 let mut match_arms = vec![];
12 for variant in &e.variants {
13 let new_struct_expr = match &variant.fields {
14 syn::Fields::Named(_) => todo!(),
15 syn::Fields::Unnamed(_) => {
16 let input = &input.ident;
17 let variant = &variant.ident;
18 quote!(#input::#variant(Effect::derive(&a,key,param)))
19 }
20 syn::Fields::Unit => panic!("Enum unit variants are not supported"),
21 };
22 let input = &input.ident;
23 let variant = &variant.ident;
24 match_arms.push(quote!(#input::#variant(a) => #new_struct_expr,));
25 }
26
27 match_arms.push(quote!(_ => panic!("Tried to derive from a different type"),));
28 let input = &input.ident;
29 proc_macro::TokenStream::from(quote!(
30 impl Effect for #input {
31 fn derive(&self, key: &str, param: &str) -> Self {
32 match self { #(#match_arms)* }
33 }
34 fn param_list() -> &'static [&'static str] {
35 &[]
36 }
37 }
38 ))
39 }
40 Data::Struct(s) => {
41 let mut match_arms = vec![];
43 let mut fields = vec![];
44
45 for f in &s.fields {
46 if let Some(ident) = &f.ident {
47 fields.push(quote!(stringify!(#ident)));
48 match_arms.push(quote!(stringify!(#ident) => Self {
49 #ident: param.parse().unwrap_or_default(),
50 ..self.clone()
51 },))
52 }
53 }
54
55 match_arms.push(quote!(_ => self.clone()));
56
57 let input = &input.ident;
58 proc_macro::TokenStream::from(quote!(
59 impl Effect for #input {
60 fn derive(&self, key: &str, param: &str) -> Self {
61 match key {#(#match_arms)*}
62 }
63
64 fn param_list() -> &'static [&'static str] {
65 &[#(#fields),*]
66 }
67 }))
68 }
69 Data::Union(_) => panic!("Unions are not supported"),
70 }
71}