liveBook · Manning

Parse_macro_input

As explained in Write Powerful Rust Macros

parse_macro_input is a syn-provided procedural macro that parses a procedural macro's input token stream into a specified Rust syntax type.

`parse_macro_input!` parses a procedural macro parameter of type `TokenStream` into a Rust syntax representation supplied after `as`. In a derive macro, parsing `item as DeriveInput` turns the decorated struct or enum into an AST that can be inspected before generating tokens. section 3.3

Use the decorated type’s actual name

A hardcoded `impl Example` breaks when the caller renames the struct. Parse the input, read `ast.ident`, and interpolate that identifier into `quote!` with `#name`: ```rust let ast = parse_macro_input!(item as DeriveInput); let name = ast.ident; quote! { impl #name { /* generated methods */ } } ``` The generated implementation then follows the caller’s type name rather than one fixed example name. section 3.3

Parsing consumes the incoming stream. A function-like macro that must also emit the original item can clone and convert the stream before parsing it, then include that copy in `quote!`. Alternatively, retaining the AST can be preferable: `DeriveInput` implements `ToTokens`, and borrowing its identifier avoids a partial move. section 5.1.2

Parse an attribute’s separate arguments

Attribute macros receive both the annotated item and the attribute tokens. Parse the item as `DeriveInput`, then parse `attr` as a custom type implementing `Parse`. A `public(exclude(fourth, third))` attribute can become an `ExcludedFields` value, which determines which fields retain their existing visibility. section 8.7

Choose the target syntax type from the macro input being interpreted:

  • Use `DeriveInput` when the input is a struct or enum supplied to a derive-style macro. section 3.3
  • Use a custom `Parse` type when an attribute accepts a focused mini-language such as an `exclude(...)` list. section 8.7
  • Parse directly as `MetaList` when only a list-shaped attribute is relevant; parse its identifiers with `Punctuated` and `parse_terminated`. section 8.7
Listing 3.7 Parsing the input and using it in our output
use quote::quote;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(Hello)]
pub fn hello(item: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(item as DeriveInput);     #1
    let name = ast.ident;                  #2

    let add_hello_world = quote! {
        impl #name {           #3
            fn hello_world(&self) { #4
                println!("Hello, World")
            }
        }                              
    };

    add_hello_world.into()
}

This minimal derive macro shows the complete path from `TokenStream` through `DeriveInput` and `ast.ident` to a name-aware `quote!` expansion. section 3.3

Listing 8.36 Our public function with a custom struct for parsing the first parameter
// imports

#[proc_macro_attribute]
pub fn public(attr: TokenStream, item: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(item as DeriveInput);
    let excluded_fields = parse_macro_input!(
        attr as ExcludedFields
    );                        #1
    let name = ast.ident;

    let fields = // still retrieving the fields
    let builder_fields = fields.iter().map(|f| {
        let name = &f.ident;
        let ty = &f.ty;
        let vis = &f.vis;

        if excluded_fields.matches_ident(name) {      #2
            quote! { #vis #name: #ty }
        } else {
            quote! { pub #name: #ty }
        }
    });

    // return output
}

This attribute macro parses two independent token streams: the annotated item and custom attribute arguments. section 8.7

How Write Powerful Rust Macros covers it

How deep it goes
Works through `DeriveInput`, custom `Parse`, `MetaList`, and punctuated identifiers, contrasting syn 2 with an older syn 1 approach.
Examples
Demonstrates a generated `hello_world` implementation and a `public(exclude(...))` attribute that preserves selected field visibility.
What it assumes
Assumes procedural-macro and Rust ownership familiarity while explaining partial moves through a concrete struct example.
What you can do after
Build it from scratch by parsing derive or attribute inputs and interpolating inspected syntax into macro output.
How it connects
Connects TokenStream, DeriveInput, quote!, Parse, MetaList, Punctuated, ownership, and partial moves.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Write Powerful Rust Macros. The section links point to the parts of the book it draws on.