1moddef::moddef!(
2 flat (pub) mod {
3 },
4 flat (pub(crate)) mod {
5 state,
6 machine,
7 transition,
8 validators
9 }
10);
11
12use crate::{
13 MachinePath, StateModulePath, ensure_machine_loaded_by_name, ensure_state_enum_loaded,
14};
15use macro_registry::callsite::current_module_path;
16use proc_macro::TokenStream;
17use syn::spanned::Spanned;
18use syn::{ItemEnum, ItemImpl, ItemStruct, parse_macro_input};
19
20#[proc_macro_attribute]
21pub fn state(_attr: TokenStream, item: TokenStream) -> TokenStream {
22 let input = parse_macro_input!(item as ItemEnum);
23
24 if let Some(error) = validate_state_enum(&input) {
26 return error.into();
27 }
28
29 let enum_info = match EnumInfo::from_item_enum(&input) {
30 Ok(info) => info,
31 Err(err) => return err.to_compile_error().into(),
32 };
33
34 store_state_enum(&enum_info);
36
37 let expanded = generate_state_impls(&enum_info.module_path);
39
40 TokenStream::from(expanded)
41}
42
43#[proc_macro_attribute]
44pub fn machine(_attr: TokenStream, item: TokenStream) -> TokenStream {
45 let input = parse_macro_input!(item as ItemStruct);
46
47 let machine_info = MachineInfo::from_item_struct(&input);
48
49 if let Some(error) = validate_machine_struct(&input, &machine_info) {
51 return error.into();
52 }
53
54 store_machine_struct(&machine_info);
56
57 let expanded = generate_machine_impls(&machine_info);
59
60 TokenStream::from(expanded)
61}
62
63#[proc_macro_attribute]
64pub fn transition(
65 _attr: proc_macro::TokenStream,
66 item: proc_macro::TokenStream,
67) -> proc_macro::TokenStream {
68 let input = parse_macro_input!(item as ItemImpl);
69
70 let tr_impl = match parse_transition_impl(&input) {
72 Ok(parsed) => parsed,
73 Err(err) => return err.into(),
74 };
75
76 let module_path = current_module_path();
77
78 let state_path: StateModulePath = module_path.clone().into();
79 let machine_path: MachinePath = module_path.clone().into();
80 let _ = ensure_state_enum_loaded(&state_path);
81 let machine_info_owned = ensure_machine_loaded_by_name(&machine_path, &tr_impl.machine_name);
82 let machine_info = match machine_info_owned.as_ref() {
83 Some(info) => info,
84 None => {
85 return missing_transition_machine_error(
86 &tr_impl.machine_name,
87 &module_path,
88 input.self_ty.span(),
89 )
90 .into();
91 }
92 };
93
94 if let Some(err) = validate_transition_functions(&tr_impl, machine_info) {
95 return err.into();
96 }
97
98 let expanded = generate_transition_impl(&input, &tr_impl, machine_info, &module_path);
100
101 expanded.into()
104}
105
106#[proc_macro_attribute]
107pub fn validators(attr: TokenStream, item: TokenStream) -> TokenStream {
108 let module_path = current_module_path();
109 parse_validators(attr, item, &module_path)
110}