MetaList is the syn structure for list-form Rust metadata: an attribute path followed by parenthesized arguments, such as #[exclude(fourth, third)]. It is the focused choice when a procedural macro needs the list contents rather than a path or name-value form. section 8.7 section 8.1.2
A practical MetaList parsing flow is:
- Parse the attribute input as MetaList, then inspect its path to confirm the expected attribute name, such as exclude. section 8.7
- Parse the list tokens into a suitable type, such as Punctuated<Ident, Token![,]> for bare field names. section 8.7
- Use LitStr instead when the syntax contains quoted values, such as exclude("fourth", "third"), and convert each literal with value. section 8.7
- Prefer require_list for simple validation, or use syn::meta::parser when custom nested parsing and clearer errors are useful. section 8.1.2 section 8.7
Selecting excluded fields
Given #[public(exclude(fourth, third))], a custom ExcludedFields parser stores the identifiers as strings. The procedural macro then checks each struct field with matches_ident: excluded fields retain their existing visibility, while other fields become public. section 8.7
Listing 8.37 ExcludedFields implementation for syn major version 2
const EXCLUDE_ATTRIBUTE_NAME: &str = "exclude";
struct ExcludedFields {
fields: Vec<String>
}
impl ExcludedFields {
fn matches_ident(&self, name: &Option<Ident>) -> bool {
name.as_ref().map(|n| n.to_string())
.map(|n| self.fields.iter().any(|f| *f == n))
.unwrap_or_else(|| false)
}
}
impl Parse for ExcludedFields {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
match input.parse::<MetaList>() { #1
Ok(meta_list) => {
if meta_list.path
.segments
.iter()
.find(|s| s.ident == EXCLUDE_ATTRIBUTE_NAME)
.is_some() #2
{
let parser = Punctuated::<Ident, Token![,]>
::parse_terminated;
let identifiers = parser.parse(
meta_list.clone().tokens.into()
).unwrap();
let fields = identifiers.iter()
.map(|v| v.to_string())
.collect(); #3
Ok(ExcludedFields { fields })
} else {
Ok(ExcludedFields { fields: vec![] })
}
}
Err(_) => Ok(
ExcludedFields { fields: vec![] } #4
)
}
}
}
Inspect the syn v2 implementation that parses MetaList, verifies the exclude path, and begins extracting comma-separated identifiers. section 8.7
