@@ -543,11 +543,6 @@ impl HasFormatSpecifier for ast::String {
543543}
544544
545545impl 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-
551546 pub fn radix ( & self ) -> Radix {
552547 match self . text ( ) . get ( ..2 ) . unwrap_or_default ( ) {
553548 "0b" => Radix :: Binary ,
@@ -580,29 +575,30 @@ impl ast::IntNumber {
580575
581576 pub fn suffix ( & self ) -> Option < & str > {
582577 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..] )
593590 }
594591}
595592
596593impl ast:: FloatNumber {
597- const SUFFIXES : & ' static [ & ' static str ] = & [ "f32" , "f64" ] ;
598594 pub fn suffix ( & self ) -> Option < & str > {
599595 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.. ] )
606602 }
607603}
608604
@@ -625,3 +621,40 @@ impl Radix {
625621 }
626622 }
627623}
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