sfsm_base/
fallible.rs

1use crate::TransitGuard;
2
3/// An error type that will be returned by the state machine if something goes wrong.
4/// 
5/// It fulfills the same purpose that the ordinary ``` SfsmError ``` does, but allows the
6/// user to extend it with custom error types that are required by the fallible state machine.
7#[derive(Debug)]
8#[non_exhaustive]
9pub enum ExtendedSfsmError<T> {
10    /// Returned if the state machine gets stuck due to an internal error or if the state
11    /// machine has not been started before stepping.
12    Internal,
13
14    /// The custom error can be returned from the error state if an error cannot be handled.
15    /// In that case, the state machine bubbles the error up to the calling start or step
16    /// function where it then must be handled by the user.
17    Custom(T)
18}
19
20/// Trait that must be implemented by all states that are used by the fallible state machine.
21///
22/// Behaves similar to the normal ``` State ``` trait, but requires the user to specify
23/// an Error type. If this error is returned, the state machine immediately transitions into the
24/// error state.
25pub trait TryState {
26
27    // The error type that can be returned by the state
28    type Error;
29
30    /// Implement any behavior that hast to be executed when entering the state.
31    /// Return ``` Ok(()) ``` if no error occurred or ``` Err(Self::Error) ``` if something happened.
32    ///
33    /// ```rust
34    /// # use sfsm_base::fallible::TryState;
35    /// # struct FooState;
36    /// # impl TryState for FooState {
37    /// #     type Error = ();
38    ///     fn try_entry(&mut self) -> Result<(), Self::Error> {
39    ///         println!("Called right after being transitioned into");
40    ///         return Ok(());
41    ///     }
42    /// # }
43    /// ```
44    fn try_entry(&mut self) -> Result<(), Self::Error> { Ok(()) }
45
46
47    /// Implement any behavior that hast to be stepping.
48    /// Return ``` Ok(()) ``` if no error occurred or ``` Err(Self::Error) ``` if something happened.
49    ///
50    /// ```rust
51    /// # use sfsm_base::fallible::TryState;
52    /// # struct FooState;
53    /// # impl TryState for FooState {
54    /// #    type Error = ();
55    ///     fn try_entry(&mut self) -> Result<(), Self::Error> {
56    ///         println!("Called during every step");
57    ///         return Ok(());
58    ///     }
59    /// # }
60    /// ```
61    fn try_execute(&mut self) -> Result<(), Self::Error> { Ok(()) }
62
63
64    /// Implement any behavior that hast to be executed when exiting the state.
65    /// Return ``` Ok(()) ``` if no error occurred or ``` Err(Self::Error) ``` if something happened.
66    ///
67    /// ```rust
68    /// # use sfsm_base::fallible::TryState;
69    /// # struct FooState;
70    /// # impl TryState for FooState {
71    /// #    type Error = ();
72    ///     fn try_entry(&mut self) -> Result<(), Self::Error> {
73    ///         println!("Called before transitioning to another state");
74    ///         return Ok(());
75    ///     }
76    /// # }
77    /// ```
78    fn try_exit(&mut self) -> Result<(), Self::Error> { Ok(()) }
79}
80
81/// Trait that must be implemented by all states have a transition.
82///
83/// Behaves similar to the ``` TryTransition ``` trait but errors can be returned during every
84/// call.
85pub trait TryTransition<DestinationState>: Into<DestinationState> + TryState {
86
87    /// Implement any behavior that hast to be executed when transitioning to the next the state.
88    /// Return ``` Ok(()) ``` if no error occurred or ``` Err(Self::Error) ``` if something happened.
89    ///
90    /// ```rust
91    /// # use sfsm_base::TransitGuard;
92    /// # use sfsm_base::fallible::{TryState, TryTransition};
93    /// # struct FooState;
94    /// # struct BarState;
95    /// # impl TryState for FooState {
96    /// #      type Error = ();
97    /// # };
98    /// # impl Into<BarState> for FooState {
99    /// #     fn into(self) -> BarState {
100    /// #         BarState{}
101    /// #     }
102    /// # }
103    ///
104    /// # impl TryTransition<BarState> for FooState {
105    ///     fn try_action(&mut self) -> Result<(), Self::Error> {
106    ///         println!("Called right after being transitioned into");
107    ///         Ok(())
108    ///     }
109    /// #    fn guard(&self) -> TransitGuard {
110    /// #            todo!()
111    /// #    }
112    /// # }
113    /// ```
114    fn try_action(&mut self) -> Result<(), Self::Error> { Ok(()) }
115
116    /// Specifies when the state has to transit. Return ``` TransitGuard::Remain ``` to remain
117    /// in the current state and ``` TransitGuard::Transit ``` to transit into the next one.
118    /// This is the only function that must be implemented by the transition.
119    /// The others are optional and situational.
120    /// ```rust
121    /// # use sfsm_base::TransitGuard;
122    /// # use sfsm_base::fallible::{TryState, TryTransition};
123    /// # struct FooState;
124    /// # struct BarState;
125    /// # impl TryState for FooState {
126    /// #      type Error = ();
127    /// # };
128    /// # impl Into<BarState> for FooState {
129    /// #     fn into(self) -> BarState {
130    /// #         BarState{}
131    /// #     }
132    /// # }
133    /// #
134    /// # impl TryTransition<BarState> for FooState {
135    ///     fn guard(&self) -> TransitGuard {
136    ///         let foo = 0;
137    ///         if foo == 0 {
138    ///             TransitGuard::Remain
139    ///         } else {
140    ///             TransitGuard::Transit
141    ///         }
142    ///     }
143    /// # }
144    /// ```
145    fn guard(&self) -> TransitGuard;
146}
147
148/// This trait must be implemented by the error state.
149///
150/// The error is being injected into the error state after it has been generated and the
151/// ``` consume_error ``` function allows to specify how the incoming error should be handled.
152pub trait TryErrorState: TryState {
153
154    /// Handle the incoming error
155    /// ```rust
156    /// # use sfsm_base::fallible::{TryState, TryErrorState};
157    /// # struct ErrorState;
158    /// # impl TryState for ErrorState {
159    /// #      type Error = ();
160    /// # };
161    /// #
162    /// # impl TryErrorState for ErrorState {
163    ///     fn consume_error(&mut self, err: Self::Error) {
164    ///         // Store it into the error trait or  it
165    ///         println!("Received an error: {:?}", err);
166    ///     }
167    /// # }
168    ///
169    /// ```
170    fn consume_error(&mut self, err: Self::Error);
171}