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