rust-typed-builder
rust-typed-builder copied to clipboard
Add ability to override default implementation
I just started using this crate today and love it.
The only thing I wish it had is a way to define the setter function for specific fields.
For instance I have a data type in a struct that I need to transform before setting that can't easily be converted using Into, or even From, since they have default implementations and specialization is not in the language yet.
I decoded what I needed to do from this repo, but It would be nice to override this behavior in a nicer way
struct A {
a: some_type
}
struct AWrapper(A);
#[derive(TypedBuilder)]
struct B {
z: u64,
a: A,
b: usize,
}
// here's what I created to override the behavior
impl BBuilder<((u64,), (), (usize,))> {
pub fn with_a(
self,
a: &AWrapper,
) -> BBuilder<((u64,), (A,), (usize,))> {
let (z, _, b) = self.fields;
let a = (a.0,);
BBuilder {
fields: (z, a, b),
_phantom: self._phantom,
}
}
This is pretty cumbersome, and only works in when part of the Builder has already been created.
I've looked around other issues, and this seems similar to skip
, however I would rather it failed compiling because there was no method that replaces it.
Ideally with #23 you should be able to do something like this (I'm not fixated on the syntax yet):
#[typed_builder::fill_generics(
B,
generic_param = T,
constraints(without(a)),
derivatives(
O(with(a)),
),
)]
impl BBuilder<T> {
pub fn with_a(self, a: AWrapper) -> O {
self.a(a.0)
}
}
Another option is to support something like this:
#[derive(TypedBuilder)]
#[builder(
builder_only_generics('a),
builder_only_fields(
with_a: &'a AWrapper,
),
)]
struct B {
z: u64,
#[builder(setter(skip), default = with_a.0)]
a: A,
b: usize,
}
#23 is a big and complex feature, and something like this would be quicker and easier to implement - and we'll still want it even after we have #23. The idea is that with_a
only exists in the builder type, and a
only exists in the actual type. So the user sets with_a
using a normal setter, and it remains there for the lifetime of the builder, but does not get copied to B
. Instead, a
's default uses the value fromwith_a
to construct a
- which gets skipped and doesn't get its own setter.