1mod codegen;
2mod parse;
3
4use proc_macro::TokenStream;
5
6#[proc_macro_attribute]
7pub fn skip_broadcast(_args: TokenStream, input: TokenStream) -> TokenStream {
8 input
9}
10
11#[proc_macro_attribute]
12pub fn broadcast(_args: TokenStream, input: TokenStream) -> TokenStream {
13 input
14}
15
16struct ActifyArgs {
18 skip_broadcast: bool,
19 custom_name: Option<syn::LitStr>,
20}
21
22impl syn::parse::Parse for ActifyArgs {
23 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
24 let mut args = ActifyArgs {
25 skip_broadcast: false,
26 custom_name: None,
27 };
28
29 while !input.is_empty() {
30 let ident: syn::Ident = input.parse()?;
31 if ident == "skip_broadcast" {
32 args.skip_broadcast = true;
33 } else if ident == "name" {
34 input.parse::<syn::Token![=]>()?;
35 let name: syn::LitStr = input.parse()?;
36 args.custom_name = Some(name);
37 } else if ident == "broadcast" {
38 return Err(syn::Error::new_spanned(
39 ident,
40 "methods already broadcast by default; `#[actify(broadcast)]` is unnecessary",
41 ));
42 } else {
43 return Err(syn::Error::new_spanned(
44 ident,
45 "unknown actify attribute; expected `skip_broadcast` or `name = \"...\"`",
46 ));
47 }
48
49 if !input.is_empty() {
50 input.parse::<syn::Token![,]>()?;
51 }
52 }
53
54 Ok(args)
55 }
56}
57
58#[proc_macro_attribute]
62pub fn actify(attr: TokenStream, item: TokenStream) -> TokenStream {
63 let args = syn::parse_macro_input!(attr as ActifyArgs);
64
65 let mut impl_block = syn::parse_macro_input!(item as syn::ItemImpl);
66 match parse::ImplInfo::from_impl_block(
67 &mut impl_block,
68 args.skip_broadcast,
69 args.custom_name,
70 ) {
71 Ok(info) => codegen::generate(&info).into(),
72 Err(err) => err.into(),
73 }
74}