Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Statechart Examples

This directory contains example applications demonstrating various features of the statechart library.

Running Examples

To run an example:

cargo run --example <example_name>

For example:

cargo run --example traffic_light

To run examples with the derive macros feature enabled:

cargo run --example media_player --features macros

Available Examples

1. Traffic Light (traffic_light.rs)

A simple traffic light controller demonstrating:

  • Basic state transitions
  • Event processing
  • Actions on transitions
  • Context state tracking

Key Concepts:

  • Simple state machine with 3 states (Red, Yellow, Green)
  • Timer-based transitions
  • Cycle counting in context

Run:

cargo run --example traffic_light

2. Door Controller (door_controller.rs)

A door controller with safety features demonstrating:

  • Guard conditions
  • Complex transition logic
  • Safety mechanisms
  • State-dependent behavior

Key Concepts:

  • Guards to control transitions based on context
  • Obstacle detection and reversal
  • Safety-enabled operation
  • Multiple transitions from same state

Run:

cargo run --example door_controller

3. Media Player (media_player.rs)

A media player with buffering demonstrating:

  • Derive macros for cleaner code
  • Multiple state transitions
  • Buffer management
  • Playback control

Key Concepts:

  • Using #[derive(StateId)], #[derive(EventId)], and #[derive(Context)]
  • Guard conditions based on buffer level
  • Position tracking
  • Play/Pause/Stop operations

Run:

cargo run --example media_player --features macros

Example Structure

Each example follows this pattern:

  1. Define State and Event Types: Enums representing states and events
  2. Define Context: Struct holding state machine data
  3. Implement Required Traits: StateId, EventId, Context (or use derive macros)
  4. Build State Machine: Use the builder API to configure states and transitions
  5. Process Events: Simulate real-world event processing
  6. Display Results: Show state changes and context updates

Learning Path

We recommend exploring the examples in this order:

  1. traffic_light.rs - Start here for basic concepts
  2. door_controller.rs - Learn about guards and complex logic
  3. media_player.rs - See derive macros and advanced features

Common Patterns

Basic State Machine

let mut machine = StateMachine::builder()
    .initial_state(MyState::Initial)
    .add_state(MyState::Initial)
    .add_state(MyState::Final)
    .add_transition(
        Transition::new(MyState::Initial, MyState::Final, MyEvent::Go)
    )
    .build()?;

With Actions

.add_transition(
    Transition::new(source, target, event)
        .with_action(|ctx: &mut MyContext| {
            // Perform action
            ctx.counter += 1;
        })
)

With Guards

.add_transition(
    Transition::new(source, target, event)
        .with_guard(|ctx: &MyContext| ctx.is_ready)
        .with_action(|ctx: &mut MyContext| {
            // Only executes if guard passes
        })
)

Using Derive Macros

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, StateId)]
enum MyState {
    Idle,
    Active,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EventId)]
enum MyEvent {
    Start,
    Stop,
}

#[derive(Debug, Clone, Context)]
struct MyContext {
    data: String,
}

Next Steps

After exploring these examples:

  1. Read the API Documentation
  2. Check out the Integration Tests for more complex scenarios
  3. Review the Architecture Documentation
  4. Try building your own state machine!

Contributing

Have an interesting use case? Consider contributing an example! Examples should:

  • Demonstrate a specific feature or pattern
  • Be well-commented and easy to understand
  • Include a description in this README
  • Follow the existing code style