上篇我们系统的介绍了关于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"
接着我们在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
至此我们成功的实现了一个派生宏属性,并且展示了如何使用我们的自定义属性。今天就到这里吧,欢迎大家多多点赞加关注走路不迷路。