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