Giter VIP home page Giter VIP logo

impl_new's Introduction

Deprecation Notice: This crate is deprecated in favor of the derive_new crate. Please use the derive_new crate instead of this crate.

Impl New ๐Ÿฆ€

A procedural macro to generate a new function implementation for your struct.

License Crates.io

Docs.rs CI CD

๐Ÿš€ Add to your project

Add this to your Cargo.toml:

[dependencies]
impl_new = "0.2.0"

Or run this command in your workspace:

cargo add impl_new

โ“ What is the new function?

The new function is a function that is used to create a new instance of a struct. It is a common pattern in Rust to use a new function to create a new instance of a struct instead of using the struct directly. This is because it is easier to add new fields to the struct without breaking the code that uses it.

๐Ÿ‘จโ€๐Ÿ’ป Usage

Is simple, just derive the impl_new::New proc macro on your struct and it will generate a new function for you.

For Named Fields

#[derive(impl_new::New)]
struct Foo {
    name: String,
    age: usize,
}

// The generated code will look like this:
// impl Foo {
//     pub fn new(name: impl Into<String>, age: Into<usize>) -> Self {
//         Self { name: name.into(), age: age.into() }
//     }
// }

fn main() {
    let foo = Foo::new("Hello", 42usize); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(foo.name, "Hello".to_string());
    assert_eq!(foo.age, 42);
}

For Unnamed Fields

Note: The #[impl_new(name = "name")] attribute is required for unnamed fields.

