liveBook · Manning

Parse_nested_meta

As explained in Write Powerful Rust Macros

parse_nested_meta is a syn parsing operation that iterates over nested metadata inside an attribute and delegates each entry to a callback.

parse_nested_meta iterates through nested metadata inside an attribute and passes each entry to a callback. In an attribute such as #[public(exclude(fourth, third))], the callback recognizes exclude, descends into its parentheses, and records each identifier. section 8.7

Parsing excluded fields

A syn version 2 parser can keep the state in a custom struct: impl AlternativeExcludedFields { fn parse(&mut self, meta: ParseNestedMeta) -> Result<(), syn::Error> { if meta.path.is_ident("exclude") { meta.parse_nested_meta(|meta| { let ident = &meta.path.segments.first().unwrap().ident; self.fields.push(ident.to_string()); Ok(()) }) } else { Err(meta.error("unsupported property")) } } } The outer callback validates the property name; the inner callback receives fourth and third and stores them. Unsupported properties produce a syn error. section 8.7

The operation is useful when an attribute parser must:

  • Inspect one level of nested metadata without manually matching MetaList structures. section 8.7
  • Delegate each nested entry to application-specific logic that updates parser state. section 8.7
  • Reject unknown properties through meta.error while accepting empty attribute streams through the parser framework. section 8.7
  • Handle metadata patterns used by established procedural macros, including serde-style options inside parentheses. section 8.9
Listing 8.39 Meta parser
#[derive(Default)]
struct AlternativeExcludedFields {
    fields: Vec<String>,
}

impl AlternativeExcludedFields {
    fn matches_ident(&self, name: &Option<Ident>) -> bool {
        // same as ExcludedFields
    }
}

impl AlternativeExcludedFields {
    fn parse(&mut self, meta: ParseNestedMeta) -> Result<(), syn::Error> {
        if meta.path.is_ident(EXCLUDE_ATTRIBUTE_NAME) {
            meta.parse_nested_meta(|meta| {
                let ident = &meta.path.segments.first().unwrap().ident;
                self.fields.push(ident.to_string());
                Ok(())             
            })
        } else {
            Err(meta.error("unsupported property"))
        }
    }
}

#[proc_macro_attribute]
pub fn public(attr: TokenStream, item: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(item as DeriveInput);
    let mut excluded_fields = AlternativeExcludedFields::default();
    let attr_parser = syn::meta::parser(|meta| excluded_fields.parse(meta));
    parse_macro_input!(attr with attr_parser);
    // everything else is the same
}

View the complete parser shape, including state storage, property validation, nested traversal, and error creation. section 8.7

How Write Powerful Rust Macros covers it

How deep it goes
Explains nested traversal, state updates, empty inputs, and errors, while stopping short of syn internals.
Examples
Uses public(exclude(fourth, third)) and relates the pattern to Tokio, Yew, and Serde attribute parsers.
What it assumes
Assumes Rust procedural macro and syn parsing familiarity while demonstrating nested metadata parsing through a concrete exclusion attribute.
What you can do after
Build an attribute parser that validates properties, collects nested identifiers, and reports unsupported input.
How it connects
Connects attributes with procedural macros, metadata, callbacks, and error handling.

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.