1#![allow(unused)]
2
3use convert_case::{Case, Casing};
4use proc_macro::TokenStream;
5use proc_macro2::{Ident, Span};
6use quote::ToTokens;
7use syn::{parse, parse_macro_input, spanned::Spanned, ItemImpl, ItemMod};
8use unpacker::build_metadata;
9
10use crate::util::path_matches;
11
12mod metadata;
13mod unpacker;
14mod util;
15
16fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
24 tokens.extend(TokenStream::from(error.into_compile_error()));
25 tokens
26}
27
28#[proc_macro_attribute]
29pub fn machine_module(_args: TokenStream, input: TokenStream) -> TokenStream {
30 match parse::<ItemMod>(input.clone()) {
32 Ok(_) => input,
33 Err(error) => token_stream_with_error(input, error),
34 }
35}
36
37#[proc_macro_attribute]
38pub fn state_machine(args: TokenStream, input: TokenStream) -> TokenStream {
39 let main_mod = match parse::<ItemMod>(input.clone()) {
41 Ok(main_mod) => main_mod,
42 Err(error) => {
43 return token_stream_with_error(input, error);
44 }
45 };
46
47 let name = if args.is_empty() {
57 Ident::new(
59 &main_mod.ident.to_string().to_case(Case::UpperCamel),
60 Span::call_site(),
61 )
62 } else {
63 parse_macro_input!(args as Ident)
64 };
65
66 match generate_state_machine(name, main_mod) {
67 Ok(output) => output.into_token_stream().into(),
68 Err(error) => error.into_compile_error().into(),
69 }
70}
71
72fn generate_state_machine(name: Ident, main_mod: ItemMod) -> Result<ItemMod, syn::Error> {
73 let metadata = build_metadata(name, main_mod)?;
74 Ok(metadata.write_state_machine())
75}