#![allow(unused)]
use convert_case::{Case, Casing};
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::ToTokens;
use syn::{parse, parse_macro_input, spanned::Spanned, ItemImpl, ItemMod};
use unpacker::build_metadata;
use crate::util::path_matches;
mod metadata;
mod unpacker;
mod util;
fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
tokens.extend(TokenStream::from(error.into_compile_error()));
tokens
}
#[proc_macro_attribute]
pub fn machine_module(_args: TokenStream, input: TokenStream) -> TokenStream {
match parse::<ItemMod>(input.clone()) {
Ok(_) => input,
Err(error) => token_stream_with_error(input, error),
}
}
#[proc_macro_attribute]
pub fn state_machine(args: TokenStream, input: TokenStream) -> TokenStream {
let main_mod = match parse::<ItemMod>(input.clone()) {
Ok(main_mod) => main_mod,
Err(error) => {
return token_stream_with_error(input, error);
}
};
let name = if args.is_empty() {
Ident::new(
&main_mod.ident.to_string().to_case(Case::UpperCamel),
Span::call_site(),
)
} else {
parse_macro_input!(args as Ident)
};
match generate_state_machine(name, main_mod) {
Ok(output) => output.into_token_stream().into(),
Err(error) => error.into_compile_error().into(),
}
}
fn generate_state_machine(name: Ident, main_mod: ItemMod) -> Result<ItemMod, syn::Error> {
let metadata = build_metadata(name, main_mod)?;
Ok(metadata.write_state_machine())
}