sfsm_base/
non_fallible.rs

1use crate::TransitGuard;
2
3/// An error type that will be returned by the state machine if something goes wrong.
4/// 
5/// Specifically, when the state machine gets stuck in a state due to an internal error.
6/// The state machine is designed in a way where this should not happen, so this can largely be
7/// ignored. It is used in situations that are other wise hard to avoid without a panic!.
8/// It might be extended in the future to contains custom error codes generated from the states
9/// themselves
10#[derive(Debug)]
11#[non_exhaustive]
12pub enum SfsmError {
13    /// Returned if the state machine gets stuck due to an internal error or if the state
14    /// machine has not been started before stepping.
15    Internal,
16}
17
18/// Trait that must be implemented by all states
19///
20/// Allows to define behavior when entering, exiting and running the state. Both the entry and exit
21/// function will only be executed once for each state. The execute function will be executed as
22/// long as the state does not transition into another state. There can only ever be one single
23/// state active.
24pub trait State {
25
26    /// Implement any behavior that hast to be executed when entering the state.
27    ///
28    /// ```rust
29    /// # use sfsm_base::non_fallible::State;
30    /// # struct FooState;
31    /// # impl State for FooState {
32    ///     fn entry(&mut self) {
33    ///         println!("Called right after being transitioned into");
34    ///     }
35    /// # }
36    /// ```
37    fn entry(&mut self) {}
38
39    /// Implement any behavior that has to be executed when the state is being executed.
40    /// This function will be called as long as the state does not transit.
41    ///
42    /// ```rust
43    /// # use sfsm_base::non_fallible::State;
44    /// # struct FooState;
45    /// # impl State for FooState {
46    ///     fn execute(&mut self) {
47    ///         println!("Called during every step");
48    ///     }
49    /// # }
50    /// ```
51    fn execute(&mut self) {}
52
53    /// Implement any behavior that hast to be executed when exiting the state.
54    ///
55    /// ```rust
56    /// # use sfsm_base::non_fallible::State;
57    /// # struct FooState;
58    /// # impl State for FooState {
59    ///     fn exit(&mut self) {
60    ///         println!("Called before transitioning to another state");
61    ///     }
62    /// # }
63    /// ```
64    fn exit(&mut self) {}
65}
66
67/// Trait that must be implemented by a state that want to transition to DestinationState.
68///
69/// All states can have none or many transitions.
70/// On top of the transition trait the state must implement the ``` Into<DestinationState> ```
71/// trait to specify what happens with the source state data while transitioning and how the
72/// destination state is generated.
73/// The action method is run once the transition executes.
74/// The only non optional method is the guard function that specifies when the state transitions.
75pub trait Transition<DestinationState>: Into<DestinationState> + State {
76    /// Implement any behavior that hast to be executed when exiting the state.
77    /// ```rust
78    /// # use sfsm_base::non_fallible::{Transition, State};
79    /// # use sfsm_base::TransitGuard;
80    /// # struct FooState;
81    /// # struct BarState;
82    /// # impl State for FooState {};
83    /// # impl Into<BarState> for FooState {
84    /// #     fn into(self) -> BarState { BarState{} }
85    /// # }
86    ///
87    /// # impl Transition<BarState> for FooState {
88    ///     fn action(&mut self) {
89    ///         println!("Called while transitioning to another state");
90    ///     }
91    /// #    fn guard(&self) -> TransitGuard {
92    /// #            todo!()
93    /// #    }
94    /// # }
95    /// ```
96    fn action(&mut self) {}
97
98    /// Specifies when the state has to transit. Return ``` TransitGuard::Remain ``` to remain
99    /// in the current state and ``` TransitGuard::Transit ``` to transit into the next one.
100    /// This is the only function that must be implemented by the transition.
101    /// The others are optional and situational.
102    /// ```rust
103    /// # use sfsm_base::non_fallible::{Transition, State};
104    /// # use sfsm_base::TransitGuard;
105    /// # struct FooState;
106    /// # struct BarState;
107    /// # impl State for FooState {};
108    /// # impl Into<BarState> for FooState {
109    /// #     fn into(self) -> BarState { BarState{} }
110    /// # }
111    ///
112    /// # impl Transition<BarState> for FooState {
113    ///     fn guard(&self) -> TransitGuard {
114    ///         let foo = 0;
115    ///         if foo == 0 {
116    ///             TransitGuard::Remain
117    ///         } else {
118    ///             TransitGuard::Transit
119    ///         }
120    ///     }
121    /// # }
122    /// ```
123    fn guard(&self) -> TransitGuard;
124}