Rust自定义派生宏库cust_derive的使用:简化代码生成与过程宏开发
Rust自定义派生宏库cust_derive的使用:简化代码生成与过程宏开发
cust_derive是一个用于简化Rust代码生成和过程宏开发的派生宏库。它提供了便捷的方式来创建自定义派生宏,减少样板代码的编写。
安装
在项目目录中运行以下Cargo命令:
cargo add cust_derive
或者在Cargo.toml中添加:
cust_derive = "0.2.0"
示例使用
cust_derive主要用于简化过程宏的开发。以下是使用cust_derive创建自定义派生宏的完整示例:
// 首先,在Cargo.toml中添加以下依赖:
// [dependencies]
// cust_derive = "0.2.0"
// proc-macro2 = "1.0"
// quote = "1.0"
// syn = { version = "1.0", features = ["full"] }
// 在lib.rs中
use cust_derive::cust_derive;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;
/// 一个简单的派生宏示例,为结构体生成默认实现
#[cust_derive]
pub fn derive_default(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let expanded = quote! {
impl Default for #name {
fn default() -> Self {
Self
}
}
};
TokenStream::from(expanded)
}
// 在main.rs中
#[derive(Default)]
struct MyStruct;
fn main() {
let my_struct = MyStruct::default();
println!("MyStruct created!");
}
完整示例demo
下面是一个更完整的示例,展示如何使用cust_derive创建一个派生宏来为结构体生成简单的Debug实现:
// 在Cargo.toml中添加依赖:
// [dependencies]
// cust_derive = "0.2.0"
// proc-macro2 = "1.0"
// quote = "1.0"
// syn = { version = "1.0", features = ["full"] }
// lib.rs
use cust_derive::cust_derive;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;
/// 自定义Debug派生宏实现
#[cust_derive]
pub fn derive_simple_debug(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
// 生成Debug实现
let expanded = quote! {
impl std::fmt::Debug for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, stringify!(#name))
}
}
};
TokenStream::from(expanded)
}
// main.rs
#[derive(SimpleDebug)] // 使用我们自定义的派生宏
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 10, y: 20 };
println!("{:?}", point); // 输出: Point
}
特性
cust_derive提供了以下特性来简化过程宏开发:
- 自动处理proc-macro的导入和导出
- 简化TokenStream的处理
- 提供便捷的宏定义语法
- 支持完整的syn和quote集成
注意事项
⚠️ 该项目仍处于早期开发阶段,可能会有bug、安全问题以及某些功能无法正常工作 ⚠️
许可证
cust_derive采用双重许可:
- MIT许可证
- Apache-2.0许可证
您可以选择其中任何一个许可证使用。
1 回复
Rust自定义派生宏库cust_derive的使用:简化代码生成与过程宏开发
cust_derive
是一个用于简化Rust中派生宏开发的库,它让创建自定义派生宏变得更加容易,减少了样板代码的编写。
主要特点
- 简化派生宏的开发流程
- 提供友好的API处理属性解析
- 自动生成高质量的代码
- 支持复杂的派生逻辑
安装
在Cargo.toml
中添加依赖:
[dependencies]
cust_derive = "0.1"
基本使用方法
1. 创建简单的派生宏
use cust_derive::*;
#[derive(CustomDerive)]
struct MyStruct {
field1: i32,
field2: String,
}
#[proc_macro_derive(CustomDerive)]
pub fn derive_custom(input: TokenStream) -> TokenStream {
cust_derive::derive(input, |input| {
// 在这里实现自定义逻辑
quote! {
impl MyStruct {
pub fn new() -> Self {
Self {
field1: 0,
field2: String::new(),
}
}
}
}
})
}
2. 带属性的派生宏
#[derive(Display, Debug)]
#[display(fmt = "{} - {}", field1, field2)]
struct MyStruct {
field1: i32,
field2: String,
}
#[proc_macro_derive(Display, attributes(display))]
pub fn derive_display(input: TokenStream) -> TokenStream {
cust_derive::derive_with_attributes(input, |input, attrs| {
let format_str = attrs.get_str("fmt").unwrap_or("{}");
// 生成Display实现
quote! {
impl std::fmt::Display for #input {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, #format_str, self.field1, self.field2)
}
}
}
})
}
高级用法
1. 处理枚举类型
#[derive(EnumString)]
enum MyEnum {
#[enum_str("variant1")]
Variant1,
#[enum_str("variant2")]
Variant2,
}
#[proc_macro_derive(EnumString, attributes(enum_str))]
pub fn derive_enum_string(input: TokenStream) -> TokenStream {
cust_derive::derive_enum(input, |variants| {
// 为每个变体生成FromStr实现
let match_arms = variants.iter().map(|v| {
let ident = &v.ident;
let str_repr = v.attrs.get_str("enum_str").unwrap();
quote! {
#str_repr => Ok(Self::#ident),
}
});
quote! {
impl std::str::FromStr for #input {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
#(#match_arms)*
_ => Err(format!("Unknown variant: {}", s)),
}
}
}
}
})
}
2. 组合多个派生宏
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Data {
id: u64,
name: String,
value: f64,
}
// 可以组合使用cust_derive和其他派生宏
最佳实践
- 错误处理:在派生宏中提供清晰的错误信息
- 文档:为生成的代码添加文档注释
- 性能:避免在派生宏中进行复杂的计算
- 测试:为派生宏编写全面的测试用例
示例项目结构
典型的派生宏项目结构:
my_derive_macro/
├── Cargo.toml
├── src/
│ ├── lib.rs # 主库文件
│ └── derive_impl.rs # 派生宏实现
└── tests/
└── test_derive.rs # 测试用例
完整示例demo
下面是一个使用cust_derive创建自定义派生宏的完整示例:
// my_derive_macro/src/lib.rs
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
// 解析输入
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
// 生成实现代码
let expanded = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("Hello, Macro! My name is {}!", stringify!(#name));
}
}
};
// 返回生成的代码
TokenStream::from(expanded)
}
// 定义trait
pub trait HelloMacro {
fn hello_macro();
}
// 使用示例
#[derive(HelloMacro)]
struct Pancakes;
fn main() {
Pancakes::hello_macro(); // 输出: Hello, Macro! My name is Pancakes!
}
这个示例展示了如何创建一个简单的HelloMacro
派生宏,它会为结构体自动实现hello_macro
方法。