`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
