4 releases
new 0.1.3 | Mar 9, 2025 |
---|---|
0.1.2 | Oct 12, 2024 |
0.1.1 | Oct 6, 2024 |
0.1.0 | Oct 6, 2024 |
#999 in Procedural macros
149 downloads per month
Used in stochastic-rs
12KB
61 lines
impl-new-derive
The impl-new-derive
procedural macro generates a new
constructor for Rust structs. This macro automatically creates a constructor that initializes:
- Public fields from provided arguments (added as parameters to
new
). - Private fields with default values using either:
- An expression specified by
#[default(...)]
, or Default::default()
if no custom default expression is provided.
- An expression specified by
Features
- Automatically generates a
new
constructor for structs. - Handles public fields: The
new
function takes all public fields of the struct as arguments. - Handles private fields:
- If the private field has a
#[default(...)]
attribute, that expression is used for initialization. - Otherwise, the private field is initialized with
Default::default()
.
- If the private field has a
- Supports generic types: The macro works with both generic and non-generic structs.
Usage
-
Add the macro to your project by including it in your
Cargo.toml
:[dependencies] impl_new_derive = "0.1"
-
Annotate your struct with
#[derive(ImplNew)]
to automatically generate anew
constructor. Optionally, you can also deriveDefault
if needed elsewhere in your code.
Example for a Non-Generic Struct
use impl_new_derive::ImplNew;
#[derive(ImplNew, Default)]
struct MyStruct {
pub name: String,
pub age: u32,
// Private field; no custom default attribute,
// so it will be initialized using Default::default()
secret: String,
}
fn main() {
// The generated constructor requires arguments
// for each PUBLIC field in the struct.
let my_struct = MyStruct::new("John".to_string(), 30);
println!("Name: {}, Age: {}", my_struct.name, my_struct.age);
// 'secret' is private and gets a default value of "" (the Default for String).
}
Using #[default(...)]
for Private Fields
use impl_new_derive::ImplNew;
#[derive(ImplNew)]
struct Credentials {
pub username: String,
// Private field with a custom default value.
// This field doesn't appear as a parameter in the `new` method.
// Instead, it will be automatically set to "empty_token".to_string().
#[default(\"empty_token\".to_string())]
token: String,
}
fn main() {
// The `new` function is generated only for public fields,
// so we pass just `username`.
let creds = Credentials::new(\"alice\".to_string());
println!(\"Username: {}, Token: {}\", creds.username, creds.token);
// Prints: Username: alice, Token: empty_token
}
Example for a Generic Struct
use impl_new_derive::ImplNew;
#[derive(ImplNew, Default)]
struct MyStruct<T> {
pub value: T,
// Private field without custom default, so it uses Default::default()
count: usize,
}
fn main() {
// In a generic struct, only the public fields appear in `new`.
let my_struct = MyStruct::new(42);
// 'count' is private, and we didn't give it a `#[default(...)]`,
// so it's initialized with `Default::default()`, i.e. 0.
println!(\"Value: {}, Count: {}\", my_struct.value, my_struct.count);
// Prints: Value: 42, Count: 0
}
How It Works
When you annotate a struct with #[derive(ImplNew)]
, the macro performs the following actions:
- It iterates over the fields of the struct.
- For each public field, it adds a corresponding parameter to the generated
new
method. - For each private field, it checks if a
#[default(expr)]
attribute is present:- If yes, it uses
expr
to initialize that field. - Otherwise, it uses
Default::default()
to initialize that field.
- If yes, it uses
- If the struct contains generics, the macro automatically handles them in the generated
impl
.
Limitations
- Only works for structs with named fields.
- If a private field doesn't implement
Default
and does not have a#[default(...)]
attribute, the macro fails to compile. - If you do use
#[default(...)]
, the expression inside must be a valid Rust expression for that field's type.
Contributing
Feel free to open issues or pull requests if you have any suggestions or improvements.
License
This project is licensed under the MIT License.
Dependencies
~215–650KB
~16K SLoC