1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{
parse::{Parse, ParseStream, Result},
parse_macro_input,
};
struct UpTo {
value: usize,
}
impl Parse for UpTo {
fn parse(input: ParseStream) -> Result<Self> {
let lit: syn::LitInt = input.parse()?;
let value = lit.base10_parse::<usize>()?;
Ok(UpTo { value })
}
}
#[proc_macro]
pub fn impl_tuples(tokens: TokenStream) -> TokenStream {
let up_to = parse_macro_input!(tokens as UpTo);
let mut out = quote! {};
for arity in 0..=up_to.value {
let t_n = (0..arity)
.map(|n| format_ident!("T{}", n))
.collect::<Vec<_>>();
let idx = (0..arity).map(syn::Index::from).collect::<Vec<_>>();
out = quote! {
#out
impl<#(#t_n),*> Introspect for (#(#t_n,)*)
where
#(
#t_n: 'static + Introspect,
)*
{
fn introspect_from<F>(&self, breadcrumbs: Breadcrumbs, mut visit: F)
where
F: FnMut(&Breadcrumbs, &dyn Any),
{
visit(&breadcrumbs, self);
#({
let mut breadcrumbs = breadcrumbs.clone();
breadcrumbs.push_back(Breadcrumb::TupleIndex(#idx));
self.#idx.introspect_from(breadcrumbs, &mut visit);
})*
}
}
}
}
out.into()
}