#[derive(impl_new::New)]
struct Foo(#[impl_new(name = "name")] String, #[impl_new(name = "age")] usize);

// The generated code will look like this:
// impl Foo {
//     pub fn new(name: impl Into<String>, age: Into<usize>) -> Self {
//         Self(name.into(), age.into())
//     }
// }

fn main() {
    let foo = Foo::new("Hello", 42usize); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(foo.0, "Hello".to_string());
    assert_eq!(foo.1, 42);
}

๐Ÿ›น Attributes

#[impl_new(name = "name")]

The name option specifies the name of the argument in the new function.

Note: This attribute is required for unnamed fields.

Example

#[derive(impl_new::New)]
struct User(#[impl_new(name = "username")] String, #[impl_new(name = "age")] i32);

// The generated code will look like this:
// impl User {
//     pub fn new(username: impl Into<String>, age: Into<i32>) -> Self {
//         Self(username.into(), age.into())
//     }

fn main() {
    let user = User::new("Hello", 42); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(user.0, "Hello".to_string());
    assert_eq!(user.1, 42);
}
#[derive(impl_new::New)]
struct User {
    #[impl_new(name = "username")]
    name: String,
    #[impl_new(name = "user_age")]
    age: i32,
}

// The generated code will look like this:
// impl User {
//     pub fn new(username: impl Into<String>, user_age: Into<i32>) -> Self {
//         Self { name: username.into(), age: user_age.into() }
//     }
// }

fn main() {
    let user = User::new("Hello", 42); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(user.name, "Hello".to_string());
    assert_eq!(user.age, 42);
}

#[impl_new(default)]

The default option will remove the field from the new function arguments and use the default value of the field type instead.

Note: This option is conflict with the name option, because the field will be removed from the new function arguments.

Example

#[derive(impl_new::New, Default, Debug, PartialEq)]
struct User {
    name: String,
    #[impl_new(default)]
    is_admin: bool,
}

// The generated code will look like this:
// impl User {
//     pub fn new(name: impl Into<String>) -> Self {
//         Self { name: name.into(), is_admin: bool::default() }
//     }
// }

#[derive(impl_new::New)]
struct Foo(#[impl_new(name = "somthing")] String, #[impl_new(default)] User);

// The generated code will look like this:
// impl Foo {
//     pub fn new(somthing: impl Into<String>) -> Self {
//         Self(somthing.into(), User::default())
//     }
// }

fn main() {
    let user = User::new("Hello"); // Will use `Into::into` to convert the arguments to the fields types.
    let some_foo = Foo::new("Hello"); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(user.name, "Hello".to_string());
    assert_eq!(user.is_admin, false);
    assert_eq!(some_foo.0, "Hello".to_string());
    assert_eq!(some_foo.1, User::default());
}

#[impl_new(value = || <VALUE>)]

The value option will set the field value to the given value.

Note: This option is conflict with the name and default options, because the field will be removed from the new function arguments.

Note: The value must be a closure that returns the field type.

Example

#[derive(impl_new::New)]
struct User {
    name: String,
    #[impl_new(value = || true)]
    is_active: bool,
}

// The generated code will look like this: (Not exactly, but you get the idea)
// impl User {
//     pub fn new(name: impl Into<String>) -> Self {
//         Self { name: name.into(), is_active: true }
//     }
// }

#[derive(impl_new::New)]
struct Foo(#[impl_new(name = "name")] String, #[impl_new(value = || true)] bool);

// The generated code will look like this: (Not exactly, but you get the idea)
// impl Foo {
//     pub fn new(name: impl Into<String>) -> Self {
//         Self(name.into(), true)
//     }
// }

fn main() {
    let user = User::new("Bob"); // Will use `Into::into` to convert the arguments to the fields types.
    let some_foo = Foo::new("Bob"); // Will use `Into::into` to convert the arguments to the fields types.
    assert_eq!(user.name, "Bob".to_string());
    assert_eq!(user.is_active, true);
    assert_eq!(some_foo.0, "Bob".to_string());
    assert_eq!(some_foo.1, true);
}

๐Ÿค— Contributing

Contributions are welcome! You can contribute in many ways, for example:

  • Improve the documentation.
  • Add more tests.
  • Add more examples.
  • Report a bug by opening an issue.
  • Suggest a new feature by opening an issue.
  • Fix a bug or add a new feature. (Please open an issue first if you want to add a new feature or if you want to fix a bug that doesn't have an issue yet.)
  • Fix a typo.
  • Refactor the code.
  • Improve the error messages.

๐Ÿค Code of Conduct

We are committed to providing a friendly, safe and welcoming environment for all. Please read and respect the Code of Conduct.

๐Ÿ“ Changelog

See CHANGELOG.md.

๐Ÿ”‘ License

This project is licensed under the MIT license.

impl_new's People

Contributors

theawiteb avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

impl_new's Issues

[Feature request]: New `impl_new` attribute option to set a default value for the field.

Feature description

New impl_new attribute option to set a default value for the field. This will remove the field from the new function arguments and use the value that you set instead. This will be useful to set a specific value for a field that you don't want to be changed by the user.

Note: This will not use Default::default to set the default value, it will use the value that you set.

Example

#[derive(impl_new::New)]
struct SomeStruct {
    #[impl_new(name = "Some_name")]
    name: String,
    #[impl_new(value = String::from("This is a default text"))]
    text: String,
}

fn main() {
    let some_struct = SomeStruct::new("Alix");
    assert_eq!(some_struct.name, "Alix".to_string());
    assert_eq!(some_struct.text, "This is a default text".to_string());
}

[Feature request]: `default` option that set the default value of the field

Feature description

default option in the impl_new attribute, which will remove the field from the new function and use the default value instead.

Conflict

This should conflict with the name option, because default will remove the field from the new function and use the default value instead, so there is no need to rename the field because it is not in the new function.

Example

#[derive(impl_new::New)]
struct User {
    username: String,
    age: u8,
    #[impl_new(default)]
    is_admin: bool,
}

// Generated code:
// impl User {
//     pub fn new(username: impl Into<String>, age: impl Into<u8>) -> Self {
//         Self {
//             username,
//             age,
//             is_admin: bool::default(),
//         }
//     }
// }

fn main() {
    let user = User::new("Alice", 18);
    assert_eq!(user.username, "Alice");
    assert_eq!(user.age, 18);
    assert_eq!(user.is_admin, false);
}

Add CI/CD workflow and issues template

Description

Add a CI/CD workflow and issues template, this will help contributors to know what to do and how to do it.

Tasks

  • Bug report template
  • Feature request template
  • question template

  • Rustfmt
  • Clippy
  • Tests

  • Add a CI/CD badge to the README.md

  • Publish to crates.io for tags

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.