• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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