1mod ast;
2mod expand;
3mod kw;
4mod parse;
5mod validate;
6
7use expand::expand::expand;
8use parse::actor_args::parse_actor_args;
9use proc_macro::TokenStream;
10use proc_macro2::TokenStream as TokenStream2;
11use syn::{DeriveInput, parse_macro_input, spanned::Spanned};
12use validate::args::validate_actor_args;
13
14macro_rules! parse_block_or_expr {
17 ($input:expr) => {
18 if let Ok(block) = syn::parse::<syn::Block>($input.clone()) {
19 block
20 } else {
21 let expr: syn::Expr = syn::parse($input).expect("expected block or expression");
22 syn::parse_quote!({ #expr })
23 }
24 };
25}
26
27#[proc_macro_attribute]
31pub fn actor(attr: TokenStream, item: TokenStream) -> TokenStream {
32 let input = parse_macro_input!(item as DeriveInput);
33 let attr_ts: TokenStream2 = attr.into();
34 let out = || -> syn::Result<_> {
35 let raw = parse_actor_args(input.span(), attr_ts)?;
36 let val = validate_actor_args(raw)?;
37 Ok(expand(&input, &val))
38 }();
39
40 match out {
41 Ok(ts) => ts.into(),
42 Err(e) => e.to_compile_error().into(),
43 }
44}
45
46#[allow(unexpected_cfgs)]
49#[proc_macro]
50pub fn actor_pre_start(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
51 let body = parse_block_or_expr!(input);
52 quote::quote! {
53 #[allow(unexpected_cfgs)]
54 #[cfg(feature="async-trait")]
55 pub async fn on_start(
56 &self,
57 myself: ractor::ActorRef<<Self as ractor::Actor>::Msg>,
58 args: <Self as ractor::Actor>::Arguments,
59 ) -> ::core::result::Result<(<Self as ractor::Actor>::State), ractor::ActorProcessingErr> {
60 #body
61 }
62
63 #[allow(unexpected_cfgs)]
64 #[cfg(not(feature="async-trait"))]
65 pub fn on_start(
66 &self,
67 myself: ractor::ActorRef<<Self as ractor::Actor>::Msg>,
68 args: <Self as ractor::Actor>::Arguments,
69 ) -> impl ::core::future::Future<Output=::core::result::Result<(<Self as ractor::Actor>::State), ractor::ActorProcessingErr>> + Send {
70 async move {
71 #body
72 }
73 }
74 }.into()
75}
76
77#[allow(unexpected_cfgs)]
80#[proc_macro]
81pub fn actor_handle(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
82 let body = parse_block_or_expr!(input);
83 quote::quote! {
84 #[allow(unexpected_cfgs)]
85 #[cfg(feature="async-trait")]
86 pub async fn handle_msg(
87 &self,
88 myself: ractor::ActorRef<<Self as ractor::Actor>::Msg>,
89 msg: <Self as ractor::Actor>::Msg,
90 state: &mut <Self as ractor::Actor>::State,
91 ) -> ::core::result::Result<(), ractor::ActorProcessingErr> {
92 #body
93 }
94
95 #[allow(unexpected_cfgs)]
96 #[cfg(not(feature="async-trait"))]
97 pub fn handle_msg(
98 &self,
99 myself: ractor::ActorRef<<Self as ractor::Actor>::Msg>,
100 msg: <Self as ractor::Actor>::Msg,
101 state: &mut <Self as ractor::Actor>::State,
102 ) -> impl ::core::future::Future<Output=::core::result::Result<(), ractor::ActorProcessingErr>> + Send {
103 async move {
104 #body
105 }
106 }
107 }.into()
108}