use darling;
use phases;
use syn;
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(state_machine_future), supports(enum_any), forward_attrs(allow, cfg))]
pub struct StateMachine<P: phases::Phase> {
pub ident: syn::Ident,
pub vis: syn::Visibility,
pub generics: syn::Generics,
pub data: darling::ast::Data<State<P>, ()>,
pub attrs: Vec<syn::Attribute>,
#[darling(default)]
pub derive: darling::util::IdentList,
#[darling(default)]
pub extra: P::StateMachineExtra,
#[darling(default)]
pub context: Option<syn::Ident>,
}
#[derive(Debug, FromVariant)]
#[darling(attributes(state_machine_future, transitions, start, ready, error),
forward_attrs(allow, doc, cfg))]
pub struct State<P: phases::Phase> {
pub ident: syn::Ident,
pub attrs: Vec<syn::Attribute>,
pub fields: darling::ast::Fields<syn::Field>,
#[darling(default)]
pub start: bool,
#[darling(default)]
pub ready: bool,
#[darling(default)]
pub error: bool,
#[darling(default)]
pub transitions: darling::util::IdentList,
#[darling(default)]
pub extra: P::StateExtra,
}
impl<P> StateMachine<P>
where
P: phases::Phase,
{
pub fn and_then<F, Q>(self, mut f: F) -> StateMachine<Q>
where
Q: phases::Phase,
F: FnMut(StateMachine<phases::NoPhase>, P::StateMachineExtra, Vec<State<P>>)
-> StateMachine<Q>,
{
let (state_machine, extra, states) = self.split();
f(state_machine, extra, states)
}
pub fn split(
self,
) -> (
StateMachine<phases::NoPhase>,
P::StateMachineExtra,
Vec<State<P>>,
) {
let states = self.data.take_enum().unwrap();
let extra = self.extra;
let machine = StateMachine {
ident: self.ident,
vis: self.vis,
generics: self.generics,
data: darling::ast::Data::Enum(vec![]),
attrs: self.attrs,
derive: self.derive,
extra: (),
context: self.context,
};
(machine, extra, states)
}
pub fn states(&self) -> &[State<P>] {
match self.data {
darling::ast::Data::Enum(ref states) => states,
darling::ast::Data::Struct(_) => unreachable!(),
}
}
}
impl StateMachine<phases::NoPhase> {
pub fn join<P>(self, extra: P::StateMachineExtra, states: Vec<State<P>>) -> StateMachine<P>
where
P: phases::Phase,
{
StateMachine {
ident: self.ident,
vis: self.vis,
generics: self.generics,
data: darling::ast::Data::Enum(states),
attrs: self.attrs,
derive: self.derive,
extra,
context: self.context,
}
}
}
impl<P> State<P>
where
P: phases::Phase,
{
pub fn and_then<F, Q>(self, mut f: F) -> State<Q>
where
F: FnMut(State<phases::NoPhase>, P::StateExtra) -> State<Q>,
Q: phases::Phase,
{
let (state, extra) = self.split();
f(state, extra)
}
pub fn split(self) -> (State<phases::NoPhase>, P::StateExtra) {
let extra = self.extra;
let state = State {
ident: self.ident,
attrs: self.attrs,
fields: self.fields,
start: self.start,
ready: self.ready,
error: self.error,
transitions: self.transitions,
extra: (),
};
(state, extra)
}
}
impl State<phases::NoPhase> {
pub fn join<P>(self, extra: P::StateExtra) -> State<P>
where
P: phases::Phase,
{
State {
ident: self.ident,
attrs: self.attrs,
fields: self.fields,
start: self.start,
ready: self.ready,
error: self.error,
transitions: self.transitions,
extra,
}
}
}