1 use crate::{IdentFragment, ToTokens, TokenStreamExt};
2 use std::fmt;
3 use std::ops::BitOr;
4
5 pub use proc_macro2::*;
6
7 pub struct HasIterator; // True
8 pub struct ThereIsNoIteratorInRepetition; // False
9
10 impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
11 type Output = ThereIsNoIteratorInRepetition;
bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition12 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
13 ThereIsNoIteratorInRepetition
14 }
15 }
16
17 impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
18 type Output = HasIterator;
bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator19 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
20 HasIterator
21 }
22 }
23
24 impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
25 type Output = HasIterator;
bitor(self, _rhs: HasIterator) -> HasIterator26 fn bitor(self, _rhs: HasIterator) -> HasIterator {
27 HasIterator
28 }
29 }
30
31 impl BitOr<HasIterator> for HasIterator {
32 type Output = HasIterator;
bitor(self, _rhs: HasIterator) -> HasIterator33 fn bitor(self, _rhs: HasIterator) -> HasIterator {
34 HasIterator
35 }
36 }
37
38 /// Extension traits used by the implementation of `quote!`. These are defined
39 /// in separate traits, rather than as a single trait due to ambiguity issues.
40 ///
41 /// These traits expose a `quote_into_iter` method which should allow calling
42 /// whichever impl happens to be applicable. Calling that method repeatedly on
43 /// the returned value should be idempotent.
44 pub 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 /// Extension trait providing the `quote_into_iter` method on iterators.
52 pub trait RepIteratorExt: Iterator + Sized {
quote_into_iter(self) -> (Self, HasIter)53 fn quote_into_iter(self) -> (Self, HasIter) {
54 (self, HasIter)
55 }
56 }
57
58 impl<T: Iterator> RepIteratorExt for T {}
59
60 /// Extension trait providing the `quote_into_iter` method for
61 /// non-iterable types. These types interpolate the same value in each
62 /// iteration of the repetition.
63 pub trait RepToTokensExt {
64 /// Pretend to be an iterator for the purposes of `quote_into_iter`.
65 /// This allows repeated calls to `quote_into_iter` to continue
66 /// correctly returning DoesNotHaveIter.
next(&self) -> Option<&Self>67 fn next(&self) -> Option<&Self> {
68 Some(self)
69 }
70
quote_into_iter(&self) -> (&Self, DoesNotHaveIter)71 fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
72 (self, DoesNotHaveIter)
73 }
74 }
75
76 impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
77
78 /// Extension trait providing the `quote_into_iter` method for types that
79 /// can be referenced as an iterator.
80 pub trait RepAsIteratorExt<'q> {
81 type Iter: Iterator;
82
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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
quote_into_iter(&'q self) -> (Self::Iter, HasIter)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 pub struct RepInterp<T>(pub T);
158
159 impl<T> RepInterp<T> {
160 // This method is intended to look like `Iterator::next`, and is called when
161 // a name is bound multiple times, as the previous binding will shadow the
162 // original `Iterator` object. This allows us to avoid advancing the
163 // iterator multiple times per iteration.
next(self) -> Option<T>164 pub fn next(self) -> Option<T> {
165 Some(self.0)
166 }
167 }
168
169 impl<T: Iterator> Iterator for RepInterp<T> {
170 type Item = T::Item;
171
next(&mut self) -> Option<Self::Item>172 fn next(&mut self) -> Option<Self::Item> {
173 self.0.next()
174 }
175 }
176
177 impl<T: ToTokens> ToTokens for RepInterp<T> {
to_tokens(&self, tokens: &mut TokenStream)178 fn to_tokens(&self, tokens: &mut TokenStream) {
179 self.0.to_tokens(tokens);
180 }
181 }
182
is_ident_start(c: u8) -> bool183 fn is_ident_start(c: u8) -> bool {
184 (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_'
185 }
186
is_ident_continue(c: u8) -> bool187 fn 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
is_ident(token: &str) -> bool191 fn 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
parse(tokens: &mut TokenStream, span: Span, s: &str)198 pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) {
199 if is_ident(s) {
200 // Fast path, since idents are the most common token.
201 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
211 macro_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
244 push_punct!(push_add '+');
245 push_punct!(push_add_eq '+' '=');
246 push_punct!(push_and '&');
247 push_punct!(push_and_and '&' '&');
248 push_punct!(push_and_eq '&' '=');
249 push_punct!(push_at '@');
250 push_punct!(push_bang '!');
251 push_punct!(push_caret '^');
252 push_punct!(push_caret_eq '^' '=');
253 push_punct!(push_colon ':');
254 push_punct!(push_colon2 ':' ':');
255 push_punct!(push_comma ',');
256 push_punct!(push_div '/');
257 push_punct!(push_div_eq '/' '=');
258 push_punct!(push_dot '.');
259 push_punct!(push_dot2 '.' '.');
260 push_punct!(push_dot3 '.' '.' '.');
261 push_punct!(push_dot_dot_eq '.' '.' '=');
262 push_punct!(push_eq '=');
263 push_punct!(push_eq_eq '=' '=');
264 push_punct!(push_ge '>' '=');
265 push_punct!(push_gt '>');
266 push_punct!(push_le '<' '=');
267 push_punct!(push_lt '<');
268 push_punct!(push_mul_eq '*' '=');
269 push_punct!(push_ne '!' '=');
270 push_punct!(push_or '|');
271 push_punct!(push_or_eq '|' '=');
272 push_punct!(push_or_or '|' '|');
273 push_punct!(push_pound '#');
274 push_punct!(push_question '?');
275 push_punct!(push_rarrow '-' '>');
276 push_punct!(push_larrow '<' '-');
277 push_punct!(push_rem '%');
278 push_punct!(push_rem_eq '%' '=');
279 push_punct!(push_fat_arrow '=' '>');
280 push_punct!(push_semi ';');
281 push_punct!(push_shl '<' '<');
282 push_punct!(push_shl_eq '<' '<' '=');
283 push_punct!(push_shr '>' '>');
284 push_punct!(push_shr_eq '>' '>' '=');
285 push_punct!(push_star '*');
286 push_punct!(push_sub '-');
287 push_punct!(push_sub_eq '-' '=');
288
289 // Helper method for constructing identifiers from the `format_ident!` macro,
290 // handling `r#` prefixes.
291 //
292 // Directly parsing the input string may produce a valid identifier,
293 // although the input string was invalid, due to ignored characters such as
294 // whitespace and comments. Instead, we always create a non-raw identifier
295 // to validate that the string is OK, and only parse again if needed.
296 //
297 // The `is_ident` method defined above is insufficient for validation, as it
298 // will reject non-ASCII identifiers.
mk_ident(id: &str, span: Option<Span>) -> Ident299 pub 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 // At this point, the identifier is raw, and the unraw-ed version of it was
309 // successfully converted into an identifier. Try to produce a valid raw
310 // identifier by running the `TokenStream` parser, and unwrapping the first
311 // token as an `Ident`.
312 //
313 // FIXME: When `Ident::new_raw` becomes stable, this method should be
314 // updated to call it when available.
315 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 // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
331 // macro, and exposes span information from these fragments.
332 //
333 // This struct also has forwarding implementations of the formatting traits
334 // `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
335 // `format_ident!`.
336 #[derive(Copy, Clone)]
337 pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
338
339 impl<T: IdentFragment> IdentFragmentAdapter<T> {
span(&self) -> Option<Span>340 pub fn span(&self) -> Option<Span> {
341 self.0.span()
342 }
343 }
344
345 impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 IdentFragment::fmt(&self.0, f)
348 }
349 }
350
351 impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result352 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 fmt::Octal::fmt(&self.0, f)
354 }
355 }
356
357 impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result358 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359 fmt::LowerHex::fmt(&self.0, f)
360 }
361 }
362
363 impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result364 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
365 fmt::UpperHex::fmt(&self.0, f)
366 }
367 }
368
369 impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result370 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
371 fmt::Binary::fmt(&self.0, f)
372 }
373 }
374