ToTokens is a quote trait for converting Rust syntax-related values into token streams. Implement it when a custom struct should participate directly in quote-generated output. section 4.6.1
A typical procedural-macro implementation follows this pattern:
- Collect the relevant syntax data into a focused struct, such as a field name and type. section 4.6.1
- Implement to_tokens with a mutable proc_macro2::TokenStream parameter. section 4.6.1
- Generate tokens with quote and append them through ToTokens, allowing iterators of custom values to be quoted directly. section 4.6.1
- Use syntax types that already implement ToTokens, including DeriveInput, when recreating received input. section 5.1.2
Rendering a custom field
StructField can store an Ident and a Type, then implement ToTokens by quoting pub followed by the field name and type. Mapping fields through StructField::new produces reusable builder_fields that quote can turn into generated declarations. section 4.6.1
Listing 4.11 An implementation that uses structs to do most of the gluing
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
// previous imports
struct StructField { #1
name: Ident,
ty: Type,
}
impl StructField {
fn new(field: &Field) -> Self { #2
Self {
name: field.ident.as_ref().unwrap().clone(),
ty: field.ty.clone(),
}
}
}
impl ToTokens for StructField {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { #3
let n = &self.name;
let t = &self.ty;
quote!(pub #n: #t).to_tokens(tokens)
}
}
#[proc_macro_attribute]
pub fn public(_attr: TokenStream, item: TokenStream) -> TokenStream {
// unchanged: get fields
let builder_fields = fields.iter().map(StructField::new); #4
// unchanged: quote for output
}
Inspect the complete StructField implementation, including its constructor, ToTokens implementation, field mapping, and quote-based output. section 4.6.1
