Feature request: Generalize `strip_option`
SOF3 opened this issue · 1 comments
Generalize strip_option
to a generic attribute accepting a method and an argument list, which the setter method would proxy to.
Example
To build a struct with a Cell
, we do not want to require the user to construct the Cell
themselves.
#[derive(TypedBuilder)]
struct Foo {
#[builder(transform = Cell::new(bar: u32))]
bar: Cell<u32>,
}
The new attribute here is (in decl macro notation) transform = $path:path( $($name:pat : $ty:ty),* )
.
A builder method is generated to require the specified parameters $name*
and pass them to the function in $path
, whose return value is used to set the field.
An equivalent notation for strip_option
is transform = ::std::option::Option::Some(field: Type)
.
Alternatives
Use a trait to standardize this to avoid attribute parsing Example:
trait BuilderParam<U> : Sized {
fn convert(self) -> U;
}
Then applying #[builder(transform)]
on field: Type
would generate
fn field(mut self, field: impl BuilderDelegate<Type>) -> Builder<...> {
Builder {
field: field.convert(),
...self
}
}
I can write a patch for this if you find this appropriate.
Syntax-wise, I'd rather have something like this:
#[derive(TypedBuilder)]
struct Foo {
#[builder(transform = |bar: u32| Cell::new(bar))]
bar: Cell<u32>,
}
It'll be easier to parse because it's legal Rust syntax, it'll be more straightforward to determine the argument, and it'll allow having multiple arguments:
struct Point {
x: f64,
y: f64,
}
#[derive(TypedBuilder)]
struct Foo {
#[builder(transform = |x: f64, y: f64| Point { x, y })]
point: Point,
}
I'm also wondering whether or not this should be under setter
(#[builder(setter(transform = ...))]
)