]> git.proxmox.com Git - cargo.git/blob - vendor/proc-macro2/src/fallback.rs
New upstream version 0.52.0
[cargo.git] / vendor / proc-macro2 / src / fallback.rs
1 use crate::parse::{self, Cursor};
2 use crate::{Delimiter, Spacing, TokenTree};
3 #[cfg(span_locations)]
4 use std::cell::RefCell;
5 #[cfg(span_locations)]
6 use std::cmp;
7 use std::fmt::{self, Debug, Display};
8 use std::iter::FromIterator;
9 use std::mem;
10 use std::ops::RangeBounds;
11 #[cfg(procmacro2_semver_exempt)]
12 use std::path::Path;
13 use std::path::PathBuf;
14 use std::str::FromStr;
15 use std::vec;
16 use unicode_xid::UnicodeXID;
17
18 /// Force use of proc-macro2's fallback implementation of the API for now, even
19 /// if the compiler's implementation is available.
20 pub fn force() {
21 #[cfg(wrap_proc_macro)]
22 crate::detection::force_fallback();
23 }
24
25 /// Resume using the compiler's implementation of the proc macro API if it is
26 /// available.
27 pub fn unforce() {
28 #[cfg(wrap_proc_macro)]
29 crate::detection::unforce_fallback();
30 }
31
32 #[derive(Clone)]
33 pub(crate) struct TokenStream {
34 pub(crate) inner: Vec<TokenTree>,
35 }
36
37 #[derive(Debug)]
38 pub(crate) struct LexError {
39 pub(crate) span: Span,
40 }
41
42 impl LexError {
43 pub(crate) fn span(&self) -> Span {
44 self.span
45 }
46 }
47
48 impl TokenStream {
49 pub fn new() -> TokenStream {
50 TokenStream { inner: Vec::new() }
51 }
52
53 pub fn is_empty(&self) -> bool {
54 self.inner.len() == 0
55 }
56
57 fn take_inner(&mut self) -> Vec<TokenTree> {
58 mem::replace(&mut self.inner, Vec::new())
59 }
60
61 fn push_token(&mut self, token: TokenTree) {
62 // https://github.com/alexcrichton/proc-macro2/issues/235
63 match token {
64 #[cfg(not(no_bind_by_move_pattern_guard))]
65 TokenTree::Literal(crate::Literal {
66 #[cfg(wrap_proc_macro)]
67 inner: crate::imp::Literal::Fallback(literal),
68 #[cfg(not(wrap_proc_macro))]
69 inner: literal,
70 ..
71 }) if literal.text.starts_with('-') => {
72 push_negative_literal(self, literal);
73 }
74 #[cfg(no_bind_by_move_pattern_guard)]
75 TokenTree::Literal(crate::Literal {
76 #[cfg(wrap_proc_macro)]
77 inner: crate::imp::Literal::Fallback(literal),
78 #[cfg(not(wrap_proc_macro))]
79 inner: literal,
80 ..
81 }) => {
82 if literal.text.starts_with('-') {
83 push_negative_literal(self, literal);
84 } else {
85 self.inner
86 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
87 }
88 }
89 _ => self.inner.push(token),
90 }
91
92 #[cold]
93 fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) {
94 literal.text.remove(0);
95 let mut punct = crate::Punct::new('-', Spacing::Alone);
96 punct.set_span(crate::Span::_new_stable(literal.span));
97 stream.inner.push(TokenTree::Punct(punct));
98 stream
99 .inner
100 .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
101 }
102 }
103 }
104
105 // Nonrecursive to prevent stack overflow.
106 impl Drop for TokenStream {
107 fn drop(&mut self) {
108 while let Some(token) = self.inner.pop() {
109 let group = match token {
110 TokenTree::Group(group) => group.inner,
111 _ => continue,
112 };
113 #[cfg(wrap_proc_macro)]
114 let group = match group {
115 crate::imp::Group::Fallback(group) => group,
116 _ => continue,
117 };
118 let mut group = group;
119 self.inner.extend(group.stream.take_inner());
120 }
121 }
122 }
123
124 #[cfg(span_locations)]
125 fn get_cursor(src: &str) -> Cursor {
126 // Create a dummy file & add it to the source map
127 SOURCE_MAP.with(|cm| {
128 let mut cm = cm.borrow_mut();
129 let name = format!("<parsed string {}>", cm.files.len());
130 let span = cm.add_file(&name, src);
131 Cursor {
132 rest: src,
133 off: span.lo,
134 }
135 })
136 }
137
138 #[cfg(not(span_locations))]
139 fn get_cursor(src: &str) -> Cursor {
140 Cursor { rest: src }
141 }
142
143 impl FromStr for TokenStream {
144 type Err = LexError;
145
146 fn from_str(src: &str) -> Result<TokenStream, LexError> {
147 // Create a dummy file & add it to the source map
148 let cursor = get_cursor(src);
149
150 parse::token_stream(cursor)
151 }
152 }
153
154 impl Display for LexError {
155 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156 f.write_str("cannot parse string into token stream")
157 }
158 }
159
160 impl Display for TokenStream {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 let mut joint = false;
163 for (i, tt) in self.inner.iter().enumerate() {
164 if i != 0 && !joint {
165 write!(f, " ")?;
166 }
167 joint = false;
168 match tt {
169 TokenTree::Group(tt) => Display::fmt(tt, f),
170 TokenTree::Ident(tt) => Display::fmt(tt, f),
171 TokenTree::Punct(tt) => {
172 joint = tt.spacing() == Spacing::Joint;
173 Display::fmt(tt, f)
174 }
175 TokenTree::Literal(tt) => Display::fmt(tt, f),
176 }?
177 }
178
179 Ok(())
180 }
181 }
182
183 impl Debug for TokenStream {
184 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185 f.write_str("TokenStream ")?;
186 f.debug_list().entries(self.clone()).finish()
187 }
188 }
189
190 #[cfg(use_proc_macro)]
191 impl From<proc_macro::TokenStream> for TokenStream {
192 fn from(inner: proc_macro::TokenStream) -> TokenStream {
193 inner
194 .to_string()
195 .parse()
196 .expect("compiler token stream parse failed")
197 }
198 }
199
200 #[cfg(use_proc_macro)]
201 impl From<TokenStream> for proc_macro::TokenStream {
202 fn from(inner: TokenStream) -> proc_macro::TokenStream {
203 inner
204 .to_string()
205 .parse()
206 .expect("failed to parse to compiler tokens")
207 }
208 }
209
210 impl From<TokenTree> for TokenStream {
211 fn from(tree: TokenTree) -> TokenStream {
212 let mut stream = TokenStream::new();
213 stream.push_token(tree);
214 stream
215 }
216 }
217
218 impl FromIterator<TokenTree> for TokenStream {
219 fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
220 let mut stream = TokenStream::new();
221 stream.extend(tokens);
222 stream
223 }
224 }
225
226 impl FromIterator<TokenStream> for TokenStream {
227 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
228 let mut v = Vec::new();
229
230 for mut stream in streams {
231 v.extend(stream.take_inner());
232 }
233
234 TokenStream { inner: v }
235 }
236 }
237
238 impl Extend<TokenTree> for TokenStream {
239 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
240 tokens.into_iter().for_each(|token| self.push_token(token));
241 }
242 }
243
244 impl Extend<TokenStream> for TokenStream {
245 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
246 self.inner.extend(streams.into_iter().flatten());
247 }
248 }
249
250 pub(crate) type TokenTreeIter = vec::IntoIter<TokenTree>;
251
252 impl IntoIterator for TokenStream {
253 type Item = TokenTree;
254 type IntoIter = TokenTreeIter;
255
256 fn into_iter(mut self) -> TokenTreeIter {
257 self.take_inner().into_iter()
258 }
259 }
260
261 #[derive(Clone, PartialEq, Eq)]
262 pub(crate) struct SourceFile {
263 path: PathBuf,
264 }
265
266 impl SourceFile {
267 /// Get the path to this source file as a string.
268 pub fn path(&self) -> PathBuf {
269 self.path.clone()
270 }
271
272 pub fn is_real(&self) -> bool {
273 // XXX(nika): Support real files in the future?
274 false
275 }
276 }
277
278 impl Debug for SourceFile {
279 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280 f.debug_struct("SourceFile")
281 .field("path", &self.path())
282 .field("is_real", &self.is_real())
283 .finish()
284 }
285 }
286
287 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
288 pub(crate) struct LineColumn {
289 pub line: usize,
290 pub column: usize,
291 }
292
293 #[cfg(span_locations)]
294 thread_local! {
295 static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
296 // NOTE: We start with a single dummy file which all call_site() and
297 // def_site() spans reference.
298 files: vec![FileInfo {
299 #[cfg(procmacro2_semver_exempt)]
300 name: "<unspecified>".to_owned(),
301 span: Span { lo: 0, hi: 0 },
302 lines: vec![0],
303 }],
304 });
305 }
306
307 #[cfg(span_locations)]
308 struct FileInfo {
309 #[cfg(procmacro2_semver_exempt)]
310 name: String,
311 span: Span,
312 lines: Vec<usize>,
313 }
314
315 #[cfg(span_locations)]
316 impl FileInfo {
317 fn offset_line_column(&self, offset: usize) -> LineColumn {
318 assert!(self.span_within(Span {
319 lo: offset as u32,
320 hi: offset as u32
321 }));
322 let offset = offset - self.span.lo as usize;
323 match self.lines.binary_search(&offset) {
324 Ok(found) => LineColumn {
325 line: found + 1,
326 column: 0,
327 },
328 Err(idx) => LineColumn {
329 line: idx,
330 column: offset - self.lines[idx - 1],
331 },
332 }
333 }
334
335 fn span_within(&self, span: Span) -> bool {
336 span.lo >= self.span.lo && span.hi <= self.span.hi
337 }
338 }
339
340 /// Computes the offsets of each line in the given source string
341 /// and the total number of characters
342 #[cfg(span_locations)]
343 fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
344 let mut lines = vec![0];
345 let mut total = 0;
346
347 for ch in s.chars() {
348 total += 1;
349 if ch == '\n' {
350 lines.push(total);
351 }
352 }
353
354 (total, lines)
355 }
356
357 #[cfg(span_locations)]
358 struct SourceMap {
359 files: Vec<FileInfo>,
360 }
361
362 #[cfg(span_locations)]
363 impl SourceMap {
364 fn next_start_pos(&self) -> u32 {
365 // Add 1 so there's always space between files.
366 //
367 // We'll always have at least 1 file, as we initialize our files list
368 // with a dummy file.
369 self.files.last().unwrap().span.hi + 1
370 }
371
372 fn add_file(&mut self, name: &str, src: &str) -> Span {
373 let (len, lines) = lines_offsets(src);
374 let lo = self.next_start_pos();
375 // XXX(nika): Shouild we bother doing a checked cast or checked add here?
376 let span = Span {
377 lo,
378 hi: lo + (len as u32),
379 };
380
381 self.files.push(FileInfo {
382 #[cfg(procmacro2_semver_exempt)]
383 name: name.to_owned(),
384 span,
385 lines,
386 });
387
388 #[cfg(not(procmacro2_semver_exempt))]
389 let _ = name;
390
391 span
392 }
393
394 fn fileinfo(&self, span: Span) -> &FileInfo {
395 for file in &self.files {
396 if file.span_within(span) {
397 return file;
398 }
399 }
400 panic!("Invalid span with no related FileInfo!");
401 }
402 }
403
404 #[derive(Clone, Copy, PartialEq, Eq)]
405 pub(crate) struct Span {
406 #[cfg(span_locations)]
407 pub(crate) lo: u32,
408 #[cfg(span_locations)]
409 pub(crate) hi: u32,
410 }
411
412 impl Span {
413 #[cfg(not(span_locations))]
414 pub fn call_site() -> Span {
415 Span {}
416 }
417
418 #[cfg(span_locations)]
419 pub fn call_site() -> Span {
420 Span { lo: 0, hi: 0 }
421 }
422
423 #[cfg(hygiene)]
424 pub fn mixed_site() -> Span {
425 Span::call_site()
426 }
427
428 #[cfg(procmacro2_semver_exempt)]
429 pub fn def_site() -> Span {
430 Span::call_site()
431 }
432
433 pub fn resolved_at(&self, _other: Span) -> Span {
434 // Stable spans consist only of line/column information, so
435 // `resolved_at` and `located_at` only select which span the
436 // caller wants line/column information from.
437 *self
438 }
439
440 pub fn located_at(&self, other: Span) -> Span {
441 other
442 }
443
444 #[cfg(procmacro2_semver_exempt)]
445 pub fn source_file(&self) -> SourceFile {
446 SOURCE_MAP.with(|cm| {
447 let cm = cm.borrow();
448 let fi = cm.fileinfo(*self);
449 SourceFile {
450 path: Path::new(&fi.name).to_owned(),
451 }
452 })
453 }
454
455 #[cfg(span_locations)]
456 pub fn start(&self) -> LineColumn {
457 SOURCE_MAP.with(|cm| {
458 let cm = cm.borrow();
459 let fi = cm.fileinfo(*self);
460 fi.offset_line_column(self.lo as usize)
461 })
462 }
463
464 #[cfg(span_locations)]
465 pub fn end(&self) -> LineColumn {
466 SOURCE_MAP.with(|cm| {
467 let cm = cm.borrow();
468 let fi = cm.fileinfo(*self);
469 fi.offset_line_column(self.hi as usize)
470 })
471 }
472
473 #[cfg(not(span_locations))]
474 pub fn join(&self, _other: Span) -> Option<Span> {
475 Some(Span {})
476 }
477
478 #[cfg(span_locations)]
479 pub fn join(&self, other: Span) -> Option<Span> {
480 SOURCE_MAP.with(|cm| {
481 let cm = cm.borrow();
482 // If `other` is not within the same FileInfo as us, return None.
483 if !cm.fileinfo(*self).span_within(other) {
484 return None;
485 }
486 Some(Span {
487 lo: cmp::min(self.lo, other.lo),
488 hi: cmp::max(self.hi, other.hi),
489 })
490 })
491 }
492
493 #[cfg(not(span_locations))]
494 fn first_byte(self) -> Self {
495 self
496 }
497
498 #[cfg(span_locations)]
499 fn first_byte(self) -> Self {
500 Span {
501 lo: self.lo,
502 hi: cmp::min(self.lo.saturating_add(1), self.hi),
503 }
504 }
505
506 #[cfg(not(span_locations))]
507 fn last_byte(self) -> Self {
508 self
509 }
510
511 #[cfg(span_locations)]
512 fn last_byte(self) -> Self {
513 Span {
514 lo: cmp::max(self.hi.saturating_sub(1), self.lo),
515 hi: self.hi,
516 }
517 }
518 }
519
520 impl Debug for Span {
521 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
522 #[cfg(span_locations)]
523 return write!(f, "bytes({}..{})", self.lo, self.hi);
524
525 #[cfg(not(span_locations))]
526 write!(f, "Span")
527 }
528 }
529
530 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
531 #[cfg(span_locations)]
532 {
533 if span.lo == 0 && span.hi == 0 {
534 return;
535 }
536 }
537
538 if cfg!(span_locations) {
539 debug.field("span", &span);
540 }
541 }
542
543 #[derive(Clone)]
544 pub(crate) struct Group {
545 delimiter: Delimiter,
546 stream: TokenStream,
547 span: Span,
548 }
549
550 impl Group {
551 pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
552 Group {
553 delimiter,
554 stream,
555 span: Span::call_site(),
556 }
557 }
558
559 pub fn delimiter(&self) -> Delimiter {
560 self.delimiter
561 }
562
563 pub fn stream(&self) -> TokenStream {
564 self.stream.clone()
565 }
566
567 pub fn span(&self) -> Span {
568 self.span
569 }
570
571 pub fn span_open(&self) -> Span {
572 self.span.first_byte()
573 }
574
575 pub fn span_close(&self) -> Span {
576 self.span.last_byte()
577 }
578
579 pub fn set_span(&mut self, span: Span) {
580 self.span = span;
581 }
582 }
583
584 impl Display for Group {
585 // We attempt to match libproc_macro's formatting.
586 // Empty parens: ()
587 // Nonempty parens: (...)
588 // Empty brackets: []
589 // Nonempty brackets: [...]
590 // Empty braces: { }
591 // Nonempty braces: { ... }
592 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593 let (open, close) = match self.delimiter {
594 Delimiter::Parenthesis => ("(", ")"),
595 Delimiter::Brace => ("{ ", "}"),
596 Delimiter::Bracket => ("[", "]"),
597 Delimiter::None => ("", ""),
598 };
599
600 f.write_str(open)?;
601 Display::fmt(&self.stream, f)?;
602 if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
603 f.write_str(" ")?;
604 }
605 f.write_str(close)?;
606
607 Ok(())
608 }
609 }
610
611 impl Debug for Group {
612 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
613 let mut debug = fmt.debug_struct("Group");
614 debug.field("delimiter", &self.delimiter);
615 debug.field("stream", &self.stream);
616 debug_span_field_if_nontrivial(&mut debug, self.span);
617 debug.finish()
618 }
619 }
620
621 #[derive(Clone)]
622 pub(crate) struct Ident {
623 sym: String,
624 span: Span,
625 raw: bool,
626 }
627
628 impl Ident {
629 fn _new(string: &str, raw: bool, span: Span) -> Ident {
630 validate_ident(string);
631
632 Ident {
633 sym: string.to_owned(),
634 span,
635 raw,
636 }
637 }
638
639 pub fn new(string: &str, span: Span) -> Ident {
640 Ident::_new(string, false, span)
641 }
642
643 pub fn new_raw(string: &str, span: Span) -> Ident {
644 Ident::_new(string, true, span)
645 }
646
647 pub fn span(&self) -> Span {
648 self.span
649 }
650
651 pub fn set_span(&mut self, span: Span) {
652 self.span = span;
653 }
654 }
655
656 pub(crate) fn is_ident_start(c: char) -> bool {
657 ('a' <= c && c <= 'z')
658 || ('A' <= c && c <= 'Z')
659 || c == '_'
660 || (c > '\x7f' && UnicodeXID::is_xid_start(c))
661 }
662
663 pub(crate) fn is_ident_continue(c: char) -> bool {
664 ('a' <= c && c <= 'z')
665 || ('A' <= c && c <= 'Z')
666 || c == '_'
667 || ('0' <= c && c <= '9')
668 || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
669 }
670
671 fn validate_ident(string: &str) {
672 let validate = string;
673 if validate.is_empty() {
674 panic!("Ident is not allowed to be empty; use Option<Ident>");
675 }
676
677 if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
678 panic!("Ident cannot be a number; use Literal instead");
679 }
680
681 fn ident_ok(string: &str) -> bool {
682 let mut chars = string.chars();
683 let first = chars.next().unwrap();
684 if !is_ident_start(first) {
685 return false;
686 }
687 for ch in chars {
688 if !is_ident_continue(ch) {
689 return false;
690 }
691 }
692 true
693 }
694
695 if !ident_ok(validate) {
696 panic!("{:?} is not a valid Ident", string);
697 }
698 }
699
700 impl PartialEq for Ident {
701 fn eq(&self, other: &Ident) -> bool {
702 self.sym == other.sym && self.raw == other.raw
703 }
704 }
705
706 impl<T> PartialEq<T> for Ident
707 where
708 T: ?Sized + AsRef<str>,
709 {
710 fn eq(&self, other: &T) -> bool {
711 let other = other.as_ref();
712 if self.raw {
713 other.starts_with("r#") && self.sym == other[2..]
714 } else {
715 self.sym == other
716 }
717 }
718 }
719
720 impl Display for Ident {
721 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
722 if self.raw {
723 f.write_str("r#")?;
724 }
725 Display::fmt(&self.sym, f)
726 }
727 }
728
729 impl Debug for Ident {
730 // Ident(proc_macro), Ident(r#union)
731 #[cfg(not(span_locations))]
732 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
733 let mut debug = f.debug_tuple("Ident");
734 debug.field(&format_args!("{}", self));
735 debug.finish()
736 }
737
738 // Ident {
739 // sym: proc_macro,
740 // span: bytes(128..138)
741 // }
742 #[cfg(span_locations)]
743 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
744 let mut debug = f.debug_struct("Ident");
745 debug.field("sym", &format_args!("{}", self));
746 debug_span_field_if_nontrivial(&mut debug, self.span);
747 debug.finish()
748 }
749 }
750
751 #[derive(Clone)]
752 pub(crate) struct Literal {
753 text: String,
754 span: Span,
755 }
756
757 macro_rules! suffixed_numbers {
758 ($($name:ident => $kind:ident,)*) => ($(
759 pub fn $name(n: $kind) -> Literal {
760 Literal::_new(format!(concat!("{}", stringify!($kind)), n))
761 }
762 )*)
763 }
764
765 macro_rules! unsuffixed_numbers {
766 ($($name:ident => $kind:ident,)*) => ($(
767 pub fn $name(n: $kind) -> Literal {
768 Literal::_new(n.to_string())
769 }
770 )*)
771 }
772
773 impl Literal {
774 pub(crate) fn _new(text: String) -> Literal {
775 Literal {
776 text,
777 span: Span::call_site(),
778 }
779 }
780
781 suffixed_numbers! {
782 u8_suffixed => u8,
783 u16_suffixed => u16,
784 u32_suffixed => u32,
785 u64_suffixed => u64,
786 u128_suffixed => u128,
787 usize_suffixed => usize,
788 i8_suffixed => i8,
789 i16_suffixed => i16,
790 i32_suffixed => i32,
791 i64_suffixed => i64,
792 i128_suffixed => i128,
793 isize_suffixed => isize,
794
795 f32_suffixed => f32,
796 f64_suffixed => f64,
797 }
798
799 unsuffixed_numbers! {
800 u8_unsuffixed => u8,
801 u16_unsuffixed => u16,
802 u32_unsuffixed => u32,
803 u64_unsuffixed => u64,
804 u128_unsuffixed => u128,
805 usize_unsuffixed => usize,
806 i8_unsuffixed => i8,
807 i16_unsuffixed => i16,
808 i32_unsuffixed => i32,
809 i64_unsuffixed => i64,
810 i128_unsuffixed => i128,
811 isize_unsuffixed => isize,
812 }
813
814 pub fn f32_unsuffixed(f: f32) -> Literal {
815 let mut s = f.to_string();
816 if !s.contains('.') {
817 s.push_str(".0");
818 }
819 Literal::_new(s)
820 }
821
822 pub fn f64_unsuffixed(f: f64) -> Literal {
823 let mut s = f.to_string();
824 if !s.contains('.') {
825 s.push_str(".0");
826 }
827 Literal::_new(s)
828 }
829
830 pub fn string(t: &str) -> Literal {
831 let mut text = String::with_capacity(t.len() + 2);
832 text.push('"');
833 for c in t.chars() {
834 if c == '\'' {
835 // escape_debug turns this into "\'" which is unnecessary.
836 text.push(c);
837 } else {
838 text.extend(c.escape_debug());
839 }
840 }
841 text.push('"');
842 Literal::_new(text)
843 }
844
845 pub fn character(t: char) -> Literal {
846 let mut text = String::new();
847 text.push('\'');
848 if t == '"' {
849 // escape_debug turns this into '\"' which is unnecessary.
850 text.push(t);
851 } else {
852 text.extend(t.escape_debug());
853 }
854 text.push('\'');
855 Literal::_new(text)
856 }
857
858 pub fn byte_string(bytes: &[u8]) -> Literal {
859 let mut escaped = "b\"".to_string();
860 for b in bytes {
861 #[allow(clippy::match_overlapping_arm)]
862 match *b {
863 b'\0' => escaped.push_str(r"\0"),
864 b'\t' => escaped.push_str(r"\t"),
865 b'\n' => escaped.push_str(r"\n"),
866 b'\r' => escaped.push_str(r"\r"),
867 b'"' => escaped.push_str("\\\""),
868 b'\\' => escaped.push_str("\\\\"),
869 b'\x20'..=b'\x7E' => escaped.push(*b as char),
870 _ => escaped.push_str(&format!("\\x{:02X}", b)),
871 }
872 }
873 escaped.push('"');
874 Literal::_new(escaped)
875 }
876
877 pub fn span(&self) -> Span {
878 self.span
879 }
880
881 pub fn set_span(&mut self, span: Span) {
882 self.span = span;
883 }
884
885 pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
886 None
887 }
888 }
889
890 impl Display for Literal {
891 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
892 Display::fmt(&self.text, f)
893 }
894 }
895
896 impl Debug for Literal {
897 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
898 let mut debug = fmt.debug_struct("Literal");
899 debug.field("lit", &format_args!("{}", self.text));
900 debug_span_field_if_nontrivial(&mut debug, self.span);
901 debug.finish()
902 }
903 }