finny/fsm/
states.rs

1use crate::{FsmBackend, lib::*};
2
3use crate::FsmResult;
4
5/// The implementation should hold all of the FSM's states as fields.
6pub trait FsmStates<TFsm>: FsmStateFactory<TFsm> where TFsm: FsmBackend {
7    /// The enum type for all states that's used as the "current state" field in the FSM's backend.
8    type StateKind: Clone + Copy + Debug + PartialEq + 'static;
9    /// An array of current states for the machine, one for each region.
10    type CurrentState: Clone + Copy + Debug + Default + AsRef<[FsmCurrentState<Self::StateKind>]> + AsMut<[FsmCurrentState<Self::StateKind>]> + 'static;
11}
12
13/// The current state of the FSM.
14#[derive(Copy, Clone, PartialEq)]
15pub enum FsmCurrentState<S> where S: Clone + Copy {
16    /// The FSM is halted and has to be started using the `start()` method.
17    Stopped,
18    /// The FSM is in this state.
19    State(S)
20}
21
22impl<S> FsmCurrentState<S> where S: Clone + Copy {
23    pub fn all_stopped(current_states: &[Self]) -> bool {
24        current_states.iter().all(|s| match s {
25            FsmCurrentState::Stopped => true,
26            _ => false
27        })
28    }
29}
30
31impl<S> Debug for FsmCurrentState<S> where S: Debug + Copy {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        match self {
34            FsmCurrentState::Stopped => f.write_str("Fsm::Stopped"),
35            FsmCurrentState::State(s) => s.fmt(f)
36        }
37    }
38}
39
40impl<S> Default for FsmCurrentState<S> where S: Clone + Copy {
41    fn default() -> Self {
42        Self::Stopped
43    }
44}
45
46/// Create a new state from the shared global context.
47pub trait FsmStateFactory<TFsm> where Self: Sized, TFsm: FsmBackend {
48    /// Constructor for building this state from the shared global context.
49    fn new_state(context: &<TFsm as FsmBackend>::Context) -> FsmResult<Self>;
50}
51
52/// The implementation of a simple state factory, where the state supports Default.
53impl<TState, TFsm> FsmStateFactory<TFsm> for TState where TState: Default, TFsm: FsmBackend {
54    fn new_state(_context: &<TFsm as FsmBackend>::Context) -> FsmResult<Self> {
55        Ok(Default::default())
56    }
57}
58
59/// Retrieve a pair of states as immutable references. Used in state transitions.
60pub trait FsmStateTransitionAsRef<T1, T2> {
61    fn as_state_transition_ref(&self) -> (&T1, &T2);
62}
63
64/// Retrieve a pair of states as mutable references. Used in state transitions.
65pub trait FsmStateTransitionAsMut<T1, T2> {
66    fn as_state_transition_mut(&mut self) -> (&mut T1, &mut T2);
67}