@@ -543,11 +543,6 @@ impl HasFormatSpecifier for ast::String {
543
543
}
544
544
545
545
impl ast:: IntNumber {
546
- const SUFFIXES : & ' static [ & ' static str ] = & [
547
- "u8" , "u16" , "u32" , "u64" , "u128" , "usize" , // Unsigned.
548
- "i8" , "i16" , "i32" , "i64" , "i128" , "isize" , // Signed.
549
- ] ;
550
-
551
546
pub fn radix ( & self ) -> Radix {
552
547
match self . text ( ) . get ( ..2 ) . unwrap_or_default ( ) {
553
548
"0b" => Radix :: Binary ,
@@ -580,29 +575,30 @@ impl ast::IntNumber {
580
575
581
576
pub fn suffix ( & self ) -> Option < & str > {
582
577
let text = self . text ( ) ;
583
- // FIXME: don't check a fixed set of suffixes, `1_0_1_l_o_l` is valid
584
- // syntax, suffix is `l_o_l`.
585
- ast:: IntNumber :: SUFFIXES . iter ( ) . chain ( ast:: FloatNumber :: SUFFIXES . iter ( ) ) . find_map (
586
- |suffix| {
587
- if text. ends_with ( suffix) {
588
- return Some ( & text[ text. len ( ) - suffix. len ( ) ..] ) ;
589
- }
590
- None
591
- } ,
592
- )
578
+ let radix = self . radix ( ) ;
579
+ let mut indices = text. char_indices ( ) ;
580
+ if radix != Radix :: Decimal {
581
+ indices. next ( ) ?;
582
+ indices. next ( ) ?;
583
+ }
584
+ let is_suffix_start: fn ( & ( usize , char ) ) -> bool = match radix {
585
+ Radix :: Hexadecimal => |( _, c) | matches ! ( c, 'g' ..='z' | 'G' ..='Z' ) ,
586
+ _ => |( _, c) | c. is_ascii_alphabetic ( ) ,
587
+ } ;
588
+ let ( suffix_start, _) = indices. find ( is_suffix_start) ?;
589
+ Some ( & text[ suffix_start..] )
593
590
}
594
591
}
595
592
596
593
impl ast:: FloatNumber {
597
- const SUFFIXES : & ' static [ & ' static str ] = & [ "f32" , "f64" ] ;
598
594
pub fn suffix ( & self ) -> Option < & str > {
599
595
let text = self . text ( ) ;
600
- ast :: FloatNumber :: SUFFIXES . iter ( ) . find_map ( |suffix| {
601
- if text . ends_with ( suffix ) {
602
- return Some ( & text [ text . len ( ) - suffix . len ( ) .. ] ) ;
603
- }
604
- None
605
- } )
596
+ let mut indices = text . char_indices ( ) ;
597
+ let ( mut suffix_start , c ) = indices . by_ref ( ) . find ( | ( _ , c ) | c . is_ascii_alphabetic ( ) ) ? ;
598
+ if c == 'e' || c == 'E' {
599
+ suffix_start = indices . find ( | ( _ , c ) | c . is_ascii_alphabetic ( ) ) ? . 0 ;
600
+ }
601
+ Some ( & text [ suffix_start.. ] )
606
602
}
607
603
}
608
604
@@ -625,3 +621,40 @@ impl Radix {
625
621
}
626
622
}
627
623
}
624
+
625
+ #[ cfg( test) ]
626
+ mod tests {
627
+ use crate :: ast:: { make, FloatNumber , IntNumber } ;
628
+
629
+ fn check_float_suffix < ' a > ( lit : & str , expected : impl Into < Option < & ' a str > > ) {
630
+ assert_eq ! ( FloatNumber { syntax: make:: tokens:: literal( lit) } . suffix( ) , expected. into( ) ) ;
631
+ }
632
+
633
+ fn check_int_suffix < ' a > ( lit : & str , expected : impl Into < Option < & ' a str > > ) {
634
+ assert_eq ! ( IntNumber { syntax: make:: tokens:: literal( lit) } . suffix( ) , expected. into( ) ) ;
635
+ }
636
+
637
+ #[ test]
638
+ fn test_float_number_suffix ( ) {
639
+ check_float_suffix ( "123.0" , None ) ;
640
+ check_float_suffix ( "123f32" , "f32" ) ;
641
+ check_float_suffix ( "123.0e" , None ) ;
642
+ check_float_suffix ( "123.0e4" , None ) ;
643
+ check_float_suffix ( "123.0ef32" , "f32" ) ;
644
+ check_float_suffix ( "123.0E4f32" , "f32" ) ;
645
+ check_float_suffix ( "1_2_3.0_f32" , "f32" ) ;
646
+ }
647
+
648
+ #[ test]
649
+ fn test_int_number_suffix ( ) {
650
+ check_int_suffix ( "123" , None ) ;
651
+ check_int_suffix ( "123i32" , "i32" ) ;
652
+ check_int_suffix ( "1_0_1_l_o_l" , "l_o_l" ) ;
653
+ check_int_suffix ( "0b11" , None ) ;
654
+ check_int_suffix ( "0o11" , None ) ;
655
+ check_int_suffix ( "0xff" , None ) ;
656
+ check_int_suffix ( "0b11u32" , "u32" ) ;
657
+ check_int_suffix ( "0o11u32" , "u32" ) ;
658
+ check_int_suffix ( "0xffu32" , "u32" ) ;
659
+ }
660
+ }
0 commit comments