cw83_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, AttributeArgs, DataEnum, DeriveInput};
4
5
6
7fn merge_variants(metadata: TokenStream, left: TokenStream, right: TokenStream) -> TokenStream {
8    use syn::Data::Enum;
9
10    // parse metadata
11    let args = parse_macro_input!(metadata as AttributeArgs);
12    if let Some(first_arg) = args.first() {
13        return syn::Error::new_spanned(first_arg, "macro takes no arguments")
14            .to_compile_error()
15            .into();
16    }
17
18    // parse the left enum
19    let mut left: DeriveInput = parse_macro_input!(left);
20    let Enum(DataEnum {
21        variants,
22        ..
23    }) = &mut left.data else {
24        return syn::Error::new(left.ident.span(), "only enums can accept variants")
25            .to_compile_error()
26            .into();
27    };
28
29    // parse the right enum
30    let right: DeriveInput = parse_macro_input!(right);
31    let Enum(DataEnum {
32        variants: to_add,
33        ..
34    }) = right.data else {
35        return syn::Error::new(left.ident.span(), "only enums can provide variants")
36            .to_compile_error()
37            .into();
38    };
39
40    // insert variants from the right to the left
41    variants.extend(to_add.into_iter());
42
43    quote! { #left }.into()
44}
45
46
47
48#[proc_macro_attribute]
49pub fn registry_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
50    merge_variants(
51        metadata,
52        input,
53        quote! {
54            enum Right {
55                #[returns(AccountInfoResponse)]
56                AccountInfo(AccountQuery)
57            }
58        }
59        .into(),
60    )
61}
62
63
64 #[proc_macro_attribute]
65pub fn registry_execute(metadata: TokenStream, input: TokenStream) -> TokenStream {
66    merge_variants(
67        metadata,
68        input,
69        quote! {
70            enum Right {
71                CreateAccount(CreateAccountMsg)
72            }
73        }
74        .into(),
75    )
76}