Summary
A context-generic builder pattern allows context-generic providers to build a generic context without direct access to the concrete type.
pub trait HasBuilder {
type Builder;
fn builder() -> Self::Builder;
}
pub trait CanBuildField<Tag, Value> {
type Next;
fn build(self, _tag: PhantomData<Tag>, value: Value) -> Self::Next;
}
pub trait MapType {
type Map<T>;
}
pub struct Filled;
impl MapType for Filled {
type Map<T> = T;
}
pub struct Empty;
impl MapType for Empty {
type Map<T> = ();
}
Example
#[derive(Builder)
pub struct Foo {
pub bar: u64,
pub baz: String,
}
would have the following derived:
pub struct FooBuilder<F1: MapType, F2: MapType> {
pub bar: F1::Map<u64>,
pub baz: F2::Map<String>,
}
impl HasBuilder for Foo {
type Builder = FooBuilder<Empty, Empty>;
fn builder() -> Self::Builder {
FooBuilder {
bar: (),
baz: (),
}
}
}
impl<F2: MapType> CanBuild<symbol!("bar"), u32> for FooBuilder<Empty, F2> {
type Next = FooBuilder<Filled, F2>;
fn build(self, _tag: PhantomData<Tag>, value: u32) -> Self::Next {
FooBuilder {
bar: value,
baz: self.baz,
}
}
}
impl<F1: MapType> CanBuild<symbol!("baz"), String> for FooBuilder<F1, Empty> {
type Next = FooBuilder<F1, Filled>;
fn build(self, _tag: PhantomData<Tag>, value: String) -> Self::Next {
FooBuilder {
bar: self.bar,
baz: value,
}
}
}
impl From<FooBuilder<Filled, Filled>> for Foo {
fn from(builder: FooBuilder<Filled, Filled>) -> Self {
Self {
bar: builder.bar,
baz: builder.baz,
}
}
}
Summary
A context-generic builder pattern allows context-generic providers to build a generic context without direct access to the concrete type.
Example
would have the following derived: