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}