1use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
2use std::collections::hash_map::DefaultHasher;
3use std::hash::{Hash, Hasher};
4use std::iter::FromIterator;
5
6pub fn wrap(output: TokenStream) -> TokenStream {
7 let mut hasher = DefaultHasher::default();
8 output.to_string().hash(&mut hasher);
9 let mangled_name = format!("_paste_{}", hasher.finish());
10 let ident = Ident::new(&mangled_name, Span::call_site());
11
12 TokenStream::from_iter(vec![
19 TokenTree::Punct(Punct::new('#', Spacing::Alone)),
20 TokenTree::Group(Group::new(
21 Delimiter::Bracket,
22 TokenStream::from_iter(vec![
23 TokenTree::Ident(Ident::new("derive", Span::call_site())),
24 TokenTree::Group(Group::new(
25 Delimiter::Parenthesis,
26 TokenStream::from_iter(vec![
27 TokenTree::Ident(Ident::new("paste", Span::call_site())),
28 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
29 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
30 TokenTree::Ident(Ident::new("EnumHack", Span::call_site())),
31 ]),
32 )),
33 ]),
34 )),
35 TokenTree::Ident(Ident::new("enum", Span::call_site())),
36 TokenTree::Ident(ident),
37 TokenTree::Group(Group::new(
38 Delimiter::Brace,
39 TokenStream::from_iter(vec![
40 TokenTree::Ident(Ident::new("Value", Span::call_site())),
41 TokenTree::Punct(Punct::new('=', Spacing::Alone)),
42 TokenTree::Group(Group::new(
43 Delimiter::Parenthesis,
44 TokenStream::from_iter(vec![
45 TokenTree::Ident(Ident::new("stringify", Span::call_site())),
46 TokenTree::Punct(Punct::new('!', Spacing::Alone)),
47 TokenTree::Group(Group::new(Delimiter::Brace, output)),
48 TokenTree::Punct(Punct::new(',', Spacing::Alone)),
49 TokenTree::Literal(Literal::usize_unsuffixed(0)),
50 ]),
51 )),
52 TokenTree::Punct(Punct::new('.', Spacing::Alone)),
53 TokenTree::Literal(Literal::usize_unsuffixed(1)),
54 TokenTree::Punct(Punct::new(',', Spacing::Alone)),
55 ]),
56 )),
57 ])
58}
59
60pub fn extract(input: TokenStream) -> TokenStream {
61 let mut tokens = input.into_iter();
62 let _ = tokens.next().expect("enum");
63 let _ = tokens.next().expect("#ident");
64 let mut braces = match tokens.next().expect("{...}") {
65 TokenTree::Group(group) => group.stream().into_iter(),
66 _ => unreachable!("{...}"),
67 };
68 let _ = braces.next().expect("Value");
69 let _ = braces.next().expect("=");
70 let mut parens = match braces.next().expect("(...)") {
71 TokenTree::Group(group) => group.stream().into_iter(),
72 _ => unreachable!("(...)"),
73 };
74 let _ = parens.next().expect("stringify");
75 let _ = parens.next().expect("!");
76 let token_stream = match parens.next().expect("{...}") {
77 TokenTree::Group(group) => group.stream(),
78 _ => unreachable!("{...}"),
79 };
80 let _ = parens.next().expect(",");
81 let _ = parens.next().expect("0");
82 let _ = braces.next().expect(".");
83 let _ = braces.next().expect("1");
84 let _ = braces.next().expect(",");
85 token_stream
86}