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#[doc(hidden)]
13pub use core::stringify;
14
15#[doc(hidden)]
16pub type Delimiter = proc_macro2::Delimiter;
17#[doc(hidden)]
18pub type Span = proc_macro2::Span;
19#[doc(hidden)]
20pub type TokenStream = proc_macro2::TokenStream;
21
22#[doc(hidden)]
23pub struct HasIterator<const B: bool>;
24
25impl BitOr<HasIterator<false>> for HasIterator<false> {
26 type Output = HasIterator<false>;
27 fn bitor(self, _rhs: HasIterator<false>) -> HasIterator<false> {
28 HasIterator::<false>
29 }
30}
31
32impl BitOr<HasIterator<false>> for HasIterator<true> {
33 type Output = HasIterator<true>;
34 fn bitor(self, _rhs: HasIterator<false>) -> HasIterator<true> {
35 HasIterator::<true>
36 }
37}
38
39impl BitOr<HasIterator<true>> for HasIterator<false> {
40 type Output = HasIterator<true>;
41 fn bitor(self, _rhs: HasIterator<true>) -> HasIterator<true> {
42 HasIterator::<true>
43 }
44}
45
46impl BitOr<HasIterator<true>> for HasIterator<true> {
47 type Output = HasIterator<true>;
48 fn bitor(self, _rhs: HasIterator<true>) -> HasIterator<true> {
49 HasIterator::<true>
50 }
51}
52
53#[doc(hidden)]
54#[cfg_attr(
55 not(no_diagnostic_namespace),
56 diagnostic::on_unimplemented(
57 message = "repetition contains no interpolated value that is an iterator",
58 label = "none of the values interpolated inside this repetition are iterable"
59 )
60)]
61pub trait CheckHasIterator<const B: bool>: Sized {
62 fn check(self) {}
63}
64
65impl CheckHasIterator<true> for HasIterator<true> {}
66
67#[doc(hidden)]
74pub mod ext {
75 use super::{HasIterator, RepInterp};
76 use crate::ToTokens;
77 use alloc::collections::btree_set::{self, BTreeSet};
78 use alloc::vec::Vec;
79 use core::slice;
80
81 #[doc(hidden)]
83 pub trait RepIteratorExt: Iterator + Sized {
84 fn quote_into_iter(self) -> (Self, HasIterator<true>) {
85 (self, HasIterator::<true>)
86 }
87 }
88
89 impl<T: Iterator> RepIteratorExt for T {}
90
91 #[doc(hidden)]
95 pub trait RepToTokensExt {
96 fn next(&self) -> Option<&Self> {
100 Some(self)
101 }
102
103 fn quote_into_iter(&self) -> (&Self, HasIterator<false>) {
104 (self, HasIterator::<false>)
105 }
106 }
107
108 impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
109
110 #[doc(hidden)]
113 pub trait RepAsIteratorExt<'q> {
114 type Iter: Iterator;
115
116 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>);
117 }
118
119 impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &T {
120 type Iter = T::Iter;
121
122 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
123 <T as RepAsIteratorExt>::quote_into_iter(*self)
124 }
125 }
126
127 impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &mut T {
128 type Iter = T::Iter;
129
130 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
131 <T as RepAsIteratorExt>::quote_into_iter(*self)
132 }
133 }
134
135 impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
136 type Iter = slice::Iter<'q, T>;
137
138 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
139 (self.iter(), HasIterator::<true>)
140 }
141 }
142
143 impl<'q, T: 'q, const N: usize> RepAsIteratorExt<'q> for [T; N] {
144 type Iter = slice::Iter<'q, T>;
145
146 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
147 (self.iter(), HasIterator::<true>)
148 }
149 }
150
151 impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
152 type Iter = slice::Iter<'q, T>;
153
154 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
155 (self.iter(), HasIterator::<true>)
156 }
157 }
158
159 impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
160 type Iter = btree_set::Iter<'q, T>;
161
162 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
163 (self.iter(), HasIterator::<true>)
164 }
165 }
166
167 impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
168 type Iter = T::Iter;
169
170 fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
171 self.0.quote_into_iter()
172 }
173 }
174}
175
176#[derive(Copy, Clone)]
179#[doc(hidden)]
180pub struct RepInterp<T>(pub T);
181
182impl<T> RepInterp<T> {
183 pub fn next(self) -> Option<T> {
188 Some(self.0)
189 }
190}
191
192impl<T: Iterator> Iterator for RepInterp<T> {
193 type Item = T::Item;
194
195 fn next(&mut self) -> Option<Self::Item> {
196 self.0.next()
197 }
198}
199
200impl<T: ToTokens> ToTokens for RepInterp<T> {
201 fn to_tokens(&self, tokens: &mut TokenStream) {
202 self.0.to_tokens(tokens);
203 }
204}
205
206#[doc(hidden)]
207#[inline]
208pub fn get_span<T>(span: T) -> GetSpan<T> {
209 GetSpan(GetSpanInner(GetSpanBase(span)))
210}
211
212mod get_span {
213 use core::ops::Deref;
214 use proc_macro2::extra::DelimSpan;
215 use proc_macro2::Span;
216
217 pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
218
219 pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
220
221 pub struct GetSpanBase<T>(pub(crate) T);
222
223 impl GetSpan<Span> {
224 #[inline]
225 pub fn __into_span(self) -> Span {
226 ((self.0).0).0
227 }
228 }
229
230 impl GetSpanInner<DelimSpan> {
231 #[inline]
232 pub fn __into_span(&self) -> Span {
233 (self.0).0.join()
234 }
235 }
236
237 impl<T> GetSpanBase<T> {
238 #[allow(clippy::unused_self)]
239 pub fn __into_span(&self) -> T {
240 unreachable!()
241 }
242 }
243
244 impl<T> Deref for GetSpan<T> {
245 type Target = GetSpanInner<T>;
246
247 #[inline]
248 fn deref(&self) -> &Self::Target {
249 &self.0
250 }
251 }
252
253 impl<T> Deref for GetSpanInner<T> {
254 type Target = GetSpanBase<T>;
255
256 #[inline]
257 fn deref(&self) -> &Self::Target {
258 &self.0
259 }
260 }
261}
262
263#[doc(hidden)]
264pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
265 tokens.append(Group::new(delimiter, inner));
266}
267
268#[doc(hidden)]
269pub fn push_group_spanned(
270 tokens: &mut TokenStream,
271 span: Span,
272 delimiter: Delimiter,
273 inner: TokenStream,
274) {
275 let mut g = Group::new(delimiter, inner);
276 g.set_span(span);
277 tokens.append(g);
278}
279
280#[doc(hidden)]
281pub fn parse(tokens: &mut TokenStream, s: &str) {
282 let s: TokenStream = s.parse().expect("invalid token stream");
283 tokens.extend(iter::once(s));
284}
285
286#[doc(hidden)]
287pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
288 let s: TokenStream = s.parse().expect("invalid token stream");
289 for token in s {
290 tokens.append(respan_token_tree(token, span));
291 }
292}
293
294fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
296 match &mut token {
297 TokenTree::Group(g) => {
298 let mut tokens = TokenStream::new();
299 for token in g.stream() {
300 tokens.append(respan_token_tree(token, span));
301 }
302 *g = Group::new(g.delimiter(), tokens);
303 g.set_span(span);
304 }
305 other => other.set_span(span),
306 }
307 token
308}
309
310#[doc(hidden)]
311pub fn push_ident(tokens: &mut TokenStream, s: &str) {
312 let span = Span::call_site();
313 push_ident_spanned(tokens, span, s);
314}
315
316#[doc(hidden)]
317pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
318 tokens.append(ident_maybe_raw(s, span));
319}
320
321#[doc(hidden)]
322pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
323 tokens.append(TokenTree::Punct(Punct::new('\'', Spacing::Joint)));
324 tokens.append(TokenTree::Ident(ident_maybe_raw(
325 &lifetime[1..],
326 Span::call_site(),
327 )));
328}
329
330#[doc(hidden)]
331pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
332 tokens.append(TokenTree::Punct({
333 let mut apostrophe = Punct::new('\'', Spacing::Joint);
334 apostrophe.set_span(span);
335 apostrophe
336 }));
337 tokens.append(TokenTree::Ident(ident_maybe_raw(&lifetime[1..], span)));
338}
339
340macro_rules! push_punct {
341 ($name:ident $spanned:ident $char1:tt) => {
342 #[doc(hidden)]
343 pub fn $name(tokens: &mut TokenStream) {
344 tokens.append(Punct::new($char1, Spacing::Alone));
345 }
346 #[doc(hidden)]
347 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
348 let mut punct = Punct::new($char1, Spacing::Alone);
349 punct.set_span(span);
350 tokens.append(punct);
351 }
352 };
353 ($name:ident $spanned:ident $char1:tt $char2:tt) => {
354 #[doc(hidden)]
355 pub fn $name(tokens: &mut TokenStream) {
356 tokens.append(Punct::new($char1, Spacing::Joint));
357 tokens.append(Punct::new($char2, Spacing::Alone));
358 }
359 #[doc(hidden)]
360 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
361 let mut punct = Punct::new($char1, Spacing::Joint);
362 punct.set_span(span);
363 tokens.append(punct);
364 let mut punct = Punct::new($char2, Spacing::Alone);
365 punct.set_span(span);
366 tokens.append(punct);
367 }
368 };
369 ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
370 #[doc(hidden)]
371 pub fn $name(tokens: &mut TokenStream) {
372 tokens.append(Punct::new($char1, Spacing::Joint));
373 tokens.append(Punct::new($char2, Spacing::Joint));
374 tokens.append(Punct::new($char3, Spacing::Alone));
375 }
376 #[doc(hidden)]
377 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
378 let mut punct = Punct::new($char1, Spacing::Joint);
379 punct.set_span(span);
380 tokens.append(punct);
381 let mut punct = Punct::new($char2, Spacing::Joint);
382 punct.set_span(span);
383 tokens.append(punct);
384 let mut punct = Punct::new($char3, Spacing::Alone);
385 punct.set_span(span);
386 tokens.append(punct);
387 }
388 };
389}
390
391push_punct!(push_add push_add_spanned '+');
392push_punct!(push_add_eq push_add_eq_spanned '+' '=');
393push_punct!(push_and push_and_spanned '&');
394push_punct!(push_and_and push_and_and_spanned '&' '&');
395push_punct!(push_and_eq push_and_eq_spanned '&' '=');
396push_punct!(push_at push_at_spanned '@');
397push_punct!(push_bang push_bang_spanned '!');
398push_punct!(push_caret push_caret_spanned '^');
399push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
400push_punct!(push_colon push_colon_spanned ':');
401push_punct!(push_colon2 push_colon2_spanned ':' ':');
402push_punct!(push_comma push_comma_spanned ',');
403push_punct!(push_div push_div_spanned '/');
404push_punct!(push_div_eq push_div_eq_spanned '/' '=');
405push_punct!(push_dot push_dot_spanned '.');
406push_punct!(push_dot2 push_dot2_spanned '.' '.');
407push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
408push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
409push_punct!(push_eq push_eq_spanned '=');
410push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
411push_punct!(push_ge push_ge_spanned '>' '=');
412push_punct!(push_gt push_gt_spanned '>');
413push_punct!(push_le push_le_spanned '<' '=');
414push_punct!(push_lt push_lt_spanned '<');
415push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
416push_punct!(push_ne push_ne_spanned '!' '=');
417push_punct!(push_or push_or_spanned '|');
418push_punct!(push_or_eq push_or_eq_spanned '|' '=');
419push_punct!(push_or_or push_or_or_spanned '|' '|');
420push_punct!(push_pound push_pound_spanned '#');
421push_punct!(push_question push_question_spanned '?');
422push_punct!(push_rarrow push_rarrow_spanned '-' '>');
423push_punct!(push_larrow push_larrow_spanned '<' '-');
424push_punct!(push_rem push_rem_spanned '%');
425push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
426push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
427push_punct!(push_semi push_semi_spanned ';');
428push_punct!(push_shl push_shl_spanned '<' '<');
429push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
430push_punct!(push_shr push_shr_spanned '>' '>');
431push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
432push_punct!(push_star push_star_spanned '*');
433push_punct!(push_sub push_sub_spanned '-');
434push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
435
436#[doc(hidden)]
437pub fn push_underscore(tokens: &mut TokenStream) {
438 push_underscore_spanned(tokens, Span::call_site());
439}
440
441#[doc(hidden)]
442pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
443 tokens.append(Ident::new("_", span));
444}
445
446#[doc(hidden)]
449pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
450 let span = span.unwrap_or_else(Span::call_site);
451 ident_maybe_raw(id, span)
452}
453
454fn ident_maybe_raw(id: &str, span: Span) -> Ident {
455 if let Some(id) = id.strip_prefix("r#") {
456 Ident::new_raw(id, span)
457 } else {
458 Ident::new(id, span)
459 }
460}
461
462#[derive(Copy, Clone)]
469#[doc(hidden)]
470pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
471
472impl<T: IdentFragment> IdentFragmentAdapter<T> {
473 pub fn span(&self) -> Option<Span> {
474 self.0.span()
475 }
476}
477
478impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
479 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480 IdentFragment::fmt(&self.0, f)
481 }
482}
483
484impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
485 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486 fmt::Octal::fmt(&self.0, f)
487 }
488}
489
490impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
491 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492 fmt::LowerHex::fmt(&self.0, f)
493 }
494}
495
496impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
497 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498 fmt::UpperHex::fmt(&self.0, f)
499 }
500}
501
502impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
503 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
504 fmt::Binary::fmt(&self.0, f)
505 }
506}