Rust那些事之过程宏

Rust那些事之过程宏

1.过程宏

过程宏是一种扩展Rust编译器和提供可用于扩展该语言的插件的方法。过程宏的工作原理非常简单:取一段称为输入TokenStream的代码,将其转换为抽象语法树(ast),从输入处获得的内容构建一个新的TokenStream(使用syn::parse()方法),并将其作为输出代码注入编译器。

最近在项目中频繁看到各种使用,例如:zombodb中如下使用:

#[pg_extern(immutable, parallel_safe)]

在我们平时debug时:

#[derive(Debug)]

那么我们如何实现类似Debug的功能呢?

2.derive宏

使用侧:

#[derive(StructShow)]
pub struct Point {
    x: f64,
    y: f64
}

我们需要使用proc-macro来实现该功能。

cargo new --lib my-macro

在Cargo.toml中设置:

[lib]
proc-macro = true

[dependencies]
syn = { version = "1.0.82", features = ["full", "extra-traits"] }
quote = "1.0.10"

一个最基本的例子为:

use proc_macro::TokenStream;
use syn::parse;

#[proc_macro_derive(StructShow)]
pub fn whatever_you_want(tokens: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(tokens).unwrap();
    TokenStream::new()
}

在这个例子中使用了proc_macro,但是对于proc_macro有如下缺点:

  • 需要在proc-macro类型的crate中才能使用

  • 不太好进行测试

因此proc-macro2解决了这些问题,api也基本兼容。

#[proc_macro_derive(StructShow)]
pub fn show(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let output = transform_stream(proc_macro2::TokenStream::from(input));
    proc_macro::TokenStream::from(output)
}

在这里将核心操作转入transform_stream函数,在该函数中使用的是proc_macro2,因此可以方便测试在其他crate中直接使用。

随后,内部实现debug功能。

功能非常简单,要实现debug功能,只需要实现Debug trait即可,因此使用quote!将rust语法转位TokenStream返回给编译器即可。

fn transform_stream(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let ast: ItemStruct = syn::parse2(input).unwrap();
    let struct_type = ast.ident;
    let implemented_show = quote! {
        // 下面就是Display trait的定义了
        // use std::fmt; // 不要这样import,因为std::fmt是全局的,无法做到卫生性(hygiene)
        // 编译器会报错重复import fmt当你多次使用Show之后
        impl std::fmt::Display for #struct_type {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{} x: {}, y: {}", stringify!(#struct_type), self.x, self.y)
            }
        }
    };
    implemented_show.into()
}

这样,我们在进行打印输出的时候便可以debug了。

let p= Point{x: 1.1, y: 2.3};
println!("{}", p);

今天写的这个例子比较简单,过程宏功能很强大,后续继续研究,期待一起探讨~

本节完~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值