@@ -404,9 +404,6 @@ fn parse(
404404 } else {
405405 ( Base :: Decimal , unsigned)
406406 } ;
407- if rest. is_empty ( ) {
408- return Err ( ExtendedParserError :: NotNumeric ) ;
409- }
410407
411408 // Parse the integral part of the number
412409 let mut chars = rest. chars ( ) . enumerate ( ) . fuse ( ) . peekable ( ) ;
@@ -472,6 +469,16 @@ fn parse(
472469
473470 // If no digit has been parsed, check if this is a special value, or declare the parsing unsuccessful
474471 if digits. is_none ( ) {
472+ // If we trimmed an initial `0x`/`0b`, return a partial match.
473+ if rest != unsigned {
474+ let ebd = if negative {
475+ ExtendedBigDecimal :: MinusZero
476+ } else {
477+ ExtendedBigDecimal :: zero ( )
478+ } ;
479+ return Err ( ExtendedParserError :: PartialMatch ( ebd, & unsigned[ 1 ..] ) ) ;
480+ }
481+
475482 return if integral_only {
476483 Err ( ExtendedParserError :: NotNumeric )
477484 } else {
@@ -876,23 +883,41 @@ mod tests {
876883 ) )
877884 ) ) ;
878885
879- // TODO: GNU coreutils treats these as partial matches.
880- assert_eq ! (
881- Err ( ExtendedParserError :: NotNumeric ) ,
882- ExtendedBigDecimal :: extended_parse( "0x" )
883- ) ;
884- assert_eq ! (
885- Err ( ExtendedParserError :: NotNumeric ) ,
886- ExtendedBigDecimal :: extended_parse( "0x." )
887- ) ;
888- assert_eq ! (
889- Err ( ExtendedParserError :: NotNumeric ) ,
890- ExtendedBigDecimal :: extended_parse( "0xp" )
891- ) ;
892- assert_eq ! (
893- Err ( ExtendedParserError :: NotNumeric ) ,
894- ExtendedBigDecimal :: extended_parse( "0xp-2" )
895- ) ;
886+ // Not actually hex numbers, but the prefixes look like it.
887+ assert ! ( matches!( f64 :: extended_parse( "0x" ) ,
888+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == 0.0 ) ) ;
889+ assert ! ( matches!( f64 :: extended_parse( "0x." ) ,
890+ Err ( ExtendedParserError :: PartialMatch ( f, "x." ) ) if f == 0.0 ) ) ;
891+ assert ! ( matches!( f64 :: extended_parse( "0xp" ) ,
892+ Err ( ExtendedParserError :: PartialMatch ( f, "xp" ) ) if f == 0.0 ) ) ;
893+ assert ! ( matches!( f64 :: extended_parse( "0xp-2" ) ,
894+ Err ( ExtendedParserError :: PartialMatch ( f, "xp-2" ) ) if f == 0.0 ) ) ;
895+ assert ! ( matches!( f64 :: extended_parse( "0x.p-2" ) ,
896+ Err ( ExtendedParserError :: PartialMatch ( f, "x.p-2" ) ) if f == 0.0 ) ) ;
897+ assert ! ( matches!( f64 :: extended_parse( "0X" ) ,
898+ Err ( ExtendedParserError :: PartialMatch ( f, "X" ) ) if f == 0.0 ) ) ;
899+ assert ! ( matches!( f64 :: extended_parse( "-0x" ) ,
900+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == -0.0 ) ) ;
901+ assert ! ( matches!( f64 :: extended_parse( "+0x" ) ,
902+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == 0.0 ) ) ;
903+ assert ! ( matches!( f64 :: extended_parse( "-0x." ) ,
904+ Err ( ExtendedParserError :: PartialMatch ( f, "x." ) ) if f == -0.0 ) ) ;
905+ assert ! ( matches!(
906+ u64 :: extended_parse( "0x" ) ,
907+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
908+ ) ) ;
909+ assert ! ( matches!(
910+ u64 :: extended_parse( "-0x" ) ,
911+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
912+ ) ) ;
913+ assert ! ( matches!(
914+ i64 :: extended_parse( "0x" ) ,
915+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
916+ ) ) ;
917+ assert ! ( matches!(
918+ i64 :: extended_parse( "-0x" ) ,
919+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
920+ ) ) ;
896921 }
897922
898923 #[ test]
@@ -926,6 +951,27 @@ mod tests {
926951 assert_eq ! ( Ok ( 0b1011 ) , u64 :: extended_parse( "+0b1011" ) ) ;
927952 assert_eq ! ( Ok ( -0b1011 ) , i64 :: extended_parse( "-0b1011" ) ) ;
928953
954+ assert ! ( matches!(
955+ u64 :: extended_parse( "0b" ) ,
956+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
957+ ) ) ;
958+ assert ! ( matches!(
959+ u64 :: extended_parse( "0b." ) ,
960+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b." ) )
961+ ) ) ;
962+ assert ! ( matches!(
963+ u64 :: extended_parse( "-0b" ) ,
964+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
965+ ) ) ;
966+ assert ! ( matches!(
967+ i64 :: extended_parse( "0b" ) ,
968+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
969+ ) ) ;
970+ assert ! ( matches!(
971+ i64 :: extended_parse( "-0b" ) ,
972+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
973+ ) ) ;
974+
929975 // Binary not allowed for floats
930976 assert ! ( matches!(
931977 f64 :: extended_parse( "0b100" ) ,
@@ -950,11 +996,6 @@ mod tests {
950996 Err ( ExtendedParserError :: PartialMatch ( ebd, "b." ) ) => ebd == ExtendedBigDecimal :: zero( ) ,
951997 _ => false ,
952998 } ) ;
953- // TODO: GNU coreutils treats this as partial match.
954- assert_eq ! (
955- Err ( ExtendedParserError :: NotNumeric ) ,
956- u64 :: extended_parse( "0b" )
957- ) ;
958999 }
9591000
9601001 #[ test]
0 commit comments