Skip to content

Instantly share code, notes, and snippets.

@phunguyen19
Created June 29, 2024 10:43
Show Gist options
  • Save phunguyen19/d952b9d5de13b85e7f85591758ea72d2 to your computer and use it in GitHub Desktop.
Save phunguyen19/d952b9d5de13b85e7f85591758ea72d2 to your computer and use it in GitHub Desktop.
Rust Type-State pattern
trait FileState {}
// We need this to define
// `close` method for multiple states
trait Closable {
fn close(self) -> File<ClosedFile>;
}
struct File<S: FileState> {
state: S,
}
struct InitialFile {}
impl FileState for InitialFile {}
struct OpenedFile {}
impl FileState for OpenedFile {}
struct ClosedFile {}
impl FileState for ClosedFile {}
struct ReadingFile {}
impl FileState for ReadingFile {}
impl File<InitialFile> {
fn new() -> Self {
println!("Creating new file");
File::<InitialFile> {
state: InitialFile {},
}
}
fn open(self) -> File<OpenedFile> {
println!("Opening file");
File::<OpenedFile> {
state: OpenedFile {},
}
}
}
impl Closable for File<OpenedFile> {
fn close(self) -> File<ClosedFile> {
println!("Closing file");
File::<ClosedFile> {
state: ClosedFile {},
}
}
}
impl File<OpenedFile> {
fn read(self) -> File<ReadingFile> {
println!("Reading file");
File::<ReadingFile> {
state: ReadingFile {},
}
}
}
impl Closable for File<ReadingFile> {
fn close(self) -> File<ClosedFile> {
println!("Closing file");
File::<ClosedFile> {
state: ClosedFile {},
}
}
}
impl File<ClosedFile> {
fn is_closed(self) -> bool {
true
}
}
fn main() {
let file = File::<InitialFile>::new();
let file = file.open();
let file = file.read();
let file = file.close();
let is_closed = file.is_closed();
println!("Is closed: {}", is_closed);
// Compiling error checking
let file = File::<InitialFile>::new();
let file = file.open();
let file = file.close();
let file = file.read(); // error on compile time
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment