use crate::kind;
use crate::machine::{EventKind, StateMachine};
pub struct MachineMetadata<S: StateMachine>
where
S::Event: EventKind,
{
pub initial_state: S,
pub all_states: Vec<S>,
pub terminal_states: Vec<S>,
pub transitions: Vec<(S, S::Event, S)>,
}
pub(crate) fn build<S: StateMachine>() -> MachineMetadata<S>
where
S::Event: EventKind + Clone,
{
let all_states = S::state_variants();
let terminal_states = all_states
.iter()
.filter(|s| s.is_terminal())
.cloned()
.collect();
let events = S::Event::event_variants();
let mut transitions = Vec::new();
for state in &all_states {
if state.is_terminal() {
continue;
}
let restriction = state.restriction();
for event in &events {
if let Some(expected) = restriction {
let accepted = matches!(event.kinds(), Some(ek) if kind::intersects(expected, ek));
if !accepted {
continue;
}
}
if let Some(target) = state.transition(event) {
transitions.push((state.clone(), event.clone(), target));
}
}
}
MachineMetadata {
initial_state: S::initial(),
all_states,
terminal_states,
transitions,
}
}