@@ -397,10 +397,9 @@ impl LiteralDigitGrouping {
397397
398398 let ( integer, fraction, _) = digit_info. split_digit_parts( ) ;
399399
400- let integral_group_size = Self :: do_lint ( integer, in_macro) ?;
400+ let integral_group_size = Self :: get_group_size ( integer. split ( '_' ) , in_macro) ?;
401401 if let Some ( fraction) = fraction {
402- let fractional_part = fraction. chars( ) . rev( ) . collect:: <String >( ) ;
403- let fractional_group_size = Self :: do_lint( & fractional_part, in_macro) ?;
402+ let fractional_group_size = Self :: get_group_size( fraction. rsplit( '_' ) , in_macro) ?;
404403
405404 let consistent = Self :: parts_consistent( integral_group_size,
406405 fractional_group_size,
@@ -425,53 +424,43 @@ impl LiteralDigitGrouping {
425424 /// parts, and the length
426425 /// of both parts, determine if the digits have been grouped consistently.
427426 #[ must_use]
428- fn parts_consistent ( int_group_size : usize , frac_group_size : usize , int_size : usize , frac_size : usize ) -> bool {
427+ fn parts_consistent (
428+ int_group_size : Option < usize > ,
429+ frac_group_size : Option < usize > ,
430+ int_size : usize ,
431+ frac_size : usize ,
432+ ) -> bool {
429433 match ( int_group_size, frac_group_size) {
430434 // No groups on either side of decimal point - trivially consistent.
431- ( 0 , 0 ) => true ,
435+ ( None , None ) => true ,
432436 // Integral part has grouped digits, fractional part does not.
433- ( _ , 0 ) => frac_size <= int_group_size,
437+ ( Some ( int_group_size ) , None ) => frac_size <= int_group_size,
434438 // Fractional part has grouped digits, integral part does not.
435- ( 0 , _ ) => int_size <= frac_group_size,
439+ ( None , Some ( frac_group_size ) ) => int_size <= frac_group_size,
436440 // Both parts have grouped digits. Groups should be the same size.
437- ( _ , _ ) => int_group_size == frac_group_size,
441+ ( Some ( int_group_size ) , Some ( frac_group_size ) ) => int_group_size == frac_group_size,
438442 }
439443 }
440444
441- /// Performs lint on `digits` (no decimal point) and returns the group
442- /// size on success or `WarningType` when emitting a warning.
443- fn do_lint ( digits : & str , in_macro : bool ) -> Result < usize , WarningType > {
444- // Grab underscore indices with respect to the units digit.
445- let underscore_positions: Vec < usize > = digits
446- . chars ( )
447- . rev ( )
448- . enumerate ( )
449- . filter_map ( |( idx, digit) | if digit == '_' { Some ( idx) } else { None } )
450- . collect ( ) ;
451-
452- if underscore_positions. is_empty ( ) {
453- // Check if literal needs underscores.
454- if !in_macro && digits. len ( ) > 5 {
455- Err ( WarningType :: UnreadableLiteral )
445+ /// Returns the size of the digit groups (or None if ungrouped) if successful,
446+ /// otherwise returns a `WarningType` for linting.
447+ fn get_group_size < ' a > ( groups : impl Iterator < Item = & ' a str > , in_macro : bool ) -> Result < Option < usize > , WarningType > {
448+ let mut groups = groups. map ( str:: len) ;
449+
450+ let first = groups. next ( ) . expect ( "At least one group" ) ;
451+
452+ if let Some ( second) = groups. next ( ) {
453+ if !groups. all ( |x| x == second) || first > second {
454+ Err ( WarningType :: InconsistentDigitGrouping )
455+ } else if second > 4 {
456+ Err ( WarningType :: LargeDigitGroups )
456457 } else {
457- Ok ( 0 )
458+ Ok ( Some ( second ) )
458459 }
460+ } else if first > 5 && !in_macro {
461+ Err ( WarningType :: UnreadableLiteral )
459462 } else {
460- // Check consistency and the sizes of the groups.
461- let group_size = underscore_positions[ 0 ] ;
462- let consistent = underscore_positions
463- . windows ( 2 )
464- . all ( |ps| ps[ 1 ] - ps[ 0 ] == group_size + 1 )
465- // number of digits to the left of the last group cannot be bigger than group size.
466- && ( digits. len ( ) - underscore_positions. last ( )
467- . expect ( "there's at least one element" ) <= group_size + 1 ) ;
468-
469- if !consistent {
470- return Err ( WarningType :: InconsistentDigitGrouping ) ;
471- } else if group_size > 4 {
472- return Err ( WarningType :: LargeDigitGroups ) ;
473- }
474- Ok ( group_size)
463+ Ok ( None )
475464 }
476465 }
477466}
0 commit comments