崩溃!自定义Rust属性原来这么简单,我竟然一直不知道

104 阅读2分钟

上篇我们系统的介绍了关于rust的属性,那么如果我们自己想实现一个自己的属性该怎么实现了,我们不仅要知道概念还要懂得如何灵活的运用。今天我们就带大家实现一个自己的属性,看到这里是不是心动了,扑通扑通的跳,不过不要着急,让我们一起探索如何实现一个自己的自定义属性,然后能在项目中使用了。

创建项目

cargo new custom_derive_macro

我们这里创建的是一个创建一个名为 Initialize 的派生宏,他会为结构体(struct)自动实现一个初始化方法。我们接着在我们刚才创建的项目中创建一个新的库项目,名为initialize_derive:

创建库项目

cargo new --lib initialize_derive

然后在在 initialize_derive/Cargo.toml文件中添加我们该项目所需要的依赖:

添加依赖

[lib]
proc-macro = true

[dependencies]
ssyn = { version = "2.0.86", features = ["full"] }
quote = "1.0"
proc-macro2 = "1.0"

429221732073718_.pic.jpg

接着我们在initialize_derive/src/lib.rs文件中实现我们的派生宏:

实现派生宏

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(Initialize)]
pub fn initialize_derive(input: TokenStream) -> TokenStream {
    // 解析输入的 TokenStream 为 DeriveInput
    let input = parse_macro_input!(input as DeriveInput);

    // 获取 struct 的名称
    let name = input.ident;

    // 构建初始化方法的实现
    let expanded = quote! {
        impl #name {
            pub fn new() -> Self {
                Self {
                    ..Default::default()
                }
            }
        }
    };

    // 将生成的代码转换回 TokenStream
    TokenStream::from(expanded)
}

到这里我们已经实现了属性最核心的,那么怎么在其他项目中使用这个派生宏了,我们在rust项目中的Cargo.toml 文件中添加以下依赖:

使用自定义属性

[dependencies]
initialize_derive = { path = "../initialize_derive" }

然后我们在main.rs中使用我们创建的Initialize 派生宏:

use initialize_derive::Initialize;

#[derive(Initialize)]
struct MyStruct {
    a: i32,
    b: String,
}

impl Default for MyStruct {
    fn default() -> Self {
        MyStruct {
            a: 42,
            b: "Hello".to_string(),
        }
    }
}

fn main() {
    let my_struct = MyStruct::new();
    println!("a: {}, b: {}", my_struct.a, my_struct.b);
}

运行这个项目,控制台会打印出一下信息:

a: 42, b: Hello

至此我们成功的实现了一个派生宏属性,并且展示了如何使用我们的自定义属性。今天就到这里吧,欢迎大家多多点赞加关注走路不迷路。

扫码_搜索联合传播样式-标准色版.png