nrc / derive-new

derive simple constructor functions for Rust structs
MIT License
525 stars 35 forks source link

implement `into` and `into_iter` #65

Closed OmarTawfik closed 2 months ago

OmarTawfik commented 10 months ago

Thank you for the awesome crate! Here is a feature suggestion, that is sorely missed in our projects. It has also been requested twice already (#43 and #62).

#[new(into)]

To make type conversion easier, #[new(into)] attribute changes the parameter type to impl Into<T>, and populates the field with value.into(). This is useful for containers like strings, accepting a String or a &str:

#[derive(new)]
struct Foo {
    #[new(into)]
    x: String,
}

let _ = Foo::new("Hello".to_string());
let _ = Foo::new(format!("Hello"));
let _ = Foo::new("Hello");

It is also useful for wrapping types like Box<T> and Rc<T>, without having to wrap at every callsite:

#[derive(new)]
struct Foo {
    #[new(into)]
    x: Rc<Bar>,
}

let _ = Foo::new(Rc::new(bar));
let _ = Foo::new(bar.into());
let _ = Foo::new(bar);

#[new(into_iter = "T")]

For iterators/collections, #[new(into_iter = "T")] attribute changes the parameter type to impl IntoIterator<Item = T>, and populates the field with value.into_iter().collect(). This allows initializing with a variety of types, like [T], Option<T>, Vec<T>, sets, maps, and even other iterators:

#[derive(new)]
struct Foo {
    #[new(into_iter = "bool")]
    x: Vec<bool>,
}

let _ = Foo::new(vec![true, false]);
let _ = Foo::new([true, false]);
let _ = Foo::new(Some(true));

About this PR

I split this into three parts to make reviewing easier:

Please let me know if I can do anything else.

OmarTawfik commented 10 months ago

cc @nrc

Closes #43 Closes #62

DenisGorbachev commented 6 months ago

@nrc Is it possible to merge this PR please? This would be a time-saver for a lot of projects

polarathene commented 5 months ago

@nrc friendly ping

nrc commented 2 months ago

Merged manually to resolve conflicts