1use crate::{IdentFragment, ToTokens, TokenStreamExt};
2use std::fmt;
3use std::ops::BitOr;
4
5pub use proc_macro2::*;
6
7pub struct HasIterator; pub struct ThereIsNoIteratorInRepetition; impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
11 type Output = ThereIsNoIteratorInRepetition;
12 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
13 ThereIsNoIteratorInRepetition
14 }
15}
16
17impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
18 type Output = HasIterator;
19 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
20 HasIterator
21 }
22}
23
24impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
25 type Output = HasIterator;
26 fn bitor(self, _rhs: HasIterator) -> HasIterator {
27 HasIterator
28 }
29}
30
31impl BitOr<HasIterator> for HasIterator {
32 type Output = HasIterator;
33 fn bitor(self, _rhs: HasIterator) -> HasIterator {
34 HasIterator
35 }
36}
37
38pub mod ext {
45 use super::RepInterp;
46 use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
47 use crate::ToTokens;
48 use std::collections::btree_set::{self, BTreeSet};
49 use std::slice;
50
51 pub trait RepIteratorExt: Iterator + Sized {
53 fn quote_into_iter(self) -> (Self, HasIter) {
54 (self, HasIter)
55 }
56 }
57
58 impl<T: Iterator> RepIteratorExt for T {}
59
60 pub trait RepToTokensExt {
64 fn next(&self) -> Option<&Self> {
68 Some(self)
69 }
70
71 fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
72 (self, DoesNotHaveIter)
73 }
74 }
75
76 impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
77
78 pub trait RepAsIteratorExt<'q> {
81 type Iter: Iterator;
82
83 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
84 }
85
86 impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T {
87 type Iter = T::Iter;
88
89 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
90 <T as RepAsIteratorExt>::quote_into_iter(*self)
91 }
92 }
93
94 impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T {
95 type Iter = T::Iter;
96
97 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
98 <T as RepAsIteratorExt>::quote_into_iter(*self)
99 }
100 }
101
102 impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
103 type Iter = slice::Iter<'q, T>;
104
105 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
106 (self.iter(), HasIter)
107 }
108 }
109
110 impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
111 type Iter = slice::Iter<'q, T>;
112
113 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
114 (self.iter(), HasIter)
115 }
116 }
117
118 impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
119 type Iter = btree_set::Iter<'q, T>;
120
121 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
122 (self.iter(), HasIter)
123 }
124 }
125
126 macro_rules! array_rep_slice {
127 ($($l:tt)*) => {
128 $(
129 impl<'q, T: 'q> RepAsIteratorExt<'q> for [T; $l] {
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 }
138 }
139
140 array_rep_slice!(
141 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
142 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
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#[derive(Copy, Clone)]
157pub struct RepInterp<T>(pub T);
158
159impl<T> RepInterp<T> {
160 pub fn next(self) -> Option<T> {
165 Some(self.0)
166 }
167}
168
169impl<T: Iterator> Iterator for RepInterp<T> {
170 type Item = T::Item;
171
172 fn next(&mut self) -> Option<Self::Item> {
173 self.0.next()
174 }
175}
176
177impl<T: ToTokens> ToTokens for RepInterp<T> {
178 fn to_tokens(&self, tokens: &mut TokenStream) {
179 self.0.to_tokens(tokens);
180 }
181}
182
183fn is_ident_start(c: u8) -> bool {
184 (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_'
185}
186
187fn is_ident_continue(c: u8) -> bool {
188 (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' || (b'0' <= c && c <= b'9')
189}
190
191fn is_ident(token: &str) -> bool {
192 let mut iter = token.bytes();
193 let first_ok = iter.next().map(is_ident_start).unwrap_or(false);
194
195 first_ok && iter.all(is_ident_continue)
196}
197
198pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) {
199 if is_ident(s) {
200 tokens.append(Ident::new(s, span));
202 } else {
203 let s: TokenStream = s.parse().expect("invalid token stream");
204 tokens.extend(s.into_iter().map(|mut t| {
205 t.set_span(span);
206 t
207 }));
208 }
209}
210
211macro_rules! push_punct {
212 ($name:ident $char1:tt) => {
213 pub fn $name(tokens: &mut TokenStream, span: Span) {
214 let mut punct = Punct::new($char1, Spacing::Alone);
215 punct.set_span(span);
216 tokens.append(punct);
217 }
218 };
219 ($name:ident $char1:tt $char2:tt) => {
220 pub fn $name(tokens: &mut TokenStream, span: Span) {
221 let mut punct = Punct::new($char1, Spacing::Joint);
222 punct.set_span(span);
223 tokens.append(punct);
224 let mut punct = Punct::new($char2, Spacing::Alone);
225 punct.set_span(span);
226 tokens.append(punct);
227 }
228 };
229 ($name:ident $char1:tt $char2:tt $char3:tt) => {
230 pub fn $name(tokens: &mut TokenStream, span: Span) {
231 let mut punct = Punct::new($char1, Spacing::Joint);
232 punct.set_span(span);
233 tokens.append(punct);
234 let mut punct = Punct::new($char2, Spacing::Joint);
235 punct.set_span(span);
236 tokens.append(punct);
237 let mut punct = Punct::new($char3, Spacing::Alone);
238 punct.set_span(span);
239 tokens.append(punct);
240 }
241 };
242}
243
244push_punct!(push_add '+');
245push_punct!(push_add_eq '+' '=');
246push_punct!(push_and '&');
247push_punct!(push_and_and '&' '&');
248push_punct!(push_and_eq '&' '=');
249push_punct!(push_at '@');
250push_punct!(push_bang '!');
251push_punct!(push_caret '^');
252push_punct!(push_caret_eq '^' '=');
253push_punct!(push_colon ':');
254push_punct!(push_colon2 ':' ':');
255push_punct!(push_comma ',');
256push_punct!(push_div '/');
257push_punct!(push_div_eq '/' '=');
258push_punct!(push_dot '.');
259push_punct!(push_dot2 '.' '.');
260push_punct!(push_dot3 '.' '.' '.');
261push_punct!(push_dot_dot_eq '.' '.' '=');
262push_punct!(push_eq '=');
263push_punct!(push_eq_eq '=' '=');
264push_punct!(push_ge '>' '=');
265push_punct!(push_gt '>');
266push_punct!(push_le '<' '=');
267push_punct!(push_lt '<');
268push_punct!(push_mul_eq '*' '=');
269push_punct!(push_ne '!' '=');
270push_punct!(push_or '|');
271push_punct!(push_or_eq '|' '=');
272push_punct!(push_or_or '|' '|');
273push_punct!(push_pound '#');
274push_punct!(push_question '?');
275push_punct!(push_rarrow '-' '>');
276push_punct!(push_larrow '<' '-');
277push_punct!(push_rem '%');
278push_punct!(push_rem_eq '%' '=');
279push_punct!(push_fat_arrow '=' '>');
280push_punct!(push_semi ';');
281push_punct!(push_shl '<' '<');
282push_punct!(push_shl_eq '<' '<' '=');
283push_punct!(push_shr '>' '>');
284push_punct!(push_shr_eq '>' '>' '=');
285push_punct!(push_star '*');
286push_punct!(push_sub '-');
287push_punct!(push_sub_eq '-' '=');
288
289pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
300 let span = span.unwrap_or_else(Span::call_site);
301
302 let is_raw = id.starts_with("r#");
303 let unraw = Ident::new(if is_raw { &id[2..] } else { id }, span);
304 if !is_raw {
305 return unraw;
306 }
307
308 match id.parse::<TokenStream>() {
316 Ok(ts) => {
317 let mut iter = ts.into_iter();
318 match (iter.next(), iter.next()) {
319 (Some(TokenTree::Ident(mut id)), None) => {
320 id.set_span(span);
321 id
322 }
323 _ => unreachable!("valid raw ident fails to parse"),
324 }
325 }
326 Err(_) => unreachable!("valid raw ident fails to parse"),
327 }
328}
329
330#[derive(Copy, Clone)]
337pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
338
339impl<T: IdentFragment> IdentFragmentAdapter<T> {
340 pub fn span(&self) -> Option<Span> {
341 self.0.span()
342 }
343}
344
345impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 IdentFragment::fmt(&self.0, f)
348 }
349}
350
351impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
352 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 fmt::Octal::fmt(&self.0, f)
354 }
355}
356
357impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
358 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359 fmt::LowerHex::fmt(&self.0, f)
360 }
361}
362
363impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
364 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
365 fmt::UpperHex::fmt(&self.0, f)
366 }
367}
368
369impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
370 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
371 fmt::Binary::fmt(&self.0, f)
372 }
373}