1use proc_macro::*;
2
3#[proc_macro]
4pub fn alloc_impl_proc(item: TokenStream) -> TokenStream {
5 let mut item = item.into_iter();
6 let Some(TokenTree::Group(krate)) = item.next() else { panic!() };
7 let krate = krate.stream();
8 let stack = match item.next() {
9 Some(TokenTree::Group(stack)) => {
10 let mut stack = stack.stream().into_iter();
11 _ = stack.next();
12 let Some(TokenTree::Ident(stack)) = stack.next() else { panic!() };
13 stack
14 },
15 Some(_) => {
16 let Some(TokenTree::Ident(stack)) = item.next() else { panic!() };
17 stack
18 },
19
20 _ => panic!(),
21 };
22 let Some(TokenTree::Group(block)) = item.next() else { panic!() };
23
24 let mut tokens = Vec::new();
25
26 tokens.extend([
27 TokenTree::Ident(Ident::new("let", Span::call_site())),
28 TokenTree::Ident(stack.clone()),
29 TokenTree::Punct(Punct::new('=', Spacing::Alone)),
30 TokenTree::Punct(Punct::new('&', Spacing::Alone)),
31 TokenTree::Ident(Ident::new("mut", Span::call_site())),
32 TokenTree::Punct(Punct::new('*', Spacing::Alone)),
33 TokenTree::Ident(stack.clone()),
34 TokenTree::Punct(Punct::new(';', Spacing::Alone)),
35 ]);
36
37 let mut cur_stmt = vec![TokenTree::Ident(stack.clone())];
38 for token in block.stream().into_iter() {
39 match token {
40 TokenTree::Punct(p) if p.as_char() == ';' => {
41 tokens.extend(krate.clone().into_iter().chain([
42 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
43 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
44 TokenTree::Ident(Ident::new("alloc_impl_rules", Span::call_site())),
45 TokenTree::Punct(Punct::new('!', Spacing::Alone)),
46 TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::from_iter(cur_stmt))),
47 TokenTree::Punct(Punct::new(';', Spacing::Alone)),
48 ]));
49
50 cur_stmt = vec![TokenTree::Ident(stack.clone())];
51 },
52 token => cur_stmt.push(token),
53 }
54 }
55
56 tokens.extend([
57 TokenTree::Ident(Ident::new("let", Span::call_site())),
58 TokenTree::Ident(Ident::new("_", Span::call_site())),
59 TokenTree::Punct(Punct::new('=', Spacing::Alone)),
60 TokenTree::Ident(stack.clone()),
61 TokenTree::Punct(Punct::new(';', Spacing::Alone)),
62 ]);
63
64 TokenStream::from_iter(tokens)
65}