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提供了以下特性来简化过程宏开发:

  1. 自动处理proc-macro的导入和导出
  2. 简化TokenStream的处理
  3. 提供便捷的宏定义语法
  4. 支持完整的syn和quote集成

注意事项

⚠️ 该项目仍处于早期开发阶段,可能会有bug、安全问题以及某些功能无法正常工作 ⚠️

许可证

cust_derive采用双重许可:

  • MIT许可证
  • Apache-2.0许可证

您可以选择其中任何一个许可证使用。


1 回复

Rust自定义派生宏库cust_derive的使用:简化代码生成与过程宏开发

cust_derive是一个用于简化Rust中派生宏开发的库,它让创建自定义派生宏变得更加容易,减少了样板代码的编写。

主要特点

  1. 简化派生宏的开发流程
  2. 提供友好的API处理属性解析
  3. 自动生成高质量的代码
  4. 支持复杂的派生逻辑

安装

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和其他派生宏

最佳实践

  1. 错误处理:在派生宏中提供清晰的错误信息
  2. 文档:为生成的代码添加文档注释
  3. 性能:避免在派生宏中进行复杂的计算
  4. 测试:为派生宏编写全面的测试用例

示例项目结构

典型的派生宏项目结构:

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方法。

回到顶部