1#[cfg(wrap_proc_macro)]
2use crate::imp;
3#[cfg(span_locations)]
4use crate::location::LineColumn;
5use crate::parse::{self, Cursor};
6use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
7use crate::{Delimiter, Spacing, TokenTree};
8use alloc::borrow::ToOwned as _;
9use alloc::boxed::Box;
10#[cfg(all(span_locations, not(fuzzing)))]
11use alloc::collections::BTreeMap;
12use alloc::format;
13use alloc::string::{String, ToString as _};
14#[cfg(all(span_locations, not(fuzzing)))]
15use alloc::vec;
16use alloc::vec::Vec;
17#[cfg(all(span_locations, not(fuzzing)))]
18use core::cell::RefCell;
19#[cfg(span_locations)]
20use core::cmp;
21#[cfg(all(span_locations, not(fuzzing)))]
22use core::cmp::Ordering;
23use core::ffi::CStr;
24use core::fmt::{self, Debug, Display, Write};
25use core::mem::ManuallyDrop;
26#[cfg(span_locations)]
27use core::ops::Range;
28use core::ops::RangeBounds;
29use core::ptr;
30use core::str;
31#[cfg(feature = "proc-macro")]
32use core::str::FromStr;
33#[cfg(wrap_proc_macro)]
34use std::panic;
35#[cfg(span_locations)]
36use std::path::PathBuf;
37#[cfg(all(span_locations, not(fuzzing)))]
38use std::thread_local;
39
40pub fn force() {
43 #[cfg(wrap_proc_macro)]
44 crate::detection::force_fallback();
45}
46
47pub fn unforce() {
50 #[cfg(wrap_proc_macro)]
51 crate::detection::unforce_fallback();
52}
53
54#[derive(#[automatically_derived]
impl ::core::clone::Clone for TokenStream {
#[inline]
fn clone(&self) -> TokenStream {
TokenStream { inner: ::core::clone::Clone::clone(&self.inner) }
}
}Clone)]
55pub(crate) struct TokenStream {
56 inner: RcVec<TokenTree>,
57}
58
59#[derive(#[automatically_derived]
impl ::core::fmt::Debug for LexError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "LexError",
"span", &&self.span)
}
}Debug)]
60pub(crate) struct LexError {
61 pub(crate) span: Span,
62}
63
64impl LexError {
65 pub(crate) fn span(&self) -> Span {
66 self.span
67 }
68
69 pub(crate) fn call_site() -> Self {
70 LexError {
71 span: Span::call_site(),
72 }
73 }
74}
75
76impl TokenStream {
77 pub(crate) fn new() -> Self {
78 TokenStream {
79 inner: RcVecBuilder::new().build(),
80 }
81 }
82
83 pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> {
84 let mut cursor = get_cursor(src);
86
87 const BYTE_ORDER_MARK: &str = "\u{feff}";
89 if cursor.starts_with(BYTE_ORDER_MARK) {
90 cursor = cursor.advance(BYTE_ORDER_MARK.len());
91 }
92
93 parse::token_stream(cursor)
94 }
95
96 #[cfg(feature = "proc-macro")]
97 pub(crate) fn from_str_unchecked(src: &str) -> Self {
98 Self::from_str_checked(src).unwrap()
99 }
100
101 pub(crate) fn is_empty(&self) -> bool {
102 self.inner.len() == 0
103 }
104
105 fn take_inner(self) -> RcVecBuilder<TokenTree> {
106 let nodrop = ManuallyDrop::new(self);
107 unsafe { ptr::read(&nodrop.inner) }.make_owned()
108 }
109}
110
111fn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) {
112 match token {
114 TokenTree::Literal(crate::Literal {
115 #[cfg(wrap_proc_macro)]
116 inner: crate::imp::Literal::Fallback(literal),
117 #[cfg(not(wrap_proc_macro))]
118 inner: literal,
119 ..
120 }) if literal.repr.starts_with('-') => {
121 push_negative_literal(vec, literal);
122 }
123 _ => vec.push(token),
124 }
125
126 #[cold]
127 fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
128 literal.repr.remove(0);
129 let mut punct = crate::Punct::new('-', Spacing::Alone);
130 punct.set_span(crate::Span::_new_fallback(literal.span));
131 vec.push(TokenTree::Punct(punct));
132 vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
133 }
134}
135
136impl Drop for TokenStream {
138 fn drop(&mut self) {
139 let mut stack = Vec::new();
140 let mut current = match self.inner.get_mut() {
141 Some(inner) => inner.take().into_iter(),
142 None => return,
143 };
144 loop {
145 while let Some(token) = current.next() {
146 let group = match token {
147 TokenTree::Group(group) => group.inner,
148 _ => continue,
149 };
150 #[cfg(wrap_proc_macro)]
151 let group = match group {
152 crate::imp::Group::Fallback(group) => group,
153 crate::imp::Group::Compiler(_) => continue,
154 };
155 let mut group = group;
156 if let Some(inner) = group.stream.inner.get_mut() {
157 stack.push(current);
158 current = inner.take().into_iter();
159 }
160 }
161 match stack.pop() {
162 Some(next) => current = next,
163 None => return,
164 }
165 }
166 }
167}
168
169pub(crate) struct TokenStreamBuilder {
170 inner: RcVecBuilder<TokenTree>,
171}
172
173impl TokenStreamBuilder {
174 pub(crate) fn new() -> Self {
175 TokenStreamBuilder {
176 inner: RcVecBuilder::new(),
177 }
178 }
179
180 pub(crate) fn with_capacity(cap: usize) -> Self {
181 TokenStreamBuilder {
182 inner: RcVecBuilder::with_capacity(cap),
183 }
184 }
185
186 pub(crate) fn push_token_from_parser(&mut self, tt: TokenTree) {
187 self.inner.push(tt);
188 }
189
190 pub(crate) fn build(self) -> TokenStream {
191 TokenStream {
192 inner: self.inner.build(),
193 }
194 }
195}
196
197#[cfg(span_locations)]
198fn get_cursor(src: &str) -> Cursor {
199 #[cfg(fuzzing)]
200 return Cursor { rest: src, off: 1 };
201
202 #[cfg(not(fuzzing))]
204 SOURCE_MAP.with(|sm| {
205 let mut sm = sm.borrow_mut();
206 let span = sm.add_file(src);
207 Cursor {
208 rest: src,
209 off: span.lo,
210 }
211 })
212}
213
214#[cfg(not(span_locations))]
215fn get_cursor(src: &str) -> Cursor {
216 Cursor { rest: src }
217}
218
219impl Display for LexError {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 f.write_str("cannot parse string into token stream")
222 }
223}
224
225impl Display for TokenStream {
226 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227 let mut joint = false;
228 for (i, tt) in self.inner.iter().enumerate() {
229 if i != 0 && !joint {
230 f.write_fmt(format_args!(" "))write!(f, " ")?;
231 }
232 joint = false;
233 match tt {
234 TokenTree::Group(tt) => f.write_fmt(format_args!("{0}", tt))write!(f, "{}", tt),
235 TokenTree::Ident(tt) => f.write_fmt(format_args!("{0}", tt))write!(f, "{}", tt),
236 TokenTree::Punct(tt) => {
237 joint = tt.spacing() == Spacing::Joint;
238 f.write_fmt(format_args!("{0}", tt))write!(f, "{}", tt)
239 }
240 TokenTree::Literal(tt) => f.write_fmt(format_args!("{0}", tt))write!(f, "{}", tt),
241 }?;
242 }
243
244 Ok(())
245 }
246}
247
248impl Debug for TokenStream {
249 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250 f.write_str("TokenStream ")?;
251 f.debug_list().entries(self.clone()).finish()
252 }
253}
254
255#[cfg(feature = "proc-macro")]
256impl From<proc_macro::TokenStream> for TokenStream {
257 fn from(inner: proc_macro::TokenStream) -> Self {
258 TokenStream::from_str_unchecked(&inner.to_string())
259 }
260}
261
262#[cfg(feature = "proc-macro")]
263impl From<TokenStream> for proc_macro::TokenStream {
264 fn from(inner: TokenStream) -> Self {
265 proc_macro::TokenStream::from_str_unchecked(&inner.to_string())
266 }
267}
268
269impl From<TokenTree> for TokenStream {
270 fn from(tree: TokenTree) -> Self {
271 let mut stream = RcVecBuilder::new();
272 push_token_from_proc_macro(stream.as_mut(), tree);
273 TokenStream {
274 inner: stream.build(),
275 }
276 }
277}
278
279impl FromIterator<TokenTree> for TokenStream {
280 fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
281 let mut stream = TokenStream::new();
282 stream.extend(tokens);
283 stream
284 }
285}
286
287impl FromIterator<TokenStream> for TokenStream {
288 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
289 let mut v = RcVecBuilder::new();
290
291 for stream in streams {
292 v.extend(stream.take_inner());
293 }
294
295 TokenStream { inner: v.build() }
296 }
297}
298
299impl Extend<TokenTree> for TokenStream {
300 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
301 let mut vec = self.inner.make_mut();
302 tokens
303 .into_iter()
304 .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token));
305 }
306}
307
308impl Extend<TokenStream> for TokenStream {
309 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
310 self.inner.make_mut().extend(streams.into_iter().flatten());
311 }
312}
313
314pub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>;
315
316impl IntoIterator for TokenStream {
317 type Item = TokenTree;
318 type IntoIter = TokenTreeIter;
319
320 fn into_iter(self) -> TokenTreeIter {
321 self.take_inner().into_iter()
322 }
323}
324
325#[cfg(all(span_locations, not(fuzzing)))]
326const SOURCE_MAP: ::std::thread::LocalKey<RefCell<SourceMap>> =
{
#[inline]
fn __rust_std_internal_init_fn() -> RefCell<SourceMap> {
RefCell::new(SourceMap {
files: <[_]>::into_vec(::alloc::boxed::box_new([FileInfo {
source_text: String::new(),
span: Span { lo: 0, hi: 0 },
lines: <[_]>::into_vec(::alloc::boxed::box_new([0])),
char_index_to_byte_offset: BTreeMap::new(),
}])),
})
}
unsafe {
::std::thread::LocalKey::new(const {
if ::std::mem::needs_drop::<RefCell<SourceMap>>() {
|__rust_std_internal_init|
{
#[thread_local]
static __RUST_STD_INTERNAL_VAL:
::std::thread::local_impl::LazyStorage<RefCell<SourceMap>,
()> =
::std::thread::local_impl::LazyStorage::new();
__RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init,
__rust_std_internal_init_fn)
}
} else {
|__rust_std_internal_init|
{
#[thread_local]
static __RUST_STD_INTERNAL_VAL:
::std::thread::local_impl::LazyStorage<RefCell<SourceMap>,
!> =
::std::thread::local_impl::LazyStorage::new();
__RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init,
__rust_std_internal_init_fn)
}
}
})
}
};thread_local! {
327 static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
328 files: vec![FileInfo {
331 source_text: String::new(),
332 span: Span { lo: 0, hi: 0 },
333 lines: vec![0],
334 char_index_to_byte_offset: BTreeMap::new(),
335 }],
336 });
337}
338
339#[cfg(span_locations)]
340pub(crate) fn invalidate_current_thread_spans() {
341 #[cfg(not(fuzzing))]
342 SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1));
343}
344
345#[cfg(all(span_locations, not(fuzzing)))]
346struct FileInfo {
347 source_text: String,
348 span: Span,
349 lines: Vec<usize>,
350 char_index_to_byte_offset: BTreeMap<usize, usize>,
351}
352
353#[cfg(all(span_locations, not(fuzzing)))]
354impl FileInfo {
355 fn offset_line_column(&self, offset: usize) -> LineColumn {
356 if !self.span_within(Span { lo: offset as u32, hi: offset as u32 }) {
::core::panicking::panic("assertion failed: self.span_within(Span { lo: offset as u32, hi: offset as u32 })")
};assert!(self.span_within(Span {
357 lo: offset as u32,
358 hi: offset as u32,
359 }));
360 let offset = offset - self.span.lo as usize;
361 match self.lines.binary_search(&offset) {
362 Ok(found) => LineColumn {
363 line: found + 1,
364 column: 0,
365 },
366 Err(idx) => LineColumn {
367 line: idx,
368 column: offset - self.lines[idx - 1],
369 },
370 }
371 }
372
373 fn span_within(&self, span: Span) -> bool {
374 span.lo >= self.span.lo && span.hi <= self.span.hi
375 }
376
377 fn byte_range(&mut self, span: Span) -> Range<usize> {
378 let lo_char = (span.lo - self.span.lo) as usize;
379
380 let (&last_char_index, &last_byte_offset) = self
384 .char_index_to_byte_offset
385 .range(..=lo_char)
386 .next_back()
387 .unwrap_or((&0, &0));
388
389 let lo_byte = if last_char_index == lo_char {
390 last_byte_offset
391 } else {
392 let total_byte_offset = match self.source_text[last_byte_offset..]
393 .char_indices()
394 .nth(lo_char - last_char_index)
395 {
396 Some((additional_offset, _ch)) => last_byte_offset + additional_offset,
397 None => self.source_text.len(),
398 };
399 self.char_index_to_byte_offset
400 .insert(lo_char, total_byte_offset);
401 total_byte_offset
402 };
403
404 let trunc_lo = &self.source_text[lo_byte..];
405 let char_len = (span.hi - span.lo) as usize;
406 lo_byte..match trunc_lo.char_indices().nth(char_len) {
407 Some((offset, _ch)) => lo_byte + offset,
408 None => self.source_text.len(),
409 }
410 }
411
412 fn source_text(&mut self, span: Span) -> String {
413 let byte_range = self.byte_range(span);
414 self.source_text[byte_range].to_owned()
415 }
416}
417
418#[cfg(all(span_locations, not(fuzzing)))]
421fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
422 let mut lines = <[_]>::into_vec(::alloc::boxed::box_new([0]))vec![0];
423 let mut total = 0;
424
425 for ch in s.chars() {
426 total += 1;
427 if ch == '\n' {
428 lines.push(total);
429 }
430 }
431
432 (total, lines)
433}
434
435#[cfg(all(span_locations, not(fuzzing)))]
436struct SourceMap {
437 files: Vec<FileInfo>,
438}
439
440#[cfg(all(span_locations, not(fuzzing)))]
441impl SourceMap {
442 fn next_start_pos(&self) -> u32 {
443 self.files.last().unwrap().span.hi + 1
448 }
449
450 fn add_file(&mut self, src: &str) -> Span {
451 let (len, lines) = lines_offsets(src);
452 let lo = self.next_start_pos();
453 let span = Span {
454 lo,
455 hi: lo + (len as u32),
456 };
457
458 self.files.push(FileInfo {
459 source_text: src.to_owned(),
460 span,
461 lines,
462 char_index_to_byte_offset: BTreeMap::new(),
464 });
465
466 span
467 }
468
469 fn find(&self, span: Span) -> usize {
470 match self.files.binary_search_by(|file| {
471 if file.span.hi < span.lo {
472 Ordering::Less
473 } else if file.span.lo > span.hi {
474 Ordering::Greater
475 } else {
476 if !file.span_within(span) {
::core::panicking::panic("assertion failed: file.span_within(span)")
};assert!(file.span_within(span));
477 Ordering::Equal
478 }
479 }) {
480 Ok(i) => i,
481 Err(_) => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Invalid span with no related FileInfo!")));
}unreachable!("Invalid span with no related FileInfo!"),
482 }
483 }
484
485 fn filepath(&self, span: Span) -> String {
486 let i = self.find(span);
487 if i == 0 {
488 "<unspecified>".to_owned()
489 } else {
490 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<parsed string {0}>", i))
})format!("<parsed string {}>", i)
491 }
492 }
493
494 fn fileinfo(&self, span: Span) -> &FileInfo {
495 let i = self.find(span);
496 &self.files[i]
497 }
498
499 fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo {
500 let i = self.find(span);
501 &mut self.files[i]
502 }
503}
504
505#[derive(#[automatically_derived]
impl ::core::clone::Clone for Span {
#[inline]
fn clone(&self) -> Span {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Span { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Span {
#[inline]
fn eq(&self, other: &Span) -> bool {
self.lo == other.lo && self.hi == other.hi
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Span {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}Eq)]
506pub(crate) struct Span {
507 #[cfg(span_locations)]
508 pub(crate) lo: u32,
509 #[cfg(span_locations)]
510 pub(crate) hi: u32,
511}
512
513impl Span {
514 #[cfg(not(span_locations))]
515 pub(crate) fn call_site() -> Self {
516 Span {}
517 }
518
519 #[cfg(span_locations)]
520 pub(crate) fn call_site() -> Self {
521 Span { lo: 0, hi: 0 }
522 }
523
524 pub(crate) fn mixed_site() -> Self {
525 Span::call_site()
526 }
527
528 #[cfg(procmacro2_semver_exempt)]
529 pub(crate) fn def_site() -> Self {
530 Span::call_site()
531 }
532
533 pub(crate) fn resolved_at(&self, _other: Span) -> Span {
534 *self
538 }
539
540 pub(crate) fn located_at(&self, other: Span) -> Span {
541 other
542 }
543
544 #[cfg(span_locations)]
545 pub(crate) fn byte_range(&self) -> Range<usize> {
546 #[cfg(fuzzing)]
547 return 0..0;
548
549 #[cfg(not(fuzzing))]
550 {
551 if self.is_call_site() {
552 0..0
553 } else {
554 SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self))
555 }
556 }
557 }
558
559 #[cfg(span_locations)]
560 pub(crate) fn start(&self) -> LineColumn {
561 #[cfg(fuzzing)]
562 return LineColumn { line: 0, column: 0 };
563
564 #[cfg(not(fuzzing))]
565 SOURCE_MAP.with(|sm| {
566 let sm = sm.borrow();
567 let fi = sm.fileinfo(*self);
568 fi.offset_line_column(self.lo as usize)
569 })
570 }
571
572 #[cfg(span_locations)]
573 pub(crate) fn end(&self) -> LineColumn {
574 #[cfg(fuzzing)]
575 return LineColumn { line: 0, column: 0 };
576
577 #[cfg(not(fuzzing))]
578 SOURCE_MAP.with(|sm| {
579 let sm = sm.borrow();
580 let fi = sm.fileinfo(*self);
581 fi.offset_line_column(self.hi as usize)
582 })
583 }
584
585 #[cfg(span_locations)]
586 pub(crate) fn file(&self) -> String {
587 #[cfg(fuzzing)]
588 return "<unspecified>".to_owned();
589
590 #[cfg(not(fuzzing))]
591 SOURCE_MAP.with(|sm| {
592 let sm = sm.borrow();
593 sm.filepath(*self)
594 })
595 }
596
597 #[cfg(span_locations)]
598 pub(crate) fn local_file(&self) -> Option<PathBuf> {
599 None
600 }
601
602 #[cfg(not(span_locations))]
603 pub(crate) fn join(&self, _other: Span) -> Option<Span> {
604 Some(Span {})
605 }
606
607 #[cfg(span_locations)]
608 pub(crate) fn join(&self, other: Span) -> Option<Span> {
609 #[cfg(fuzzing)]
610 return {
611 let _ = other;
612 None
613 };
614
615 #[cfg(not(fuzzing))]
616 SOURCE_MAP.with(|sm| {
617 let sm = sm.borrow();
618 if !sm.fileinfo(*self).span_within(other) {
620 return None;
621 }
622 Some(Span {
623 lo: cmp::min(self.lo, other.lo),
624 hi: cmp::max(self.hi, other.hi),
625 })
626 })
627 }
628
629 #[cfg(not(span_locations))]
630 pub(crate) fn source_text(&self) -> Option<String> {
631 None
632 }
633
634 #[cfg(span_locations)]
635 pub(crate) fn source_text(&self) -> Option<String> {
636 #[cfg(fuzzing)]
637 return None;
638
639 #[cfg(not(fuzzing))]
640 {
641 if self.is_call_site() {
642 None
643 } else {
644 Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
645 }
646 }
647 }
648
649 #[cfg(not(span_locations))]
650 pub(crate) fn first_byte(self) -> Self {
651 self
652 }
653
654 #[cfg(span_locations)]
655 pub(crate) fn first_byte(self) -> Self {
656 Span {
657 lo: self.lo,
658 hi: cmp::min(self.lo.saturating_add(1), self.hi),
659 }
660 }
661
662 #[cfg(not(span_locations))]
663 pub(crate) fn last_byte(self) -> Self {
664 self
665 }
666
667 #[cfg(span_locations)]
668 pub(crate) fn last_byte(self) -> Self {
669 Span {
670 lo: cmp::max(self.hi.saturating_sub(1), self.lo),
671 hi: self.hi,
672 }
673 }
674
675 #[cfg(span_locations)]
676 fn is_call_site(&self) -> bool {
677 self.lo == 0 && self.hi == 0
678 }
679}
680
681impl Debug for Span {
682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683 #[cfg(span_locations)]
684 return f.write_fmt(format_args!("bytes({0}..{1})", self.lo, self.hi))write!(f, "bytes({}..{})", self.lo, self.hi);
685
686 #[cfg(not(span_locations))]
687 write!(f, "Span")
688 }
689}
690
691pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
692 #[cfg(span_locations)]
693 {
694 if span.is_call_site() {
695 return;
696 }
697 }
698
699 if truecfg!(span_locations) {
700 debug.field("span", &span);
701 }
702}
703
704#[derive(#[automatically_derived]
impl ::core::clone::Clone for Group {
#[inline]
fn clone(&self) -> Group {
Group {
delimiter: ::core::clone::Clone::clone(&self.delimiter),
stream: ::core::clone::Clone::clone(&self.stream),
span: ::core::clone::Clone::clone(&self.span),
}
}
}Clone)]
705pub(crate) struct Group {
706 delimiter: Delimiter,
707 stream: TokenStream,
708 span: Span,
709}
710
711impl Group {
712 pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
713 Group {
714 delimiter,
715 stream,
716 span: Span::call_site(),
717 }
718 }
719
720 pub(crate) fn delimiter(&self) -> Delimiter {
721 self.delimiter
722 }
723
724 pub(crate) fn stream(&self) -> TokenStream {
725 self.stream.clone()
726 }
727
728 pub(crate) fn span(&self) -> Span {
729 self.span
730 }
731
732 pub(crate) fn span_open(&self) -> Span {
733 self.span.first_byte()
734 }
735
736 pub(crate) fn span_close(&self) -> Span {
737 self.span.last_byte()
738 }
739
740 pub(crate) fn set_span(&mut self, span: Span) {
741 self.span = span;
742 }
743}
744
745impl Display for Group {
746 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
754 let (open, close) = match self.delimiter {
755 Delimiter::Parenthesis => ("(", ")"),
756 Delimiter::Brace => ("{ ", "}"),
757 Delimiter::Bracket => ("[", "]"),
758 Delimiter::None => ("", ""),
759 };
760
761 f.write_str(open)?;
762 Display::fmt(&self.stream, f)?;
763 if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
764 f.write_str(" ")?;
765 }
766 f.write_str(close)?;
767
768 Ok(())
769 }
770}
771
772impl Debug for Group {
773 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
774 let mut debug = fmt.debug_struct("Group");
775 debug.field("delimiter", &self.delimiter);
776 debug.field("stream", &self.stream);
777 debug_span_field_if_nontrivial(&mut debug, self.span);
778 debug.finish()
779 }
780}
781
782#[derive(#[automatically_derived]
impl ::core::clone::Clone for Ident {
#[inline]
fn clone(&self) -> Ident {
Ident {
sym: ::core::clone::Clone::clone(&self.sym),
span: ::core::clone::Clone::clone(&self.span),
raw: ::core::clone::Clone::clone(&self.raw),
}
}
}Clone)]
783pub(crate) struct Ident {
784 sym: Box<str>,
785 span: Span,
786 raw: bool,
787}
788
789impl Ident {
790 #[track_caller]
791 pub(crate) fn new_checked(string: &str, span: Span) -> Self {
792 validate_ident(string);
793 Ident::new_unchecked(string, span)
794 }
795
796 pub(crate) fn new_unchecked(string: &str, span: Span) -> Self {
797 Ident {
798 sym: Box::from(string),
799 span,
800 raw: false,
801 }
802 }
803
804 #[track_caller]
805 pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self {
806 validate_ident_raw(string);
807 Ident::new_raw_unchecked(string, span)
808 }
809
810 pub(crate) fn new_raw_unchecked(string: &str, span: Span) -> Self {
811 Ident {
812 sym: Box::from(string),
813 span,
814 raw: true,
815 }
816 }
817
818 pub(crate) fn span(&self) -> Span {
819 self.span
820 }
821
822 pub(crate) fn set_span(&mut self, span: Span) {
823 self.span = span;
824 }
825}
826
827pub(crate) fn is_ident_start(c: char) -> bool {
828 c == '_' || unicode_ident::is_xid_start(c)
829}
830
831pub(crate) fn is_ident_continue(c: char) -> bool {
832 unicode_ident::is_xid_continue(c)
833}
834
835#[track_caller]
836fn validate_ident(string: &str) {
837 if string.is_empty() {
838 {
::core::panicking::panic_fmt(format_args!("Ident is not allowed to be empty; use Option<Ident>"));
};panic!("Ident is not allowed to be empty; use Option<Ident>");
839 }
840
841 if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') {
842 {
::core::panicking::panic_fmt(format_args!("Ident cannot be a number; use Literal instead"));
};panic!("Ident cannot be a number; use Literal instead");
843 }
844
845 fn ident_ok(string: &str) -> bool {
846 let mut chars = string.chars();
847 let first = chars.next().unwrap();
848 if !is_ident_start(first) {
849 return false;
850 }
851 for ch in chars {
852 if !is_ident_continue(ch) {
853 return false;
854 }
855 }
856 true
857 }
858
859 if !ident_ok(string) {
860 {
::core::panicking::panic_fmt(format_args!("{0:?} is not a valid Ident",
string));
};panic!("{:?} is not a valid Ident", string);
861 }
862}
863
864#[track_caller]
865fn validate_ident_raw(string: &str) {
866 validate_ident(string);
867
868 match string {
869 "_" | "super" | "self" | "Self" | "crate" => {
870 {
::core::panicking::panic_fmt(format_args!("`r#{0}` cannot be a raw identifier",
string));
};panic!("`r#{}` cannot be a raw identifier", string);
871 }
872 _ => {}
873 }
874}
875
876impl PartialEq for Ident {
877 fn eq(&self, other: &Ident) -> bool {
878 self.sym == other.sym && self.raw == other.raw
879 }
880}
881
882impl<T> PartialEq<T> for Ident
883where
884 T: ?Sized + AsRef<str>,
885{
886 fn eq(&self, other: &T) -> bool {
887 let other = other.as_ref();
888 if self.raw {
889 other.starts_with("r#") && *self.sym == other[2..]
890 } else {
891 *self.sym == *other
892 }
893 }
894}
895
896impl Display for Ident {
897 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
898 if self.raw {
899 f.write_str("r#")?;
900 }
901 f.write_str(&self.sym)
902 }
903}
904
905#[allow(clippy::missing_fields_in_debug)]
906impl Debug for Ident {
907 #[cfg(not(span_locations))]
909 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
910 let mut debug = f.debug_tuple("Ident");
911 debug.field(&format_args!("{}", self));
912 debug.finish()
913 }
914
915 #[cfg(span_locations)]
920 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
921 let mut debug = f.debug_struct("Ident");
922 debug.field("sym", &format_args!("{0}", self)format_args!("{}", self));
923 debug_span_field_if_nontrivial(&mut debug, self.span);
924 debug.finish()
925 }
926}
927
928#[derive(#[automatically_derived]
impl ::core::clone::Clone for Literal {
#[inline]
fn clone(&self) -> Literal {
Literal {
repr: ::core::clone::Clone::clone(&self.repr),
span: ::core::clone::Clone::clone(&self.span),
}
}
}Clone)]
929pub(crate) struct Literal {
930 pub(crate) repr: String,
931 span: Span,
932}
933
934macro_rules! suffixed_numbers {
935 ($($name:ident => $kind:ident,)*) => ($(
936 pub(crate) fn $name(n: $kind) -> Literal {
937 Literal::_new(format!(concat!("{}", stringify!($kind)), n))
938 }
939 )*)
940}
941
942macro_rules! unsuffixed_numbers {
943 ($($name:ident => $kind:ident,)*) => ($(
944 pub(crate) fn $name(n: $kind) -> Literal {
945 Literal::_new(n.to_string())
946 }
947 )*)
948}
949
950impl Literal {
951 pub(crate) fn _new(repr: String) -> Self {
952 Literal {
953 repr,
954 span: Span::call_site(),
955 }
956 }
957
958 pub(crate) fn from_str_checked(repr: &str) -> Result<Self, LexError> {
959 let mut cursor = get_cursor(repr);
960 #[cfg(span_locations)]
961 let lo = cursor.off;
962
963 let negative = cursor.starts_with_char('-');
964 if negative {
965 cursor = cursor.advance(1);
966 if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
967 return Err(LexError::call_site());
968 }
969 }
970
971 if let Ok((rest, mut literal)) = parse::literal(cursor) {
972 if rest.is_empty() {
973 if negative {
974 literal.repr.insert(0, '-');
975 }
976 literal.span = Span {
977 #[cfg(span_locations)]
978 lo,
979 #[cfg(span_locations)]
980 hi: rest.off,
981 };
982 return Ok(literal);
983 }
984 }
985 Err(LexError::call_site())
986 }
987
988 pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
989 Literal::_new(repr.to_owned())
990 }
991
992 n
Literal
Literal::_new(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}f64", n))
}));suffixed_numbers! {
993 u8_suffixed => u8,
994 u16_suffixed => u16,
995 u32_suffixed => u32,
996 u64_suffixed => u64,
997 u128_suffixed => u128,
998 usize_suffixed => usize,
999 i8_suffixed => i8,
1000 i16_suffixed => i16,
1001 i32_suffixed => i32,
1002 i64_suffixed => i64,
1003 i128_suffixed => i128,
1004 isize_suffixed => isize,
1005
1006 f32_suffixed => f32,
1007 f64_suffixed => f64,
1008 }
1009
1010 n
Literal
Literal::_new(n.to_string());unsuffixed_numbers! {
1011 u8_unsuffixed => u8,
1012 u16_unsuffixed => u16,
1013 u32_unsuffixed => u32,
1014 u64_unsuffixed => u64,
1015 u128_unsuffixed => u128,
1016 usize_unsuffixed => usize,
1017 i8_unsuffixed => i8,
1018 i16_unsuffixed => i16,
1019 i32_unsuffixed => i32,
1020 i64_unsuffixed => i64,
1021 i128_unsuffixed => i128,
1022 isize_unsuffixed => isize,
1023 }
1024
1025 pub(crate) fn f32_unsuffixed(f: f32) -> Literal {
1026 let mut s = f.to_string();
1027 if !s.contains('.') {
1028 s.push_str(".0");
1029 }
1030 Literal::_new(s)
1031 }
1032
1033 pub(crate) fn f64_unsuffixed(f: f64) -> Literal {
1034 let mut s = f.to_string();
1035 if !s.contains('.') {
1036 s.push_str(".0");
1037 }
1038 Literal::_new(s)
1039 }
1040
1041 pub(crate) fn string(string: &str) -> Literal {
1042 let mut repr = String::with_capacity(string.len() + 2);
1043 repr.push('"');
1044 escape_utf8(string, &mut repr);
1045 repr.push('"');
1046 Literal::_new(repr)
1047 }
1048
1049 pub(crate) fn character(ch: char) -> Literal {
1050 let mut repr = String::new();
1051 repr.push('\'');
1052 if ch == '"' {
1053 repr.push(ch);
1055 } else {
1056 repr.extend(ch.escape_debug());
1057 }
1058 repr.push('\'');
1059 Literal::_new(repr)
1060 }
1061
1062 pub(crate) fn byte_character(byte: u8) -> Literal {
1063 let mut repr = "b'".to_string();
1064 #[allow(clippy::match_overlapping_arm)]
1065 match byte {
1066 b'\0' => repr.push_str(r"\0"),
1067 b'\t' => repr.push_str(r"\t"),
1068 b'\n' => repr.push_str(r"\n"),
1069 b'\r' => repr.push_str(r"\r"),
1070 b'\'' => repr.push_str(r"\'"),
1071 b'\\' => repr.push_str(r"\\"),
1072 b'\x20'..=b'\x7E' => repr.push(byte as char),
1073 _ => {
1074 let _ = repr.write_fmt(format_args!("\\x{0:02X}", byte))write!(repr, r"\x{:02X}", byte);
1075 }
1076 }
1077 repr.push('\'');
1078 Literal::_new(repr)
1079 }
1080
1081 pub(crate) fn byte_string(bytes: &[u8]) -> Literal {
1082 let mut repr = "b\"".to_string();
1083 let mut bytes = bytes.iter();
1084 while let Some(&b) = bytes.next() {
1085 #[allow(clippy::match_overlapping_arm)]
1086 match b {
1087 b'\0' => repr.push_str(match bytes.as_slice().first() {
1088 Some(b'0'..=b'7') => r"\x00",
1090 _ => r"\0",
1091 }),
1092 b'\t' => repr.push_str(r"\t"),
1093 b'\n' => repr.push_str(r"\n"),
1094 b'\r' => repr.push_str(r"\r"),
1095 b'"' => repr.push_str("\\\""),
1096 b'\\' => repr.push_str(r"\\"),
1097 b'\x20'..=b'\x7E' => repr.push(b as char),
1098 _ => {
1099 let _ = repr.write_fmt(format_args!("\\x{0:02X}", b))write!(repr, r"\x{:02X}", b);
1100 }
1101 }
1102 }
1103 repr.push('"');
1104 Literal::_new(repr)
1105 }
1106
1107 pub(crate) fn c_string(string: &CStr) -> Literal {
1108 let mut repr = "c\"".to_string();
1109 let mut bytes = string.to_bytes();
1110 while !bytes.is_empty() {
1111 let (valid, invalid) = match str::from_utf8(bytes) {
1112 Ok(all_valid) => {
1113 bytes = b"";
1114 (all_valid, bytes)
1115 }
1116 Err(utf8_error) => {
1117 let (valid, rest) = bytes.split_at(utf8_error.valid_up_to());
1118 let valid = str::from_utf8(valid).unwrap();
1119 let invalid = utf8_error
1120 .error_len()
1121 .map_or(rest, |error_len| &rest[..error_len]);
1122 bytes = &bytes[valid.len() + invalid.len()..];
1123 (valid, invalid)
1124 }
1125 };
1126 escape_utf8(valid, &mut repr);
1127 for &byte in invalid {
1128 let _ = repr.write_fmt(format_args!("\\x{0:02X}", byte))write!(repr, r"\x{:02X}", byte);
1129 }
1130 }
1131 repr.push('"');
1132 Literal::_new(repr)
1133 }
1134
1135 pub(crate) fn span(&self) -> Span {
1136 self.span
1137 }
1138
1139 pub(crate) fn set_span(&mut self, span: Span) {
1140 self.span = span;
1141 }
1142
1143 pub(crate) fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
1144 #[cfg(not(span_locations))]
1145 {
1146 let _ = range;
1147 None
1148 }
1149
1150 #[cfg(span_locations)]
1151 {
1152 use core::ops::Bound;
1153
1154 let lo = match range.start_bound() {
1155 Bound::Included(start) => {
1156 let start = u32::try_from(*start).ok()?;
1157 self.span.lo.checked_add(start)?
1158 }
1159 Bound::Excluded(start) => {
1160 let start = u32::try_from(*start).ok()?;
1161 self.span.lo.checked_add(start)?.checked_add(1)?
1162 }
1163 Bound::Unbounded => self.span.lo,
1164 };
1165 let hi = match range.end_bound() {
1166 Bound::Included(end) => {
1167 let end = u32::try_from(*end).ok()?;
1168 self.span.lo.checked_add(end)?.checked_add(1)?
1169 }
1170 Bound::Excluded(end) => {
1171 let end = u32::try_from(*end).ok()?;
1172 self.span.lo.checked_add(end)?
1173 }
1174 Bound::Unbounded => self.span.hi,
1175 };
1176 if lo <= hi && hi <= self.span.hi {
1177 Some(Span { lo, hi })
1178 } else {
1179 None
1180 }
1181 }
1182 }
1183}
1184
1185impl Display for Literal {
1186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1187 Display::fmt(&self.repr, f)
1188 }
1189}
1190
1191impl Debug for Literal {
1192 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1193 let mut debug = fmt.debug_struct("Literal");
1194 debug.field("lit", &format_args!("{0}", self.repr)format_args!("{}", self.repr));
1195 debug_span_field_if_nontrivial(&mut debug, self.span);
1196 debug.finish()
1197 }
1198}
1199
1200fn escape_utf8(string: &str, repr: &mut String) {
1201 let mut chars = string.chars();
1202 while let Some(ch) = chars.next() {
1203 if ch == '\0' {
1204 repr.push_str(
1205 if chars
1206 .as_str()
1207 .starts_with(|next| '0' <= next && next <= '7')
1208 {
1209 r"\x00"
1211 } else {
1212 r"\0"
1213 },
1214 );
1215 } else if ch == '\'' {
1216 repr.push(ch);
1218 } else {
1219 repr.extend(ch.escape_debug());
1220 }
1221 }
1222}
1223
1224#[cfg(feature = "proc-macro")]
1225pub(crate) trait FromStr2: FromStr<Err = proc_macro::LexError> {
1226 #[cfg(wrap_proc_macro)]
1227 fn valid(src: &str) -> bool;
1228
1229 #[cfg(wrap_proc_macro)]
1230 fn from_str_checked(src: &str) -> Result<Self, imp::LexError> {
1231 if !Self::valid(src) {
1235 return Err(imp::LexError::CompilerPanic);
1236 }
1237
1238 match panic::catch_unwind(|| Self::from_str(src)) {
1240 Ok(Ok(ok)) => Ok(ok),
1241 Ok(Err(lex)) => Err(imp::LexError::Compiler(lex)),
1242 Err(_panic) => Err(imp::LexError::CompilerPanic),
1243 }
1244 }
1245
1246 fn from_str_unchecked(src: &str) -> Self {
1247 Self::from_str(src).unwrap()
1248 }
1249}
1250
1251#[cfg(feature = "proc-macro")]
1252impl FromStr2 for proc_macro::TokenStream {
1253 #[cfg(wrap_proc_macro)]
1254 fn valid(src: &str) -> bool {
1255 TokenStream::from_str_checked(src).is_ok()
1256 }
1257}
1258
1259#[cfg(feature = "proc-macro")]
1260impl FromStr2 for proc_macro::Literal {
1261 #[cfg(wrap_proc_macro)]
1262 fn valid(src: &str) -> bool {
1263 Literal::from_str_checked(src).is_ok()
1264 }
1265}