1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_quote, DeriveInput, GenericParam, WherePredicate};
4
5#[proc_macro_derive(Actor)]
6pub fn actor_derive(input: TokenStream) -> TokenStream {
7 let derive_input = syn::parse::<DeriveInput>(input).expect("macro to be used as custom-derive");
8
9 let send_and_static_bounds = send_and_static_bounds(&derive_input);
10 let actor_ident = derive_input.ident;
11 let (impl_generics, type_generics, where_clause) = derive_input.generics.split_for_impl();
12 let where_clause = match where_clause.cloned() {
13 None => parse_quote! { where #(#send_and_static_bounds),* },
14 Some(mut existing) => {
15 existing.predicates.extend(send_and_static_bounds);
16
17 existing
18 }
19 };
20
21 quote! {
22 impl #impl_generics xtra::Actor for #actor_ident #type_generics #where_clause {
23 type Stop = ();
24
25 async fn stopped(self) { }
26 }
27 }
28 .into()
29}
30
31fn send_and_static_bounds(input: &DeriveInput) -> Vec<WherePredicate> {
33 input
34 .generics
35 .params
36 .iter()
37 .filter_map(|gp| match gp {
38 GenericParam::Type(tp) => Some(&tp.ident),
39 GenericParam::Lifetime(_) => None,
40 GenericParam::Const(_) => None,
41 })
42 .map(|ident| {
43 parse_quote! {
44 #ident: Send + 'static
45 }
46 })
47 .collect::<Vec<WherePredicate>>()
48}