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