3个版本 (破坏性更新)

使用旧的Rust 2015

0.3.0 2018年9月14日
0.2.0 2018年6月2日
0.1.0 2018年5月29日

进程宏中排名1864


用于enum_to_str_derive

MIT许可证

7KB
173

build status

进程宏助手

自1.15.0(2017-02-02)以来,基本进程宏允许自定义 #[derive]。要使用它,你可以分配一个函数作为处理程序,这个处理程序接受目标 StructEnumTokenStream

但是直接从 TokenStream 读取很麻烦,相反,你可以通过 syn 读取它,这是一个将Rust令牌流解析为Rust源代码语法树的解析库。

但是为了通用性,syn 非常复杂。在你的代码中,必须有大量噪声

#[proc_macro_derive(Table1, attributes(PrimaryKey))]
pub fn table1(input: TokenStream) -> TokenStream {
    let derive_input = syn::parse::<DeriveInput>(input).unwrap();
    let data_struct = if let Data::Struct(ref data) = derive_input.data {
        data
    } else {
        unreachable!();
    };

    let primary_field_idents: Vec<String> = data_struct
        .fields
        .iter()
        .filter(|field| {
            field
                .attrs
                .iter()
                .find(|x| x.interpret_meta().unwrap().name() == "PrimaryKey")
                .is_some()
        })
        .map(|x| x.ident.unwrap().to_string())
        .collect();
    let result_len = primary_field_idents.len();

    quote!(const PRIMARY_FIELDS1: [&'static str; #result_len] = [
        #(#primary_field_idents),*
    ];)
        .into()
}

使用这个仓库,你的代码可以是

use proc_macro_helper::prelude::*;

#[proc_macro_derive(Table2, attributes(PrimaryKey))]
pub fn table2(input: TokenStream) -> TokenStream {
    let derive_input = syn::parse::<DeriveInput>(input).unwrap();
    let target_struct: Struct = Struct::parse(&derive_input);
    let primary_field_idents = target_struct
        .fields
        .iter()
        .filter(|x| x.attributes.iter().find(|x| x.name == "PrimaryKey").is_some())
        .map(|x| x.name.clone().unwrap())
        .collect::<Vec<String>>();
    let result_len = primary_field_idents.len();
    quote!(const PRIMARY_FIELDS2: [&'static str; #result_len] = [
        #(#primary_field_idents),*
    ];)
        .into()
}

当前状态

  • 需要更多测试用例。
  • 需要更多功能请求。
  • 需要更多错误报告。

待办事项

  • 实现枚举助手
  • 移除对 quote 的依赖

依赖

~2MB
~46K SLoC