Skip to main content

pfc_dust_collector_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 DAO DAO:
8/// https://github.com/DA0-DA0/dao-contracts/blob/74bd3881fdd86829e5e8b132b9952dd64f2d0737/packages/dao-macros/src/lib.rs#L9
9// Merges the variants of two enums.
10fn merge_variants(metadata: TokenStream, left: TokenStream, right: TokenStream) -> TokenStream {
11    use syn::Data::Enum;
12
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    let mut left: DeriveInput = parse_macro_input!(left);
21    let right: DeriveInput = parse_macro_input!(right);
22
23    if let (
24        Enum(DataEnum {
25            variants,
26            ..
27        }),
28        Enum(DataEnum {
29            variants: to_add,
30            ..
31        }),
32    ) = (&mut left.data, right.data)
33    {
34        variants.extend(to_add);
35
36        quote! { #left }.into()
37    } else {
38        syn::Error::new(left.ident.span(), "variants may only be added for enums")
39            .to_compile_error()
40            .into()
41    }
42}
43
44/// Append dust-collection execute messages variant(s) to an enum.
45///
46/// For example, apply the `pfc_dust_collect` macro to the following enum:
47///
48/// ```rust
49/// use cosmwasm_schema::cw_serde;
50/// use cw_ownable::cw_ownable_execute;
51/// use pfc_dust_collector_derive::pfc_dust_collect;
52///
53/// #[pfc_dust_collect]
54/// #[cw_serde]
55/// enum ExecuteMsg {
56///     Foo {},
57///     Bar {},
58/// }
59/// ```
60///
61/// Is equivalent to:
62///
63/// ```rust
64/// use cosmwasm_schema::cw_serde;
65///
66///
67/// #[cw_serde]
68/// enum ExecuteMsg {
69///     DustReceived {},
70///     FlushDust {},
71///     SetReturnContract { contract:String },
72
73/// }
74/// ```
75/// 
76/// Note: `#[pfc_dust_collect]` must be applied _before_ `#[cw_serde]`.
77#[proc_macro_attribute]
78pub fn pfc_dust_collect(metadata: TokenStream, input: TokenStream) -> TokenStream {
79    merge_variants(
80        metadata,
81        input,
82        quote! {
83            enum Right {
84                ///  Receive dust from somewhere
85                DustReceived {},
86                /// Flush the dust
87                FlushDust{} ,
88                SetReturnContract{ contract: String },
89            }
90        }
91        .into(),
92    )
93}