3 releases (breaking)

Uses old Rust 2015

0.3.0 Sep 14, 2018
0.2.0 Jun 2, 2018
0.1.0 May 29, 2018

#1847 in Procedural macros

Used in enum_to_str_derive

MIT license

173 lines

build status

Procedural Macros Helper

Since 1.15.0(2017-02-02), basic procedural macros allowing custom #[derive]. To use it, you could assign a function as handler, this handler take a TokenStream for target Struct or Enum.

But read directly from TokenStream is cumbersome, instead, you can read it via syn, a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code.

But for generality, syn is very complex. In your code, there must be a lot noise:

#[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 {
    } else {

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

    quote!(const PRIMARY_FIELDS1: [&'static str; #result_len] = [

With this repo, your code could be:

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
        .filter(|x| x.attributes.iter().find(|x| x.name == "PrimaryKey").is_some())
        .map(|x| x.name.clone().unwrap())
    let result_len = primary_field_idents.len();
    quote!(const PRIMARY_FIELDS2: [&'static str; #result_len] = [

Current status

  • Need more test cases.
  • Need more feature request.
  • Need more bug reports.


  • Implement helper for enum
  • Remove dependency on quote


~45K SLoC