cw81_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, AttributeArgs, DataEnum, DeriveInput};
4
5/// Merges the variants of two enums.
6///
7/// Adapted from Stargaze Launchpad:
8/// https://github.com/public-awesome/launchpad/tree/main/packages/mint-hooks/derive
9fn merge_variants(metadata: TokenStream, left: TokenStream, right: TokenStream) -> TokenStream {
10    use syn::Data::Enum;
11
12    // parse metadata
13    let args = parse_macro_input!(metadata as AttributeArgs);
14    if let Some(first_arg) = args.first() {
15        return syn::Error::new_spanned(first_arg, "macro takes no arguments")
16            .to_compile_error()
17            .into();
18    }
19
20    // parse the left enum
21    let mut left: DeriveInput = parse_macro_input!(left);
22    let Enum(DataEnum {
23        variants,
24        ..
25    }) = &mut left.data else {
26        return syn::Error::new(left.ident.span(), "only enums can accept variants")
27            .to_compile_error()
28            .into();
29    };
30
31    // parse the right enum
32    let right: DeriveInput = parse_macro_input!(right);
33    let Enum(DataEnum {
34        variants: to_add,
35        ..
36    }) = right.data else {
37        return syn::Error::new(left.ident.span(), "only enums can provide variants")
38            .to_compile_error()
39            .into();
40    };
41
42    // insert variants from the right to the left
43    variants.extend(to_add.into_iter());
44
45    quote! { #left }.into()
46}
47
48
49
50
51/// Note: `#[valid_signature_query]` must be applied _before_ `#[cw_serde]`.
52#[proc_macro_attribute]
53pub fn valid_signature_query(metadata: TokenStream, input: TokenStream) -> TokenStream {
54    merge_variants(
55        metadata,
56        input,
57        quote! {
58            enum Right {
59                #[returns(::cw81::ValidSignatureResponse)]
60                ValidSignature {
61                    data: ::cosmwasm_std::Binary,
62                    signature: ::cosmwasm_std::Binary,
63                    payload: Option<::cosmwasm_std::Binary>
64                },
65
66                #[returns(::cw81::ValidSignaturesResponse)]
67                ValidSignatures {
68                    data: Vec<::cosmwasm_std::Binary>,
69                    signatures: Vec<::cosmwasm_std::Binary>,
70                    payload: Option<::cosmwasm_std::Binary>
71                }
72            }
73        }
74        .into(),
75    )
76}