@@ -450,9 +450,6 @@ pub(crate) fn parse<'a>(
450450 } else {
451451 ( Base :: Decimal , unsigned)
452452 } ;
453- if rest. is_empty ( ) {
454- return Err ( ExtendedParserError :: NotNumeric ) ;
455- }
456453
457454 // Parse the integral part of the number
458455 let mut chars = rest. chars ( ) . enumerate ( ) . fuse ( ) . peekable ( ) ;
@@ -518,6 +515,16 @@ pub(crate) fn parse<'a>(
518515
519516 // If no digit has been parsed, check if this is a special value, or declare the parsing unsuccessful
520517 if digits. is_none ( ) {
518+ // If we trimmed an initial `0x`/`0b`, return a partial match.
519+ if rest != unsigned {
520+ let ebd = if negative {
521+ ExtendedBigDecimal :: MinusZero
522+ } else {
523+ ExtendedBigDecimal :: zero ( )
524+ } ;
525+ return Err ( ExtendedParserError :: PartialMatch ( ebd, & unsigned[ 1 ..] ) ) ;
526+ }
527+
521528 return if target == ParseTarget :: Integral {
522529 Err ( ExtendedParserError :: NotNumeric )
523530 } else {
@@ -968,23 +975,41 @@ mod tests {
968975 ) )
969976 ) ) ;
970977
971- // TODO: GNU coreutils treats these as partial matches.
972- assert_eq ! (
973- Err ( ExtendedParserError :: NotNumeric ) ,
974- ExtendedBigDecimal :: extended_parse( "0x" )
975- ) ;
976- assert_eq ! (
977- Err ( ExtendedParserError :: NotNumeric ) ,
978- ExtendedBigDecimal :: extended_parse( "0x." )
979- ) ;
980- assert_eq ! (
981- Err ( ExtendedParserError :: NotNumeric ) ,
982- ExtendedBigDecimal :: extended_parse( "0xp" )
983- ) ;
984- assert_eq ! (
985- Err ( ExtendedParserError :: NotNumeric ) ,
986- ExtendedBigDecimal :: extended_parse( "0xp-2" )
987- ) ;
978+ // Not actually hex numbers, but the prefixes look like it.
979+ assert ! ( matches!( f64 :: extended_parse( "0x" ) ,
980+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == 0.0 ) ) ;
981+ assert ! ( matches!( f64 :: extended_parse( "0x." ) ,
982+ Err ( ExtendedParserError :: PartialMatch ( f, "x." ) ) if f == 0.0 ) ) ;
983+ assert ! ( matches!( f64 :: extended_parse( "0xp" ) ,
984+ Err ( ExtendedParserError :: PartialMatch ( f, "xp" ) ) if f == 0.0 ) ) ;
985+ assert ! ( matches!( f64 :: extended_parse( "0xp-2" ) ,
986+ Err ( ExtendedParserError :: PartialMatch ( f, "xp-2" ) ) if f == 0.0 ) ) ;
987+ assert ! ( matches!( f64 :: extended_parse( "0x.p-2" ) ,
988+ Err ( ExtendedParserError :: PartialMatch ( f, "x.p-2" ) ) if f == 0.0 ) ) ;
989+ assert ! ( matches!( f64 :: extended_parse( "0X" ) ,
990+ Err ( ExtendedParserError :: PartialMatch ( f, "X" ) ) if f == 0.0 ) ) ;
991+ assert ! ( matches!( f64 :: extended_parse( "-0x" ) ,
992+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == -0.0 ) ) ;
993+ assert ! ( matches!( f64 :: extended_parse( "+0x" ) ,
994+ Err ( ExtendedParserError :: PartialMatch ( f, "x" ) ) if f == 0.0 ) ) ;
995+ assert ! ( matches!( f64 :: extended_parse( "-0x." ) ,
996+ Err ( ExtendedParserError :: PartialMatch ( f, "x." ) ) if f == -0.0 ) ) ;
997+ assert ! ( matches!(
998+ u64 :: extended_parse( "0x" ) ,
999+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
1000+ ) ) ;
1001+ assert ! ( matches!(
1002+ u64 :: extended_parse( "-0x" ) ,
1003+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
1004+ ) ) ;
1005+ assert ! ( matches!(
1006+ i64 :: extended_parse( "0x" ) ,
1007+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
1008+ ) ) ;
1009+ assert ! ( matches!(
1010+ i64 :: extended_parse( "-0x" ) ,
1011+ Err ( ExtendedParserError :: PartialMatch ( 0 , "x" ) )
1012+ ) ) ;
9881013 }
9891014
9901015 #[ test]
@@ -1018,6 +1043,27 @@ mod tests {
10181043 assert_eq ! ( Ok ( 0b1011 ) , u64 :: extended_parse( "+0b1011" ) ) ;
10191044 assert_eq ! ( Ok ( -0b1011 ) , i64 :: extended_parse( "-0b1011" ) ) ;
10201045
1046+ assert ! ( matches!(
1047+ u64 :: extended_parse( "0b" ) ,
1048+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
1049+ ) ) ;
1050+ assert ! ( matches!(
1051+ u64 :: extended_parse( "0b." ) ,
1052+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b." ) )
1053+ ) ) ;
1054+ assert ! ( matches!(
1055+ u64 :: extended_parse( "-0b" ) ,
1056+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
1057+ ) ) ;
1058+ assert ! ( matches!(
1059+ i64 :: extended_parse( "0b" ) ,
1060+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
1061+ ) ) ;
1062+ assert ! ( matches!(
1063+ i64 :: extended_parse( "-0b" ) ,
1064+ Err ( ExtendedParserError :: PartialMatch ( 0 , "b" ) )
1065+ ) ) ;
1066+
10211067 // Binary not allowed for floats
10221068 assert ! ( matches!(
10231069 f64 :: extended_parse( "0b100" ) ,
@@ -1042,11 +1088,6 @@ mod tests {
10421088 Err ( ExtendedParserError :: PartialMatch ( ebd, "b." ) ) => ebd == ExtendedBigDecimal :: zero( ) ,
10431089 _ => false ,
10441090 } ) ;
1045- // TODO: GNU coreutils treats this as partial match.
1046- assert_eq ! (
1047- Err ( ExtendedParserError :: NotNumeric ) ,
1048- u64 :: extended_parse( "0b" )
1049- ) ;
10501091 }
10511092
10521093 #[ test]
0 commit comments