Skip to content

Instantly share code, notes, and snippets.

@MRGRAVITY817
Last active June 21, 2022 02:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MRGRAVITY817/3fe92b209ac32d93e6fc0ebaf647288b to your computer and use it in GitHub Desktop.
Save MRGRAVITY817/3fe92b209ac32d93e6fc0ebaf647288b to your computer and use it in GitHub Desktop.
State machine template built with Rust
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