Last active
June 21, 2022 02:58
-
-
Save MRGRAVITY817/3fe92b209ac32d93e6fc0ebaf647288b to your computer and use it in GitHub Desktop.
State machine template built with Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::marker::PhantomData; | |
struct Reserved; | |
struct Cooking; | |
struct Delivering; | |
struct Arrived; | |
struct FoodDelivery<State = Reserved> { | |
state: PhantomData<State>, | |
} | |
impl Default for FoodDelivery<Reserved> { | |
fn default() -> Self { | |
let state = PhantomData; | |
Self { state } | |
} | |
} | |
impl FoodDelivery<Reserved> { | |
fn reserved(&self) -> FoodDelivery<Cooking> { | |
println!("Your delivery has been successfully placed!"); | |
println!("Now we'll start cooking your food.\n"); | |
self.proceed::<Cooking>() | |
} | |
fn cancel_order(&self) -> Self { | |
println!("Order canceled - money refunded."); | |
println!("We hope you to see in another service.\n"); | |
self.stay() | |
} | |
} | |
impl FoodDelivery<Cooking> { | |
fn cooking_finished(&self) -> FoodDelivery<Delivering> { | |
println!("Your food is successfully cooked!"); | |
println!("Now we'll send your food via delivery guy.\n"); | |
self.proceed::<Delivering>() | |
} | |
fn cannot_cook(&self) -> FoodDelivery<Reserved> { | |
println!("Cannot cook your food - ingredients are out of stock."); | |
println!("We'll guide you to cancel your order and get refunded.\n"); | |
self.proceed::<Reserved>() | |
} | |
} | |
impl FoodDelivery<Delivering> { | |
fn delivered(&self) -> FoodDelivery<Arrived> { | |
println!("Delivery guy finished delivering your food.\n"); | |
self.proceed::<Arrived>() | |
} | |
fn taking_food_back(&self) -> FoodDelivery<Cooking> { | |
println!("We are taking your food back to the kitchen."); | |
println!("We will tell chef to cook your food again.\n"); | |
self.proceed::<Cooking>() | |
} | |
} | |
impl FoodDelivery<Arrived> { | |
fn confirm_arrival(&self) -> Self { | |
println!("Food has arrived! Have a nice meal :)\n"); | |
self.stay() | |
} | |
fn cancel_arrival(&self) -> FoodDelivery<Delivering> { | |
println!("Oh no! Wrong food :("); | |
println!("We will take your food again via delivery man/woman\n"); | |
self.proceed::<Delivering>() | |
} | |
} | |
impl<State> FoodDelivery<State> { | |
fn proceed<NextState>(&self) -> FoodDelivery<NextState> { | |
FoodDelivery { state: PhantomData } | |
} | |
fn stay(&self) -> Self { | |
Self { state: PhantomData } | |
} | |
} | |
fn main() { | |
println!("\n{:=^50}\n", " Happy Path "); | |
let happy_path = FoodDelivery::default() | |
.reserved() | |
.cooking_finished() | |
.delivered() | |
.confirm_arrival(); | |
println!("\n{:=^50}\n", " Turns out Sad Path "); | |
let _turns_out_sad = happy_path | |
.cancel_arrival() | |
.taking_food_back() | |
.cannot_cook() | |
.cancel_order(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment