1use self::get_span::{GetSpan, GetSpanBase, GetSpanInner};
2use crate::{IdentFragment, ToTokens, TokenStreamExt};
3use core::fmt;
4use core::iter;
5use core::ops::BitOr;
6use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};
7
8pub use core::option::Option;
9pub use proc_macro2::{Delimiter, Span, TokenStream};
10pub use std::format;
11
12pub struct HasIterator; // True
13pub struct ThereIsNoIteratorInRepetition; // False
14
15impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
16 type Output = ThereIsNoIteratorInRepetition;
17 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
18 ThereIsNoIteratorInRepetition
19 }
20}
21
22impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
23 type Output = HasIterator;
24 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
25 HasIterator
26 }
27}
28
29impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
30 type Output = HasIterator;
31 fn bitor(self, _rhs: HasIterator) -> HasIterator {
32 HasIterator
33 }
34}
35
36impl BitOr<HasIterator> for HasIterator {
37 type Output = HasIterator;
38 fn bitor(self, _rhs: HasIterator) -> HasIterator {
39 HasIterator
40 }
41}
42
43/// Extension traits used by the implementation of `quote!`. These are defined
44/// in separate traits, rather than as a single trait due to ambiguity issues.
45///
46/// These traits expose a `quote_into_iter` method which should allow calling
47/// whichever impl happens to be applicable. Calling that method repeatedly on
48/// the returned value should be idempotent.
49pub mod ext {
50 use super::RepInterp;
51 use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
52 use crate::ToTokens;
53 use core::slice;
54 use std::collections::btree_set::{self, BTreeSet};
55
56 /// Extension trait providing the `quote_into_iter` method on iterators.
57 pub trait RepIteratorExt: Iterator + Sized {
58 fn quote_into_iter(self) -> (Self, HasIter) {
59 (self, HasIter)
60 }
61 }
62
63 impl<T: Iterator> RepIteratorExt for T {}
64
65 /// Extension trait providing the `quote_into_iter` method for
66 /// non-iterable types. These types interpolate the same value in each
67 /// iteration of the repetition.
68 pub trait RepToTokensExt {
69 /// Pretend to be an iterator for the purposes of `quote_into_iter`.
70 /// This allows repeated calls to `quote_into_iter` to continue
71 /// correctly returning DoesNotHaveIter.
72 fn next(&self) -> Option<&Self> {
73 Some(self)
74 }
75
76 fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
77 (self, DoesNotHaveIter)
78 }
79 }
80
81 impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
82
83 /// Extension trait providing the `quote_into_iter` method for types that
84 /// can be referenced as an iterator.
85 pub trait RepAsIteratorExt<'q> {
86 type Iter: Iterator;
87
88 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
89 }
90
91 impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T {
92 type Iter = T::Iter;
93
94 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
95 <T as RepAsIteratorExt>::quote_into_iter(*self)
96 }
97 }
98
99 impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T {
100 type Iter = T::Iter;
101
102 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
103 <T as RepAsIteratorExt>::quote_into_iter(*self)
104 }
105 }
106
107 impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
108 type Iter = slice::Iter<'q, T>;
109
110 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
111 (self.iter(), HasIter)
112 }
113 }
114
115 impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
116 type Iter = slice::Iter<'q, T>;
117
118 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
119 (self.iter(), HasIter)
120 }
121 }
122
123 impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
124 type Iter = btree_set::Iter<'q, T>;
125
126 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
127 (self.iter(), HasIter)
128 }
129 }
130
131 impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
132 type Iter = T::Iter;
133
134 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
135 self.0.quote_into_iter()
136 }
137 }
138}
139
140// Helper type used within interpolations to allow for repeated binding names.
141// Implements the relevant traits, and exports a dummy `next()` method.
142#[derive(Copy, Clone)]
143pub struct RepInterp<T>(pub T);
144
145impl<T> RepInterp<T> {
146 // This method is intended to look like `Iterator::next`, and is called when
147 // a name is bound multiple times, as the previous binding will shadow the
148 // original `Iterator` object. This allows us to avoid advancing the
149 // iterator multiple times per iteration.
150 pub fn next(self) -> Option<T> {
151 Some(self.0)
152 }
153}
154
155impl<T: Iterator> Iterator for RepInterp<T> {
156 type Item = T::Item;
157
158 fn next(&mut self) -> Option<Self::Item> {
159 self.0.next()
160 }
161}
162
163impl<T: ToTokens> ToTokens for RepInterp<T> {
164 fn to_tokens(&self, tokens: &mut TokenStream) {
165 self.0.to_tokens(tokens);
166 }
167}
168
169#[inline]
170pub fn get_span<T>(span: T) -> GetSpan<T> {
171 GetSpan(GetSpanInner(GetSpanBase(span)))
172}
173
174mod get_span {
175 use core::ops::Deref;
176 use proc_macro2::extra::DelimSpan;
177 use proc_macro2::Span;
178
179 pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
180
181 pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
182
183 pub struct GetSpanBase<T>(pub(crate) T);
184
185 impl GetSpan<Span> {
186 #[inline]
187 pub fn __into_span(self) -> Span {
188 ((self.0).0).0
189 }
190 }
191
192 impl GetSpanInner<DelimSpan> {
193 #[inline]
194 pub fn __into_span(&self) -> Span {
195 (self.0).0.join()
196 }
197 }
198
199 impl<T> GetSpanBase<T> {
200 #[allow(clippy::unused_self)]
201 pub fn __into_span(&self) -> T {
202 unreachable!()
203 }
204 }
205
206 impl<T> Deref for GetSpan<T> {
207 type Target = GetSpanInner<T>;
208
209 #[inline]
210 fn deref(&self) -> &Self::Target {
211 &self.0
212 }
213 }
214
215 impl<T> Deref for GetSpanInner<T> {
216 type Target = GetSpanBase<T>;
217
218 #[inline]
219 fn deref(&self) -> &Self::Target {
220 &self.0
221 }
222 }
223}
224
225pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
226 tokens.append(token:Group::new(delimiter, stream:inner));
227}
228
229pub fn push_group_spanned(
230 tokens: &mut TokenStream,
231 span: Span,
232 delimiter: Delimiter,
233 inner: TokenStream,
234) {
235 let mut g: Group = Group::new(delimiter, stream:inner);
236 g.set_span(span);
237 tokens.append(token:g);
238}
239
240pub fn parse(tokens: &mut TokenStream, s: &str) {
241 let s: TokenStream = s.parse().expect(msg:"invalid token stream");
242 tokens.extend(iter:iter::once(s));
243}
244
245pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
246 let s: TokenStream = s.parse().expect(msg:"invalid token stream");
247 tokens.extend(iter:s.into_iter().map(|t: TokenTree| respan_token_tree(token:t, span)));
248}
249
250// Token tree with every span replaced by the given one.
251fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
252 match &mut token {
253 TokenTree::Group(g: &mut Group) => {
254 let stream: TokenStream = gimpl Iterator
255 .stream()
256 .into_iter()
257 .map(|token: TokenTree| respan_token_tree(token, span))
258 .collect();
259 *g = Group::new(g.delimiter(), stream);
260 g.set_span(span);
261 }
262 other: &mut TokenTree => other.set_span(span),
263 }
264 token
265}
266
267pub fn push_ident(tokens: &mut TokenStream, s: &str) {
268 let span: Span = Span::call_site();
269 push_ident_spanned(tokens, span, s);
270}
271
272pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
273 tokens.append(token:ident_maybe_raw(id:s, span));
274}
275
276pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
277 struct Lifetime<'a> {
278 name: &'a str,
279 state: u8,
280 }
281
282 impl<'a> Iterator for Lifetime<'a> {
283 type Item = TokenTree;
284
285 fn next(&mut self) -> Option<Self::Item> {
286 match self.state {
287 0 => {
288 self.state = 1;
289 Some(TokenTree::Punct(Punct::new('\'', Spacing::Joint)))
290 }
291 1 => {
292 self.state = 2;
293 Some(TokenTree::Ident(Ident::new(self.name, Span::call_site())))
294 }
295 _ => None,
296 }
297 }
298 }
299
300 tokens.extend(Lifetime {
301 name: &lifetime[1..],
302 state: 0,
303 });
304}
305
306pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
307 struct Lifetime<'a> {
308 name: &'a str,
309 span: Span,
310 state: u8,
311 }
312
313 impl<'a> Iterator for Lifetime<'a> {
314 type Item = TokenTree;
315
316 fn next(&mut self) -> Option<Self::Item> {
317 match self.state {
318 0 => {
319 self.state = 1;
320 let mut apostrophe = Punct::new('\'', Spacing::Joint);
321 apostrophe.set_span(self.span);
322 Some(TokenTree::Punct(apostrophe))
323 }
324 1 => {
325 self.state = 2;
326 Some(TokenTree::Ident(Ident::new(self.name, self.span)))
327 }
328 _ => None,
329 }
330 }
331 }
332
333 tokens.extend(Lifetime {
334 name: &lifetime[1..],
335 span,
336 state: 0,
337 });
338}
339
340macro_rules! push_punct {
341 ($name:ident $spanned:ident $char1:tt) => {
342 pub fn $name(tokens: &mut TokenStream) {
343 tokens.append(Punct::new($char1, Spacing::Alone));
344 }
345 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
346 let mut punct = Punct::new($char1, Spacing::Alone);
347 punct.set_span(span);
348 tokens.append(punct);
349 }
350 };
351 ($name:ident $spanned:ident $char1:tt $char2:tt) => {
352 pub fn $name(tokens: &mut TokenStream) {
353 tokens.append(Punct::new($char1, Spacing::Joint));
354 tokens.append(Punct::new($char2, Spacing::Alone));
355 }
356 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
357 let mut punct = Punct::new($char1, Spacing::Joint);
358 punct.set_span(span);
359 tokens.append(punct);
360 let mut punct = Punct::new($char2, Spacing::Alone);
361 punct.set_span(span);
362 tokens.append(punct);
363 }
364 };
365 ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
366 pub fn $name(tokens: &mut TokenStream) {
367 tokens.append(Punct::new($char1, Spacing::Joint));
368 tokens.append(Punct::new($char2, Spacing::Joint));
369 tokens.append(Punct::new($char3, Spacing::Alone));
370 }
371 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
372 let mut punct = Punct::new($char1, Spacing::Joint);
373 punct.set_span(span);
374 tokens.append(punct);
375 let mut punct = Punct::new($char2, Spacing::Joint);
376 punct.set_span(span);
377 tokens.append(punct);
378 let mut punct = Punct::new($char3, Spacing::Alone);
379 punct.set_span(span);
380 tokens.append(punct);
381 }
382 };
383}
384
385push_punct!(push_add push_add_spanned '+');
386push_punct!(push_add_eq push_add_eq_spanned '+' '=');
387push_punct!(push_and push_and_spanned '&');
388push_punct!(push_and_and push_and_and_spanned '&' '&');
389push_punct!(push_and_eq push_and_eq_spanned '&' '=');
390push_punct!(push_at push_at_spanned '@');
391push_punct!(push_bang push_bang_spanned '!');
392push_punct!(push_caret push_caret_spanned '^');
393push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
394push_punct!(push_colon push_colon_spanned ':');
395push_punct!(push_colon2 push_colon2_spanned ':' ':');
396push_punct!(push_comma push_comma_spanned ',');
397push_punct!(push_div push_div_spanned '/');
398push_punct!(push_div_eq push_div_eq_spanned '/' '=');
399push_punct!(push_dot push_dot_spanned '.');
400push_punct!(push_dot2 push_dot2_spanned '.' '.');
401push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
402push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
403push_punct!(push_eq push_eq_spanned '=');
404push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
405push_punct!(push_ge push_ge_spanned '>' '=');
406push_punct!(push_gt push_gt_spanned '>');
407push_punct!(push_le push_le_spanned '<' '=');
408push_punct!(push_lt push_lt_spanned '<');
409push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
410push_punct!(push_ne push_ne_spanned '!' '=');
411push_punct!(push_or push_or_spanned '|');
412push_punct!(push_or_eq push_or_eq_spanned '|' '=');
413push_punct!(push_or_or push_or_or_spanned '|' '|');
414push_punct!(push_pound push_pound_spanned '#');
415push_punct!(push_question push_question_spanned '?');
416push_punct!(push_rarrow push_rarrow_spanned '-' '>');
417push_punct!(push_larrow push_larrow_spanned '<' '-');
418push_punct!(push_rem push_rem_spanned '%');
419push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
420push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
421push_punct!(push_semi push_semi_spanned ';');
422push_punct!(push_shl push_shl_spanned '<' '<');
423push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
424push_punct!(push_shr push_shr_spanned '>' '>');
425push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
426push_punct!(push_star push_star_spanned '*');
427push_punct!(push_sub push_sub_spanned '-');
428push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
429
430pub fn push_underscore(tokens: &mut TokenStream) {
431 push_underscore_spanned(tokens, Span::call_site());
432}
433
434pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
435 tokens.append(token:Ident::new(string:"_", span));
436}
437
438// Helper method for constructing identifiers from the `format_ident!` macro,
439// handling `r#` prefixes.
440pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
441 let span: Span = span.unwrap_or_else(Span::call_site);
442 ident_maybe_raw(id, span)
443}
444
445fn ident_maybe_raw(id: &str, span: Span) -> Ident {
446 if id.starts_with("r#") {
447 Ident::new_raw(&id[2..], span)
448 } else {
449 Ident::new(string:id, span)
450 }
451}
452
453// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
454// macro, and exposes span information from these fragments.
455//
456// This struct also has forwarding implementations of the formatting traits
457// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
458// `format_ident!`.
459#[derive(Copy, Clone)]
460pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
461
462impl<T: IdentFragment> IdentFragmentAdapter<T> {
463 pub fn span(&self) -> Option<Span> {
464 self.0.span()
465 }
466}
467
468impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
469 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470 IdentFragment::fmt(&self.0, f)
471 }
472}
473
474impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
475 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476 fmt::Octal::fmt(&self.0, f)
477 }
478}
479
480impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
481 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482 fmt::LowerHex::fmt(&self.0, f)
483 }
484}
485
486impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
487 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
488 fmt::UpperHex::fmt(&self.0, f)
489 }
490}
491
492impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
493 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
494 fmt::Binary::fmt(&self.0, f)
495 }
496}
497