sfsm_base/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), no_std)]
3
4/// Contains definitions for a state machine that contains error handling mechanisms
5pub mod fallible;
6
7/// Contains definitions used by a state machine without any error handling support
8pub mod non_fallible;
9
10/// Contains definitions and code for the messaging system
11pub mod message;
12
13/// Enum used to indicate to the guard function if the transition should transit to the
14/// next state or remain in the current one.
15/// ```rust
16/// # use sfsm_base::non_fallible::{Transition, State};
17/// # use sfsm_base::TransitGuard;
18/// # struct FooState;
19/// # struct BarState;
20/// # impl State for FooState {};
21/// # impl Into<BarState> for FooState {
22/// #     fn into(self) -> BarState {
23/// #         BarState{}
24/// #     }
25/// # }
26///
27/// # impl Transition<BarState> for FooState {
28///     fn guard(&self) -> TransitGuard {
29///         let foo = 0;
30///         if foo == 0 {
31///             TransitGuard::Remain
32///         } else {
33///             TransitGuard::Transit
34///         }
35///     }
36/// # }
37/// ```
38#[derive(PartialEq)]
39pub enum TransitGuard {
40    /// Remains in the current state
41    Remain,
42    /// Transits into the next state
43    Transit
44}
45
46/// Implements from<bool> trait for use of use.
47/// This allows to transit by returning true. Which simplify the code since it allows to return the
48/// TransitGuard from a simple comparison.
49/// ```rust
50/// # use sfsm_base::non_fallible::{Transition, State};
51/// # use sfsm_base::TransitGuard;
52/// # struct FooState;
53/// # struct BarState;
54/// # impl State for FooState {};
55/// # impl Into<BarState> for FooState {
56/// #     fn into(self) -> BarState {
57/// #         BarState{}
58/// #     }
59/// # }
60///
61/// # impl Transition<BarState> for FooState {
62///     fn guard(&self) -> TransitGuard {
63///         let foo = 0;
64///         (foo == 0).into() // Returns TransitGuard::Transit
65///     }
66/// # }
67/// ```
68impl From<bool> for TransitGuard {
69    fn from(transit: bool) -> Self {
70        if transit {
71            TransitGuard::Transit
72        } else {
73            TransitGuard::Remain
74        }
75    }
76}
77
78/// Contains traits that are used to interact with the state machine but should not be implemented
79/// manually. All necessary implementations will be created by the macros.
80pub mod __protected {
81
82    /// Trait that will be implemented for the state machine.
83    pub trait StateMachine {
84        /// The initial state of the state machine.
85        type InitialState;
86
87        /// The returned error. This is also implemented in non fallible state machines,
88        /// but will be ignore as there is no case this error could occur.
89        type Error;
90
91        /// The generator enum containing all states
92        type StatesEnum;
93
94        /// Start function that must be called first. It populates the internal enum with the
95        /// initial state. If step is called before start, the state machine will return an error.
96        fn start(&mut self, state: Self::InitialState) -> Result<(), Self::Error>;
97
98        /// The step function that executes all states and transitions.
99        fn step(&mut self) -> Result<(), Self::Error>;
100
101        /// If desired, the state machine can be stopped. When doing so, the internal states enum
102        /// is returned.
103        fn stop(self) -> Result<Self::StatesEnum, Self::Error>;
104
105        /// Peek the internal states enum.
106        fn peek_state(&self) -> &Self::StatesEnum;
107    }
108
109    /// An implementation of this trait will be generated for every state.
110    /// This is can be used to test if the state machine is in a desired state.
111    pub trait IsState<State>: StateMachine {
112        /// The method must be called with the turbo fish syntax as otherwise Rust cannot figure out
113        /// which implementation to call. To check if the state machine is in a given state call:
114        ///
115        /// ```ignore
116        /// let is_in_state: bool = IsState::<State>::is_state(&sfsm);
117        /// ```
118        fn is_state(&self) -> bool;
119    }
120}
121
122pub use __protected::*;
123pub use non_fallible::*;
124pub use fallible::*;
125pub use message::*;
126pub use message::__protected::*;
127
128