1 use proc_macro2::{Literal, Span};
2 use std::fmt::{self, Display};
3 use std::str::{self, FromStr};
4 
5 #[cfg(feature = "printing")]
6 use proc_macro2::Ident;
7 
8 #[cfg(feature = "parsing")]
9 use proc_macro2::TokenStream;
10 
11 use proc_macro2::TokenTree;
12 
13 #[cfg(feature = "extra-traits")]
14 use std::hash::{Hash, Hasher};
15 
16 #[cfg(feature = "parsing")]
17 use crate::lookahead;
18 #[cfg(feature = "parsing")]
19 use crate::parse::{Parse, Parser};
20 use crate::{Error, Result};
21 
22 ast_enum_of_structs! {
23     /// A Rust literal such as a string or integer or boolean.
24     ///
25     /// # Syntax tree enum
26     ///
27     /// This type is a [syntax tree enum].
28     ///
29     /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
30     //
31     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
32     // blocked on https://github.com/rust-lang/rust/issues/62833
33     pub enum Lit #manual_extra_traits {
34         /// A UTF-8 string literal: `"foo"`.
35         Str(LitStr),
36 
37         /// A byte string literal: `b"foo"`.
38         ByteStr(LitByteStr),
39 
40         /// A byte literal: `b'f'`.
41         Byte(LitByte),
42 
43         /// A character literal: `'a'`.
44         Char(LitChar),
45 
46         /// An integer literal: `1` or `1u16`.
47         Int(LitInt),
48 
49         /// A floating point literal: `1f64` or `1.0e10f64`.
50         ///
51         /// Must be finite. May not be infinte or NaN.
52         Float(LitFloat),
53 
54         /// A boolean literal: `true` or `false`.
55         Bool(LitBool),
56 
57         /// A raw token literal not interpreted by Syn.
58         Verbatim(Literal),
59     }
60 }
61 
62 ast_struct! {
63     /// A UTF-8 string literal: `"foo"`.
64     pub struct LitStr #manual_extra_traits_debug {
65         repr: Box<LitRepr>,
66     }
67 }
68 
69 ast_struct! {
70     /// A byte string literal: `b"foo"`.
71     pub struct LitByteStr #manual_extra_traits_debug {
72         repr: Box<LitRepr>,
73     }
74 }
75 
76 ast_struct! {
77     /// A byte literal: `b'f'`.
78     pub struct LitByte #manual_extra_traits_debug {
79         repr: Box<LitRepr>,
80     }
81 }
82 
83 ast_struct! {
84     /// A character literal: `'a'`.
85     pub struct LitChar #manual_extra_traits_debug {
86         repr: Box<LitRepr>,
87     }
88 }
89 
90 #[cfg_attr(feature = "clone-impls", derive(Clone))]
91 struct LitRepr {
92     token: Literal,
93     suffix: Box<str>,
94 }
95 
96 ast_struct! {
97     /// An integer literal: `1` or `1u16`.
98     pub struct LitInt #manual_extra_traits_debug {
99         repr: Box<LitIntRepr>,
100     }
101 }
102 
103 #[cfg_attr(feature = "clone-impls", derive(Clone))]
104 struct LitIntRepr {
105     token: Literal,
106     digits: Box<str>,
107     suffix: Box<str>,
108 }
109 
110 ast_struct! {
111     /// A floating point literal: `1f64` or `1.0e10f64`.
112     ///
113     /// Must be finite. May not be infinte or NaN.
114     pub struct LitFloat #manual_extra_traits_debug {
115         repr: Box<LitFloatRepr>,
116     }
117 }
118 
119 #[cfg_attr(feature = "clone-impls", derive(Clone))]
120 struct LitFloatRepr {
121     token: Literal,
122     digits: Box<str>,
123     suffix: Box<str>,
124 }
125 
126 ast_struct! {
127     /// A boolean literal: `true` or `false`.
128     pub struct LitBool #manual_extra_traits_debug {
129         pub value: bool,
130         pub span: Span,
131     }
132 }
133 
134 #[cfg(feature = "extra-traits")]
135 impl Eq for Lit {}
136 
137 #[cfg(feature = "extra-traits")]
138 impl PartialEq for Lit {
eq(&self, other: &Self) -> bool139     fn eq(&self, other: &Self) -> bool {
140         match (self, other) {
141             (Lit::Str(this), Lit::Str(other)) => this == other,
142             (Lit::ByteStr(this), Lit::ByteStr(other)) => this == other,
143             (Lit::Byte(this), Lit::Byte(other)) => this == other,
144             (Lit::Char(this), Lit::Char(other)) => this == other,
145             (Lit::Int(this), Lit::Int(other)) => this == other,
146             (Lit::Float(this), Lit::Float(other)) => this == other,
147             (Lit::Bool(this), Lit::Bool(other)) => this == other,
148             (Lit::Verbatim(this), Lit::Verbatim(other)) => this.to_string() == other.to_string(),
149             _ => false,
150         }
151     }
152 }
153 
154 #[cfg(feature = "extra-traits")]
155 impl Hash for Lit {
hash<H>(&self, hash: &mut H) where H: Hasher,156     fn hash<H>(&self, hash: &mut H)
157     where
158         H: Hasher,
159     {
160         match self {
161             Lit::Str(lit) => {
162                 hash.write_u8(0);
163                 lit.hash(hash);
164             }
165             Lit::ByteStr(lit) => {
166                 hash.write_u8(1);
167                 lit.hash(hash);
168             }
169             Lit::Byte(lit) => {
170                 hash.write_u8(2);
171                 lit.hash(hash);
172             }
173             Lit::Char(lit) => {
174                 hash.write_u8(3);
175                 lit.hash(hash);
176             }
177             Lit::Int(lit) => {
178                 hash.write_u8(4);
179                 lit.hash(hash);
180             }
181             Lit::Float(lit) => {
182                 hash.write_u8(5);
183                 lit.hash(hash);
184             }
185             Lit::Bool(lit) => {
186                 hash.write_u8(6);
187                 lit.hash(hash);
188             }
189             Lit::Verbatim(lit) => {
190                 hash.write_u8(7);
191                 lit.to_string().hash(hash);
192             }
193         }
194     }
195 }
196 
197 impl LitStr {
new(value: &str, span: Span) -> Self198     pub fn new(value: &str, span: Span) -> Self {
199         let mut token = Literal::string(value);
200         token.set_span(span);
201         LitStr {
202             repr: Box::new(LitRepr {
203                 token,
204                 suffix: Box::<str>::default(),
205             }),
206         }
207     }
208 
value(&self) -> String209     pub fn value(&self) -> String {
210         let repr = self.repr.token.to_string();
211         let (value, _suffix) = value::parse_lit_str(&repr);
212         String::from(value)
213     }
214 
215     /// Parse a syntax tree node from the content of this string literal.
216     ///
217     /// All spans in the syntax tree will point to the span of this `LitStr`.
218     ///
219     /// # Example
220     ///
221     /// ```
222     /// use proc_macro2::Span;
223     /// use syn::{Attribute, Error, Ident, Lit, Meta, MetaNameValue, Path, Result};
224     ///
225     /// // Parses the path from an attribute that looks like:
226     /// //
227     /// //     #[path = "a::b::c"]
228     /// //
229     /// // or returns `None` if the input is some other attribute.
230     /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
231     ///     if !attr.path.is_ident("path") {
232     ///         return Ok(None);
233     ///     }
234     ///
235     ///     match attr.parse_meta()? {
236     ///         Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
237     ///             lit_str.parse().map(Some)
238     ///         }
239     ///         _ => {
240     ///             let message = "expected #[path = \"...\"]";
241     ///             Err(Error::new_spanned(attr, message))
242     ///         }
243     ///     }
244     /// }
245     /// ```
246     #[cfg(feature = "parsing")]
parse<T: Parse>(&self) -> Result<T>247     pub fn parse<T: Parse>(&self) -> Result<T> {
248         self.parse_with(T::parse)
249     }
250 
251     /// Invoke parser on the content of this string literal.
252     ///
253     /// All spans in the syntax tree will point to the span of this `LitStr`.
254     ///
255     /// # Example
256     ///
257     /// ```
258     /// # use proc_macro2::Span;
259     /// # use syn::{LitStr, Result};
260     /// #
261     /// # fn main() -> Result<()> {
262     /// #     let lit_str = LitStr::new("a::b::c", Span::call_site());
263     /// #
264     /// #     const IGNORE: &str = stringify! {
265     /// let lit_str: LitStr = /* ... */;
266     /// #     };
267     ///
268     /// // Parse a string literal like "a::b::c" into a Path, not allowing
269     /// // generic arguments on any of the path segments.
270     /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
271     /// #
272     /// #     Ok(())
273     /// # }
274     /// ```
275     #[cfg(feature = "parsing")]
parse_with<F: Parser>(&self, parser: F) -> Result<F::Output>276     pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
277         use proc_macro2::Group;
278 
279         // Token stream with every span replaced by the given one.
280         fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
281             stream
282                 .into_iter()
283                 .map(|token| respan_token_tree(token, span))
284                 .collect()
285         }
286 
287         // Token tree with every span replaced by the given one.
288         fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
289             match &mut token {
290                 TokenTree::Group(g) => {
291                     let stream = respan_token_stream(g.stream(), span);
292                     *g = Group::new(g.delimiter(), stream);
293                     g.set_span(span);
294                 }
295                 other => other.set_span(span),
296             }
297             token
298         }
299 
300         // Parse string literal into a token stream with every span equal to the
301         // original literal's span.
302         let mut tokens = crate::parse_str(&self.value())?;
303         tokens = respan_token_stream(tokens, self.span());
304 
305         parser.parse2(tokens)
306     }
307 
span(&self) -> Span308     pub fn span(&self) -> Span {
309         self.repr.token.span()
310     }
311 
set_span(&mut self, span: Span)312     pub fn set_span(&mut self, span: Span) {
313         self.repr.token.set_span(span)
314     }
315 
suffix(&self) -> &str316     pub fn suffix(&self) -> &str {
317         &self.repr.suffix
318     }
319 }
320 
321 impl LitByteStr {
new(value: &[u8], span: Span) -> Self322     pub fn new(value: &[u8], span: Span) -> Self {
323         let mut token = Literal::byte_string(value);
324         token.set_span(span);
325         LitByteStr {
326             repr: Box::new(LitRepr {
327                 token,
328                 suffix: Box::<str>::default(),
329             }),
330         }
331     }
332 
value(&self) -> Vec<u8>333     pub fn value(&self) -> Vec<u8> {
334         let repr = self.repr.token.to_string();
335         let (value, _suffix) = value::parse_lit_byte_str(&repr);
336         value
337     }
338 
span(&self) -> Span339     pub fn span(&self) -> Span {
340         self.repr.token.span()
341     }
342 
set_span(&mut self, span: Span)343     pub fn set_span(&mut self, span: Span) {
344         self.repr.token.set_span(span)
345     }
346 
suffix(&self) -> &str347     pub fn suffix(&self) -> &str {
348         &self.repr.suffix
349     }
350 }
351 
352 impl LitByte {
new(value: u8, span: Span) -> Self353     pub fn new(value: u8, span: Span) -> Self {
354         let mut token = Literal::u8_suffixed(value);
355         token.set_span(span);
356         LitByte {
357             repr: Box::new(LitRepr {
358                 token,
359                 suffix: Box::<str>::default(),
360             }),
361         }
362     }
363 
value(&self) -> u8364     pub fn value(&self) -> u8 {
365         let repr = self.repr.token.to_string();
366         let (value, _suffix) = value::parse_lit_byte(&repr);
367         value
368     }
369 
span(&self) -> Span370     pub fn span(&self) -> Span {
371         self.repr.token.span()
372     }
373 
set_span(&mut self, span: Span)374     pub fn set_span(&mut self, span: Span) {
375         self.repr.token.set_span(span)
376     }
377 
suffix(&self) -> &str378     pub fn suffix(&self) -> &str {
379         &self.repr.suffix
380     }
381 }
382 
383 impl LitChar {
new(value: char, span: Span) -> Self384     pub fn new(value: char, span: Span) -> Self {
385         let mut token = Literal::character(value);
386         token.set_span(span);
387         LitChar {
388             repr: Box::new(LitRepr {
389                 token,
390                 suffix: Box::<str>::default(),
391             }),
392         }
393     }
394 
value(&self) -> char395     pub fn value(&self) -> char {
396         let repr = self.repr.token.to_string();
397         let (value, _suffix) = value::parse_lit_char(&repr);
398         value
399     }
400 
span(&self) -> Span401     pub fn span(&self) -> Span {
402         self.repr.token.span()
403     }
404 
set_span(&mut self, span: Span)405     pub fn set_span(&mut self, span: Span) {
406         self.repr.token.set_span(span)
407     }
408 
suffix(&self) -> &str409     pub fn suffix(&self) -> &str {
410         &self.repr.suffix
411     }
412 }
413 
414 impl LitInt {
new(repr: &str, span: Span) -> Self415     pub fn new(repr: &str, span: Span) -> Self {
416         let (digits, suffix) = match value::parse_lit_int(repr) {
417             Some(parse) => parse,
418             None => panic!("Not an integer literal: `{}`", repr),
419         };
420 
421         let mut token = match value::to_literal(repr, &digits, &suffix) {
422             Some(token) => token,
423             None => panic!("Unsupported integer literal: `{}`", repr),
424         };
425 
426         token.set_span(span);
427         LitInt {
428             repr: Box::new(LitIntRepr {
429                 token,
430                 digits,
431                 suffix,
432             }),
433         }
434     }
435 
base10_digits(&self) -> &str436     pub fn base10_digits(&self) -> &str {
437         &self.repr.digits
438     }
439 
440     /// Parses the literal into a selected number type.
441     ///
442     /// This is equivalent to `lit.base10_digits().parse()` except that the
443     /// resulting errors will be correctly spanned to point to the literal token
444     /// in the macro input.
445     ///
446     /// ```
447     /// use syn::LitInt;
448     /// use syn::parse::{Parse, ParseStream, Result};
449     ///
450     /// struct Port {
451     ///     value: u16,
452     /// }
453     ///
454     /// impl Parse for Port {
455     ///     fn parse(input: ParseStream) -> Result<Self> {
456     ///         let lit: LitInt = input.parse()?;
457     ///         let value = lit.base10_parse::<u16>()?;
458     ///         Ok(Port { value })
459     ///     }
460     /// }
461     /// ```
base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display,462     pub fn base10_parse<N>(&self) -> Result<N>
463     where
464         N: FromStr,
465         N::Err: Display,
466     {
467         self.base10_digits()
468             .parse()
469             .map_err(|err| Error::new(self.span(), err))
470     }
471 
suffix(&self) -> &str472     pub fn suffix(&self) -> &str {
473         &self.repr.suffix
474     }
475 
span(&self) -> Span476     pub fn span(&self) -> Span {
477         self.repr.token.span()
478     }
479 
set_span(&mut self, span: Span)480     pub fn set_span(&mut self, span: Span) {
481         self.repr.token.set_span(span)
482     }
483 }
484 
485 impl From<Literal> for LitInt {
from(token: Literal) -> Self486     fn from(token: Literal) -> Self {
487         let repr = token.to_string();
488         if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
489             LitInt {
490                 repr: Box::new(LitIntRepr {
491                     token,
492                     digits,
493                     suffix,
494                 }),
495             }
496         } else {
497             panic!("Not an integer literal: `{}`", repr);
498         }
499     }
500 }
501 
502 impl Display for LitInt {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result503     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
504         self.repr.token.fmt(formatter)
505     }
506 }
507 
508 impl LitFloat {
new(repr: &str, span: Span) -> Self509     pub fn new(repr: &str, span: Span) -> Self {
510         let (digits, suffix) = match value::parse_lit_float(repr) {
511             Some(parse) => parse,
512             None => panic!("Not a float literal: `{}`", repr),
513         };
514 
515         let mut token = match value::to_literal(repr, &digits, &suffix) {
516             Some(token) => token,
517             None => panic!("Unsupported float literal: `{}`", repr),
518         };
519 
520         token.set_span(span);
521         LitFloat {
522             repr: Box::new(LitFloatRepr {
523                 token,
524                 digits,
525                 suffix,
526             }),
527         }
528     }
529 
base10_digits(&self) -> &str530     pub fn base10_digits(&self) -> &str {
531         &self.repr.digits
532     }
533 
base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display,534     pub fn base10_parse<N>(&self) -> Result<N>
535     where
536         N: FromStr,
537         N::Err: Display,
538     {
539         self.base10_digits()
540             .parse()
541             .map_err(|err| Error::new(self.span(), err))
542     }
543 
suffix(&self) -> &str544     pub fn suffix(&self) -> &str {
545         &self.repr.suffix
546     }
547 
span(&self) -> Span548     pub fn span(&self) -> Span {
549         self.repr.token.span()
550     }
551 
set_span(&mut self, span: Span)552     pub fn set_span(&mut self, span: Span) {
553         self.repr.token.set_span(span)
554     }
555 }
556 
557 impl From<Literal> for LitFloat {
from(token: Literal) -> Self558     fn from(token: Literal) -> Self {
559         let repr = token.to_string();
560         if let Some((digits, suffix)) = value::parse_lit_float(&repr) {
561             LitFloat {
562                 repr: Box::new(LitFloatRepr {
563                     token,
564                     digits,
565                     suffix,
566                 }),
567             }
568         } else {
569             panic!("Not a float literal: `{}`", repr);
570         }
571     }
572 }
573 
574 impl Display for LitFloat {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result575     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
576         self.repr.token.fmt(formatter)
577     }
578 }
579 
580 #[cfg(feature = "extra-traits")]
581 mod debug_impls {
582     use super::*;
583     use std::fmt::{self, Debug};
584 
585     impl Debug for LitStr {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result586         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
587             formatter
588                 .debug_struct("LitStr")
589                 .field("token", &format_args!("{}", self.repr.token))
590                 .finish()
591         }
592     }
593 
594     impl Debug for LitByteStr {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result595         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
596             formatter
597                 .debug_struct("LitByteStr")
598                 .field("token", &format_args!("{}", self.repr.token))
599                 .finish()
600         }
601     }
602 
603     impl Debug for LitByte {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result604         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
605             formatter
606                 .debug_struct("LitByte")
607                 .field("token", &format_args!("{}", self.repr.token))
608                 .finish()
609         }
610     }
611 
612     impl Debug for LitChar {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result613         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
614             formatter
615                 .debug_struct("LitChar")
616                 .field("token", &format_args!("{}", self.repr.token))
617                 .finish()
618         }
619     }
620 
621     impl Debug for LitInt {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result622         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
623             formatter
624                 .debug_struct("LitInt")
625                 .field("token", &format_args!("{}", self.repr.token))
626                 .finish()
627         }
628     }
629 
630     impl Debug for LitFloat {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result631         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
632             formatter
633                 .debug_struct("LitFloat")
634                 .field("token", &format_args!("{}", self.repr.token))
635                 .finish()
636         }
637     }
638 
639     impl Debug for LitBool {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result640         fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
641             formatter
642                 .debug_struct("LitBool")
643                 .field("value", &self.value)
644                 .finish()
645         }
646     }
647 }
648 
649 macro_rules! lit_extra_traits {
650     ($ty:ident, $($field:ident).+) => {
651         #[cfg(feature = "extra-traits")]
652         impl Eq for $ty {}
653 
654         #[cfg(feature = "extra-traits")]
655         impl PartialEq for $ty {
656             fn eq(&self, other: &Self) -> bool {
657                 self.$($field).+.to_string() == other.$($field).+.to_string()
658             }
659         }
660 
661         #[cfg(feature = "extra-traits")]
662         impl Hash for $ty {
663             fn hash<H>(&self, state: &mut H)
664             where
665                 H: Hasher,
666             {
667                 self.$($field).+.to_string().hash(state);
668             }
669         }
670 
671         #[cfg(feature = "parsing")]
672         #[doc(hidden)]
673         #[allow(non_snake_case)]
674         pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
675             match marker {}
676         }
677     };
678 }
679 
680 lit_extra_traits!(LitStr, repr.token);
681 lit_extra_traits!(LitByteStr, repr.token);
682 lit_extra_traits!(LitByte, repr.token);
683 lit_extra_traits!(LitChar, repr.token);
684 lit_extra_traits!(LitInt, repr.token);
685 lit_extra_traits!(LitFloat, repr.token);
686 lit_extra_traits!(LitBool, value);
687 
688 ast_enum! {
689     /// The style of a string literal, either plain quoted or a raw string like
690     /// `r##"data"##`.
691     pub enum StrStyle #no_visit {
692         /// An ordinary string like `"data"`.
693         Cooked,
694         /// A raw string like `r##"data"##`.
695         ///
696         /// The unsigned integer is the number of `#` symbols used.
697         Raw(usize),
698     }
699 }
700 
701 #[cfg(feature = "parsing")]
702 #[doc(hidden)]
703 #[allow(non_snake_case)]
Lit(marker: lookahead::TokenMarker) -> Lit704 pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
705     match marker {}
706 }
707 
708 #[cfg(feature = "parsing")]
709 pub mod parsing {
710     use super::*;
711     use crate::buffer::Cursor;
712     use crate::parse::{Parse, ParseStream, Result};
713     use proc_macro2::Punct;
714 
715     impl Parse for Lit {
parse(input: ParseStream) -> Result<Self>716         fn parse(input: ParseStream) -> Result<Self> {
717             input.step(|cursor| {
718                 if let Some((lit, rest)) = cursor.literal() {
719                     return Ok((Lit::new(lit), rest));
720                 }
721 
722                 if let Some((ident, rest)) = cursor.ident() {
723                     let value = ident == "true";
724                     if value || ident == "false" {
725                         let lit_bool = LitBool {
726                             value,
727                             span: ident.span(),
728                         };
729                         return Ok((Lit::Bool(lit_bool), rest));
730                     }
731                 }
732 
733                 if let Some((punct, rest)) = cursor.punct() {
734                     if punct.as_char() == '-' {
735                         if let Some((lit, rest)) = parse_negative_lit(punct, rest) {
736                             return Ok((lit, rest));
737                         }
738                     }
739                 }
740 
741                 Err(cursor.error("expected literal"))
742             })
743         }
744     }
745 
parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)>746     fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> {
747         let (lit, rest) = cursor.literal()?;
748 
749         let mut span = neg.span();
750         span = span.join(lit.span()).unwrap_or(span);
751 
752         let mut repr = lit.to_string();
753         repr.insert(0, '-');
754 
755         if !(repr.ends_with("f32") || repr.ends_with("f64")) {
756             if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
757                 if let Some(mut token) = value::to_literal(&repr, &digits, &suffix) {
758                     token.set_span(span);
759                     return Some((
760                         Lit::Int(LitInt {
761                             repr: Box::new(LitIntRepr {
762                                 token,
763                                 digits,
764                                 suffix,
765                             }),
766                         }),
767                         rest,
768                     ));
769                 }
770             }
771         }
772 
773         let (digits, suffix) = value::parse_lit_float(&repr)?;
774         let mut token = value::to_literal(&repr, &digits, &suffix)?;
775         token.set_span(span);
776         Some((
777             Lit::Float(LitFloat {
778                 repr: Box::new(LitFloatRepr {
779                     token,
780                     digits,
781                     suffix,
782                 }),
783             }),
784             rest,
785         ))
786     }
787 
788     impl Parse for LitStr {
parse(input: ParseStream) -> Result<Self>789         fn parse(input: ParseStream) -> Result<Self> {
790             let head = input.fork();
791             match input.parse()? {
792                 Lit::Str(lit) => Ok(lit),
793                 _ => Err(head.error("expected string literal")),
794             }
795         }
796     }
797 
798     impl Parse for LitByteStr {
parse(input: ParseStream) -> Result<Self>799         fn parse(input: ParseStream) -> Result<Self> {
800             let head = input.fork();
801             match input.parse()? {
802                 Lit::ByteStr(lit) => Ok(lit),
803                 _ => Err(head.error("expected byte string literal")),
804             }
805         }
806     }
807 
808     impl Parse for LitByte {
parse(input: ParseStream) -> Result<Self>809         fn parse(input: ParseStream) -> Result<Self> {
810             let head = input.fork();
811             match input.parse()? {
812                 Lit::Byte(lit) => Ok(lit),
813                 _ => Err(head.error("expected byte literal")),
814             }
815         }
816     }
817 
818     impl Parse for LitChar {
parse(input: ParseStream) -> Result<Self>819         fn parse(input: ParseStream) -> Result<Self> {
820             let head = input.fork();
821             match input.parse()? {
822                 Lit::Char(lit) => Ok(lit),
823                 _ => Err(head.error("expected character literal")),
824             }
825         }
826     }
827 
828     impl Parse for LitInt {
parse(input: ParseStream) -> Result<Self>829         fn parse(input: ParseStream) -> Result<Self> {
830             let head = input.fork();
831             match input.parse()? {
832                 Lit::Int(lit) => Ok(lit),
833                 _ => Err(head.error("expected integer literal")),
834             }
835         }
836     }
837 
838     impl Parse for LitFloat {
parse(input: ParseStream) -> Result<Self>839         fn parse(input: ParseStream) -> Result<Self> {
840             let head = input.fork();
841             match input.parse()? {
842                 Lit::Float(lit) => Ok(lit),
843                 _ => Err(head.error("expected floating point literal")),
844             }
845         }
846     }
847 
848     impl Parse for LitBool {
parse(input: ParseStream) -> Result<Self>849         fn parse(input: ParseStream) -> Result<Self> {
850             let head = input.fork();
851             match input.parse()? {
852                 Lit::Bool(lit) => Ok(lit),
853                 _ => Err(head.error("expected boolean literal")),
854             }
855         }
856     }
857 }
858 
859 #[cfg(feature = "printing")]
860 mod printing {
861     use super::*;
862     use proc_macro2::TokenStream;
863     use quote::{ToTokens, TokenStreamExt};
864 
865     impl ToTokens for LitStr {
to_tokens(&self, tokens: &mut TokenStream)866         fn to_tokens(&self, tokens: &mut TokenStream) {
867             self.repr.token.to_tokens(tokens);
868         }
869     }
870 
871     impl ToTokens for LitByteStr {
to_tokens(&self, tokens: &mut TokenStream)872         fn to_tokens(&self, tokens: &mut TokenStream) {
873             self.repr.token.to_tokens(tokens);
874         }
875     }
876 
877     impl ToTokens for LitByte {
to_tokens(&self, tokens: &mut TokenStream)878         fn to_tokens(&self, tokens: &mut TokenStream) {
879             self.repr.token.to_tokens(tokens);
880         }
881     }
882 
883     impl ToTokens for LitChar {
to_tokens(&self, tokens: &mut TokenStream)884         fn to_tokens(&self, tokens: &mut TokenStream) {
885             self.repr.token.to_tokens(tokens);
886         }
887     }
888 
889     impl ToTokens for LitInt {
to_tokens(&self, tokens: &mut TokenStream)890         fn to_tokens(&self, tokens: &mut TokenStream) {
891             self.repr.token.to_tokens(tokens);
892         }
893     }
894 
895     impl ToTokens for LitFloat {
to_tokens(&self, tokens: &mut TokenStream)896         fn to_tokens(&self, tokens: &mut TokenStream) {
897             self.repr.token.to_tokens(tokens);
898         }
899     }
900 
901     impl ToTokens for LitBool {
to_tokens(&self, tokens: &mut TokenStream)902         fn to_tokens(&self, tokens: &mut TokenStream) {
903             let s = if self.value { "true" } else { "false" };
904             tokens.append(Ident::new(s, self.span));
905         }
906     }
907 }
908 
909 mod value {
910     use super::*;
911     use crate::bigint::BigInt;
912     use proc_macro2::TokenStream;
913     use std::char;
914     use std::ops::{Index, RangeFrom};
915 
916     impl Lit {
917         /// Interpret a Syn literal from a proc-macro2 literal.
new(token: Literal) -> Self918         pub fn new(token: Literal) -> Self {
919             let repr = token.to_string();
920 
921             match byte(&repr, 0) {
922                 b'"' | b'r' => {
923                     let (_, suffix) = parse_lit_str(&repr);
924                     return Lit::Str(LitStr {
925                         repr: Box::new(LitRepr { token, suffix }),
926                     });
927                 }
928                 b'b' => match byte(&repr, 1) {
929                     b'"' | b'r' => {
930                         let (_, suffix) = parse_lit_byte_str(&repr);
931                         return Lit::ByteStr(LitByteStr {
932                             repr: Box::new(LitRepr { token, suffix }),
933                         });
934                     }
935                     b'\'' => {
936                         let (_, suffix) = parse_lit_byte(&repr);
937                         return Lit::Byte(LitByte {
938                             repr: Box::new(LitRepr { token, suffix }),
939                         });
940                     }
941                     _ => {}
942                 },
943                 b'\'' => {
944                     let (_, suffix) = parse_lit_char(&repr);
945                     return Lit::Char(LitChar {
946                         repr: Box::new(LitRepr { token, suffix }),
947                     });
948                 }
949                 b'0'..=b'9' | b'-' => {
950                     if !(repr.ends_with("f32") || repr.ends_with("f64")) {
951                         if let Some((digits, suffix)) = parse_lit_int(&repr) {
952                             return Lit::Int(LitInt {
953                                 repr: Box::new(LitIntRepr {
954                                     token,
955                                     digits,
956                                     suffix,
957                                 }),
958                             });
959                         }
960                     }
961                     if let Some((digits, suffix)) = parse_lit_float(&repr) {
962                         return Lit::Float(LitFloat {
963                             repr: Box::new(LitFloatRepr {
964                                 token,
965                                 digits,
966                                 suffix,
967                             }),
968                         });
969                     }
970                 }
971                 b't' | b'f' => {
972                     if repr == "true" || repr == "false" {
973                         return Lit::Bool(LitBool {
974                             value: repr == "true",
975                             span: token.span(),
976                         });
977                     }
978                 }
979                 _ => {}
980             }
981 
982             panic!("Unrecognized literal: `{}`", repr);
983         }
984 
suffix(&self) -> &str985         pub fn suffix(&self) -> &str {
986             match self {
987                 Lit::Str(lit) => lit.suffix(),
988                 Lit::ByteStr(lit) => lit.suffix(),
989                 Lit::Byte(lit) => lit.suffix(),
990                 Lit::Char(lit) => lit.suffix(),
991                 Lit::Int(lit) => lit.suffix(),
992                 Lit::Float(lit) => lit.suffix(),
993                 Lit::Bool(_) | Lit::Verbatim(_) => "",
994             }
995         }
996     }
997 
998     /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
999     /// past the end of the input buffer.
byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u81000     pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
1001         let s = s.as_ref();
1002         if idx < s.len() {
1003             s[idx]
1004         } else {
1005             0
1006         }
1007     }
1008 
next_chr(s: &str) -> char1009     fn next_chr(s: &str) -> char {
1010         s.chars().next().unwrap_or('\0')
1011     }
1012 
1013     // Returns (content, suffix).
parse_lit_str(s: &str) -> (Box<str>, Box<str>)1014     pub fn parse_lit_str(s: &str) -> (Box<str>, Box<str>) {
1015         match byte(s, 0) {
1016             b'"' => parse_lit_str_cooked(s),
1017             b'r' => parse_lit_str_raw(s),
1018             _ => unreachable!(),
1019         }
1020     }
1021 
1022     // Clippy false positive
1023     // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1024     #[allow(clippy::needless_continue)]
parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>)1025     fn parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>) {
1026         assert_eq!(byte(s, 0), b'"');
1027         s = &s[1..];
1028 
1029         let mut content = String::new();
1030         'outer: loop {
1031             let ch = match byte(s, 0) {
1032                 b'"' => break,
1033                 b'\\' => {
1034                     let b = byte(s, 1);
1035                     s = &s[2..];
1036                     match b {
1037                         b'x' => {
1038                             let (byte, rest) = backslash_x(s);
1039                             s = rest;
1040                             assert!(byte <= 0x80, "Invalid \\x byte in string literal");
1041                             char::from_u32(u32::from(byte)).unwrap()
1042                         }
1043                         b'u' => {
1044                             let (chr, rest) = backslash_u(s);
1045                             s = rest;
1046                             chr
1047                         }
1048                         b'n' => '\n',
1049                         b'r' => '\r',
1050                         b't' => '\t',
1051                         b'\\' => '\\',
1052                         b'0' => '\0',
1053                         b'\'' => '\'',
1054                         b'"' => '"',
1055                         b'\r' | b'\n' => loop {
1056                             let ch = next_chr(s);
1057                             if ch.is_whitespace() {
1058                                 s = &s[ch.len_utf8()..];
1059                             } else {
1060                                 continue 'outer;
1061                             }
1062                         },
1063                         b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1064                     }
1065                 }
1066                 b'\r' => {
1067                     assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
1068                     s = &s[2..];
1069                     '\n'
1070                 }
1071                 _ => {
1072                     let ch = next_chr(s);
1073                     s = &s[ch.len_utf8()..];
1074                     ch
1075                 }
1076             };
1077             content.push(ch);
1078         }
1079 
1080         assert!(s.starts_with('"'));
1081         let content = content.into_boxed_str();
1082         let suffix = s[1..].to_owned().into_boxed_str();
1083         (content, suffix)
1084     }
1085 
parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>)1086     fn parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>) {
1087         assert_eq!(byte(s, 0), b'r');
1088         s = &s[1..];
1089 
1090         let mut pounds = 0;
1091         while byte(s, pounds) == b'#' {
1092             pounds += 1;
1093         }
1094         assert_eq!(byte(s, pounds), b'"');
1095         let close = s.rfind('"').unwrap();
1096         for end in s[close + 1..close + 1 + pounds].bytes() {
1097             assert_eq!(end, b'#');
1098         }
1099 
1100         let content = s[pounds + 1..close].to_owned().into_boxed_str();
1101         let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str();
1102         (content, suffix)
1103     }
1104 
1105     // Returns (content, suffix).
parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>)1106     pub fn parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>) {
1107         assert_eq!(byte(s, 0), b'b');
1108         match byte(s, 1) {
1109             b'"' => parse_lit_byte_str_cooked(s),
1110             b'r' => parse_lit_byte_str_raw(s),
1111             _ => unreachable!(),
1112         }
1113     }
1114 
1115     // Clippy false positive
1116     // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1117     #[allow(clippy::needless_continue)]
parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>)1118     fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>) {
1119         assert_eq!(byte(s, 0), b'b');
1120         assert_eq!(byte(s, 1), b'"');
1121         s = &s[2..];
1122 
1123         // We're going to want to have slices which don't respect codepoint boundaries.
1124         let mut v = s.as_bytes();
1125 
1126         let mut out = Vec::new();
1127         'outer: loop {
1128             let byte = match byte(v, 0) {
1129                 b'"' => break,
1130                 b'\\' => {
1131                     let b = byte(v, 1);
1132                     v = &v[2..];
1133                     match b {
1134                         b'x' => {
1135                             let (b, rest) = backslash_x(v);
1136                             v = rest;
1137                             b
1138                         }
1139                         b'n' => b'\n',
1140                         b'r' => b'\r',
1141                         b't' => b'\t',
1142                         b'\\' => b'\\',
1143                         b'0' => b'\0',
1144                         b'\'' => b'\'',
1145                         b'"' => b'"',
1146                         b'\r' | b'\n' => loop {
1147                             let byte = byte(v, 0);
1148                             let ch = char::from_u32(u32::from(byte)).unwrap();
1149                             if ch.is_whitespace() {
1150                                 v = &v[1..];
1151                             } else {
1152                                 continue 'outer;
1153                             }
1154                         },
1155                         b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1156                     }
1157                 }
1158                 b'\r' => {
1159                     assert_eq!(byte(v, 1), b'\n', "Bare CR not allowed in string");
1160                     v = &v[2..];
1161                     b'\n'
1162                 }
1163                 b => {
1164                     v = &v[1..];
1165                     b
1166                 }
1167             };
1168             out.push(byte);
1169         }
1170 
1171         assert_eq!(byte(v, 0), b'"');
1172         let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1173         (out, suffix)
1174     }
1175 
parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>)1176     fn parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>) {
1177         assert_eq!(byte(s, 0), b'b');
1178         let (value, suffix) = parse_lit_str_raw(&s[1..]);
1179         (String::from(value).into_bytes(), suffix)
1180     }
1181 
1182     // Returns (value, suffix).
parse_lit_byte(s: &str) -> (u8, Box<str>)1183     pub fn parse_lit_byte(s: &str) -> (u8, Box<str>) {
1184         assert_eq!(byte(s, 0), b'b');
1185         assert_eq!(byte(s, 1), b'\'');
1186 
1187         // We're going to want to have slices which don't respect codepoint boundaries.
1188         let mut v = s[2..].as_bytes();
1189 
1190         let b = match byte(v, 0) {
1191             b'\\' => {
1192                 let b = byte(v, 1);
1193                 v = &v[2..];
1194                 match b {
1195                     b'x' => {
1196                         let (b, rest) = backslash_x(v);
1197                         v = rest;
1198                         b
1199                     }
1200                     b'n' => b'\n',
1201                     b'r' => b'\r',
1202                     b't' => b'\t',
1203                     b'\\' => b'\\',
1204                     b'0' => b'\0',
1205                     b'\'' => b'\'',
1206                     b'"' => b'"',
1207                     b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1208                 }
1209             }
1210             b => {
1211                 v = &v[1..];
1212                 b
1213             }
1214         };
1215 
1216         assert_eq!(byte(v, 0), b'\'');
1217         let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1218         (b, suffix)
1219     }
1220 
1221     // Returns (value, suffix).
parse_lit_char(mut s: &str) -> (char, Box<str>)1222     pub fn parse_lit_char(mut s: &str) -> (char, Box<str>) {
1223         assert_eq!(byte(s, 0), b'\'');
1224         s = &s[1..];
1225 
1226         let ch = match byte(s, 0) {
1227             b'\\' => {
1228                 let b = byte(s, 1);
1229                 s = &s[2..];
1230                 match b {
1231                     b'x' => {
1232                         let (byte, rest) = backslash_x(s);
1233                         s = rest;
1234                         assert!(byte <= 0x80, "Invalid \\x byte in string literal");
1235                         char::from_u32(u32::from(byte)).unwrap()
1236                     }
1237                     b'u' => {
1238                         let (chr, rest) = backslash_u(s);
1239                         s = rest;
1240                         chr
1241                     }
1242                     b'n' => '\n',
1243                     b'r' => '\r',
1244                     b't' => '\t',
1245                     b'\\' => '\\',
1246                     b'0' => '\0',
1247                     b'\'' => '\'',
1248                     b'"' => '"',
1249                     b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
1250                 }
1251             }
1252             _ => {
1253                 let ch = next_chr(s);
1254                 s = &s[ch.len_utf8()..];
1255                 ch
1256             }
1257         };
1258         assert_eq!(byte(s, 0), b'\'');
1259         let suffix = s[1..].to_owned().into_boxed_str();
1260         (ch, suffix)
1261     }
1262 
backslash_x<S>(s: &S) -> (u8, &S) where S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,1263     fn backslash_x<S>(s: &S) -> (u8, &S)
1264     where
1265         S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1266     {
1267         let mut ch = 0;
1268         let b0 = byte(s, 0);
1269         let b1 = byte(s, 1);
1270         ch += 0x10
1271             * match b0 {
1272                 b'0'..=b'9' => b0 - b'0',
1273                 b'a'..=b'f' => 10 + (b0 - b'a'),
1274                 b'A'..=b'F' => 10 + (b0 - b'A'),
1275                 _ => panic!("unexpected non-hex character after \\x"),
1276             };
1277         ch += match b1 {
1278             b'0'..=b'9' => b1 - b'0',
1279             b'a'..=b'f' => 10 + (b1 - b'a'),
1280             b'A'..=b'F' => 10 + (b1 - b'A'),
1281             _ => panic!("unexpected non-hex character after \\x"),
1282         };
1283         (ch, &s[2..])
1284     }
1285 
backslash_u(mut s: &str) -> (char, &str)1286     fn backslash_u(mut s: &str) -> (char, &str) {
1287         if byte(s, 0) != b'{' {
1288             panic!("expected {{ after \\u");
1289         }
1290         s = &s[1..];
1291 
1292         let mut ch = 0;
1293         for _ in 0..6 {
1294             let b = byte(s, 0);
1295             match b {
1296                 b'0'..=b'9' => {
1297                     ch *= 0x10;
1298                     ch += u32::from(b - b'0');
1299                     s = &s[1..];
1300                 }
1301                 b'a'..=b'f' => {
1302                     ch *= 0x10;
1303                     ch += u32::from(10 + b - b'a');
1304                     s = &s[1..];
1305                 }
1306                 b'A'..=b'F' => {
1307                     ch *= 0x10;
1308                     ch += u32::from(10 + b - b'A');
1309                     s = &s[1..];
1310                 }
1311                 b'}' => break,
1312                 _ => panic!("unexpected non-hex character after \\u"),
1313             }
1314         }
1315         assert!(byte(s, 0) == b'}');
1316         s = &s[1..];
1317 
1318         if let Some(ch) = char::from_u32(ch) {
1319             (ch, s)
1320         } else {
1321             panic!("character code {:x} is not a valid unicode character", ch);
1322         }
1323     }
1324 
1325     // Returns base 10 digits and suffix.
parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)>1326     pub fn parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1327         let negative = byte(s, 0) == b'-';
1328         if negative {
1329             s = &s[1..];
1330         }
1331 
1332         let base = match (byte(s, 0), byte(s, 1)) {
1333             (b'0', b'x') => {
1334                 s = &s[2..];
1335                 16
1336             }
1337             (b'0', b'o') => {
1338                 s = &s[2..];
1339                 8
1340             }
1341             (b'0', b'b') => {
1342                 s = &s[2..];
1343                 2
1344             }
1345             (b'0'..=b'9', _) => 10,
1346             _ => return None,
1347         };
1348 
1349         let mut value = BigInt::new();
1350         loop {
1351             let b = byte(s, 0);
1352             let digit = match b {
1353                 b'0'..=b'9' => b - b'0',
1354                 b'a'..=b'f' if base > 10 => b - b'a' + 10,
1355                 b'A'..=b'F' if base > 10 => b - b'A' + 10,
1356                 b'_' => {
1357                     s = &s[1..];
1358                     continue;
1359                 }
1360                 // NOTE: Looking at a floating point literal, we don't want to
1361                 // consider these integers.
1362                 b'.' if base == 10 => return None,
1363                 b'e' | b'E' if base == 10 => return None,
1364                 _ => break,
1365             };
1366 
1367             if digit >= base {
1368                 return None;
1369             }
1370 
1371             value *= base;
1372             value += digit;
1373             s = &s[1..];
1374         }
1375 
1376         let suffix = s;
1377         if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1378             let mut repr = value.to_string();
1379             if negative {
1380                 repr.insert(0, '-');
1381             }
1382             Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str()))
1383         } else {
1384             None
1385         }
1386     }
1387 
1388     // Returns base 10 digits and suffix.
parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)>1389     pub fn parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)> {
1390         // Rust's floating point literals are very similar to the ones parsed by
1391         // the standard library, except that rust's literals can contain
1392         // ignorable underscores. Let's remove those underscores.
1393 
1394         let mut bytes = input.to_owned().into_bytes();
1395 
1396         let start = (*bytes.get(0)? == b'-') as usize;
1397         match bytes.get(start)? {
1398             b'0'..=b'9' => {}
1399             _ => return None,
1400         }
1401 
1402         let mut read = start;
1403         let mut write = start;
1404         let mut has_dot = false;
1405         let mut has_e = false;
1406         let mut has_sign = false;
1407         let mut has_exponent = false;
1408         while read < bytes.len() {
1409             match bytes[read] {
1410                 b'_' => {
1411                     // Don't increase write
1412                     read += 1;
1413                     continue;
1414                 }
1415                 b'0'..=b'9' => {
1416                     if has_e {
1417                         has_exponent = true;
1418                     }
1419                     bytes[write] = bytes[read];
1420                 }
1421                 b'.' => {
1422                     if has_e || has_dot {
1423                         return None;
1424                     }
1425                     has_dot = true;
1426                     bytes[write] = b'.';
1427                 }
1428                 b'e' | b'E' => {
1429                     if has_e {
1430                         return None;
1431                     }
1432                     has_e = true;
1433                     bytes[write] = b'e';
1434                 }
1435                 b'-' | b'+' => {
1436                     if has_sign || has_exponent || !has_e {
1437                         return None;
1438                     }
1439                     has_sign = true;
1440                     if bytes[read] == b'-' {
1441                         bytes[write] = bytes[read];
1442                     } else {
1443                         // Omit '+'
1444                         read += 1;
1445                         continue;
1446                     }
1447                 }
1448                 _ => break,
1449             }
1450             read += 1;
1451             write += 1;
1452         }
1453 
1454         if has_e && !has_exponent {
1455             return None;
1456         }
1457 
1458         let mut digits = String::from_utf8(bytes).unwrap();
1459         let suffix = digits.split_off(read);
1460         digits.truncate(write);
1461         if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1462             Some((digits.into_boxed_str(), suffix.into_boxed_str()))
1463         } else {
1464             None
1465         }
1466     }
1467 
to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal>1468     pub fn to_literal(repr: &str, digits: &str, suffix: &str) -> Option<Literal> {
1469         if repr.starts_with('-') {
1470             if suffix == "f64" {
1471                 digits.parse().ok().map(Literal::f64_suffixed)
1472             } else if suffix == "f32" {
1473                 digits.parse().ok().map(Literal::f32_suffixed)
1474             } else if suffix == "i64" {
1475                 digits.parse().ok().map(Literal::i64_suffixed)
1476             } else if suffix == "i32" {
1477                 digits.parse().ok().map(Literal::i32_suffixed)
1478             } else if suffix == "i16" {
1479                 digits.parse().ok().map(Literal::i16_suffixed)
1480             } else if suffix == "i8" {
1481                 digits.parse().ok().map(Literal::i8_suffixed)
1482             } else if !suffix.is_empty() {
1483                 None
1484             } else if digits.contains('.') {
1485                 digits.parse().ok().map(Literal::f64_unsuffixed)
1486             } else {
1487                 digits.parse().ok().map(Literal::i64_unsuffixed)
1488             }
1489         } else {
1490             let stream = repr.parse::<TokenStream>().unwrap();
1491             match stream.into_iter().next().unwrap() {
1492                 TokenTree::Literal(l) => Some(l),
1493                 _ => unreachable!(),
1494             }
1495         }
1496     }
1497 }
1498