1 unstable release
0.1.1 | Sep 30, 2023 |
---|---|
0.1.0 |
|
#1613 in Procedural macros
11KB
142 lines
named-ctor
Procedural macro to generate an alternative of named parameters with native Rust.
Named parameters alternative
Rust don't has support for named parameters, but is possible to use a simulation with data structures.
This alternative is special easy to implement in Rust tanks to From
trait.
For example:
pub struct User {
id: u8,
name: String,
email: String,
password: String,
is_active: bool,
is_admin: bool,
}
impl User {
// ...
}
pub struct UserValues {
id: u8,
name: String,
email: String,
password: String,
is_active: bool,
is_admin: bool,
}
impl From<UserValues> for User {
fn from(aux: UserValues) -> Self {
Self {
id: aux.id,
name: aux.name,
email: aux.email,
password: aux.password,
is_active: aux.is_active,
is_admin: aux.is_admin,
}
}
}
pub fn main() {
let user: User = User::from(UserValues {
id: 0,
email: "john@doe.com".to_string(),
name: "John Doe".to_string(),
is_active: true,
password: "1234".to_string(),
is_admin: false,
});
}
Whats the problem? First, too boilerplate. Second, its not easy to maintain, if User
is modified, is absolutely necessary modify UserValues
.
Using NamedCtor
macro
The behavior is the same as last example, but now the macro is the responsable to create both aux struct (_User
) and From
implementation.
use named_ctor::NamedCtor;
#[derive(NamedCtor)]
pub struct User {
id: u8,
name: String,
email: String,
password: String,
is_active: bool,
is_admin: bool,
}
impl User {
// ...
}
pub fn main() {
let user: User = User::from(_User {
id: 0,
email: "john@doe.com".to_string(),
name: "John Doe".to_string(),
is_active: true,
password: "1234".to_string(),
is_admin: false,
});
}
Macro attributes
Is possible to use a custom name for the axiliar struct, and change the constructor function:
use named_ctor::NamedCtor;
use core::fmt::Display;
#[derive(NamedCtor)]
#[named_ctor(name = "TaskInitValues", constructor = "new")]
pub struct Task<'a, T>
where
T: Display
{
id: T,
name: &'a str,
}
let user: Task<&str> = Task::new(TaskInitValues {
id: "example.id",
name: "Example",
});
WARNING: Generics support only via where clause
Dependencies
~1.5MB
~37K SLoC