Skip to main content

time_macros/
quote.rs

1macro_rules! quote {
2    ($($x:tt)*) => {{
3        use proc_macro::*;
4        quote_inner!([] [] $($x)*)
5    }};
6}
7
8macro_rules! quote_inner {
9    ([] []) => {
10        TokenStream::new()
11    };
12    ([] [$($tokens:tt)+]) => {
13        TokenStream::from_iter([$($tokens)+])
14    };
15    ([$($streams:tt)+] []) => {
16        TokenStream::from_iter([$($streams)+])
17    };
18    ([$($streams:tt)+] [$($tokens:tt)+]) => {
19        TokenStream::from_iter([
20            $($streams)+
21            TokenStream::from_iter([$($tokens)+])
22        ])
23    };
24
25    // Only stream interpolation splits the accumulated token array.
26    ([$($streams:tt)*] [] #S($e:expr) $($tail:tt)*) => {
27        quote_inner!([
28            $($streams)*
29            $crate::to_tokens::ToTokenStream::into_token_stream($e),
30        ] [] $($tail)*)
31    };
32    ([$($streams:tt)*] [$($tokens:tt)+] #S($e:expr) $($tail:tt)*) => {
33        quote_inner!([
34            $($streams)*
35            TokenStream::from_iter([$($tokens)+]),
36            $crate::to_tokens::ToTokenStream::into_token_stream($e),
37        ] [] $($tail)*)
38    };
39    ($streams:tt [$($tokens:tt)*] #($e:expr) $($tail:tt)*) => {
40        quote_inner!($streams [
41            $($tokens)*
42            $crate::to_tokens::ToTokenTree::into_token_tree($e),
43        ] $($tail)*)
44    };
45    ($streams:tt [$($tokens:tt)*] #[$($inner:tt)*] $($tail:tt)*) => {
46        quote_inner!($streams [
47            $($tokens)*
48            TokenTree::from(Punct::new('#', Spacing::Alone)),
49            TokenTree::from(Group::new(
50                Delimiter::Bracket,
51                quote_inner!([] [] $($inner)*),
52            )),
53        ] $($tail)*)
54    };
55
56    ($streams:tt [$($tokens:tt)*] :: $($tail:tt)*) => {
57        quote_inner!($streams [
58            $($tokens)*
59            TokenTree::from(Punct::new(':', Spacing::Joint)),
60            TokenTree::from(Punct::new(':', Spacing::Alone)),
61        ] $($tail)*)
62    };
63    ($streams:tt [$($tokens:tt)*] >> $($tail:tt)*) => {
64        quote_inner!($streams [
65            $($tokens)*
66            TokenTree::from(Punct::new('>', Spacing::Joint)),
67            TokenTree::from(Punct::new('>', Spacing::Alone)),
68        ] $($tail)*)
69    };
70    ($streams:tt [$($tokens:tt)*] -> $($tail:tt)*) => {
71        quote_inner!($streams [
72            $($tokens)*
73            TokenTree::from(Punct::new('-', Spacing::Joint)),
74            TokenTree::from(Punct::new('>', Spacing::Alone)),
75        ] $($tail)*)
76    };
77    ($streams:tt [$($tokens:tt)*] $l:lifetime $($tail:tt)*) => {
78        quote_inner!($streams [
79            $($tokens)*
80            TokenTree::from(Punct::new('\'', Spacing::Joint)),
81            TokenTree::from(Ident::new(
82                stringify!($l).trim_start_matches('\''),
83                Span::mixed_site(),
84            )),
85        ] $($tail)*)
86    };
87
88    ($streams:tt [$($tokens:tt)*] $first:tt :: $($tail:tt)*) => {
89        quote_inner!($streams [
90            $($tokens)*
91            quote_token!($first),
92            TokenTree::from(Punct::new(':', Spacing::Joint)),
93            TokenTree::from(Punct::new(':', Spacing::Alone)),
94        ] $($tail)*)
95    };
96    ($streams:tt [$($tokens:tt)*] $first:tt -> $($tail:tt)*) => {
97        quote_inner!($streams [
98            $($tokens)*
99            quote_token!($first),
100            TokenTree::from(Punct::new('-', Spacing::Joint)),
101            TokenTree::from(Punct::new('>', Spacing::Alone)),
102        ] $($tail)*)
103    };
104    ($streams:tt [$($tokens:tt)*] $first:tt # $($tail:tt)*) => {
105        quote_inner!($streams [
106            $($tokens)*
107            quote_token!($first),
108        ] # $($tail)*)
109    };
110    ($streams:tt [$($tokens:tt)*] $first:tt $second:tt $($tail:tt)*) => {
111        quote_inner!($streams [
112            $($tokens)*
113            quote_token!($first),
114            quote_token!($second),
115        ] $($tail)*)
116    };
117    ($streams:tt [$($tokens:tt)*] $token:tt $($tail:tt)*) => {
118        quote_inner!($streams [
119            $($tokens)*
120            quote_token!($token),
121        ] $($tail)*)
122    };
123}
124
125macro_rules! quote_token {
126    ($i:ident) => {
127        TokenTree::from(Ident::new(stringify!($i), Span::mixed_site()))
128    };
129    (0) => {
130        TokenTree::from(Literal::usize_unsuffixed(0))
131    };
132    ($l:literal) => {
133        TokenTree::from(Literal::string(&$l))
134    };
135    (($($inner:tt)*)) => {
136        TokenTree::from(Group::new(
137            Delimiter::Parenthesis,
138            quote_inner!([] [] $($inner)*),
139        ))
140    };
141    ([$($inner:tt)*]) => {
142        TokenTree::from(Group::new(
143            Delimiter::Bracket,
144            quote_inner!([] [] $($inner)*),
145        ))
146    };
147    ({$($inner:tt)*}) => {
148        TokenTree::from(Group::new(
149            Delimiter::Brace,
150            quote_inner!([] [] $($inner)*),
151        ))
152    };
153    (:) => { TokenTree::from(Punct::new(':', Spacing::Alone)) };
154    (=) => { TokenTree::from(Punct::new('=', Spacing::Alone)) };
155    (;) => { TokenTree::from(Punct::new(';', Spacing::Alone)) };
156    (,) => { TokenTree::from(Punct::new(',', Spacing::Alone)) };
157    (.) => { TokenTree::from(Punct::new('.', Spacing::Alone)) };
158    (&) => { TokenTree::from(Punct::new('&', Spacing::Alone)) };
159    (<) => { TokenTree::from(Punct::new('<', Spacing::Alone)) };
160    (>) => { TokenTree::from(Punct::new('>', Spacing::Alone)) };
161    (?) => { TokenTree::from(Punct::new('?', Spacing::Alone)) };
162    (!) => { TokenTree::from(Punct::new('!', Spacing::Alone)) };
163    (|) => { TokenTree::from(Punct::new('|', Spacing::Alone)) };
164    (*) => { TokenTree::from(Punct::new('*', Spacing::Alone)) };
165    (+) => { TokenTree::from(Punct::new('+', Spacing::Alone)) };
166}