use sfsm::*; // An example of how a hierarchical state machine can be built pub struct Offline {} pub struct Standby {} pub struct Requesting {} pub struct Observing {} pub struct Reporting {} add_state_machine!( ForwardObserver, Offline, [Offline, Online], [ Offline => Online, Online => Offline, ] ); // Defines the Online inner state machine. add_state_machine!( Online, Standby, [Standby, Requesting, Observing, Reporting], [ Standby => Requesting, Requesting => Observing, Observing => Reporting, Reporting => Standby, ] ); derive_state!(Offline); derive_state!(Standby); derive_state!(Requesting); derive_state!(Observing); derive_state!(Reporting); impl Into for Online { fn into(self) -> Offline { Offline {} } } impl Transition for Offline { fn guard(&self) -> TransitGuard { true.into() } } impl Transition for Online { fn guard(&self) -> TransitGuard { false.into() } } impl Into for Standby { fn into(self) -> Requesting { Requesting {} } } impl Transition for Standby { fn guard(&self) -> TransitGuard { true.into() } } impl Into for Requesting { fn into(self) -> Observing { Observing {} } } impl Transition for Requesting { fn guard(&self) -> TransitGuard { true.into() } } impl Into for Observing { fn into(self) -> Reporting { Reporting {} } } impl Transition for Observing { fn guard(&self) -> TransitGuard { true.into() } } impl Into for Reporting { fn into(self) -> Standby { Standby {} } } impl Transition for Reporting { fn guard(&self) -> TransitGuard { true.into() } } impl State for Online { /// Executes the sub-state machine on each step. fn execute(&mut self) { self.step().unwrap(); } } // Initialize the Online state machine on transition. impl From for Online { /// Constructs, and starts, the [`Online`] state machine on a transition from Offline fn from(_: Offline) -> Self { let mut machine = Self::new(); machine.start(Standby {}).unwrap(); machine } } /// Register a logger function /// Enable the trace features for the tracing to work /// The logger function receives logs from the state machine and forwards them /// to what ever logging mechanism desired. #[sfsm_trace] fn trace(log: &str) { println!("{}", log); } fn run_hierarchical_simple() -> Result<(), SfsmError> { // Build the outer state machine let mut forward_observer = ForwardObserver::new(); // Build the initial state let offline = Offline {}; forward_observer.start(offline)?; // The IsState trait can be used to check in which state the state machine is in. assert!(IsState::::is_state(&forward_observer)); // Run the state machine with .step(). forward_observer.step()?; assert!(IsState::::is_state(&forward_observer)); forward_observer.step()?; assert!(IsState::::is_state(&forward_observer)); forward_observer.step()?; assert!(IsState::::is_state(&forward_observer)); forward_observer.step()?; assert!(IsState::::is_state(&forward_observer)); forward_observer.step()?; assert!(IsState::::is_state(&forward_observer)); Ok(()) } fn main() { run_hierarchical_simple().unwrap(); } #[cfg(test)] mod tests { use crate::run_hierarchical_simple; #[test] fn hierarchical_simple() { run_hierarchical_simple().unwrap(); } }