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;
}