Skip to main content

StateMachine

Trait StateMachine 

Source
pub trait StateMachine<T, U, V>{
    // Required methods
    fn update(&mut self);
    fn top_down_update(&mut self);
    fn transition(&mut self, target: T);
    fn exact_transition(&mut self, target: T);
    fn state(&self) -> T;
    fn state_matches(&self, state: T) -> bool;
    fn top_ref(&self) -> &V;
    fn top_mut(&mut self) -> &mut V;
    fn name(&self) -> &str;
    fn set_name(&mut self, name: String);
    fn handle_event(&mut self, event: &U);
    fn state_list(&self) -> Vec<T>;
}
Expand description

A state machine.

Required Methods§

Source

fn update(&mut self)

Update the state machine.

Starting with the deepest state, calls Substate::update (or TopState::update).

If any state returns Some(state) from its update method, that transition will be completed and the state machine will continue updating states starting from the nearest common ancestor of the previous state and the new state after transition.

§Example

For some machine:

Top
├─ Foo
│  └─ Bar
└─ Fizz
   └─ Buzz

If the Substate::update method of the Bar state returns State::Buzz.into(), then:

assert!(matches!(machine.state(), State::Bar));
machine.update();

Will have the log output of:

Example: Updating
│Updating Bar
│Transitioning from Bar to Buzz
││Exiting Bar
││Exiting Foo
││Entering Fizz
││Entering Buzz
│└Transition complete
│Updating Top
└Update complete

Top being the nearest common ancestor of the starting state, Bar, and the new state, Buzz, so the update continues from Top.

Source

fn top_down_update(&mut self)

Top-down update the state machine.

Starting with the TopState, calls Substate::top_down_update (or TopState::top_down_update).

Useful for propagating changes to state fields before calling StateMachine::update, or for simply inverting the precedence of transitions (superstates may trigger transitions before their substates).

If any state returns Some(state) from its update method, that transition will be completed and the state machine will continue updating states starting from the first active descendent of the nearest common ancestor of the previous state and the new state after transition.

§Example

For some machine:

Top
├─ Foo
│  └─ Bar
└─ Fizz
   └─ Buzz

If the Substate::top_down_update method of the Foo state returns State::Buzz.into(), then:

assert!(matches!(machine.state(), State::Foo));
machine.top_down_update();

Will have the log output of:

Example: Top-down updating
│Top-down updating Top
│Top-down updating Foo
│Transitioning from Foo to Fizz
││Exiting Foo
││Entering Fizz
││Entering Buzz
│└Transition complete
│Top-down updating Fizz
│Top-down updating Buzz
└Top-down update complete

Top being the nearest common ancestor of the starting state, Foo, and the new state, Fizz, so the top-down update continues from the first active descendent of Top: Fizz.

Source

fn transition(&mut self, target: T)

Attempt to transition the StateMachine to the target state.

If the target state is already in the currently active state hierarchy, no transition is made. To force re-entry of an active state, use StateMachine::exact_transition.

Subject to interruption by short circuit transitions (from Substate::enter or Substate::exit) and initial transitions (from Substate::init or TopState::init).

§Example
// where Bar is a substate of Top:
machine.transition(State::Bar);
assert!(matches!(machine.state(), State::Bar));

machine.transition(State::Top);
assert!(matches!(machine.state(), State::Bar));
Source

fn exact_transition(&mut self, target: T)

Attempt to transition the StateMachine to the target state regardless of currently active states.

Makes the transition even if the target state is in the current active state hierarchy. The state will be re-initialized; Substate::enter and Substate::init will be called.

Subject to interruption by short circuit transitions (from Substate::enter or Substate::exit) and initial transitions (from Substate::init or TopState::init).

§Example
// where Bar is a substate of Top:
machine.transition(State::Bar);
assert!(matches!(machine.state(), State::Bar));

machine.transition(State::Top);
assert!(matches!(machine.state(), State::Bar));

machine.exact_transition(State::Top);
assert!(matches!(machine.state(), State::Top));
Source

fn state(&self) -> T

Get the current state of the StateMachine.

Returns the deepest active state.

§Example

For some machine:

Top
└─ Foo
   └─ Bar
machine.transition(State::Bar);
assert!(matches!(machine.state(), State::Bar));
Source

fn state_matches(&self, state: T) -> bool

Check if a given state matches the current state of this StateMachine or any active superstate.

§Example

For some machine:

Top
├─ Foo
│  └─ Bar
└─ Fizz
machine.transition(State::Bar);
assert!(machine.state_matches(State::Top));
assert!(machine.state_matches(State::Foo));
assert!(machine.state_matches(State::Bar));
assert!(!machine.state_matches(State::Fizz));
Source

fn top_ref(&self) -> &V

Get a reference to the top state.

§Example
// ...
    pub struct Top {
       pub foo: u8,
    }

    impl TopState for Top {}
// ...

dbg!(machine.top_ref().foo);
Source

fn top_mut(&mut self) -> &mut V

Get a mutable reference to the top state.

§Example
// ...
    pub struct Top {
       pub foo: u8,
    }

    impl TopState for Top {}
// ...

machine.top_mut().foo = 8;
Source

fn name(&self) -> &str

Get the name of this state machine.

This name is used in moku log messages.

§Example
assert_eq!(machine.name(), "Example");
Source

fn set_name(&mut self, name: String)

Available on crate feature std only.

Set the name of this state machine.

This name is used in moku log messages.

§Example
machine.set_name("Kikai".to_owned());
assert_eq!(machine.name(), "Kikai");
Source

fn handle_event(&mut self, event: &U)

Handle an event.

Starting with the deepest state, calls Substate::handle_event (or TopState::handle_event) for each active state.

If a state returns Response::Next with Next::None, event handling will continue with its superstate.

If any state returns Response::Next with something other than Next::None, the given transition will be completed and no further handle_event functions are called.

If any state returns Response::Drop, event handling stops immediately and no further handle_event functions are called.

§Example
// ...
    pub enum Event { A }
    impl StateMachineEvent for Event {}

    pub struct Top;
    impl TopState for Top {}
// ...
machine.handle_event(&example::Event::A);
Source

fn state_list(&self) -> Vec<T>

Available on crate feature std only.

Get a list of currently active states, starting from the TopState.

§Example

For some machine:

Top
├─ Foo
│  └─ Bar
└─ Fizz
   └─ Buzz
assert!(matches!(machine.state(), State::Bar));
assert_eq!(
    machine.state_list(),
    vec![State::Top, State::Foo, State::Bar]
);

Implementors§