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 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 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 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 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}