Skip to main content

syn/
lit.rs

1#[cfg(feature = "parsing")]
2use crate::ext::TokenStreamExt as _;
3#[cfg(feature = "parsing")]
4use crate::lookahead;
5#[cfg(feature = "parsing")]
6use crate::parse::{Parse, Parser};
7use crate::{Error, Result};
8use alloc::boxed::Box;
9use alloc::ffi::CString;
10#[cfg(feature = "parsing")]
11use alloc::format;
12use alloc::string::{String, ToString};
13use alloc::vec::Vec;
14use core::ffi::CStr;
15use core::fmt::{self, Display};
16#[cfg(feature = "extra-traits")]
17use core::hash::{Hash, Hasher};
18use core::str::{self, FromStr};
19use proc_macro2::{Ident, Literal, Span};
20#[cfg(feature = "parsing")]
21use proc_macro2::{TokenStream, TokenTree};
22
23ast_enum_of_structs! {
24    /// A Rust literal such as a string or integer or boolean.
25    ///
26    /// # Syntax tree enum
27    ///
28    /// This type is a [syntax tree enum].
29    ///
30    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
31    #[non_exhaustive]
32    pub enum Lit {
33        /// A UTF-8 string literal: `"foo"`.
34        Str(LitStr),
35
36        /// A byte string literal: `b"foo"`.
37        ByteStr(LitByteStr),
38
39        /// A nul-terminated C-string literal: `c"foo"`.
40        CStr(LitCStr),
41
42        /// A byte literal: `b'f'`.
43        Byte(LitByte),
44
45        /// A character literal: `'a'`.
46        Char(LitChar),
47
48        /// An integer literal: `1` or `1u16`.
49        Int(LitInt),
50
51        /// A floating point literal: `1f64` or `1.0e10f64`.
52        ///
53        /// Must be finite. May not be infinite or NaN.
54        Float(LitFloat),
55
56        /// A boolean literal: `true` or `false`.
57        Bool(LitBool),
58
59        /// A raw token literal not interpreted by Syn.
60        Verbatim(Literal),
61    }
62}
63
64ast_struct! {
65    /// A UTF-8 string literal: `"foo"`.
66    pub struct LitStr {
67        repr: Box<LitRepr>,
68    }
69}
70
71ast_struct! {
72    /// A byte string literal: `b"foo"`.
73    pub struct LitByteStr {
74        repr: Box<LitRepr>,
75    }
76}
77
78ast_struct! {
79    /// A nul-terminated C-string literal: `c"foo"`.
80    pub struct LitCStr {
81        repr: Box<LitRepr>,
82    }
83}
84
85ast_struct! {
86    /// A byte literal: `b'f'`.
87    pub struct LitByte {
88        repr: Box<LitRepr>,
89    }
90}
91
92ast_struct! {
93    /// A character literal: `'a'`.
94    pub struct LitChar {
95        repr: Box<LitRepr>,
96    }
97}
98
99struct LitRepr {
100    token: Literal,
101    suffix: Box<str>,
102}
103
104ast_struct! {
105    /// An integer literal: `1` or `1u16`.
106    pub struct LitInt {
107        repr: Box<LitIntRepr>,
108    }
109}
110
111struct LitIntRepr {
112    token: Literal,
113    digits: Box<str>,
114    suffix: Box<str>,
115}
116
117ast_struct! {
118    /// A floating point literal: `1f64` or `1.0e10f64`.
119    ///
120    /// Must be finite. May not be infinite or NaN.
121    pub struct LitFloat {
122        repr: Box<LitFloatRepr>,
123    }
124}
125
126struct LitFloatRepr {
127    token: Literal,
128    digits: Box<str>,
129    suffix: Box<str>,
130}
131
132ast_struct! {
133    /// A boolean literal: `true` or `false`.
134    pub struct LitBool {
135        pub value: bool,
136        pub span: Span,
137    }
138}
139
140impl LitStr {
141    pub fn new(value: &str, span: Span) -> Self {
142        let mut token = Literal::string(value);
143        token.set_span(span);
144        LitStr {
145            repr: Box::new(LitRepr {
146                token,
147                suffix: Box::<str>::default(),
148            }),
149        }
150    }
151
152    pub fn value(&self) -> String {
153        let repr = self.repr.token.to_string();
154        let (value, _suffix) = value::parse_lit_str(&repr).unwrap();
155        String::from(value)
156    }
157
158    /// Parse a syntax tree node from the content of this string literal.
159    ///
160    /// All spans in the syntax tree will point to the span of this `LitStr`.
161    ///
162    /// # Example
163    ///
164    /// ```
165    /// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result};
166    ///
167    /// // Parses the path from an attribute that looks like:
168    /// //
169    /// //     #[path = "a::b::c"]
170    /// //
171    /// // or returns `None` if the input is some other attribute.
172    /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
173    ///     if !attr.path().is_ident("path") {
174    ///         return Ok(None);
175    ///     }
176    ///
177    ///     if let Meta::NameValue(meta) = &attr.meta {
178    ///         if let Expr::Lit(expr) = &meta.value {
179    ///             if let Lit::Str(lit_str) = &expr.lit {
180    ///                 return lit_str.parse().map(Some);
181    ///             }
182    ///         }
183    ///     }
184    ///
185    ///     let message = "expected #[path = \"...\"]";
186    ///     Err(Error::new_spanned(attr, message))
187    /// }
188    /// ```
189    #[cfg(feature = "parsing")]
190    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
191    pub fn parse<T: Parse>(&self) -> Result<T> {
192        self.parse_with(T::parse)
193    }
194
195    /// Invoke parser on the content of this string literal.
196    ///
197    /// All spans in the syntax tree will point to the span of this `LitStr`.
198    ///
199    /// # Example
200    ///
201    /// ```
202    /// # use proc_macro2::Span;
203    /// # use syn::{LitStr, Result};
204    /// #
205    /// # fn main() -> Result<()> {
206    /// #     let lit_str = LitStr::new("a::b::c", Span::call_site());
207    /// #
208    /// #     const IGNORE: &str = stringify! {
209    /// let lit_str: LitStr = /* ... */;
210    /// #     };
211    ///
212    /// // Parse a string literal like "a::b::c" into a Path, not allowing
213    /// // generic arguments on any of the path segments.
214    /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
215    /// #
216    /// #     Ok(())
217    /// # }
218    /// ```
219    #[cfg(feature = "parsing")]
220    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
221    pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
222        use proc_macro2::Group;
223
224        // Token stream with every span replaced by the given one.
225        fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
226            let mut tokens = TokenStream::new();
227            for token in stream {
228                tokens.append(respan_token_tree(token, span));
229            }
230            tokens
231        }
232
233        // Token tree with every span replaced by the given one.
234        fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
235            match &mut token {
236                TokenTree::Group(g) => {
237                    let stream = respan_token_stream(g.stream(), span);
238                    *g = Group::new(g.delimiter(), stream);
239                    g.set_span(span);
240                }
241                other => other.set_span(span),
242            }
243            token
244        }
245
246        // Parse string literal into a token stream with every span equal to the
247        // original literal's span.
248        let span = self.span();
249        let mut tokens = TokenStream::from_str(&self.value())?;
250        tokens = respan_token_stream(tokens, span);
251
252        let result = crate::parse::parse_scoped(parser, span, tokens)?;
253
254        let suffix = self.suffix();
255        if !suffix.is_empty() {
256            return Err(Error::new(
257                self.span(),
258                format!("unexpected suffix `{}` on string literal", suffix),
259            ));
260        }
261
262        Ok(result)
263    }
264
265    pub fn span(&self) -> Span {
266        self.repr.token.span()
267    }
268
269    pub fn set_span(&mut self, span: Span) {
270        self.repr.token.set_span(span);
271    }
272
273    pub fn suffix(&self) -> &str {
274        &self.repr.suffix
275    }
276
277    pub fn token(&self) -> Literal {
278        self.repr.token.clone()
279    }
280}
281
282impl LitByteStr {
283    pub fn new(value: &[u8], span: Span) -> Self {
284        let mut token = Literal::byte_string(value);
285        token.set_span(span);
286        LitByteStr {
287            repr: Box::new(LitRepr {
288                token,
289                suffix: Box::<str>::default(),
290            }),
291        }
292    }
293
294    pub fn value(&self) -> Vec<u8> {
295        let repr = self.repr.token.to_string();
296        let (value, _suffix) = value::parse_lit_byte_str(&repr).unwrap();
297        value
298    }
299
300    pub fn span(&self) -> Span {
301        self.repr.token.span()
302    }
303
304    pub fn set_span(&mut self, span: Span) {
305        self.repr.token.set_span(span);
306    }
307
308    pub fn suffix(&self) -> &str {
309        &self.repr.suffix
310    }
311
312    pub fn token(&self) -> Literal {
313        self.repr.token.clone()
314    }
315}
316
317impl LitCStr {
318    pub fn new(value: &CStr, span: Span) -> Self {
319        let mut token = Literal::c_string(value);
320        token.set_span(span);
321        LitCStr {
322            repr: Box::new(LitRepr {
323                token,
324                suffix: Box::<str>::default(),
325            }),
326        }
327    }
328
329    pub fn value(&self) -> CString {
330        let repr = self.repr.token.to_string();
331        let (value, _suffix) = value::parse_lit_c_str(&repr).unwrap();
332        value
333    }
334
335    pub fn span(&self) -> Span {
336        self.repr.token.span()
337    }
338
339    pub fn set_span(&mut self, span: Span) {
340        self.repr.token.set_span(span);
341    }
342
343    pub fn suffix(&self) -> &str {
344        &self.repr.suffix
345    }
346
347    pub fn token(&self) -> Literal {
348        self.repr.token.clone()
349    }
350}
351
352impl LitByte {
353    pub fn new(value: u8, span: Span) -> Self {
354        let mut token = Literal::byte_character(value);
355        token.set_span(span);
356        LitByte {
357            repr: Box::new(LitRepr {
358                token,
359                suffix: Box::<str>::default(),
360            }),
361        }
362    }
363
364    pub fn value(&self) -> u8 {
365        let repr = self.repr.token.to_string();
366        let (value, _suffix) = value::parse_lit_byte(&repr).unwrap();
367        value
368    }
369
370    pub fn span(&self) -> Span {
371        self.repr.token.span()
372    }
373
374    pub fn set_span(&mut self, span: Span) {
375        self.repr.token.set_span(span);
376    }
377
378    pub fn suffix(&self) -> &str {
379        &self.repr.suffix
380    }
381
382    pub fn token(&self) -> Literal {
383        self.repr.token.clone()
384    }
385}
386
387impl LitChar {
388    pub fn new(value: char, span: Span) -> Self {
389        let mut token = Literal::character(value);
390        token.set_span(span);
391        LitChar {
392            repr: Box::new(LitRepr {
393                token,
394                suffix: Box::<str>::default(),
395            }),
396        }
397    }
398
399    pub fn value(&self) -> char {
400        let repr = self.repr.token.to_string();
401        let (value, _suffix) = value::parse_lit_char(&repr).unwrap();
402        value
403    }
404
405    pub fn span(&self) -> Span {
406        self.repr.token.span()
407    }
408
409    pub fn set_span(&mut self, span: Span) {
410        self.repr.token.set_span(span);
411    }
412
413    pub fn suffix(&self) -> &str {
414        &self.repr.suffix
415    }
416
417    pub fn token(&self) -> Literal {
418        self.repr.token.clone()
419    }
420}
421
422impl LitInt {
423    #[track_caller]
424    pub fn new(repr: &str, span: Span) -> Self {
425        let (digits, suffix) = match value::parse_lit_int(repr) {
426            Some(parse) => parse,
427            None => panic!("not an integer literal: `{}`", repr),
428        };
429
430        let mut token: Literal = repr.parse().unwrap();
431        token.set_span(span);
432        LitInt {
433            repr: Box::new(LitIntRepr {
434                token,
435                digits,
436                suffix,
437            }),
438        }
439    }
440
441    pub fn base10_digits(&self) -> &str {
442        &self.repr.digits
443    }
444
445    /// Parses the literal into a selected number type.
446    ///
447    /// This is equivalent to `lit.base10_digits().parse()` except that the
448    /// resulting errors will be correctly spanned to point to the literal token
449    /// in the macro input.
450    ///
451    /// ```
452    /// use syn::LitInt;
453    /// use syn::parse::{Parse, ParseStream, Result};
454    ///
455    /// struct Port {
456    ///     value: u16,
457    /// }
458    ///
459    /// impl Parse for Port {
460    ///     fn parse(input: ParseStream) -> Result<Self> {
461    ///         let lit: LitInt = input.parse()?;
462    ///         let value = lit.base10_parse::<u16>()?;
463    ///         Ok(Port { value })
464    ///     }
465    /// }
466    /// ```
467    pub fn base10_parse<N>(&self) -> Result<N>
468    where
469        N: FromStr,
470        N::Err: Display,
471    {
472        self.base10_digits()
473            .parse()
474            .map_err(|err| Error::new(self.span(), err))
475    }
476
477    pub fn suffix(&self) -> &str {
478        &self.repr.suffix
479    }
480
481    pub fn span(&self) -> Span {
482        self.repr.token.span()
483    }
484
485    pub fn set_span(&mut self, span: Span) {
486        self.repr.token.set_span(span);
487    }
488
489    pub fn token(&self) -> Literal {
490        self.repr.token.clone()
491    }
492}
493
494impl From<Literal> for LitInt {
495    #[track_caller]
496    fn from(token: Literal) -> Self {
497        let repr = token.to_string();
498        if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
499            LitInt {
500                repr: Box::new(LitIntRepr {
501                    token,
502                    digits,
503                    suffix,
504                }),
505            }
506        } else {
507            panic!("not an integer literal: `{}`", repr);
508        }
509    }
510}
511
512impl Display for LitInt {
513    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
514        self.repr.token.fmt(formatter)
515    }
516}
517
518impl LitFloat {
519    #[track_caller]
520    pub fn new(repr: &str, span: Span) -> Self {
521        let (digits, suffix) = match value::parse_lit_float(repr) {
522            Some(parse) => parse,
523            None => panic!("not a float literal: `{}`", repr),
524        };
525
526        let mut token: Literal = repr.parse().unwrap();
527        token.set_span(span);
528        LitFloat {
529            repr: Box::new(LitFloatRepr {
530                token,
531                digits,
532                suffix,
533            }),
534        }
535    }
536
537    pub fn base10_digits(&self) -> &str {
538        &self.repr.digits
539    }
540
541    pub fn base10_parse<N>(&self) -> Result<N>
542    where
543        N: FromStr,
544        N::Err: Display,
545    {
546        self.base10_digits()
547            .parse()
548            .map_err(|err| Error::new(self.span(), err))
549    }
550
551    pub fn suffix(&self) -> &str {
552        &self.repr.suffix
553    }
554
555    pub fn span(&self) -> Span {
556        self.repr.token.span()
557    }
558
559    pub fn set_span(&mut self, span: Span) {
560        self.repr.token.set_span(span);
561    }
562
563    pub fn token(&self) -> Literal {
564        self.repr.token.clone()
565    }
566}
567
568impl From<Literal> for LitFloat {
569    #[track_caller]
570    fn from(token: Literal) -> Self {
571        let repr = token.to_string();
572        if let Some((digits, suffix)) = value::parse_lit_float(&repr) {
573            LitFloat {
574                repr: Box::new(LitFloatRepr {
575                    token,
576                    digits,
577                    suffix,
578                }),
579            }
580        } else {
581            panic!("not a float literal: `{}`", repr);
582        }
583    }
584}
585
586impl Display for LitFloat {
587    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
588        self.repr.token.fmt(formatter)
589    }
590}
591
592impl LitBool {
593    pub fn new(value: bool, span: Span) -> Self {
594        LitBool { value, span }
595    }
596
597    pub fn value(&self) -> bool {
598        self.value
599    }
600
601    pub fn span(&self) -> Span {
602        self.span
603    }
604
605    pub fn set_span(&mut self, span: Span) {
606        self.span = span;
607    }
608
609    pub fn token(&self) -> Ident {
610        let s = if self.value { "true" } else { "false" };
611        Ident::new(s, self.span)
612    }
613}
614
615#[cfg(feature = "extra-traits")]
616mod debug_impls {
617    use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
618    use core::fmt::{self, Debug};
619
620    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
621    impl Debug for LitStr {
622        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
623            self.debug(formatter, "LitStr")
624        }
625    }
626
627    impl LitStr {
628        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
629            formatter
630                .debug_struct(name)
631                .field("token", &format_args!("{}", self.repr.token))
632                .finish()
633        }
634    }
635
636    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
637    impl Debug for LitByteStr {
638        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
639            self.debug(formatter, "LitByteStr")
640        }
641    }
642
643    impl LitByteStr {
644        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
645            formatter
646                .debug_struct(name)
647                .field("token", &format_args!("{}", self.repr.token))
648                .finish()
649        }
650    }
651
652    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
653    impl Debug for LitCStr {
654        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
655            self.debug(formatter, "LitCStr")
656        }
657    }
658
659    impl LitCStr {
660        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
661            formatter
662                .debug_struct(name)
663                .field("token", &format_args!("{}", self.repr.token))
664                .finish()
665        }
666    }
667
668    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
669    impl Debug for LitByte {
670        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
671            self.debug(formatter, "LitByte")
672        }
673    }
674
675    impl LitByte {
676        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
677            formatter
678                .debug_struct(name)
679                .field("token", &format_args!("{}", self.repr.token))
680                .finish()
681        }
682    }
683
684    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
685    impl Debug for LitChar {
686        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
687            self.debug(formatter, "LitChar")
688        }
689    }
690
691    impl LitChar {
692        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
693            formatter
694                .debug_struct(name)
695                .field("token", &format_args!("{}", self.repr.token))
696                .finish()
697        }
698    }
699
700    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
701    impl Debug for LitInt {
702        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
703            self.debug(formatter, "LitInt")
704        }
705    }
706
707    impl LitInt {
708        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
709            formatter
710                .debug_struct(name)
711                .field("token", &format_args!("{}", self.repr.token))
712                .finish()
713        }
714    }
715
716    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
717    impl Debug for LitFloat {
718        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
719            self.debug(formatter, "LitFloat")
720        }
721    }
722
723    impl LitFloat {
724        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
725            formatter
726                .debug_struct(name)
727                .field("token", &format_args!("{}", self.repr.token))
728                .finish()
729        }
730    }
731
732    #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
733    impl Debug for LitBool {
734        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
735            self.debug(formatter, "LitBool")
736        }
737    }
738
739    impl LitBool {
740        pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
741            formatter
742                .debug_struct(name)
743                .field("value", &self.value)
744                .finish()
745        }
746    }
747}
748
749#[cfg(feature = "clone-impls")]
750#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
751impl Clone for LitRepr {
752    fn clone(&self) -> Self {
753        LitRepr {
754            token: self.token.clone(),
755            suffix: self.suffix.clone(),
756        }
757    }
758}
759
760#[cfg(feature = "clone-impls")]
761#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
762impl Clone for LitIntRepr {
763    fn clone(&self) -> Self {
764        LitIntRepr {
765            token: self.token.clone(),
766            digits: self.digits.clone(),
767            suffix: self.suffix.clone(),
768        }
769    }
770}
771
772#[cfg(feature = "clone-impls")]
773#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
774impl Clone for LitFloatRepr {
775    fn clone(&self) -> Self {
776        LitFloatRepr {
777            token: self.token.clone(),
778            digits: self.digits.clone(),
779            suffix: self.suffix.clone(),
780        }
781    }
782}
783
784macro_rules! lit_extra_traits {
785    ($ty:ident) => {
786        #[cfg(feature = "clone-impls")]
787        #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
788        impl Clone for $ty {
789            fn clone(&self) -> Self {
790                $ty {
791                    repr: self.repr.clone(),
792                }
793            }
794        }
795
796        #[cfg(feature = "extra-traits")]
797        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
798        impl PartialEq for $ty {
799            fn eq(&self, other: &Self) -> bool {
800                self.repr.token.to_string() == other.repr.token.to_string()
801            }
802        }
803
804        #[cfg(feature = "extra-traits")]
805        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
806        impl Hash for $ty {
807            fn hash<H>(&self, state: &mut H)
808            where
809                H: Hasher,
810            {
811                self.repr.token.to_string().hash(state);
812            }
813        }
814
815        #[cfg(feature = "parsing")]
816        pub_if_not_doc! {
817            #[doc(hidden)]
818            #[allow(non_snake_case)]
819            pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
820                match marker {}
821            }
822        }
823    };
824}
825
826lit_extra_traits!(LitStr);
827lit_extra_traits!(LitByteStr);
828lit_extra_traits!(LitCStr);
829lit_extra_traits!(LitByte);
830lit_extra_traits!(LitChar);
831lit_extra_traits!(LitInt);
832lit_extra_traits!(LitFloat);
833
834#[cfg(feature = "parsing")]
835pub_if_not_doc! {
836    #[doc(hidden)]
837    #[allow(non_snake_case)]
838    pub fn LitBool(marker: lookahead::TokenMarker) -> LitBool {
839        match marker {}
840    }
841}
842
843/// The style of a string literal, either plain quoted or a raw string like
844/// `r##"data"##`.
845#[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566
846pub enum StrStyle {
847    /// An ordinary string like `"data"`.
848    Cooked,
849    /// A raw string like `r##"data"##`.
850    ///
851    /// The unsigned integer is the number of `#` symbols used.
852    Raw(usize),
853}
854
855#[cfg(feature = "parsing")]
856pub_if_not_doc! {
857    #[doc(hidden)]
858    #[allow(non_snake_case)]
859    pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
860        match marker {}
861    }
862}
863
864#[cfg(feature = "parsing")]
865pub(crate) mod parsing {
866    use crate::buffer::Cursor;
867    use crate::error::Result;
868    use crate::lit::{
869        value, Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
870        LitIntRepr, LitStr,
871    };
872    use crate::parse::{Parse, ParseStream, Unexpected};
873    use crate::token::{self, Token};
874    use alloc::boxed::Box;
875    use alloc::rc::Rc;
876    use alloc::string::ToString;
877    use core::cell::Cell;
878    use proc_macro2::{Literal, Punct, Span};
879
880    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
881    impl Parse for Lit {
882        fn parse(input: ParseStream) -> Result<Self> {
883            input.step(|cursor| {
884                if let Some((lit, rest)) = cursor.literal() {
885                    return Ok((Lit::new(lit), rest));
886                }
887
888                if let Some((ident, rest)) = cursor.ident() {
889                    let value = ident == "true";
890                    if value || ident == "false" {
891                        let lit_bool = LitBool {
892                            value,
893                            span: ident.span(),
894                        };
895                        return Ok((Lit::Bool(lit_bool), rest));
896                    }
897                }
898
899                if let Some((punct, rest)) = cursor.punct() {
900                    if punct.as_char() == '-' {
901                        if let Some((lit, rest)) = parse_negative_lit(punct, rest) {
902                            return Ok((lit, rest));
903                        }
904                    }
905                }
906
907                Err(cursor.error("expected literal"))
908            })
909        }
910    }
911
912    fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> {
913        let (lit, rest) = cursor.literal()?;
914
915        let mut span = neg.span();
916        span = span.join(lit.span()).unwrap_or(span);
917
918        let mut repr = lit.to_string();
919        repr.insert(0, '-');
920
921        if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
922            let mut token: Literal = repr.parse().unwrap();
923            token.set_span(span);
924            return Some((
925                Lit::Int(LitInt {
926                    repr: Box::new(LitIntRepr {
927                        token,
928                        digits,
929                        suffix,
930                    }),
931                }),
932                rest,
933            ));
934        }
935
936        let (digits, suffix) = value::parse_lit_float(&repr)?;
937        let mut token: Literal = repr.parse().unwrap();
938        token.set_span(span);
939        Some((
940            Lit::Float(LitFloat {
941                repr: Box::new(LitFloatRepr {
942                    token,
943                    digits,
944                    suffix,
945                }),
946            }),
947            rest,
948        ))
949    }
950
951    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
952    impl Parse for LitStr {
953        fn parse(input: ParseStream) -> Result<Self> {
954            let head = input.fork();
955            match input.parse() {
956                Ok(Lit::Str(lit)) => Ok(lit),
957                _ => Err(head.error("expected string literal")),
958            }
959        }
960    }
961
962    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
963    impl Parse for LitByteStr {
964        fn parse(input: ParseStream) -> Result<Self> {
965            let head = input.fork();
966            match input.parse() {
967                Ok(Lit::ByteStr(lit)) => Ok(lit),
968                _ => Err(head.error("expected byte string literal")),
969            }
970        }
971    }
972
973    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
974    impl Parse for LitCStr {
975        fn parse(input: ParseStream) -> Result<Self> {
976            let head = input.fork();
977            match input.parse() {
978                Ok(Lit::CStr(lit)) => Ok(lit),
979                _ => Err(head.error("expected C string literal")),
980            }
981        }
982    }
983
984    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
985    impl Parse for LitByte {
986        fn parse(input: ParseStream) -> Result<Self> {
987            let head = input.fork();
988            match input.parse() {
989                Ok(Lit::Byte(lit)) => Ok(lit),
990                _ => Err(head.error("expected byte literal")),
991            }
992        }
993    }
994
995    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
996    impl Parse for LitChar {
997        fn parse(input: ParseStream) -> Result<Self> {
998            let head = input.fork();
999            match input.parse() {
1000                Ok(Lit::Char(lit)) => Ok(lit),
1001                _ => Err(head.error("expected character literal")),
1002            }
1003        }
1004    }
1005
1006    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1007    impl Parse for LitInt {
1008        fn parse(input: ParseStream) -> Result<Self> {
1009            let head = input.fork();
1010            match input.parse() {
1011                Ok(Lit::Int(lit)) => Ok(lit),
1012                _ => Err(head.error("expected integer literal")),
1013            }
1014        }
1015    }
1016
1017    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1018    impl Parse for LitFloat {
1019        fn parse(input: ParseStream) -> Result<Self> {
1020            let head = input.fork();
1021            match input.parse() {
1022                Ok(Lit::Float(lit)) => Ok(lit),
1023                _ => Err(head.error("expected floating point literal")),
1024            }
1025        }
1026    }
1027
1028    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1029    impl Parse for LitBool {
1030        fn parse(input: ParseStream) -> Result<Self> {
1031            let head = input.fork();
1032            match input.parse() {
1033                Ok(Lit::Bool(lit)) => Ok(lit),
1034                _ => Err(head.error("expected boolean literal")),
1035            }
1036        }
1037    }
1038
1039    fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
1040        let scope = Span::call_site();
1041        let unexpected = Rc::new(Cell::new(Unexpected::None));
1042        let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected);
1043        peek(&buffer)
1044    }
1045
1046    macro_rules! impl_token {
1047        ($display:literal $name:ty) => {
1048            impl Token for $name {
1049                fn peek(cursor: Cursor) -> bool {
1050                    fn peek(input: ParseStream) -> bool {
1051                        <$name as Parse>::parse(input).is_ok()
1052                    }
1053                    peek_impl(cursor, peek)
1054                }
1055
1056                fn display() -> &'static str {
1057                    $display
1058                }
1059            }
1060
1061            impl token::private::Sealed for $name {}
1062        };
1063    }
1064
1065    impl_token!("literal" Lit);
1066    impl_token!("string literal" LitStr);
1067    impl_token!("byte string literal" LitByteStr);
1068    impl_token!("C-string literal" LitCStr);
1069    impl_token!("byte literal" LitByte);
1070    impl_token!("character literal" LitChar);
1071    impl_token!("integer literal" LitInt);
1072    impl_token!("floating point literal" LitFloat);
1073    impl_token!("boolean literal" LitBool);
1074}
1075
1076#[cfg(feature = "printing")]
1077mod printing {
1078    use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
1079    use proc_macro2::TokenStream;
1080    use quote::{ToTokens, TokenStreamExt as _};
1081
1082    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1083    impl ToTokens for LitStr {
1084        fn to_tokens(&self, tokens: &mut TokenStream) {
1085            self.repr.token.to_tokens(tokens);
1086        }
1087    }
1088
1089    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1090    impl ToTokens for LitByteStr {
1091        fn to_tokens(&self, tokens: &mut TokenStream) {
1092            self.repr.token.to_tokens(tokens);
1093        }
1094    }
1095
1096    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1097    impl ToTokens for LitCStr {
1098        fn to_tokens(&self, tokens: &mut TokenStream) {
1099            self.repr.token.to_tokens(tokens);
1100        }
1101    }
1102
1103    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1104    impl ToTokens for LitByte {
1105        fn to_tokens(&self, tokens: &mut TokenStream) {
1106            self.repr.token.to_tokens(tokens);
1107        }
1108    }
1109
1110    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1111    impl ToTokens for LitChar {
1112        fn to_tokens(&self, tokens: &mut TokenStream) {
1113            self.repr.token.to_tokens(tokens);
1114        }
1115    }
1116
1117    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1118    impl ToTokens for LitInt {
1119        fn to_tokens(&self, tokens: &mut TokenStream) {
1120            self.repr.token.to_tokens(tokens);
1121        }
1122    }
1123
1124    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1125    impl ToTokens for LitFloat {
1126        fn to_tokens(&self, tokens: &mut TokenStream) {
1127            self.repr.token.to_tokens(tokens);
1128        }
1129    }
1130
1131    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1132    impl ToTokens for LitBool {
1133        fn to_tokens(&self, tokens: &mut TokenStream) {
1134            tokens.append(self.token());
1135        }
1136    }
1137}
1138
1139mod value {
1140    use crate::bigint::BigInt;
1141    use crate::lit::{
1142        Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
1143        LitIntRepr, LitRepr, LitStr,
1144    };
1145    use alloc::borrow::ToOwned;
1146    use alloc::boxed::Box;
1147    use alloc::ffi::CString;
1148    use alloc::string::{String, ToString};
1149    use alloc::vec::Vec;
1150    use core::char;
1151    use core::ops::{Index, RangeFrom};
1152    use proc_macro2::{Literal, Span};
1153
1154    impl Lit {
1155        /// Interpret a Syn literal from a proc-macro2 literal.
1156        pub fn new(token: Literal) -> Self {
1157            let repr = token.to_string();
1158            Lit::from_str(token, &repr)
1159        }
1160
1161        #[cfg(fuzzing)]
1162        #[doc(hidden)]
1163        pub fn from_str_for_fuzzing(repr: &str) -> Self {
1164            let token = Literal::u8_unsuffixed(0);
1165            Lit::from_str(token, repr)
1166        }
1167
1168        fn from_str(token: Literal, repr: &str) -> Self {
1169            match byte(repr, 0) {
1170                // "...", r"...", r#"..."#
1171                b'"' | b'r' => {
1172                    if let Some((_, suffix)) = parse_lit_str(repr) {
1173                        return Lit::Str(LitStr {
1174                            repr: Box::new(LitRepr { token, suffix }),
1175                        });
1176                    }
1177                }
1178                b'b' => match byte(repr, 1) {
1179                    // b"...", br"...", br#"...#"
1180                    b'"' | b'r' => {
1181                        if let Some((_, suffix)) = parse_lit_byte_str(repr) {
1182                            return Lit::ByteStr(LitByteStr {
1183                                repr: Box::new(LitRepr { token, suffix }),
1184                            });
1185                        }
1186                    }
1187                    // b'...'
1188                    b'\'' => {
1189                        if let Some((_, suffix)) = parse_lit_byte(repr) {
1190                            return Lit::Byte(LitByte {
1191                                repr: Box::new(LitRepr { token, suffix }),
1192                            });
1193                        }
1194                    }
1195                    _ => {}
1196                },
1197                b'c' => match byte(repr, 1) {
1198                    // c"...", cr"...", cr#"..."#
1199                    b'"' | b'r' => {
1200                        if let Some((_, suffix)) = parse_lit_c_str(repr) {
1201                            return Lit::CStr(LitCStr {
1202                                repr: Box::new(LitRepr { token, suffix }),
1203                            });
1204                        }
1205                    }
1206                    _ => {}
1207                },
1208                // '...'
1209                b'\'' => {
1210                    if let Some((_, suffix)) = parse_lit_char(repr) {
1211                        return Lit::Char(LitChar {
1212                            repr: Box::new(LitRepr { token, suffix }),
1213                        });
1214                    }
1215                }
1216                b'0'..=b'9' | b'-' => {
1217                    // 0, 123, 0xFF, 0o77, 0b11
1218                    if let Some((digits, suffix)) = parse_lit_int(repr) {
1219                        return Lit::Int(LitInt {
1220                            repr: Box::new(LitIntRepr {
1221                                token,
1222                                digits,
1223                                suffix,
1224                            }),
1225                        });
1226                    }
1227                    // 1.0, 1e-1, 1e+1
1228                    if let Some((digits, suffix)) = parse_lit_float(repr) {
1229                        return Lit::Float(LitFloat {
1230                            repr: Box::new(LitFloatRepr {
1231                                token,
1232                                digits,
1233                                suffix,
1234                            }),
1235                        });
1236                    }
1237                }
1238                // true, false
1239                b't' | b'f' if repr == "true" || repr == "false" => {
1240                    return Lit::Bool(LitBool {
1241                        value: repr == "true",
1242                        span: token.span(),
1243                    });
1244                }
1245                b'(' if repr == "(/*ERROR*/)" => return Lit::Verbatim(token),
1246                _ => {}
1247            }
1248
1249            Lit::Verbatim(token)
1250        }
1251
1252        pub fn suffix(&self) -> &str {
1253            match self {
1254                Lit::Str(lit) => lit.suffix(),
1255                Lit::ByteStr(lit) => lit.suffix(),
1256                Lit::CStr(lit) => lit.suffix(),
1257                Lit::Byte(lit) => lit.suffix(),
1258                Lit::Char(lit) => lit.suffix(),
1259                Lit::Int(lit) => lit.suffix(),
1260                Lit::Float(lit) => lit.suffix(),
1261                Lit::Bool(_) | Lit::Verbatim(_) => "",
1262            }
1263        }
1264
1265        pub fn span(&self) -> Span {
1266            match self {
1267                Lit::Str(lit) => lit.span(),
1268                Lit::ByteStr(lit) => lit.span(),
1269                Lit::CStr(lit) => lit.span(),
1270                Lit::Byte(lit) => lit.span(),
1271                Lit::Char(lit) => lit.span(),
1272                Lit::Int(lit) => lit.span(),
1273                Lit::Float(lit) => lit.span(),
1274                Lit::Bool(lit) => lit.span,
1275                Lit::Verbatim(lit) => lit.span(),
1276            }
1277        }
1278
1279        pub fn set_span(&mut self, span: Span) {
1280            match self {
1281                Lit::Str(lit) => lit.set_span(span),
1282                Lit::ByteStr(lit) => lit.set_span(span),
1283                Lit::CStr(lit) => lit.set_span(span),
1284                Lit::Byte(lit) => lit.set_span(span),
1285                Lit::Char(lit) => lit.set_span(span),
1286                Lit::Int(lit) => lit.set_span(span),
1287                Lit::Float(lit) => lit.set_span(span),
1288                Lit::Bool(lit) => lit.span = span,
1289                Lit::Verbatim(lit) => lit.set_span(span),
1290            }
1291        }
1292    }
1293
1294    /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
1295    /// past the end of the input buffer.
1296    pub(crate) fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
1297        let s = s.as_ref();
1298        if idx < s.len() {
1299            s[idx]
1300        } else {
1301            0
1302        }
1303    }
1304
1305    fn next_chr(s: &str) -> char {
1306        s.chars().next().unwrap_or('\0')
1307    }
1308
1309    // Returns (content, suffix).
1310    pub(crate) fn parse_lit_str(s: &str) -> Option<(Box<str>, Box<str>)> {
1311        match byte(s, 0) {
1312            b'"' => parse_lit_str_cooked(s),
1313            b'r' => parse_lit_str_raw(s),
1314            _ => unreachable!(),
1315        }
1316    }
1317
1318    fn parse_lit_str_cooked(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1319        assert_eq!(byte(s, 0), b'"');
1320        s = &s[1..];
1321
1322        let mut content = String::new();
1323        'outer: loop {
1324            let ch = match byte(s, 0) {
1325                b'"' => break,
1326                b'\\' => {
1327                    let b = byte(s, 1);
1328                    s = s.get(2..)?;
1329                    match b {
1330                        b'x' => {
1331                            let (byte, rest) = backslash_x(s)?;
1332                            s = rest;
1333                            if byte > 0x7F {
1334                                // invalid \x byte in string literal
1335                                return None;
1336                            }
1337                            char::from(byte)
1338                        }
1339                        b'u' => {
1340                            let (ch, rest) = backslash_u(s)?;
1341                            s = rest;
1342                            ch
1343                        }
1344                        b'n' => '\n',
1345                        b'r' => '\r',
1346                        b't' => '\t',
1347                        b'\\' => '\\',
1348                        b'0' => '\0',
1349                        b'\'' => '\'',
1350                        b'"' => '"',
1351                        b'\r' | b'\n' => loop {
1352                            let b = byte(s, 0);
1353                            match b {
1354                                b' ' | b'\t' | b'\n' | b'\r' => s = &s[1..],
1355                                _ => continue 'outer,
1356                            }
1357                        },
1358                        _ => {
1359                            // unexpected byte after backslash
1360                            return None;
1361                        }
1362                    }
1363                }
1364                b'\r' => {
1365                    if byte(s, 1) != b'\n' {
1366                        // bare carriage return not allowed in string
1367                        return None;
1368                    }
1369                    s = &s[2..];
1370                    '\n'
1371                }
1372                _ => {
1373                    let ch = next_chr(s);
1374                    s = s.get(ch.len_utf8()..)?;
1375                    ch
1376                }
1377            };
1378            content.push(ch);
1379        }
1380
1381        assert!(s.starts_with('"'));
1382        let content = content.into_boxed_str();
1383        let suffix = s[1..].to_owned().into_boxed_str();
1384        Some((content, suffix))
1385    }
1386
1387    fn parse_lit_str_raw(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1388        assert_eq!(byte(s, 0), b'r');
1389        s = &s[1..];
1390
1391        let mut pounds = 0;
1392        loop {
1393            match byte(s, pounds) {
1394                b'#' => pounds += 1,
1395                b'"' => break,
1396                _ => return None,
1397            }
1398        }
1399        let close = s.rfind('"').unwrap();
1400        for end in s.get(close + 1..close + 1 + pounds)?.bytes() {
1401            if end != b'#' {
1402                return None;
1403            }
1404        }
1405
1406        let content = s.get(pounds + 1..close)?.to_owned().into_boxed_str();
1407        let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str();
1408        Some((content, suffix))
1409    }
1410
1411    // Returns (content, suffix).
1412    pub(crate) fn parse_lit_byte_str(s: &str) -> Option<(Vec<u8>, Box<str>)> {
1413        assert_eq!(byte(s, 0), b'b');
1414        match byte(s, 1) {
1415            b'"' => parse_lit_byte_str_cooked(s),
1416            b'r' => parse_lit_byte_str_raw(s),
1417            _ => unreachable!(),
1418        }
1419    }
1420
1421    fn parse_lit_byte_str_cooked(mut s: &str) -> Option<(Vec<u8>, Box<str>)> {
1422        assert_eq!(byte(s, 0), b'b');
1423        assert_eq!(byte(s, 1), b'"');
1424        s = &s[2..];
1425
1426        // We're going to want to have slices which don't respect codepoint boundaries.
1427        let mut v = s.as_bytes();
1428
1429        let mut out = Vec::new();
1430        'outer: loop {
1431            let byte = match byte(v, 0) {
1432                b'"' => break,
1433                b'\\' => {
1434                    let b = byte(v, 1);
1435                    v = v.get(2..)?;
1436                    match b {
1437                        b'x' => {
1438                            let (b, rest) = backslash_x(v)?;
1439                            v = rest;
1440                            b
1441                        }
1442                        b'n' => b'\n',
1443                        b'r' => b'\r',
1444                        b't' => b'\t',
1445                        b'\\' => b'\\',
1446                        b'0' => b'\0',
1447                        b'\'' => b'\'',
1448                        b'"' => b'"',
1449                        b'\r' | b'\n' => loop {
1450                            let byte = byte(v, 0);
1451                            if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
1452                                v = &v[1..];
1453                            } else {
1454                                continue 'outer;
1455                            }
1456                        },
1457                        _ => {
1458                            // unexpected byte after backslash
1459                            return None;
1460                        }
1461                    }
1462                }
1463                b'\r' => {
1464                    if byte(v, 1) != b'\n' {
1465                        // bare carriage return not allowed in string
1466                        return None;
1467                    }
1468                    v = &v[2..];
1469                    b'\n'
1470                }
1471                b => {
1472                    v = v.get(1..)?;
1473                    b
1474                }
1475            };
1476            out.push(byte);
1477        }
1478
1479        assert_eq!(byte(v, 0), b'"');
1480        let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1481        Some((out, suffix))
1482    }
1483
1484    fn parse_lit_byte_str_raw(s: &str) -> Option<(Vec<u8>, Box<str>)> {
1485        assert_eq!(byte(s, 0), b'b');
1486        let (value, suffix) = parse_lit_str_raw(&s[1..])?;
1487        Some((String::from(value).into_bytes(), suffix))
1488    }
1489
1490    // Returns (content, suffix).
1491    pub(crate) fn parse_lit_c_str(s: &str) -> Option<(CString, Box<str>)> {
1492        assert_eq!(byte(s, 0), b'c');
1493        match byte(s, 1) {
1494            b'"' => parse_lit_c_str_cooked(s),
1495            b'r' => parse_lit_c_str_raw(s),
1496            _ => unreachable!(),
1497        }
1498    }
1499
1500    fn parse_lit_c_str_cooked(mut s: &str) -> Option<(CString, Box<str>)> {
1501        assert_eq!(byte(s, 0), b'c');
1502        assert_eq!(byte(s, 1), b'"');
1503        s = &s[2..];
1504
1505        // We're going to want to have slices which don't respect codepoint boundaries.
1506        let mut v = s.as_bytes();
1507
1508        let mut out = Vec::new();
1509        'outer: loop {
1510            let byte = match byte(v, 0) {
1511                b'"' => break,
1512                b'\\' => {
1513                    let b = byte(v, 1);
1514                    v = v.get(2..)?;
1515                    match b {
1516                        b'x' => {
1517                            let (b, rest) = backslash_x(v)?;
1518                            if b == 0 {
1519                                // \x00 is not allowed in C-string literal
1520                                return None;
1521                            }
1522                            v = rest;
1523                            b
1524                        }
1525                        b'u' => {
1526                            let (ch, rest) = backslash_u(v)?;
1527                            if ch == '\0' {
1528                                // \u{0} is not allowed in C-string literal
1529                                return None;
1530                            }
1531                            v = rest;
1532                            out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes());
1533                            continue 'outer;
1534                        }
1535                        b'n' => b'\n',
1536                        b'r' => b'\r',
1537                        b't' => b'\t',
1538                        b'\\' => b'\\',
1539                        b'\'' => b'\'',
1540                        b'"' => b'"',
1541                        b'\r' | b'\n' => loop {
1542                            let byte = byte(v, 0);
1543                            if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
1544                                v = &v[1..];
1545                            } else {
1546                                continue 'outer;
1547                            }
1548                        },
1549                        _ => {
1550                            // unexpected byte after backslash
1551                            return None;
1552                        }
1553                    }
1554                }
1555                b'\r' => {
1556                    if byte(v, 1) != b'\n' {
1557                        // bare carriage return not allowed in string
1558                        return None;
1559                    }
1560                    v = &v[2..];
1561                    b'\n'
1562                }
1563                b => {
1564                    v = v.get(1..)?;
1565                    b
1566                }
1567            };
1568            out.push(byte);
1569        }
1570
1571        assert_eq!(byte(v, 0), b'"');
1572        let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1573        let cstring = CString::new(out).ok()?;
1574        Some((cstring, suffix))
1575    }
1576
1577    fn parse_lit_c_str_raw(s: &str) -> Option<(CString, Box<str>)> {
1578        assert_eq!(byte(s, 0), b'c');
1579        let (value, suffix) = parse_lit_str_raw(&s[1..])?;
1580        let cstring = CString::new(String::from(value)).ok()?;
1581        Some((cstring, suffix))
1582    }
1583
1584    // Returns (value, suffix).
1585    pub(crate) fn parse_lit_byte(s: &str) -> Option<(u8, Box<str>)> {
1586        assert_eq!(byte(s, 0), b'b');
1587        assert_eq!(byte(s, 1), b'\'');
1588
1589        // We're going to want to have slices which don't respect codepoint boundaries.
1590        let mut v = &s.as_bytes()[2..];
1591
1592        let b = match byte(v, 0) {
1593            b'\\' => {
1594                let b = byte(v, 1);
1595                v = v.get(2..)?;
1596                match b {
1597                    b'x' => {
1598                        let (b, rest) = backslash_x(v)?;
1599                        v = rest;
1600                        b
1601                    }
1602                    b'n' => b'\n',
1603                    b'r' => b'\r',
1604                    b't' => b'\t',
1605                    b'\\' => b'\\',
1606                    b'0' => b'\0',
1607                    b'\'' => b'\'',
1608                    b'"' => b'"',
1609                    _ => {
1610                        // unexpected byte after backslash
1611                        return None;
1612                    }
1613                }
1614            }
1615            b => {
1616                v = v.get(1..)?;
1617                b
1618            }
1619        };
1620
1621        if byte(v, 0) != b'\'' {
1622            return None;
1623        }
1624
1625        let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1626        Some((b, suffix))
1627    }
1628
1629    // Returns (value, suffix).
1630    pub(crate) fn parse_lit_char(mut s: &str) -> Option<(char, Box<str>)> {
1631        assert_eq!(byte(s, 0), b'\'');
1632        s = &s[1..];
1633
1634        let ch = match byte(s, 0) {
1635            b'\\' => {
1636                let b = byte(s, 1);
1637                s = s.get(2..)?;
1638                match b {
1639                    b'x' => {
1640                        let (byte, rest) = backslash_x(s)?;
1641                        s = rest;
1642                        if byte > 0x7F {
1643                            // invalid \x byte in character literal
1644                            return None;
1645                        }
1646                        char::from(byte)
1647                    }
1648                    b'u' => {
1649                        let (ch, rest) = backslash_u(s)?;
1650                        s = rest;
1651                        ch
1652                    }
1653                    b'n' => '\n',
1654                    b'r' => '\r',
1655                    b't' => '\t',
1656                    b'\\' => '\\',
1657                    b'0' => '\0',
1658                    b'\'' => '\'',
1659                    b'"' => '"',
1660                    _ => {
1661                        // unexpected byte after backslash
1662                        return None;
1663                    }
1664                }
1665            }
1666            _ => {
1667                let ch = next_chr(s);
1668                s = s.get(ch.len_utf8()..)?;
1669                ch
1670            }
1671        };
1672
1673        if byte(s, 0) != b'\'' {
1674            return None;
1675        }
1676
1677        let suffix = s[1..].to_owned().into_boxed_str();
1678        Some((ch, suffix))
1679    }
1680
1681    fn backslash_x<S>(s: &S) -> Option<(u8, &S)>
1682    where
1683        S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1684    {
1685        let mut ch = 0;
1686        let b0 = byte(s, 0);
1687        let b1 = byte(s, 1);
1688        ch += 0x10
1689            * match b0 {
1690                b'0'..=b'9' => b0 - b'0',
1691                b'a'..=b'f' => 10 + (b0 - b'a'),
1692                b'A'..=b'F' => 10 + (b0 - b'A'),
1693                _ => return None,
1694            };
1695        ch += match b1 {
1696            b'0'..=b'9' => b1 - b'0',
1697            b'a'..=b'f' => 10 + (b1 - b'a'),
1698            b'A'..=b'F' => 10 + (b1 - b'A'),
1699            _ => return None,
1700        };
1701        Some((ch, &s[2..]))
1702    }
1703
1704    fn backslash_u<S>(mut s: &S) -> Option<(char, &S)>
1705    where
1706        S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1707    {
1708        if byte(s, 0) != b'{' {
1709            return None;
1710        }
1711        s = &s[1..];
1712
1713        let mut ch = 0;
1714        let mut digits = 0;
1715        loop {
1716            let b = byte(s, 0);
1717            let digit = match b {
1718                b'0'..=b'9' => b - b'0',
1719                b'a'..=b'f' => 10 + b - b'a',
1720                b'A'..=b'F' => 10 + b - b'A',
1721                b'_' if digits > 0 => {
1722                    s = &s[1..];
1723                    continue;
1724                }
1725                b'}' if digits == 0 => return None,
1726                b'}' => break,
1727                _ => return None,
1728            };
1729            if digits == 6 {
1730                return None;
1731            }
1732            ch *= 0x10;
1733            ch += u32::from(digit);
1734            digits += 1;
1735            s = &s[1..];
1736        }
1737        if byte(s, 0) != b'}' {
1738            return None;
1739        }
1740        s = &s[1..];
1741
1742        let ch = char::from_u32(ch)?;
1743        Some((ch, s))
1744    }
1745
1746    // Returns base 10 digits and suffix.
1747    pub(crate) fn parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1748        let negative = byte(s, 0) == b'-';
1749        if negative {
1750            s = &s[1..];
1751        }
1752
1753        let base = match (byte(s, 0), byte(s, 1)) {
1754            (b'0', b'x') => {
1755                s = &s[2..];
1756                16
1757            }
1758            (b'0', b'o') => {
1759                s = &s[2..];
1760                8
1761            }
1762            (b'0', b'b') => {
1763                s = &s[2..];
1764                2
1765            }
1766            (b'0'..=b'9', _) => 10,
1767            _ => return None,
1768        };
1769
1770        let mut value = BigInt::new();
1771        let mut has_digit = false;
1772        'outer: loop {
1773            let b = byte(s, 0);
1774            let digit = match b {
1775                b'0'..=b'9' => b - b'0',
1776                b'a'..=b'f' if base > 10 => b - b'a' + 10,
1777                b'A'..=b'F' if base > 10 => b - b'A' + 10,
1778                b'_' => {
1779                    s = &s[1..];
1780                    continue;
1781                }
1782                // If looking at a floating point literal, we don't want to
1783                // consider it an integer.
1784                b'.' if base == 10 => return None,
1785                b'e' | b'E' if base == 10 => {
1786                    let mut has_exp = false;
1787                    for (i, b) in s[1..].bytes().enumerate() {
1788                        match b {
1789                            b'_' => {}
1790                            b'-' | b'+' => return None,
1791                            b'0'..=b'9' => has_exp = true,
1792                            _ => {
1793                                let suffix = &s[1 + i..];
1794                                if has_exp && crate::ident::xid_ok(suffix) {
1795                                    return None;
1796                                } else {
1797                                    break 'outer;
1798                                }
1799                            }
1800                        }
1801                    }
1802                    if has_exp {
1803                        return None;
1804                    } else {
1805                        break;
1806                    }
1807                }
1808                _ => break,
1809            };
1810
1811            if digit >= base {
1812                return None;
1813            }
1814
1815            has_digit = true;
1816            value *= base;
1817            value += digit;
1818            s = &s[1..];
1819        }
1820
1821        if !has_digit {
1822            return None;
1823        }
1824
1825        let suffix = s;
1826        if suffix.is_empty() || crate::ident::xid_ok(suffix) {
1827            let mut repr = value.to_string();
1828            if negative {
1829                repr.insert(0, '-');
1830            }
1831            Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str()))
1832        } else {
1833            None
1834        }
1835    }
1836
1837    // Returns base 10 digits and suffix.
1838    pub(crate) fn parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)> {
1839        // Rust's floating point literals are very similar to the ones parsed by
1840        // the standard library, except that rust's literals can contain
1841        // ignorable underscores. Let's remove those underscores.
1842
1843        let mut bytes = input.to_owned().into_bytes();
1844
1845        let start = (*bytes.first()? == b'-') as usize;
1846        match bytes.get(start)? {
1847            b'0'..=b'9' => {}
1848            _ => return None,
1849        }
1850
1851        let mut read = start;
1852        let mut write = start;
1853        let mut has_dot = false;
1854        let mut has_e = false;
1855        let mut has_sign = false;
1856        let mut has_exponent = false;
1857        while read < bytes.len() {
1858            match bytes[read] {
1859                b'_' => {
1860                    // Don't increase write
1861                    read += 1;
1862                    continue;
1863                }
1864                b'0'..=b'9' => {
1865                    if has_e {
1866                        has_exponent = true;
1867                    }
1868                    bytes[write] = bytes[read];
1869                }
1870                b'.' => {
1871                    if has_e || has_dot {
1872                        return None;
1873                    }
1874                    has_dot = true;
1875                    bytes[write] = b'.';
1876                }
1877                b'e' | b'E' => {
1878                    match bytes[read + 1..]
1879                        .iter()
1880                        .find(|b| **b != b'_')
1881                        .unwrap_or(&b'\0')
1882                    {
1883                        b'-' | b'+' | b'0'..=b'9' => {}
1884                        _ => break,
1885                    }
1886                    if has_e {
1887                        if has_exponent {
1888                            break;
1889                        } else {
1890                            return None;
1891                        }
1892                    }
1893                    has_e = true;
1894                    bytes[write] = b'e';
1895                }
1896                b'-' | b'+' => {
1897                    if has_sign || has_exponent || !has_e {
1898                        return None;
1899                    }
1900                    has_sign = true;
1901                    if bytes[read] == b'-' {
1902                        bytes[write] = bytes[read];
1903                    } else {
1904                        // Omit '+'
1905                        read += 1;
1906                        continue;
1907                    }
1908                }
1909                _ => break,
1910            }
1911            read += 1;
1912            write += 1;
1913        }
1914
1915        if has_e && !has_exponent {
1916            return None;
1917        }
1918
1919        let mut digits = String::from_utf8(bytes).unwrap();
1920        let suffix = digits.split_off(read);
1921        digits.truncate(write);
1922        if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1923            Some((digits.into_boxed_str(), suffix.into_boxed_str()))
1924        } else {
1925            None
1926        }
1927    }
1928}