syn_pub_items/
lit.rs

1use proc_macro2::{Literal, Span};
2use std::str;
3
4#[cfg(feature = "printing")]
5use proc_macro2::Ident;
6
7#[cfg(feature = "parsing")]
8use proc_macro2::TokenStream;
9
10use proc_macro2::TokenTree;
11
12#[cfg(feature = "extra-traits")]
13use std::hash::{Hash, Hasher};
14
15#[cfg(feature = "parsing")]
16use lookahead;
17#[cfg(feature = "parsing")]
18use parse::{Parse, Parser, Result};
19
20ast_enum_of_structs! {
21    /// A Rust literal such as a string or integer or boolean.
22    ///
23    /// *This type is available if Syn is built with the `"derive"` or `"full"`
24    /// feature.*
25    ///
26    /// # Syntax tree enum
27    ///
28    /// This type is a [syntax tree enum].
29    ///
30    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
31    pub enum Lit {
32        /// A UTF-8 string literal: `"foo"`.
33        ///
34        /// *This type is available if Syn is built with the `"derive"` or
35        /// `"full"` feature.*
36        pub Str(LitStr #manual_extra_traits {
37            token: Literal,
38        }),
39
40        /// A byte string literal: `b"foo"`.
41        ///
42        /// *This type is available if Syn is built with the `"derive"` or
43        /// `"full"` feature.*
44        pub ByteStr(LitByteStr #manual_extra_traits {
45            token: Literal,
46        }),
47
48        /// A byte literal: `b'f'`.
49        ///
50        /// *This type is available if Syn is built with the `"derive"` or
51        /// `"full"` feature.*
52        pub Byte(LitByte #manual_extra_traits {
53            token: Literal,
54        }),
55
56        /// A character literal: `'a'`.
57        ///
58        /// *This type is available if Syn is built with the `"derive"` or
59        /// `"full"` feature.*
60        pub Char(LitChar #manual_extra_traits {
61            token: Literal,
62        }),
63
64        /// An integer literal: `1` or `1u16`.
65        ///
66        /// Holds up to 64 bits of data. Use `LitVerbatim` for any larger
67        /// integer literal.
68        ///
69        /// *This type is available if Syn is built with the `"derive"` or
70        /// `"full"` feature.*
71        pub Int(LitInt #manual_extra_traits {
72            token: Literal,
73        }),
74
75        /// A floating point literal: `1f64` or `1.0e10f64`.
76        ///
77        /// Must be finite. May not be infinte or NaN.
78        ///
79        /// *This type is available if Syn is built with the `"derive"` or
80        /// `"full"` feature.*
81        pub Float(LitFloat #manual_extra_traits {
82            token: Literal,
83        }),
84
85        /// A boolean literal: `true` or `false`.
86        ///
87        /// *This type is available if Syn is built with the `"derive"` or
88        /// `"full"` feature.*
89        pub Bool(LitBool #manual_extra_traits {
90            pub value: bool,
91            pub span: Span,
92        }),
93
94        /// A raw token literal not interpreted by Syn, possibly because it
95        /// represents an integer larger than 64 bits.
96        ///
97        /// *This type is available if Syn is built with the `"derive"` or
98        /// `"full"` feature.*
99        pub Verbatim(LitVerbatim #manual_extra_traits {
100            pub token: Literal,
101        }),
102    }
103}
104
105impl LitStr {
106    pub fn new(value: &str, span: Span) -> Self {
107        let mut lit = Literal::string(value);
108        lit.set_span(span);
109        LitStr { token: lit }
110    }
111
112    pub fn value(&self) -> String {
113        value::parse_lit_str(&self.token.to_string())
114    }
115
116    /// Parse a syntax tree node from the content of this string literal.
117    ///
118    /// All spans in the syntax tree will point to the span of this `LitStr`.
119    ///
120    /// # Example
121    ///
122    /// ```edition2018
123    /// use proc_macro2::Span;
124    /// use syn::{Attribute, Error, Ident, Lit, Meta, MetaNameValue, Path, Result};
125    ///
126    /// // Parses the path from an attribute that looks like:
127    /// //
128    /// //     #[path = "a::b::c"]
129    /// //
130    /// // or returns `None` if the input is some other attribute.
131    /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
132    ///     if !attr.path.is_ident("path") {
133    ///         return Ok(None);
134    ///     }
135    ///
136    ///     match attr.parse_meta()? {
137    ///         Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
138    ///             lit_str.parse().map(Some)
139    ///         }
140    ///         _ => {
141    ///             let message = "expected #[path = \"...\"]";
142    ///             Err(Error::new_spanned(attr, message))
143    ///         }
144    ///     }
145    /// }
146    /// ```
147    #[cfg(feature = "parsing")]
148    pub fn parse<T: Parse>(&self) -> Result<T> {
149        self.parse_with(T::parse)
150    }
151
152    /// Invoke parser on the content of this string literal.
153    ///
154    /// All spans in the syntax tree will point to the span of this `LitStr`.
155    ///
156    /// # Example
157    ///
158    /// ```edition2018
159    /// # use proc_macro2::Span;
160    /// # use syn::{LitStr, Result};
161    /// #
162    /// # fn main() -> Result<()> {
163    /// #     let lit_str = LitStr::new("a::b::c", Span::call_site());
164    /// #
165    /// #     const IGNORE: &str = stringify! {
166    /// let lit_str: LitStr = /* ... */;
167    /// #     };
168    ///
169    /// // Parse a string literal like "a::b::c" into a Path, not allowing
170    /// // generic arguments on any of the path segments.
171    /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
172    /// #
173    /// #     Ok(())
174    /// # }
175    /// ```
176    #[cfg(feature = "parsing")]
177    pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
178        use proc_macro2::Group;
179
180        // Token stream with every span replaced by the given one.
181        fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
182            stream
183                .into_iter()
184                .map(|token| respan_token_tree(token, span))
185                .collect()
186        }
187
188        // Token tree with every span replaced by the given one.
189        fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
190            match token {
191                TokenTree::Group(ref mut g) => {
192                    let stream = respan_token_stream(g.stream().clone(), span);
193                    *g = Group::new(g.delimiter(), stream);
194                    g.set_span(span);
195                }
196                ref mut other => other.set_span(span),
197            }
198            token
199        }
200
201        // Parse string literal into a token stream with every span equal to the
202        // original literal's span.
203        let mut tokens = ::parse_str(&self.value())?;
204        tokens = respan_token_stream(tokens, self.span());
205
206        parser.parse2(tokens)
207    }
208
209    pub fn span(&self) -> Span {
210        self.token.span()
211    }
212
213    pub fn set_span(&mut self, span: Span) {
214        self.token.set_span(span)
215    }
216}
217
218impl LitByteStr {
219    pub fn new(value: &[u8], span: Span) -> Self {
220        let mut token = Literal::byte_string(value);
221        token.set_span(span);
222        LitByteStr { token: token }
223    }
224
225    pub fn value(&self) -> Vec<u8> {
226        value::parse_lit_byte_str(&self.token.to_string())
227    }
228
229    pub fn span(&self) -> Span {
230        self.token.span()
231    }
232
233    pub fn set_span(&mut self, span: Span) {
234        self.token.set_span(span)
235    }
236}
237
238impl LitByte {
239    pub fn new(value: u8, span: Span) -> Self {
240        let mut token = Literal::u8_suffixed(value);
241        token.set_span(span);
242        LitByte { token: token }
243    }
244
245    pub fn value(&self) -> u8 {
246        value::parse_lit_byte(&self.token.to_string())
247    }
248
249    pub fn span(&self) -> Span {
250        self.token.span()
251    }
252
253    pub fn set_span(&mut self, span: Span) {
254        self.token.set_span(span)
255    }
256}
257
258impl LitChar {
259    pub fn new(value: char, span: Span) -> Self {
260        let mut token = Literal::character(value);
261        token.set_span(span);
262        LitChar { token: token }
263    }
264
265    pub fn value(&self) -> char {
266        value::parse_lit_char(&self.token.to_string())
267    }
268
269    pub fn span(&self) -> Span {
270        self.token.span()
271    }
272
273    pub fn set_span(&mut self, span: Span) {
274        self.token.set_span(span)
275    }
276}
277
278impl LitInt {
279    pub fn new(value: u64, suffix: IntSuffix, span: Span) -> Self {
280        let mut token = match suffix {
281            IntSuffix::Isize => Literal::isize_suffixed(value as isize),
282            IntSuffix::I8 => Literal::i8_suffixed(value as i8),
283            IntSuffix::I16 => Literal::i16_suffixed(value as i16),
284            IntSuffix::I32 => Literal::i32_suffixed(value as i32),
285            IntSuffix::I64 => Literal::i64_suffixed(value as i64),
286            IntSuffix::I128 => value::to_literal(&format!("{}i128", value)),
287            IntSuffix::Usize => Literal::usize_suffixed(value as usize),
288            IntSuffix::U8 => Literal::u8_suffixed(value as u8),
289            IntSuffix::U16 => Literal::u16_suffixed(value as u16),
290            IntSuffix::U32 => Literal::u32_suffixed(value as u32),
291            IntSuffix::U64 => Literal::u64_suffixed(value),
292            IntSuffix::U128 => value::to_literal(&format!("{}u128", value)),
293            IntSuffix::None => Literal::u64_unsuffixed(value),
294        };
295        token.set_span(span);
296        LitInt { token: token }
297    }
298
299    pub fn value(&self) -> u64 {
300        value::parse_lit_int(&self.token.to_string()).unwrap()
301    }
302
303    pub fn suffix(&self) -> IntSuffix {
304        let value = self.token.to_string();
305        for (s, suffix) in vec![
306            ("i8", IntSuffix::I8),
307            ("i16", IntSuffix::I16),
308            ("i32", IntSuffix::I32),
309            ("i64", IntSuffix::I64),
310            ("i128", IntSuffix::I128),
311            ("isize", IntSuffix::Isize),
312            ("u8", IntSuffix::U8),
313            ("u16", IntSuffix::U16),
314            ("u32", IntSuffix::U32),
315            ("u64", IntSuffix::U64),
316            ("u128", IntSuffix::U128),
317            ("usize", IntSuffix::Usize),
318        ] {
319            if value.ends_with(s) {
320                return suffix;
321            }
322        }
323        IntSuffix::None
324    }
325
326    pub fn span(&self) -> Span {
327        self.token.span()
328    }
329
330    pub fn set_span(&mut self, span: Span) {
331        self.token.set_span(span)
332    }
333}
334
335impl LitFloat {
336    pub fn new(value: f64, suffix: FloatSuffix, span: Span) -> Self {
337        let mut token = match suffix {
338            FloatSuffix::F32 => Literal::f32_suffixed(value as f32),
339            FloatSuffix::F64 => Literal::f64_suffixed(value),
340            FloatSuffix::None => Literal::f64_unsuffixed(value),
341        };
342        token.set_span(span);
343        LitFloat { token: token }
344    }
345
346    pub fn value(&self) -> f64 {
347        value::parse_lit_float(&self.token.to_string())
348    }
349
350    pub fn suffix(&self) -> FloatSuffix {
351        let value = self.token.to_string();
352        for (s, suffix) in vec![("f32", FloatSuffix::F32), ("f64", FloatSuffix::F64)] {
353            if value.ends_with(s) {
354                return suffix;
355            }
356        }
357        FloatSuffix::None
358    }
359
360    pub fn span(&self) -> Span {
361        self.token.span()
362    }
363
364    pub fn set_span(&mut self, span: Span) {
365        self.token.set_span(span)
366    }
367}
368
369macro_rules! lit_extra_traits {
370    ($ty:ident, $field:ident) => {
371        #[cfg(feature = "extra-traits")]
372        impl Eq for $ty {}
373
374        #[cfg(feature = "extra-traits")]
375        impl PartialEq for $ty {
376            fn eq(&self, other: &Self) -> bool {
377                self.$field.to_string() == other.$field.to_string()
378            }
379        }
380
381        #[cfg(feature = "extra-traits")]
382        impl Hash for $ty {
383            fn hash<H>(&self, state: &mut H)
384            where
385                H: Hasher,
386            {
387                self.$field.to_string().hash(state);
388            }
389        }
390
391        #[cfg(feature = "parsing")]
392        #[doc(hidden)]
393        #[allow(non_snake_case)]
394        pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
395            match marker {}
396        }
397    };
398}
399
400impl LitVerbatim {
401    pub fn span(&self) -> Span {
402        self.token.span()
403    }
404
405    pub fn set_span(&mut self, span: Span) {
406        self.token.set_span(span)
407    }
408}
409
410lit_extra_traits!(LitStr, token);
411lit_extra_traits!(LitByteStr, token);
412lit_extra_traits!(LitByte, token);
413lit_extra_traits!(LitChar, token);
414lit_extra_traits!(LitInt, token);
415lit_extra_traits!(LitFloat, token);
416lit_extra_traits!(LitBool, value);
417lit_extra_traits!(LitVerbatim, token);
418
419ast_enum! {
420    /// The style of a string literal, either plain quoted or a raw string like
421    /// `r##"data"##`.
422    ///
423    /// *This type is available if Syn is built with the `"derive"` or `"full"`
424    /// feature.*
425    pub enum StrStyle #no_visit {
426        /// An ordinary string like `"data"`.
427        Cooked,
428        /// A raw string like `r##"data"##`.
429        ///
430        /// The unsigned integer is the number of `#` symbols used.
431        Raw(usize),
432    }
433}
434
435ast_enum! {
436    /// The suffix on an integer literal if any, like the `u8` in `127u8`.
437    ///
438    /// *This type is available if Syn is built with the `"derive"` or `"full"`
439    /// feature.*
440    pub enum IntSuffix #no_visit {
441        I8,
442        I16,
443        I32,
444        I64,
445        I128,
446        Isize,
447        U8,
448        U16,
449        U32,
450        U64,
451        U128,
452        Usize,
453        None,
454    }
455}
456
457ast_enum! {
458    /// The suffix on a floating point literal if any, like the `f32` in
459    /// `1.0f32`.
460    ///
461    /// *This type is available if Syn is built with the `"derive"` or `"full"`
462    /// feature.*
463    pub enum FloatSuffix #no_visit {
464        F32,
465        F64,
466        None,
467    }
468}
469
470#[cfg(feature = "parsing")]
471#[doc(hidden)]
472#[allow(non_snake_case)]
473pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
474    match marker {}
475}
476
477#[cfg(feature = "parsing")]
478pub mod parsing {
479    use super::*;
480    use parse::{Parse, ParseStream, Result};
481
482    impl Parse for Lit {
483        fn parse(input: ParseStream) -> Result<Self> {
484            input.step(|cursor| {
485                if let Some((lit, rest)) = cursor.literal() {
486                    return Ok((Lit::new(lit), rest));
487                }
488                while let Some((ident, rest)) = cursor.ident() {
489                    let value = if ident == "true" {
490                        true
491                    } else if ident == "false" {
492                        false
493                    } else {
494                        break;
495                    };
496                    let lit_bool = LitBool {
497                        value: value,
498                        span: ident.span(),
499                    };
500                    return Ok((Lit::Bool(lit_bool), rest));
501                }
502                Err(cursor.error("expected literal"))
503            })
504        }
505    }
506
507    impl Parse for LitStr {
508        fn parse(input: ParseStream) -> Result<Self> {
509            let head = input.fork();
510            match input.parse()? {
511                Lit::Str(lit) => Ok(lit),
512                _ => Err(head.error("expected string literal")),
513            }
514        }
515    }
516
517    impl Parse for LitByteStr {
518        fn parse(input: ParseStream) -> Result<Self> {
519            let head = input.fork();
520            match input.parse()? {
521                Lit::ByteStr(lit) => Ok(lit),
522                _ => Err(head.error("expected byte string literal")),
523            }
524        }
525    }
526
527    impl Parse for LitByte {
528        fn parse(input: ParseStream) -> Result<Self> {
529            let head = input.fork();
530            match input.parse()? {
531                Lit::Byte(lit) => Ok(lit),
532                _ => Err(head.error("expected byte literal")),
533            }
534        }
535    }
536
537    impl Parse for LitChar {
538        fn parse(input: ParseStream) -> Result<Self> {
539            let head = input.fork();
540            match input.parse()? {
541                Lit::Char(lit) => Ok(lit),
542                _ => Err(head.error("expected character literal")),
543            }
544        }
545    }
546
547    impl Parse for LitInt {
548        fn parse(input: ParseStream) -> Result<Self> {
549            let head = input.fork();
550            match input.parse()? {
551                Lit::Int(lit) => Ok(lit),
552                _ => Err(head.error("expected integer literal")),
553            }
554        }
555    }
556
557    impl Parse for LitFloat {
558        fn parse(input: ParseStream) -> Result<Self> {
559            let head = input.fork();
560            match input.parse()? {
561                Lit::Float(lit) => Ok(lit),
562                _ => Err(head.error("expected floating point literal")),
563            }
564        }
565    }
566
567    impl Parse for LitBool {
568        fn parse(input: ParseStream) -> Result<Self> {
569            let head = input.fork();
570            match input.parse()? {
571                Lit::Bool(lit) => Ok(lit),
572                _ => Err(head.error("expected boolean literal")),
573            }
574        }
575    }
576}
577
578#[cfg(feature = "printing")]
579mod printing {
580    use super::*;
581    use proc_macro2::TokenStream;
582    use quote::{ToTokens, TokenStreamExt};
583
584    impl ToTokens for LitStr {
585        fn to_tokens(&self, tokens: &mut TokenStream) {
586            self.token.to_tokens(tokens);
587        }
588    }
589
590    impl ToTokens for LitByteStr {
591        fn to_tokens(&self, tokens: &mut TokenStream) {
592            self.token.to_tokens(tokens);
593        }
594    }
595
596    impl ToTokens for LitByte {
597        fn to_tokens(&self, tokens: &mut TokenStream) {
598            self.token.to_tokens(tokens);
599        }
600    }
601
602    impl ToTokens for LitChar {
603        fn to_tokens(&self, tokens: &mut TokenStream) {
604            self.token.to_tokens(tokens);
605        }
606    }
607
608    impl ToTokens for LitInt {
609        fn to_tokens(&self, tokens: &mut TokenStream) {
610            self.token.to_tokens(tokens);
611        }
612    }
613
614    impl ToTokens for LitFloat {
615        fn to_tokens(&self, tokens: &mut TokenStream) {
616            self.token.to_tokens(tokens);
617        }
618    }
619
620    impl ToTokens for LitBool {
621        fn to_tokens(&self, tokens: &mut TokenStream) {
622            let s = if self.value { "true" } else { "false" };
623            tokens.append(Ident::new(s, self.span));
624        }
625    }
626
627    impl ToTokens for LitVerbatim {
628        fn to_tokens(&self, tokens: &mut TokenStream) {
629            self.token.to_tokens(tokens);
630        }
631    }
632}
633
634mod value {
635    use super::*;
636    use proc_macro2::TokenStream;
637    use std::char;
638    use std::ops::{Index, RangeFrom};
639
640    impl Lit {
641        /// Interpret a Syn literal from a proc-macro2 literal.
642        ///
643        /// Not all proc-macro2 literals are valid Syn literals. In particular,
644        /// doc comments are considered by proc-macro2 to be literals but in Syn
645        /// they are [`Attribute`].
646        ///
647        /// [`Attribute`]: struct.Attribute.html
648        ///
649        /// # Panics
650        ///
651        /// Panics if the input is a doc comment literal.
652        pub fn new(token: Literal) -> Self {
653            let value = token.to_string();
654
655            match value::byte(&value, 0) {
656                b'"' | b'r' => return Lit::Str(LitStr { token: token }),
657                b'b' => match value::byte(&value, 1) {
658                    b'"' | b'r' => return Lit::ByteStr(LitByteStr { token: token }),
659                    b'\'' => return Lit::Byte(LitByte { token: token }),
660                    _ => {}
661                },
662                b'\'' => return Lit::Char(LitChar { token: token }),
663                b'0'...b'9' => {
664                    if number_is_int(&value) {
665                        return Lit::Int(LitInt { token: token });
666                    } else if number_is_float(&value) {
667                        return Lit::Float(LitFloat { token: token });
668                    } else {
669                        // number overflow
670                        return Lit::Verbatim(LitVerbatim { token: token });
671                    }
672                }
673                _ => {
674                    if value == "true" || value == "false" {
675                        return Lit::Bool(LitBool {
676                            value: value == "true",
677                            span: token.span(),
678                        });
679                    }
680                }
681            }
682
683            panic!("Unrecognized literal: {}", value);
684        }
685    }
686
687    fn number_is_int(value: &str) -> bool {
688        if number_is_float(value) {
689            false
690        } else {
691            value::parse_lit_int(value).is_some()
692        }
693    }
694
695    fn number_is_float(value: &str) -> bool {
696        if value.contains('.') {
697            true
698        } else if value.starts_with("0x") || value.ends_with("size") {
699            false
700        } else {
701            value.contains('e') || value.contains('E')
702        }
703    }
704
705    /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
706    /// past the end of the input buffer.
707    pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
708        let s = s.as_ref();
709        if idx < s.len() {
710            s[idx]
711        } else {
712            0
713        }
714    }
715
716    fn next_chr(s: &str) -> char {
717        s.chars().next().unwrap_or('\0')
718    }
719
720    pub fn parse_lit_str(s: &str) -> String {
721        match byte(s, 0) {
722            b'"' => parse_lit_str_cooked(s),
723            b'r' => parse_lit_str_raw(s),
724            _ => unreachable!(),
725        }
726    }
727
728    // Clippy false positive
729    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
730    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
731    fn parse_lit_str_cooked(mut s: &str) -> String {
732        assert_eq!(byte(s, 0), b'"');
733        s = &s[1..];
734
735        let mut out = String::new();
736        'outer: loop {
737            let ch = match byte(s, 0) {
738                b'"' => break,
739                b'\\' => {
740                    let b = byte(s, 1);
741                    s = &s[2..];
742                    match b {
743                        b'x' => {
744                            let (byte, rest) = backslash_x(s);
745                            s = rest;
746                            assert!(byte <= 0x80, "Invalid \\x byte in string literal");
747                            char::from_u32(u32::from(byte)).unwrap()
748                        }
749                        b'u' => {
750                            let (chr, rest) = backslash_u(s);
751                            s = rest;
752                            chr
753                        }
754                        b'n' => '\n',
755                        b'r' => '\r',
756                        b't' => '\t',
757                        b'\\' => '\\',
758                        b'0' => '\0',
759                        b'\'' => '\'',
760                        b'"' => '"',
761                        b'\r' | b'\n' => loop {
762                            let ch = next_chr(s);
763                            if ch.is_whitespace() {
764                                s = &s[ch.len_utf8()..];
765                            } else {
766                                continue 'outer;
767                            }
768                        },
769                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
770                    }
771                }
772                b'\r' => {
773                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
774                    s = &s[2..];
775                    '\n'
776                }
777                _ => {
778                    let ch = next_chr(s);
779                    s = &s[ch.len_utf8()..];
780                    ch
781                }
782            };
783            out.push(ch);
784        }
785
786        assert_eq!(s, "\"");
787        out
788    }
789
790    fn parse_lit_str_raw(mut s: &str) -> String {
791        assert_eq!(byte(s, 0), b'r');
792        s = &s[1..];
793
794        let mut pounds = 0;
795        while byte(s, pounds) == b'#' {
796            pounds += 1;
797        }
798        assert_eq!(byte(s, pounds), b'"');
799        assert_eq!(byte(s, s.len() - pounds - 1), b'"');
800        for end in s[s.len() - pounds..].bytes() {
801            assert_eq!(end, b'#');
802        }
803
804        s[pounds + 1..s.len() - pounds - 1].to_owned()
805    }
806
807    pub fn parse_lit_byte_str(s: &str) -> Vec<u8> {
808        assert_eq!(byte(s, 0), b'b');
809        match byte(s, 1) {
810            b'"' => parse_lit_byte_str_cooked(s),
811            b'r' => parse_lit_byte_str_raw(s),
812            _ => unreachable!(),
813        }
814    }
815
816    // Clippy false positive
817    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
818    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
819    fn parse_lit_byte_str_cooked(mut s: &str) -> Vec<u8> {
820        assert_eq!(byte(s, 0), b'b');
821        assert_eq!(byte(s, 1), b'"');
822        s = &s[2..];
823
824        // We're going to want to have slices which don't respect codepoint boundaries.
825        let mut s = s.as_bytes();
826
827        let mut out = Vec::new();
828        'outer: loop {
829            let byte = match byte(s, 0) {
830                b'"' => break,
831                b'\\' => {
832                    let b = byte(s, 1);
833                    s = &s[2..];
834                    match b {
835                        b'x' => {
836                            let (b, rest) = backslash_x(s);
837                            s = rest;
838                            b
839                        }
840                        b'n' => b'\n',
841                        b'r' => b'\r',
842                        b't' => b'\t',
843                        b'\\' => b'\\',
844                        b'0' => b'\0',
845                        b'\'' => b'\'',
846                        b'"' => b'"',
847                        b'\r' | b'\n' => loop {
848                            let byte = byte(s, 0);
849                            let ch = char::from_u32(u32::from(byte)).unwrap();
850                            if ch.is_whitespace() {
851                                s = &s[1..];
852                            } else {
853                                continue 'outer;
854                            }
855                        },
856                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
857                    }
858                }
859                b'\r' => {
860                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
861                    s = &s[2..];
862                    b'\n'
863                }
864                b => {
865                    s = &s[1..];
866                    b
867                }
868            };
869            out.push(byte);
870        }
871
872        assert_eq!(s, b"\"");
873        out
874    }
875
876    fn parse_lit_byte_str_raw(s: &str) -> Vec<u8> {
877        assert_eq!(byte(s, 0), b'b');
878        parse_lit_str_raw(&s[1..]).into_bytes()
879    }
880
881    pub fn parse_lit_byte(s: &str) -> u8 {
882        assert_eq!(byte(s, 0), b'b');
883        assert_eq!(byte(s, 1), b'\'');
884
885        // We're going to want to have slices which don't respect codepoint boundaries.
886        let mut s = s[2..].as_bytes();
887
888        let b = match byte(s, 0) {
889            b'\\' => {
890                let b = byte(s, 1);
891                s = &s[2..];
892                match b {
893                    b'x' => {
894                        let (b, rest) = backslash_x(s);
895                        s = rest;
896                        b
897                    }
898                    b'n' => b'\n',
899                    b'r' => b'\r',
900                    b't' => b'\t',
901                    b'\\' => b'\\',
902                    b'0' => b'\0',
903                    b'\'' => b'\'',
904                    b'"' => b'"',
905                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
906                }
907            }
908            b => {
909                s = &s[1..];
910                b
911            }
912        };
913
914        assert_eq!(byte(s, 0), b'\'');
915        b
916    }
917
918    pub fn parse_lit_char(mut s: &str) -> char {
919        assert_eq!(byte(s, 0), b'\'');
920        s = &s[1..];
921
922        let ch = match byte(s, 0) {
923            b'\\' => {
924                let b = byte(s, 1);
925                s = &s[2..];
926                match b {
927                    b'x' => {
928                        let (byte, rest) = backslash_x(s);
929                        s = rest;
930                        assert!(byte <= 0x80, "Invalid \\x byte in string literal");
931                        char::from_u32(u32::from(byte)).unwrap()
932                    }
933                    b'u' => {
934                        let (chr, rest) = backslash_u(s);
935                        s = rest;
936                        chr
937                    }
938                    b'n' => '\n',
939                    b'r' => '\r',
940                    b't' => '\t',
941                    b'\\' => '\\',
942                    b'0' => '\0',
943                    b'\'' => '\'',
944                    b'"' => '"',
945                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
946                }
947            }
948            _ => {
949                let ch = next_chr(s);
950                s = &s[ch.len_utf8()..];
951                ch
952            }
953        };
954        assert_eq!(s, "\'", "Expected end of char literal");
955        ch
956    }
957
958    fn backslash_x<S>(s: &S) -> (u8, &S)
959    where
960        S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
961    {
962        let mut ch = 0;
963        let b0 = byte(s, 0);
964        let b1 = byte(s, 1);
965        ch += 0x10
966            * match b0 {
967                b'0'...b'9' => b0 - b'0',
968                b'a'...b'f' => 10 + (b0 - b'a'),
969                b'A'...b'F' => 10 + (b0 - b'A'),
970                _ => panic!("unexpected non-hex character after \\x"),
971            };
972        ch += match b1 {
973            b'0'...b'9' => b1 - b'0',
974            b'a'...b'f' => 10 + (b1 - b'a'),
975            b'A'...b'F' => 10 + (b1 - b'A'),
976            _ => panic!("unexpected non-hex character after \\x"),
977        };
978        (ch, &s[2..])
979    }
980
981    fn backslash_u(mut s: &str) -> (char, &str) {
982        if byte(s, 0) != b'{' {
983            panic!("expected {{ after \\u");
984        }
985        s = &s[1..];
986
987        let mut ch = 0;
988        for _ in 0..6 {
989            let b = byte(s, 0);
990            match b {
991                b'0'...b'9' => {
992                    ch *= 0x10;
993                    ch += u32::from(b - b'0');
994                    s = &s[1..];
995                }
996                b'a'...b'f' => {
997                    ch *= 0x10;
998                    ch += u32::from(10 + b - b'a');
999                    s = &s[1..];
1000                }
1001                b'A'...b'F' => {
1002                    ch *= 0x10;
1003                    ch += u32::from(10 + b - b'A');
1004                    s = &s[1..];
1005                }
1006                b'}' => break,
1007                _ => panic!("unexpected non-hex character after \\u"),
1008            }
1009        }
1010        assert!(byte(s, 0) == b'}');
1011        s = &s[1..];
1012
1013        if let Some(ch) = char::from_u32(ch) {
1014            (ch, s)
1015        } else {
1016            panic!("character code {:x} is not a valid unicode character", ch);
1017        }
1018    }
1019
1020    pub fn parse_lit_int(mut s: &str) -> Option<u64> {
1021        let base = match (byte(s, 0), byte(s, 1)) {
1022            (b'0', b'x') => {
1023                s = &s[2..];
1024                16
1025            }
1026            (b'0', b'o') => {
1027                s = &s[2..];
1028                8
1029            }
1030            (b'0', b'b') => {
1031                s = &s[2..];
1032                2
1033            }
1034            (b'0'...b'9', _) => 10,
1035            _ => unreachable!(),
1036        };
1037
1038        let mut value = 0u64;
1039        loop {
1040            let b = byte(s, 0);
1041            let digit = match b {
1042                b'0'...b'9' => u64::from(b - b'0'),
1043                b'a'...b'f' if base > 10 => 10 + u64::from(b - b'a'),
1044                b'A'...b'F' if base > 10 => 10 + u64::from(b - b'A'),
1045                b'_' => {
1046                    s = &s[1..];
1047                    continue;
1048                }
1049                // NOTE: Looking at a floating point literal, we don't want to
1050                // consider these integers.
1051                b'.' if base == 10 => return None,
1052                b'e' | b'E' if base == 10 => return None,
1053                _ => break,
1054            };
1055
1056            if digit >= base {
1057                panic!("Unexpected digit {:x} out of base range", digit);
1058            }
1059
1060            value = match value.checked_mul(base) {
1061                Some(value) => value,
1062                None => return None,
1063            };
1064            value = match value.checked_add(digit) {
1065                Some(value) => value,
1066                None => return None,
1067            };
1068            s = &s[1..];
1069        }
1070
1071        Some(value)
1072    }
1073
1074    pub fn parse_lit_float(input: &str) -> f64 {
1075        // Rust's floating point literals are very similar to the ones parsed by
1076        // the standard library, except that rust's literals can contain
1077        // ignorable underscores. Let's remove those underscores.
1078        let mut bytes = input.to_owned().into_bytes();
1079        let mut write = 0;
1080        for read in 0..bytes.len() {
1081            if bytes[read] == b'_' {
1082                continue; // Don't increase write
1083            }
1084            if write != read {
1085                let x = bytes[read];
1086                bytes[write] = x;
1087            }
1088            write += 1;
1089        }
1090        bytes.truncate(write);
1091        let input = String::from_utf8(bytes).unwrap();
1092        let end = input.find('f').unwrap_or_else(|| input.len());
1093        input[..end].parse().unwrap()
1094    }
1095
1096    pub fn to_literal(s: &str) -> Literal {
1097        let stream = s.parse::<TokenStream>().unwrap();
1098        match stream.into_iter().next().unwrap() {
1099            TokenTree::Literal(l) => l,
1100            _ => unreachable!(),
1101        }
1102    }
1103}