statemachine_macro/
model.rs

1mod state;
2mod states;
3mod transition;
4
5use quote::quote;
6use states::States;
7use syn::{parse, parse_quote};
8
9pub struct StateMachine {
10    pub struct_item: syn::ItemStruct,
11    pub states: States
12}
13
14impl StateMachine {
15    pub fn to_stream(&self) -> proc_macro2::TokenStream {
16        let state_struct = &self.struct_item;
17        let states = self.states.to_tokens(&state_struct.ident, &state_struct.vis);
18        quote! {
19            #state_struct
20            #states
21        }
22    }
23}
24
25impl parse::Parse for StateMachine {
26    fn parse(buf: parse::ParseStream) -> syn::Result<Self> {
27        let mut struct_item: syn::ItemStruct = buf.parse()?;
28        let states: States = buf.parse()?;
29
30        // Add state tracking field
31        let ty = &states.name;
32        let mut field: syn::FieldsNamed = parse_quote! {
33            { _statemachine_state: #ty }
34        };
35        match &mut struct_item.fields {
36            syn::Fields::Named(v) => {
37                v.named.push(field.named.pop().unwrap().into_value());
38            },
39            syn::Fields::Unit => {
40                struct_item.fields = syn::Fields::Named(field);
41            },
42            syn::Fields::Unnamed(_) => panic!("Unnamed fields are not supported in the state machine struct")
43        }
44
45        Ok(StateMachine { struct_item, states })
46    }
47}