How to Implement the Typestate Pattern in Rust

Implement the Typestate pattern by defining an enum where each variant represents a valid state and using `match` to enforce state transitions at compile time.

How to Implement the Typestate Pattern in Rust

Implement the Typestate pattern by defining an enum where each variant represents a valid state and using match to enforce state transitions at compile time.

use std::mem;

enum TcpStream {
    Unconnected,
    Connected,
    Writing,
    Closed,
}

impl TcpStream {
    fn connect(&mut self) {
        match self {
            TcpStream::Unconnected => *self = TcpStream::Connected,
            _ => panic!("Cannot connect"),
        }
    }

    fn write(&mut self, _data: &[u8]) {
        match self {
            TcpStream::Connected => *self = TcpStream::Writing,
            _ => panic!("Cannot write"),
        }
    }

    fn close(&mut self) {
        match self {
            TcpStream::Writing | TcpStream::Connected => *self = TcpStream::Closed,
            _ => panic!("Cannot close"),
        }
    }
}

fn main() {
    let mut stream = TcpStream::Unconnected;
    stream.connect();
    stream.write(b"hello");
    stream.close();
}

This approach ensures that invalid state transitions (like writing before connecting) are caught by the compiler or runtime logic, preventing bugs.