Skip to content

Instantly share code, notes, and snippets.

@robert-king
Created October 25, 2025 04:42
Show Gist options
  • Save robert-king/c279a300cdbe21e79218e1ca4909b18c to your computer and use it in GitHub Desktop.
Save robert-king/c279a300cdbe21e79218e1ca4909b18c to your computer and use it in GitHub Desktop.
builder pattern
#![feature(type_changing_struct_update)]
use std::marker::PhantomData;
struct Set;
struct Unset;
struct PizzaBuilder<Dough, Topping> {
dough: Option<String>,
topping: Option<String>,
state: PhantomData<(Dough, Topping)>,
}
impl<T> PizzaBuilder<Unset, T> {
fn with_dough(self, dough: &str) -> PizzaBuilder<Set, T> {
PizzaBuilder {
dough: Some(dough.to_string()),
state: PhantomData,
..self
}
}
}
impl<T> PizzaBuilder<T, Unset> {
fn with_topping(self, topping: &str) -> PizzaBuilder<T, Set> {
PizzaBuilder {
topping: Some(topping.to_string()),
state: PhantomData,
..self
}
}
}
impl PizzaBuilder<Set, Set> {
fn build(self) -> Pizza {
Pizza {
dough: self.dough.unwrap(),
topping: self.topping.unwrap(),
}
}
}
#[derive(Debug)]
struct Pizza {
#[allow(dead_code)]
dough: String,
#[allow(dead_code)]
topping: String,
}
impl Pizza {
fn builder() -> PizzaBuilder<Unset, Unset> {
PizzaBuilder {
dough: None,
topping: None,
state: PhantomData,
}
}
}
fn main() {
let x = Pizza::builder()
.with_topping("topping")
.with_dough("dough")
.build();
print!("{x:?}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment