1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{DeriveInput, Meta, MetaList, parse_macro_input};
4
5#[proc_macro_derive(State)]
6pub fn state(input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as DeriveInput);
8
9 let name = input.ident;
10 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
11
12 let expanded = quote! {
13 impl #impl_generics State for #name #ty_generics #where_clause {}
14 };
15
16 TokenStream::from(expanded)
17}
18
19#[proc_macro_derive(Stateful, attributes(state))]
20pub fn stateful(input: TokenStream) -> TokenStream {
21 let input = parse_macro_input!(input as DeriveInput);
22 let state_attrs: Vec<_> = input
23 .attrs
24 .iter()
25 .filter(|attr| attr.style == syn::AttrStyle::Outer)
26 .filter(|attr| attr.path().is_ident("state"))
27 .collect();
28 if state_attrs.len() != 1 {
29 panic!("#[derive(Stateful)] requires specifying the state with #[state(<State>)] attribute")
30 }
31
32 let state_toks: Vec<_> = match state_attrs[0].meta.clone() {
33 Meta::List(MetaList { tokens, .. }) => tokens.into_iter().collect(),
34 _ => panic!("#[state(<State>)] is the proper way to describe the state"),
35 };
36
37 let state = if state_toks.len() != 1 {
38 panic!("Only one state allowed in #[state(<State>)] attribute")
39 } else {
40 &state_toks[0]
41 };
42
43 let name = input.ident;
44 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
45
46 let expanded = quote! {
47 impl #impl_generics Stateful for #name #ty_generics #where_clause {
48 type State = #state;
49 }
50 };
51
52 TokenStream::from(expanded)
53}
54
55#[proc_macro_derive(SelfTransitionable)]
56pub fn self_transitionable(input: TokenStream) -> TokenStream {
57 let input = parse_macro_input!(input as DeriveInput);
58
59 let name = input.ident;
60 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
61
62 let expanded = quote! {
63 impl #impl_generics SelfTransitionable for #name #ty_generics #where_clause {
64 }
65 };
66
67 TokenStream::from(expanded)
68}