1use crate::ext::TokenStreamExt as _;
9use crate::Lifetime;
10use alloc::boxed::Box;
11use alloc::vec::Vec;
12use core::cmp::Ordering;
13use core::marker::PhantomData;
14use core::ptr;
15use proc_macro2::extra::DelimSpan;
16use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
17
18enum Entry {
21 Group(Group, usize),
24 Ident(Ident),
25 Punct(Punct),
26 Literal(Literal),
27 End(isize, isize),
30}
31
32pub struct TokenBuffer {
36 entries: Box<[Entry]>,
39}
40
41impl TokenBuffer {
42 fn recursive_new(entries: &mut Vec<Entry>, stream: TokenStream) {
43 for tt in stream {
44 match tt {
45 TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
46 TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
47 TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
48 TokenTree::Group(group) => {
49 let group_start_index = entries.len();
50 entries.push(Entry::End(0, 0)); Self::recursive_new(entries, group.stream());
52 let group_end_index = entries.len();
53 let group_offset = group_end_index - group_start_index;
54 entries.push(Entry::End(
55 -(group_end_index as isize),
56 -(group_offset as isize),
57 ));
58 entries[group_start_index] = Entry::Group(group, group_offset);
59 }
60 }
61 }
62 }
63
64 #[cfg(feature = "proc-macro")]
67 #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))]
68 pub fn new(stream: proc_macro::TokenStream) -> Self {
69 Self::new2(stream.into())
70 }
71
72 pub fn new2(stream: TokenStream) -> Self {
75 let mut entries = Vec::new();
76 Self::recursive_new(&mut entries, stream);
77 entries.push(Entry::End(-(entries.len() as isize), 0));
78 Self {
79 entries: entries.into_boxed_slice(),
80 }
81 }
82
83 pub fn begin(&self) -> Cursor {
86 let ptr = self.entries.as_ptr();
87 unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
88 }
89}
90
91pub struct Cursor<'a> {
100 ptr: *const Entry,
102 scope: *const Entry,
105 marker: PhantomData<&'a Entry>,
108}
109
110impl<'a> Cursor<'a> {
111 pub fn empty() -> Self {
113 struct UnsafeSyncEntry(Entry);
121 unsafe impl Sync for UnsafeSyncEntry {}
122 static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0, 0));
123
124 Cursor {
125 ptr: &EMPTY_ENTRY.0,
126 scope: &EMPTY_ENTRY.0,
127 marker: PhantomData,
128 }
129 }
130
131 unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
135 while let Entry::End(..) = unsafe { &*ptr } {
140 if ptr::eq(ptr, scope) {
141 break;
142 }
143 ptr = unsafe { ptr.add(1) };
144 }
145
146 Cursor {
147 ptr,
148 scope,
149 marker: PhantomData,
150 }
151 }
152
153 fn entry(self) -> &'a Entry {
155 unsafe { &*self.ptr }
156 }
157
158 unsafe fn bump_ignore_group(self) -> Cursor<'a> {
165 unsafe { Cursor::create(self.ptr.add(1), self.scope) }
166 }
167
168 fn ignore_none(&mut self) {
174 while let Entry::Group(group, _) = self.entry() {
175 if group.delimiter() == Delimiter::None {
176 unsafe { *self = self.bump_ignore_group() };
177 } else {
178 break;
179 }
180 }
181 }
182
183 pub fn eof(self) -> bool {
186 ptr::eq(self.ptr, self.scope)
188 }
189
190 pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
193 self.ignore_none();
194 match self.entry() {
195 Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
196 _ => None,
197 }
198 }
199
200 pub(crate) fn peek_keyword(mut self, token: &str) -> bool {
201 self.ignore_none();
202 match self.entry() {
203 Entry::Ident(ident) => ident == token,
204 _ => false,
205 }
206 }
207
208 pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
211 self.ignore_none();
212 match self.entry() {
213 Entry::Punct(punct) if punct.as_char() != '\'' => {
214 Some((punct.clone(), unsafe { self.bump_ignore_group() }))
215 }
216 _ => None,
217 }
218 }
219
220 pub(crate) fn peek_punct(mut self, token: &str) -> bool {
221 for (i, ch) in token.chars().enumerate() {
222 self.ignore_none();
223 match self.entry() {
224 Entry::Punct(punct) if punct.as_char() == ch => {
225 if i == token.len() - 1 {
226 return true;
227 } else if punct.spacing() != Spacing::Joint {
228 break;
229 }
230 self = unsafe { self.bump_ignore_group() };
231 }
232 _ => break,
233 }
234 }
235 false
236 }
237
238 pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
241 self.ignore_none();
242 match self.entry() {
243 Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
244 _ => None,
245 }
246 }
247
248 pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
251 self.ignore_none();
252 match self.entry() {
253 Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
254 let next = unsafe { self.bump_ignore_group() };
255 let (ident, rest) = next.ident()?;
256 let lifetime = Lifetime {
257 apostrophe: punct.span(),
258 ident,
259 };
260 Some((lifetime, rest))
261 }
262 _ => None,
263 }
264 }
265
266 pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> {
269 if delim != Delimiter::None {
273 self.ignore_none();
274 }
275
276 if let Entry::Group(group, end_offset) = self.entry() {
277 if group.delimiter() == delim {
278 let span = group.delim_span();
279 let end_of_group = unsafe { self.ptr.add(*end_offset) };
280 let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
281 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
282 return Some((inside_of_group, span, after_group));
283 }
284 }
285
286 None
287 }
288
289 pub fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> {
292 if let Entry::Group(group, end_offset) = self.entry() {
293 let delimiter = group.delimiter();
294 let span = group.delim_span();
295 let end_of_group = unsafe { self.ptr.add(*end_offset) };
296 let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
297 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
298 return Some((inside_of_group, delimiter, span, after_group));
299 }
300
301 None
302 }
303
304 pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> {
305 if let Entry::Group(group, end_offset) = self.entry() {
306 let end_of_group = unsafe { self.ptr.add(*end_offset) };
307 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
308 return Some((group.clone(), after_group));
309 }
310
311 None
312 }
313
314 pub fn token_stream(self) -> TokenStream {
317 let mut tokens = TokenStream::new();
318 let mut cursor = self;
319 while let Some((tt, rest)) = cursor.token_tree() {
320 tokens.append(tt);
321 cursor = rest;
322 }
323 tokens
324 }
325
326 pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
334 let (tree, len) = match self.entry() {
335 Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
336 Entry::Literal(literal) => (literal.clone().into(), 1),
337 Entry::Ident(ident) => (ident.clone().into(), 1),
338 Entry::Punct(punct) => (punct.clone().into(), 1),
339 Entry::End(..) => return None,
340 };
341
342 let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
343 Some((tree, rest))
344 }
345
346 pub fn span(mut self) -> Span {
349 match self.entry() {
350 Entry::Group(group, _) => group.span(),
351 Entry::Literal(literal) => literal.span(),
352 Entry::Ident(ident) => ident.span(),
353 Entry::Punct(punct) => punct.span(),
354 Entry::End(_, offset) => {
355 self.ptr = unsafe { self.ptr.offset(*offset) };
356 if let Entry::Group(group, _) = self.entry() {
357 group.span_close()
358 } else {
359 Span::call_site()
360 }
361 }
362 }
363 }
364
365 pub fn prev_span(mut self) -> Span {
368 if start_of_buffer(self) < self.ptr {
369 self.ptr = unsafe { self.ptr.sub(1) };
370 }
371 self.span()
372 }
373
374 pub(crate) fn skip(mut self) -> Option<Cursor<'a>> {
379 self.ignore_none();
380
381 let len = match self.entry() {
382 Entry::End(..) => return None,
383
384 Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
386 match unsafe { &*self.ptr.add(1) } {
387 Entry::Ident(_) => 2,
388 _ => 1,
389 }
390 }
391
392 Entry::Group(_, end_offset) => *end_offset,
393 _ => 1,
394 };
395
396 Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
397 }
398
399 pub(crate) fn scope_delimiter(self) -> Delimiter {
400 match unsafe { &*self.scope } {
401 Entry::End(_, offset) => match unsafe { &*self.scope.offset(*offset) } {
402 Entry::Group(group, _) => group.delimiter(),
403 _ => Delimiter::None,
404 },
405 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
406 }
407 }
408}
409
410impl<'a> Copy for Cursor<'a> {}
411
412impl<'a> Clone for Cursor<'a> {
413 fn clone(&self) -> Self {
414 *self
415 }
416}
417
418impl<'a> Eq for Cursor<'a> {}
419
420impl<'a> PartialEq for Cursor<'a> {
421 fn eq(&self, other: &Self) -> bool {
422 ptr::eq(self.ptr, other.ptr)
423 }
424}
425
426impl<'a> PartialOrd for Cursor<'a> {
427 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
428 if same_buffer(*self, *other) {
429 Some(cmp_assuming_same_buffer(*self, *other))
430 } else {
431 None
432 }
433 }
434}
435
436pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
437 ptr::eq(a.scope, b.scope)
438}
439
440pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool {
441 ptr::eq(start_of_buffer(a), start_of_buffer(b))
442}
443
444fn start_of_buffer(cursor: Cursor) -> *const Entry {
445 unsafe {
446 match &*cursor.scope {
447 Entry::End(offset, _) => cursor.scope.offset(*offset),
448 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
449 }
450 }
451}
452
453pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering {
454 a.ptr.cmp(&b.ptr)
455}
456
457pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
458 match cursor.entry() {
459 Entry::Group(group, _) => group.span_open(),
460 _ => cursor.span(),
461 }
462}