Function-like macros
Function-like macros are that are used like declarative macros and can take any valid token stream input. They take a TokenStream as input, and output a TokenStream.
They have the following signature:
#![allow(unused)] fn main() { #[proc_macro] pub fn my_macro(input: TokenStream) -> TokenStream { ... } }
This macro can then be used in code as such:
#![allow(unused)] fn main() { my_macro_crate::my_macro!(...); }
As an example, lets make a macro that takes an identifier, and a literal and create a constant for us:
#![allow(unused)] fn main() { use proc_macro::TokenStream; /// The ParsedInput structure will be used to store the input to our macros. struct ParsedInput { /// Identifier for the generated constant. ident: syn::Ident, /// String expression. expr: syn::LitStr, } /// Implement the Parse trait from syn to parse the input impl syn::parse::Parse for ParsedInput { fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { // Parse our first macro argument, the identifier. let ident = input.parse()?; // Parse the comma and ignore it. let _: syn::Token![,] = input.parse()?; // Parse our second macro argument, the string expression. let expr = input.parse()?; Ok(Self { ident, expr }) } } #[proc_macro] pub fn make_constant(input: TokenStream) -> TokenStream { let ParsedInput { ident, expr } = syn::parse_macro_input!(input as ParsedInput); // Use the quote crate to create the constant. quote::quote! { const #ident: &str = #expr; } .into() } }