Skip to content

Instantly share code, notes, and snippets.

@nesteruk
Created July 24, 2017 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nesteruk/d1fcfbd8d9fbedce27a478a26a8d65cf to your computer and use it in GitHub Desktop.
Save nesteruk/d1fcfbd8d9fbedce27a478a26a8d65cf to your computer and use it in GitHub Desktop.
Fluent builder with lifetime/references removed... doesn't compile.
use std::marker::PhantomData;
use std::rc::Rc;
use std::fmt::Display;
struct Person
{
street_address: String,
postcode: String,
city: String,
company_name: String,
position: String,
annual_income: usize
}
impl ToString for Person
{
fn to_string(&self) -> String
{
format!("I live at {}, {}, {} and work as a {} at {} earning {}",
self.street_address, self.city, self.postcode,
self.company_name, self.position, self.annual_income)
}
}
struct PersonBuilder
{
person: Person
}
impl PersonBuilder
{
fn new() -> PersonBuilder
{
PersonBuilder {
person: Person {
street_address: String::new(),
postcode: String::new(),
city: String::new(),
company_name: String::new(),
position: String::new(),
annual_income: 0
}
}
}
}
trait Builder
{
fn lives(&self) -> PersonAddressBuilder;
fn works(&self) -> PersonJobBuilder;
}
macro_rules! impl_Builder
{
($T:ty) =>
{
impl Builder for $T
{
fn lives(&self) -> PersonAddressBuilder
{
PersonAddressBuilder::new(self.person)
}
fn works(&self) -> PersonJobBuilder
{
PersonJobBuilder::new(self.person)
}
}
//
// impl<$L> Into<Person<$L>> for $T
// {
// fn into(self) -> $T
// {
// self.person
// }
// }
}
}
struct PersonAddressBuilder
{
person: Person
}
impl PersonAddressBuilder
{
fn new(person: Person) -> PersonAddressBuilder
{
PersonAddressBuilder { person: person }
}
fn at(&self, street_address: &str) -> &PersonAddressBuilder
{
self.person.street_address = street_address.to_string();
self
}
fn with_postcode(&self, postcode: &str) -> &PersonAddressBuilder
{
self.person.postcode = postcode.to_string();
self
}
fn in_city(&self, city: &str) -> &PersonAddressBuilder
{
self.person.city = city.to_string();
self
}
}
struct PersonJobBuilder
{
person: Person
}
impl PersonJobBuilder
{
fn new(person: Person) -> PersonJobBuilder
{
PersonJobBuilder { person: person }
}
fn at(&self, company_name: &str) -> &PersonJobBuilder
{
self.person.company_name = company_name.to_string();
self
}
fn as_a(&self, position: &str) -> &PersonJobBuilder
{
self.person.position = position.to_string();
self
}
fn earning(&self, annual_income: usize) -> &PersonJobBuilder
{
self.person.annual_income = annual_income;
self
}
}
impl_Builder!(PersonBuilder);
impl_Builder!(PersonJobBuilder);
impl_Builder!(PersonAddressBuilder);
fn main()
{
let pb = PersonBuilder::new();
let p = pb
.lives()
.at("123 London Road")
.in_city("London")
.with_postcode("PO12SW")
.works()
.at("Fabrikam")
.as_a("Developer")
.earning(123000)
.person;
println!("{}", p.to_string());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment