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 fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
203 self.ignore_none();
204 match self.entry() {
205 Entry::Punct(punct) if punct.as_char() != '\'' => {
206 Some((punct.clone(), unsafe { self.bump_ignore_group() }))
207 }
208 _ => None,
209 }
210 }
211
212 pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
215 self.ignore_none();
216 match self.entry() {
217 Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
218 _ => None,
219 }
220 }
221
222 pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
225 self.ignore_none();
226 match self.entry() {
227 Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
228 let next = unsafe { self.bump_ignore_group() };
229 let (ident, rest) = next.ident()?;
230 let lifetime = Lifetime {
231 apostrophe: punct.span(),
232 ident,
233 };
234 Some((lifetime, rest))
235 }
236 _ => None,
237 }
238 }
239
240 pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> {
243 if delim != Delimiter::None {
247 self.ignore_none();
248 }
249
250 if let Entry::Group(group, end_offset) = self.entry() {
251 if group.delimiter() == delim {
252 let span = group.delim_span();
253 let end_of_group = unsafe { self.ptr.add(*end_offset) };
254 let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
255 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
256 return Some((inside_of_group, span, after_group));
257 }
258 }
259
260 None
261 }
262
263 pub fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> {
266 if let Entry::Group(group, end_offset) = self.entry() {
267 let delimiter = group.delimiter();
268 let span = group.delim_span();
269 let end_of_group = unsafe { self.ptr.add(*end_offset) };
270 let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
271 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
272 return Some((inside_of_group, delimiter, span, after_group));
273 }
274
275 None
276 }
277
278 pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> {
279 if let Entry::Group(group, end_offset) = self.entry() {
280 let end_of_group = unsafe { self.ptr.add(*end_offset) };
281 let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
282 return Some((group.clone(), after_group));
283 }
284
285 None
286 }
287
288 pub fn token_stream(self) -> TokenStream {
291 let mut tokens = TokenStream::new();
292 let mut cursor = self;
293 while let Some((tt, rest)) = cursor.token_tree() {
294 tokens.append(tt);
295 cursor = rest;
296 }
297 tokens
298 }
299
300 pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
308 let (tree, len) = match self.entry() {
309 Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
310 Entry::Literal(literal) => (literal.clone().into(), 1),
311 Entry::Ident(ident) => (ident.clone().into(), 1),
312 Entry::Punct(punct) => (punct.clone().into(), 1),
313 Entry::End(..) => return None,
314 };
315
316 let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
317 Some((tree, rest))
318 }
319
320 pub fn span(mut self) -> Span {
323 match self.entry() {
324 Entry::Group(group, _) => group.span(),
325 Entry::Literal(literal) => literal.span(),
326 Entry::Ident(ident) => ident.span(),
327 Entry::Punct(punct) => punct.span(),
328 Entry::End(_, offset) => {
329 self.ptr = unsafe { self.ptr.offset(*offset) };
330 if let Entry::Group(group, _) = self.entry() {
331 group.span_close()
332 } else {
333 Span::call_site()
334 }
335 }
336 }
337 }
338
339 #[cfg(any(feature = "full", feature = "derive"))]
342 pub(crate) fn prev_span(mut self) -> Span {
343 if start_of_buffer(self) < self.ptr {
344 self.ptr = unsafe { self.ptr.sub(1) };
345 }
346 self.span()
347 }
348
349 pub(crate) fn skip(mut self) -> Option<Cursor<'a>> {
354 self.ignore_none();
355
356 let len = match self.entry() {
357 Entry::End(..) => return None,
358
359 Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
361 match unsafe { &*self.ptr.add(1) } {
362 Entry::Ident(_) => 2,
363 _ => 1,
364 }
365 }
366
367 Entry::Group(_, end_offset) => *end_offset,
368 _ => 1,
369 };
370
371 Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
372 }
373
374 pub(crate) fn scope_delimiter(self) -> Delimiter {
375 match unsafe { &*self.scope } {
376 Entry::End(_, offset) => match unsafe { &*self.scope.offset(*offset) } {
377 Entry::Group(group, _) => group.delimiter(),
378 _ => Delimiter::None,
379 },
380 _ => unreachable!(),
381 }
382 }
383}
384
385impl<'a> Copy for Cursor<'a> {}
386
387impl<'a> Clone for Cursor<'a> {
388 fn clone(&self) -> Self {
389 *self
390 }
391}
392
393impl<'a> Eq for Cursor<'a> {}
394
395impl<'a> PartialEq for Cursor<'a> {
396 fn eq(&self, other: &Self) -> bool {
397 ptr::eq(self.ptr, other.ptr)
398 }
399}
400
401impl<'a> PartialOrd for Cursor<'a> {
402 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
403 if same_buffer(*self, *other) {
404 Some(cmp_assuming_same_buffer(*self, *other))
405 } else {
406 None
407 }
408 }
409}
410
411pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
412 ptr::eq(a.scope, b.scope)
413}
414
415pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool {
416 ptr::eq(start_of_buffer(a), start_of_buffer(b))
417}
418
419fn start_of_buffer(cursor: Cursor) -> *const Entry {
420 unsafe {
421 match &*cursor.scope {
422 Entry::End(offset, _) => cursor.scope.offset(*offset),
423 _ => unreachable!(),
424 }
425 }
426}
427
428pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering {
429 a.ptr.cmp(&b.ptr)
430}
431
432pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
433 match cursor.entry() {
434 Entry::Group(group, _) => group.span_open(),
435 _ => cursor.span(),
436 }
437}