Skip to main content

actify_macros/
lib.rs

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
16/// Parsed arguments from `#[actify(...)]`.
17struct 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/// The actify macro expands an impl block of a rust struct to support usage in an actor model.
59/// Effectively, this macro allows to remotely call an actor method through a handle.
60/// By using traits, the methods on the handle have the same signatures, so that type checking is enforced
61#[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}