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