variadics_macro/
lib.rs

1#![doc = include_str!("../README.md")]
2extern crate proc_macro;
3
4use proc_macro::TokenStream;
5use proc_macro2::Ident;
6use quote::{format_ident, quote};
7use syn::parse::{Parse, ParseStream};
8use syn::{LitInt, parse_macro_input};
9
10struct InputLen {
11    input: Ident,
12    len: LitInt,
13}
14
15impl Parse for InputLen {
16    fn parse(ts: ParseStream) -> syn::Result<Self> {
17        let input = ts.parse()?;
18        ts.parse::<syn::Token![,]>()?;
19        let len = ts.parse()?;
20        Ok(InputLen { input, len })
21    }
22}
23
24#[proc_macro]
25pub fn tuple(ts: TokenStream) -> TokenStream {
26    let InputLen { input, len } = parse_macro_input!(ts as InputLen);
27    let len = len.base10_parse::<usize>().unwrap();
28    let pattern = (0..len)
29        .rev()
30        .map(|i| format_ident!("x{}", i))
31        .fold(quote! { () }, |rest, item| quote! { (#item, #rest) });
32    let idents = (0..len).map(|i| format_ident!("x{}", i));
33    let tuple = quote! {
34        ( #( #idents, )* )
35    };
36
37    // Create the assignment statement
38    let expanded = quote! {
39        {
40            let #pattern = #input;
41            let retval = #tuple;
42            retval
43        }
44    };
45
46    expanded.into()
47}