A finite-state machine models a system as named states and permitted transitions between them. In Rust, traits and generics can make those rules part of the type system: a method available in one state need not exist in another. section 8.1
Consider a user session with Initial, Anonymous, Authenticated, and LoggedOut states. Define each state as a marker type implementing SessionState, then tag Session<State> with PhantomData<State>. The session still carries its ID and properties; its type also identifies which operations are valid. section 8.1
Listing 8.1 Modeling session state with traits and struct tagging
pub trait SessionState {}
#[derive(Debug, Default)]
pub struct Session<State: SessionState = Initial> { #1
session_id: Uuid,
props: HashMap<String, String>, #2
phantom: PhantomData<State>,
}
#[derive(Debug, Default)]
pub struct Initial;
#[derive(Debug, Default)]
pub struct Anonymous;
#[derive(Debug, Default)]
pub struct Authenticated;
#[derive(Debug, Default)]
pub struct LoggedOut;
impl SessionState for Initial {}
impl SessionState for Anonymous {}
impl SessionState for Authenticated {}
impl SessionState for LoggedOut {}
The listing shows the marker types, their shared trait, and the generic Session structure that ties a session value to a state. section 8.1
Authenticate, update, log out
Session::new() creates an anonymous session. authenticate(self, username, password) returns either Session<Authenticated> or the original Session<Anonymous> on failure. Only the authenticated implementation provides update_property and logout; logout consumes that session and returns Session<LoggedOut>. The example credential check is deliberately simple, and resuming an ID omits the database lookup and validation a real session would need. section 8.1
Use this pattern when state-specific operations make a stateful system hard to reason about. It is not a panacea, but small, type-safe machines can rule out invalid transitions before the program runs. Coroutines show a related use of the model: the Rust compiler tracks whether a coroutine has started, yielded, or completed. section 8.1 section 8.2








