named-ctor

Crates.ionamed-ctor
lib.rsnamed-ctor
version0.1.1
sourcesrc
created_at2023-09-30 00:48:37.89058
updated_at2023-09-30 04:49:31.120065
descriptionproc-macro to generate constructor functions with syntaxt similar to named params
homepage
repositoryhttps://github.com/jonhteper/named-ctor
max_upload_size
id988309
size11,276
JP (jonhteper)

documentation

README

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

Commit count: 5

cargo fmt