@@ -397,10 +397,9 @@ impl LiteralDigitGrouping {
397
397
398
398
let ( integer, fraction, _) = digit_info. split_digit_parts( ) ;
399
399
400
- let integral_group_size = Self :: do_lint ( integer, in_macro) ?;
400
+ let integral_group_size = Self :: get_group_size ( integer. split ( '_' ) , in_macro) ?;
401
401
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) ?;
404
403
405
404
let consistent = Self :: parts_consistent( integral_group_size,
406
405
fractional_group_size,
@@ -425,53 +424,43 @@ impl LiteralDigitGrouping {
425
424
/// parts, and the length
426
425
/// of both parts, determine if the digits have been grouped consistently.
427
426
#[ 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 {
429
433
match ( int_group_size, frac_group_size) {
430
434
// No groups on either side of decimal point - trivially consistent.
431
- ( 0 , 0 ) => true ,
435
+ ( None , None ) => true ,
432
436
// 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,
434
438
// 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,
436
440
// 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,
438
442
}
439
443
}
440
444
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 )
456
457
} else {
457
- Ok ( 0 )
458
+ Ok ( Some ( second ) )
458
459
}
460
+ } else if first > 5 && !in_macro {
461
+ Err ( WarningType :: UnreadableLiteral )
459
462
} 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 )
475
464
}
476
465
}
477
466
}
0 commit comments