🦀 Statum: Zero-Boilerplate Compile-Time State Machines in Rust

112 points Known_Cod8398 35 comments

Hey Rustaceans! I've created a library for building type-safe state machines in Rust that makes state transitions impossible to get wrong at compile time.

Key Features

  • 🛡️ Compile-time state transition validation
  • 🔒 Type-safe state data access
  • ⚡ Zero boilerplate implementation
  • 📦 Simple, intuitive API

Quick Example

use statum::{state, machine};

#[state]
pub enum TaskState {
    New,
    InProgress,
    Complete,
}

#[machine]
struct Task<S: TaskState> {
    id: String,
    name: String,
}

impl Task<New> {
    fn start(self) -> Task<InProgress> {
        self.transition()
    }
}

impl Task<InProgress> {
    fn complete(self) -> Task<Complete> {
        self.transition()
    }
}

fn main() {
    let task = Task::new("task-1".to_owned(), "Important Task".to_owned())
        .start()
        .complete();
}

States with Data

Need to attach data to specific states? No problem:

#[state]
pub enum DocumentState {
    Draft,
    Review(ReviewData),    // State with associated data
    Published,
}

struct ReviewData {
    reviewer: String,
    comments: Vec<String>,
}

impl Document<Draft> {
    fn submit_for_review(self, reviewer: String) -> Document<Review> {
        self.transition_with(ReviewData {
            reviewer,
            comments: vec![],
        })
    }
}

Accessing State Data

When a state has associated data, you can access it safely:

impl Document<Review> {
    fn add_comment(&mut self, comment: String) {
        // Safely modify state data
        if let Some(review_data) = self.get_state_data_mut() {
            review_data.comments.push(comment);
        }
    }

    fn get_reviewer(&self) -> Option<&str> {
        // Safely read state data
        self.get_state_data().map(|data| data.reviewer.as_str())
    }

    fn approve(self) -> Document<Published> {
        // Transition to a state without data
        self.transition()
    }
}

Why Statum?

I created Statum because existing state machine libraries often require:

  • Complex trait implementations
  • Manual state transition validation
  • Runtime checks for state data access

Statum moves all these checks to compile-time while keeping the API simple and ergonomic.

Looking for Feedback!

The crate is in active development, and I'd love to hear from the community:

  • What state machine patterns do you commonly use?
  • Are there specific features you'd like to see?
  • Any suggestions for improving the API?

Try It Out

cargo add statum

GitHub: https://github.com/eboody/statum
Crates.io: https://crates.io/crates/statum

Let me know what you think! 🦀