@@ -456,12 +456,12 @@ pub(crate) fn parse<'a>(
456456
457457 // Parse the integral part of the number
458458 let mut chars = rest. chars ( ) . enumerate ( ) . fuse ( ) . peekable ( ) ;
459- let mut digits = BigUint :: zero ( ) ;
459+ let mut digits: Option < BigUint > = None ;
460460 let mut scale = 0u64 ;
461461 let mut exponent = BigInt :: zero ( ) ;
462462 while let Some ( d) = chars. peek ( ) . and_then ( |& ( _, c) | base. digit ( c) ) {
463463 chars. next ( ) ;
464- digits = digits * base as u8 + d;
464+ digits = Some ( digits. unwrap_or_default ( ) * base as u8 + d) ;
465465 }
466466
467467 // Parse fractional/exponent part of the number for supported bases.
@@ -472,7 +472,7 @@ pub(crate) fn parse<'a>(
472472 chars. next ( ) ;
473473 while let Some ( d) = chars. peek ( ) . and_then ( |& ( _, c) | base. digit ( c) ) {
474474 chars. next ( ) ;
475- ( digits, scale) = ( digits * base as u8 + d, scale + 1 ) ;
475+ ( digits, scale) = ( Some ( digits. unwrap_or_default ( ) * base as u8 + d) , scale + 1 ) ;
476476 }
477477 }
478478
@@ -509,15 +509,17 @@ pub(crate) fn parse<'a>(
509509 }
510510 }
511511
512- // If nothing has been parsed, check if this is a special value, or declare the parsing unsuccessful
513- if let Some ( ( 0 , _ ) ) = chars . peek ( ) {
512+ // If no digit has been parsed, check if this is a special value, or declare the parsing unsuccessful
513+ if digits . is_none ( ) {
514514 return if target == ParseTarget :: Integral {
515515 Err ( ExtendedParserError :: NotNumeric )
516516 } else {
517517 parse_special_value ( unsigned, negative, allowed_suffixes)
518518 } ;
519519 }
520520
521+ let mut digits = digits. unwrap ( ) ;
522+
521523 if let Some ( ( _, ch) ) = chars. peek ( ) {
522524 if let Some ( times) = allowed_suffixes
523525 . iter ( )
@@ -529,7 +531,8 @@ pub(crate) fn parse<'a>(
529531 }
530532 }
531533
532- let ebd_result = construct_extended_big_decimal ( digits, negative, base, scale, exponent) ;
534+ let ebd_result =
535+ construct_extended_big_decimal ( digits, negative, base, scale, exponent) ;
533536
534537 // Return what has been parsed so far. If there are extra characters, mark the
535538 // parsing as a partial match.
@@ -625,6 +628,15 @@ mod tests {
625628 i64 :: extended_parse( & format!( "{}" , i64 :: MIN as i128 - 1 ) ) ,
626629 Err ( ExtendedParserError :: Overflow ( i64 :: MIN ) )
627630 ) ) ;
631+
632+ assert ! ( matches!(
633+ i64 :: extended_parse( "" ) ,
634+ Err ( ExtendedParserError :: NotNumeric )
635+ ) ) ;
636+ assert ! ( matches!(
637+ i64 :: extended_parse( "." ) ,
638+ Err ( ExtendedParserError :: NotNumeric )
639+ ) ) ;
628640 }
629641
630642 #[ test]
@@ -811,6 +823,16 @@ mod tests {
811823 ExtendedBigDecimal :: extended_parse( & format!( "-0e{}" , i64 :: MIN + 2 ) ) ,
812824 Ok ( ExtendedBigDecimal :: MinusZero )
813825 ) ;
826+
827+ /* Invalid numbers */
828+ assert_eq ! (
829+ Err ( ExtendedParserError :: NotNumeric ) ,
830+ ExtendedBigDecimal :: extended_parse( "" )
831+ ) ;
832+ assert_eq ! (
833+ Err ( ExtendedParserError :: NotNumeric ) ,
834+ ExtendedBigDecimal :: extended_parse( "." )
835+ ) ;
814836 }
815837
816838 #[ test]
@@ -887,6 +909,16 @@ mod tests {
887909 ExtendedBigDecimal :: MinusZero
888910 ) )
889911 ) ) ;
912+
913+ // TODO: GNU coreutils treats these 2 as partial match.
914+ assert_eq ! (
915+ Err ( ExtendedParserError :: NotNumeric ) ,
916+ ExtendedBigDecimal :: extended_parse( "0x" )
917+ ) ;
918+ assert_eq ! (
919+ Err ( ExtendedParserError :: NotNumeric ) ,
920+ ExtendedBigDecimal :: extended_parse( "0x." )
921+ ) ;
890922 }
891923
892924 #[ test]
@@ -935,6 +967,20 @@ mod tests {
935967 ebd == ExtendedBigDecimal :: zero( ) ,
936968 _ => false ,
937969 } ) ;
970+
971+ assert ! ( match ExtendedBigDecimal :: extended_parse( "0b" ) {
972+ Err ( ExtendedParserError :: PartialMatch ( ebd, "b" ) ) => ebd == ExtendedBigDecimal :: zero( ) ,
973+ _ => false ,
974+ } ) ;
975+ assert ! ( match ExtendedBigDecimal :: extended_parse( "0b." ) {
976+ Err ( ExtendedParserError :: PartialMatch ( ebd, "b." ) ) => ebd == ExtendedBigDecimal :: zero( ) ,
977+ _ => false ,
978+ } ) ;
979+ // TODO: GNU coreutils treats this as partial match.
980+ assert_eq ! (
981+ Err ( ExtendedParserError :: NotNumeric ) ,
982+ u64 :: extended_parse( "0b" )
983+ ) ;
938984 }
939985
940986 #[ test]
0 commit comments