Rust宏编程库yare-macro的使用,yare-macro提供高效编译时代码生成和过程宏开发工具

yare-macro

yare-macro 是为 Yare 实现的宏,Yare 是一个基于过程宏的参数化测试库。

安装

在项目目录中运行以下 Cargo 命令:

cargo add yare-macro

或者在 Cargo.toml 中添加以下行:

yare-macro = "3.0.0"

使用示例

以下是使用 yare-macro 进行参数化测试的完整示例:

use yare_macro::parameterized;

// 测试平方函数
#[parameterized]
#[case(0, 0)]     // 输入0,期望输出0
#[case(1, 1)]     // 输入1,期望输出1
#[case(2, 4)]     // 输入2,期望输出4
#[case(3, 9)]     // 输入3,期望输出9
#[case(4, 16)]    // 输入4,期望输出16
fn test_square(input: i32, expected: i32) {
    assert_eq!(input * input, expected);
}

// 测试加法函数
#[parameterized]
#[case(1, 1, 2)]     // 1+1=2
#[case(5, 5, 10)]    // 5+5=10
#[case(10, 20, 30)]  // 10+20=30
fn test_addition(a: i32, b: i32, expected: i32) {
    assert_eq!(a + b, expected);
}

完整示例

以下是更完整的 yare-macro 使用示例,展示更多功能和用例:

use yare_macro::parameterized;

// 测试字符串处理
#[parameterized]
#[case("hello", "HELLO")]  // 测试小写转大写
#[case("world", "WORLD")]  // 测试小写转大写
#[case("", "")]            // 测试空字符串
fn test_to_uppercase(input: &str, expected: &str) {
    assert_eq!(input.to_uppercase(), expected);
}

// 测试布尔逻辑
#[parameterized]
#[case(true, false, false)]  // true AND false = false
#[case(true, true, true)]    // true AND true = true
#[case(false, false, false)] // false AND false = false
fn test_and_operation(a: bool, b: bool, expected: bool) {
    assert_eq!(a && b, expected);
}

// 测试浮点数比较(使用近似比较)
#[parameterized]
#[case(0.1 + 0.2, 0.3)]  // 浮点数相加
#[case(1.0 / 3.0, 0.333333)]  // 浮点数除法
fn test_float_operations(result: f64, expected: f64) {
    assert!((result - expected).abs() < 1e-6);
}

// 测试元组作为参数
#[parameterized]
#[case((1, 2), 3)]  // 元组解构
#[case((3, 4), 7)]
fn test_tuple_addition(input: (i32, i32), expected: i32) {
    assert_eq!(input.0 + input.1, expected);
}

参数化测试说明

  1. 使用 #[parameterized] 宏标记测试函数
  2. 每个 #[case] 宏定义一组测试参数
  3. 测试函数参数与 #[case] 参数一一对应
  4. 每个 #[case] 会生成独立的测试实例

特性

  • 编译时代码生成,无运行时开销
  • 支持多种参数类型
  • 清晰的测试失败报告
  • 与标准 Rust 测试框架无缝集成

文档

更多详细用法请参考官方文档。

许可证

yare-macro 采用 MIT 或 Apache-2.0 双重许可。


1 回复

Rust宏编程库yare-macro使用指南

简介

yare-macro是一个高效的Rust宏编程库,专注于编译时代码生成和简化过程宏开发。它提供了简洁的API和强大的工具集,帮助开发者更容易地创建和使用宏。

主要特性

  • 高效的编译时代码生成
  • 简化过程宏开发流程
  • 提供友好的宏定义语法
  • 支持属性宏、派生宏和函数式宏

使用方法

1. 添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
yare-macro = "0.1"

2. 基本示例:创建属性宏

use yare_macro::attribute;

#[attribute]
fn log_call(item: syn::ItemFn) -> proc_macro2::TokenStream {
    let fn_name = &item.sig.ident;
    let block = &item.block;
    
    quote::quote! {
        fn #fn_name() {
            println!("Calling function: {}", stringify!(#fn_name));
            #block
        }
    }
}

// 使用示例
#[log_call]
fn my_function() {
    println!("Inside my_function");
}

3. 派生宏示例

use yare_macro::derive;

#[derive]
fn DefaultValue(input: syn::DeriveInput) -> proc_macro2::TokenStream {
    let name = &input.ident;
    
    quote::quote! {
        impl Default for #name {
            fn default() -> Self {
                Self {
                    // 默认字段初始化
                }
            }
        }
    }
}

