windows_tokens/
lib.rs

1#![forbid(unsafe_code)]
2
3mod to_tokens;
4mod token_stream;
5
6// Not public API.
7#[doc(hidden)]
8#[path = "runtime.rs"]
9pub mod __private;
10
11pub use to_tokens::*;
12pub use token_stream::*;
13
14/// The whole point.
15///
16/// Performs variable interpolation against the input and produces it as
17/// [`TokenStream`].
18///
19/// # Interpolation
20///
21/// Variable interpolation is done with `#var` (similar to `$var` in
22/// `macro_rules!` macros). This grabs the `var` variable that is currently in
23/// scope and inserts it in that location in the output tokens. Any type
24/// implementing the [`ToTokens`] trait can be interpolated. This includes most
25/// Rust primitive types.
26///
27/// [`ToTokens`]: trait.ToTokens.html
28///
29/// Repetition is done using `#(...)*` or `#(...),*` again similar to
30/// `macro_rules!`. This iterates through the elements of any variable
31/// interpolated within the repetition and inserts a copy of the repetition body
32/// for each one. The variables in an interpolation may be a `Vec`, slice,
33/// `BTreeSet`, or any `Iterator`.
34///
35/// - `#(#var)*` — no separators
36/// - `#(#var),*` — the character before the asterisk is used as a separator
37/// - `#( struct #var; )*` — the repetition can contain other tokens
38/// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
39#[macro_export]
40macro_rules! quote {
41    () => {
42        $crate::TokenStream::new()
43    };
44    ($($tt:tt)*) => {{
45        let mut _s = $crate::TokenStream::new();
46        $crate::quote_each_token!(_s $($tt)*);
47        _s
48    }};
49}
50
51/// Formatting macro for constructing a `TokenStream`.
52///
53/// <br>
54///
55/// # Syntax
56///
57/// Syntax is copied from the [`format!`] macro, supporting both positional and
58/// named arguments.
59#[macro_export]
60macro_rules!  format_token {
61    ($($fmt:tt)*) => {
62        $crate::TokenStream::from(format!($($fmt)*))
63    };
64}
65
66// Extract the names of all #metavariables and pass them to the $call macro.
67//
68// in:   pounded_var_names!(then!(...) a #b c #( #d )* #e)
69// out:  then!(... b);
70//       then!(... d);
71//       then!(... e);
72#[macro_export]
73#[doc(hidden)]
74macro_rules! pounded_var_names {
75    ($call:ident! $extra:tt $($tts:tt)*) => {
76        $crate::pounded_var_names_with_context!($call! $extra
77            (@ $($tts)*)
78            ($($tts)* @)
79        )
80    };
81}
82
83#[macro_export]
84#[doc(hidden)]
85macro_rules! pounded_var_names_with_context {
86    ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => {
87        $(
88            $crate::pounded_var_with_context!($call! $extra $b1 $curr);
89        )*
90    };
91}
92
93#[macro_export]
94#[doc(hidden)]
95macro_rules! pounded_var_with_context {
96    ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => {
97        $crate::pounded_var_names!($call! $extra $($inner)*);
98    };
99
100    ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => {
101        $crate::pounded_var_names!($call! $extra $($inner)*);
102    };
103
104    ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => {
105        $crate::pounded_var_names!($call! $extra $($inner)*);
106    };
107
108    ($call:ident!($($extra:tt)*) # $var:ident) => {
109        $crate::$call!($($extra)* $var);
110    };
111
112    ($call:ident! $extra:tt $b1:tt $curr:tt) => {};
113}
114
115#[macro_export]
116#[doc(hidden)]
117macro_rules! quote_bind_into_iter {
118    ($has_iter:ident $var:ident) => {
119        // `mut` may be unused if $var occurs multiple times in the list.
120        #[allow(unused_mut)]
121        let (mut $var, i) = $var.quote_into_iter();
122        let $has_iter = $has_iter | i;
123    };
124}
125
126#[macro_export]
127#[doc(hidden)]
128macro_rules! quote_bind_next_or_break {
129    ($var:ident) => {
130        let $var = match $var.next() {
131            Some(_x) => $crate::__private::RepInterp(_x),
132            None => break,
133        };
134    };
135}
136
137#[macro_export]
138#[doc(hidden)]
139macro_rules! quote_each_token {
140    ($tokens:ident $($tts:tt)*) => {
141        $crate::quote_tokens_with_context!($tokens
142            (@ @ @ @ @ @ $($tts)*)
143            (@ @ @ @ @ $($tts)* @)
144            (@ @ @ @ $($tts)* @ @)
145            (@ @ @ $(($tts))* @ @ @)
146            (@ @ $($tts)* @ @ @ @)
147            (@ $($tts)* @ @ @ @ @)
148            ($($tts)* @ @ @ @ @ @)
149        );
150    };
151}
152
153#[macro_export]
154#[doc(hidden)]
155macro_rules! quote_tokens_with_context {
156    ($tokens:ident
157        ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*)
158        ($($curr:tt)*)
159        ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
160    ) => {
161        $(
162            $crate::quote_token_with_context!($tokens $b3 $b2 $b1 $curr $a1 $a2 $a3);
163        )*
164    };
165}
166
167#[macro_export]
168#[doc(hidden)]
169macro_rules! quote_token_with_context {
170    ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
171
172    ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
173        use $crate::__private::ext::*;
174        let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
175        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
176        let _: $crate::__private::HasIterator = has_iter;
177        // This is `while true` instead of `loop` because if there are no
178        // iterators used inside of this repetition then the body would not
179        // contain any `break`, so the compiler would emit unreachable code
180        // warnings on anything below the loop. We use has_iter to detect and
181        // fail to compile when there are no iterators, so here we just work
182        // around the unneeded extra warning.
183        while true {
184            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
185            $crate::quote_each_token!($tokens $($inner)*);
186        }
187    }};
188    ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
189    ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
190
191    ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
192        use $crate::__private::ext::*;
193        let mut _i = 0usize;
194        let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
195        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
196        let _: $crate::__private::HasIterator = has_iter;
197        while true {
198            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
199            if _i > 0 {
200                $crate::quote_token!($tokens $sep);
201            }
202            _i += 1;
203            $crate::quote_each_token!($tokens $($inner)*);
204        }
205    }};
206    ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
207    ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
208    ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
209        // https://github.com/dtolnay/quote/issues/130
210        $crate::quote_token!($tokens *);
211    };
212    ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
213
214    ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
215        $crate::ToTokens::to_tokens(&$var, &mut $tokens);
216    };
217    ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
218    ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
219        $crate::quote_token!($tokens $curr);
220    };
221}
222
223#[macro_export]
224#[doc(hidden)]
225macro_rules! quote_token {
226    ($tokens:ident ( $($inner:tt)* )) => {
227        $crate::__private::push_group(
228            &mut $tokens,
229            $crate::Delimiter::Parenthesis,
230            $crate::quote!($($inner)*),
231        );
232    };
233
234    ($tokens:ident [ $($inner:tt)* ]) => {
235        $crate::__private::push_group(
236            &mut $tokens,
237            $crate::Delimiter::Bracket,
238            $crate::quote!($($inner)*),
239        );
240    };
241
242    ($tokens:ident { $($inner:tt)* }) => {
243        $crate::__private::push_group(
244            &mut $tokens,
245            $crate::Delimiter::Brace,
246            $crate::quote!($($inner)*),
247        );
248    };
249
250    ($tokens:ident +) => {
251        $crate::__private::push_add(&mut $tokens);
252    };
253
254    ($tokens:ident +=) => {
255        $crate::__private::push_add_eq(&mut $tokens);
256    };
257
258    ($tokens:ident &) => {
259        $crate::__private::push_and(&mut $tokens);
260    };
261
262    ($tokens:ident &&) => {
263        $crate::__private::push_and_and(&mut $tokens);
264    };
265
266    ($tokens:ident &=) => {
267        $crate::__private::push_and_eq(&mut $tokens);
268    };
269
270    ($tokens:ident @) => {
271        $crate::__private::push_at(&mut $tokens);
272    };
273
274    ($tokens:ident !) => {
275        $crate::__private::push_bang(&mut $tokens);
276    };
277
278    ($tokens:ident ^) => {
279        $crate::__private::push_caret(&mut $tokens);
280    };
281
282    ($tokens:ident ^=) => {
283        $crate::__private::push_caret_eq(&mut $tokens);
284    };
285
286    ($tokens:ident :) => {
287        $crate::__private::push_colon(&mut $tokens);
288    };
289
290    ($tokens:ident ::) => {
291        $crate::__private::push_colon2(&mut $tokens);
292    };
293
294    ($tokens:ident ,) => {
295        $crate::__private::push_comma(&mut $tokens);
296    };
297
298    ($tokens:ident /) => {
299        $crate::__private::push_div(&mut $tokens);
300    };
301
302    ($tokens:ident /=) => {
303        $crate::__private::push_div_eq(&mut $tokens);
304    };
305
306    ($tokens:ident .) => {
307        $crate::__private::push_dot(&mut $tokens);
308    };
309
310    ($tokens:ident ..) => {
311        $crate::__private::push_dot2(&mut $tokens);
312    };
313
314    ($tokens:ident ...) => {
315        $crate::__private::push_dot3(&mut $tokens);
316    };
317
318    ($tokens:ident ..=) => {
319        $crate::__private::push_dot_dot_eq(&mut $tokens);
320    };
321
322    ($tokens:ident =) => {
323        $crate::__private::push_eq(&mut $tokens);
324    };
325
326    ($tokens:ident ==) => {
327        $crate::__private::push_eq_eq(&mut $tokens);
328    };
329
330    ($tokens:ident >=) => {
331        $crate::__private::push_ge(&mut $tokens);
332    };
333
334    ($tokens:ident >) => {
335        $crate::__private::push_gt(&mut $tokens);
336    };
337
338    ($tokens:ident <=) => {
339        $crate::__private::push_le(&mut $tokens);
340    };
341
342    ($tokens:ident <) => {
343        $crate::__private::push_lt(&mut $tokens);
344    };
345
346    ($tokens:ident *=) => {
347        $crate::__private::push_mul_eq(&mut $tokens);
348    };
349
350    ($tokens:ident !=) => {
351        $crate::__private::push_ne(&mut $tokens);
352    };
353
354    ($tokens:ident |) => {
355        $crate::__private::push_or(&mut $tokens);
356    };
357
358    ($tokens:ident |=) => {
359        $crate::__private::push_or_eq(&mut $tokens);
360    };
361
362    ($tokens:ident ||) => {
363        $crate::__private::push_or_or(&mut $tokens);
364    };
365
366    ($tokens:ident #) => {
367        $crate::__private::push_pound(&mut $tokens);
368    };
369
370    ($tokens:ident ?) => {
371        $crate::__private::push_question(&mut $tokens);
372    };
373
374    ($tokens:ident ->) => {
375        $crate::__private::push_rarrow(&mut $tokens);
376    };
377
378    ($tokens:ident <-) => {
379        $crate::__private::push_larrow(&mut $tokens);
380    };
381
382    ($tokens:ident %) => {
383        $crate::__private::push_rem(&mut $tokens);
384    };
385
386    ($tokens:ident %=) => {
387        $crate::__private::push_rem_eq(&mut $tokens);
388    };
389
390    ($tokens:ident =>) => {
391        $crate::__private::push_fat_arrow(&mut $tokens);
392    };
393
394    ($tokens:ident ;) => {
395        $crate::__private::push_semi(&mut $tokens);
396    };
397
398    ($tokens:ident <<) => {
399        $crate::__private::push_shl(&mut $tokens);
400    };
401
402    ($tokens:ident <<=) => {
403        $crate::__private::push_shl_eq(&mut $tokens);
404    };
405
406    ($tokens:ident >>) => {
407        $crate::__private::push_shr(&mut $tokens);
408    };
409
410    ($tokens:ident >>=) => {
411        $crate::__private::push_shr_eq(&mut $tokens);
412    };
413
414    ($tokens:ident *) => {
415        $crate::__private::push_star(&mut $tokens);
416    };
417
418    ($tokens:ident -) => {
419        $crate::__private::push_sub(&mut $tokens);
420    };
421
422    ($tokens:ident -=) => {
423        $crate::__private::push_sub_eq(&mut $tokens);
424    };
425
426    ($tokens:ident $ident:ident) => {
427        $crate::__private::push_ident(&mut $tokens, stringify!($ident));
428    };
429
430    ($tokens:ident $other:tt) => {
431        $crate::__private::parse(&mut $tokens, stringify!($other));
432    };
433}