#proc-macro #impl #proc-macro-derive #macro-derive #derive #macro #proc

已删除 impl_new

[已弃用] 一个用于为您生成新函数实现块的过程宏

0.2.2 2024年5月17日
0.2.1 2023年9月6日
0.2.0 2023年9月6日
0.1.1 2023年8月31日
0.1.0 2023年8月30日

#110 in #impl

Download history 128/week @ 2024-04-10 53/week @ 2024-04-17 64/week @ 2024-04-24 283/week @ 2024-05-01 94/week @ 2024-05-08 191/week @ 2024-05-15 19/week @ 2024-05-22 8/week @ 2024-05-29 1/week @ 2024-06-05 1/week @ 2024-06-12 1/week @ 2024-06-19

646 每月下载量
用于 4 crates

MIT 许可证

28KB
421 代码行

弃用通知:此crate已被derive_new crate取代。请使用derive_new crate代替此crate。

Impl New 🦀

一个用于为您生成新函数实现的过程宏。

License Crates.io

Docs.rs CI CD

🚀 添加到您的项目

将以下内容添加到您的 Cargo.toml

[dependencies]
impl_new = "0.2.0"

或者在您的 workspace 中运行此命令

cargo add impl_new

❓ 新函数是什么?

new 函数是一个用于创建结构体新实例的函数。在 Rust 中,使用 new 函数创建结构体新实例是一种常见的模式,而不是直接使用结构体。这是因为在不破坏使用它的代码的情况下,更容易向结构体添加新字段。

👨‍💻 使用方法

很简单,只需在您的结构体上使用 impl_new::New proc macro,它将为您生成一个 new 函数。

对于命名字段

#[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);
}

对于未命名字段

注意:对于未命名字段,需要使用 #[impl_new)] 属性。

#[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);
}

🛹 属性

#[impl_new(name= "name")]

name 选项指定了 new 函数中参数的名称。

注意:对于未命名字段,此属性是必需的。

示例

#[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)]

default 选项将从 new 函数参数中删除字段,并使用字段类型的默认值。

注意:此选项与 name 选项冲突,因为字段将从 new 函数参数中删除。

示例

#[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>)]

选项value会将字段值设置为给定的值。

注意:此选项与namedefault选项冲突,因为字段将从new函数参数中删除。

注意:值必须是一个返回字段类型的闭包。

示例

#[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);
}

🤗 贡献

欢迎贡献!您可以通过多种方式贡献,例如

  • 改进文档。
  • 添加更多测试。
  • 添加更多示例。
  • 通过创建问题来报告错误。
  • 通过创建问题来建议新功能。
  • 修复错误或添加新功能。(如果您想添加新功能或修复尚未有问题的错误,请先创建一个问题。)
  • 修复错别字。
  • 重构代码。
  • 改进错误信息。

🤝 行为准则

我们致力于为所有人提供一个友好、安全和欢迎的环境。请阅读并尊重行为准则

📝 变更日志

查看CHANGELOG.md

🔑 许可证

本项目采用MIT许可证

依赖项

~0.6–1.1MB
~24K SLoC