// 使用示例
#[derive(DefaultValue)]
struct MyStruct {
    field1: i32,
    field2: String,
}

4. 函数式宏示例

use yare_macro::function;

#[function]
fn vec_from(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let elements: Vec<_> = input.into_iter().collect();
    
    quote::quote! {
        vec![#(#elements),*]
    }
}

// 使用示例
let v = vec_from!(1, 2, 3, 4);

高级用法

1. 宏组合

#[attribute]
fn timed(item: syn::ItemFn) -> proc_macro2::TokenStream {
    let fn_name = &item.sig.ident;
    let block = &item.block;
    
    quote::quote! {
        fn #fn_name() {
            let start = std::time::Instant::now();
            #block
            println!("{} took {:?}", stringify!(#fn_name), start.elapsed());
        }
    }
}

#[timed]
#[log_call]
fn important_operation() {
    // 复杂操作
}

2. 自定义错误处理

#[attribute]
fn non_empty(item: syn::ItemFn) -> Result<proc_macro2::TokenStream, syn::Error> {
    if item.block.stmts.is_empty() {
        return Err(syn::Error::new_spanned(
            &item.sig.ident,
            "Function cannot be empty",
        ));
    }
    
    Ok(quote::quote!(#item))
}

性能建议

  1. 尽量在编译时完成尽可能多的工作
  2. 使用synquote库进行高效的TokenStream处理
  3. 避免在宏中执行复杂的运行时逻辑

总结

yare-macro为Rust宏开发提供了简洁高效的API,特别适合需要频繁使用宏或开发复杂宏的项目。通过其提供的各种宏类型,可以轻松实现代码生成、元编程和各种DSL开发。

完整示例代码

下面是一个完整的示例,展示如何使用yare-macro创建一个综合项目:

// Cargo.toml
/*
[dependencies]
yare-macro = "0.1"
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
*/

// main.rs
use yare_macro::{attribute, derive, function};
use syn;
use quote::quote;

// 1. 属性宏示例 - 自动添加日志
#[attribute]
pub fn log_call(item: syn::ItemFn) -> proc_macro2::TokenStream {
    let fn_name = &item.sig.ident;
    let inputs = &item.sig.inputs;
    let output = &item.sig.output;
    let block = &item.block;
    
    quote! {
        fn #fn_name(#inputs) #output {
            println!("[LOG] 调用函数: {}", stringify!(#fn_name));
            #block
        }
    }
}

// 2. 派生宏示例 - 自动实现Builder模式
#[derive]
pub fn Builder(input: syn::DeriveInput) -> proc_macro2::TokenStream {
    let name = &input.ident;
    let builder_name = syn::Ident::new(&format!("{}Builder", name), name.span());
    
    quote! {
        impl #name {
            pub fn builder() -> #builder_name {
                #builder_name::default()
            }
        }
        
        #[derive(Default)]
        struct #builder_name {
            // 这里可以添加字段
        }
        
        impl #builder_name {
            pub fn build(self) -> #name {
                #name {
                    // 这里可以初始化字段
                }
            }
        }
    }
}

// 3. 函数式宏示例 - 创建测试用例
#[function]
pub fn test_case(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let test_name = format!("test_{}", input.to_string().replace(" ", "_"));
    let test_name = syn::Ident::new(&test_name, proc_macro2::Span::call_site());
    
    quote! {
        #[test]
        fn #test_name() {
            println!("运行测试: {}", stringify!(#test_name));
            assert!(#input);
        }
    }
}

// 使用示例
#[derive(Builder)]
struct User {
    id: u64,
    name: String,
}

#[log_call]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

test_case!(1 + 1 == 2);

fn main() {
    let user_builder = User::builder();
    let _user = user_builder.build();
    
    println!("1 + 2 = {}", add(1, 2));
}

这个完整示例展示了:

  1. 使用属性宏自动为函数添加日志功能
  2. 使用派生宏为结构体自动生成Builder模式
  3. 使用函数式宏创建测试用例
  4. 综合使用这些宏的示例

要运行这个示例,需要确保在Cargo.toml中添加了所有必要的依赖项。

回到顶部