Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to override default implementation #34

Open
ac566 opened this issue Mar 12, 2020 · 2 comments
Open

Add ability to override default implementation #34

ac566 opened this issue Mar 12, 2020 · 2 comments

Comments

@ac566
Copy link

ac566 commented Mar 12, 2020

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.

@idanarye
Copy link
Owner

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)
    }
}

@idanarye
Copy link
Owner

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants