@@ -356,7 +356,9 @@ impl std::str::FromStr for ParsedDecimal128 {
356356 exp_str = post;
357357 }
358358 }
359- let mut exp = exp_str. parse :: < i16 > ( ) . map_err ( |e| {
359+ // Initially parse the exponent as an i128 to handle corner cases with zero
360+ // coefficients and very large exponents.
361+ let mut wide_exp = exp_str. parse :: < i128 > ( ) . map_err ( |e| {
360362 Error :: decimal128 ( Decimal128ErrorKind :: InvalidExponent { } ) . with_message ( e)
361363 } ) ?;
362364
@@ -367,7 +369,7 @@ impl std::str::FromStr for ParsedDecimal128 {
367369 . len ( )
368370 . try_into ( )
369371 . map_err ( |_| Error :: decimal128 ( Decimal128ErrorKind :: Underflow { } ) ) ?;
370- exp = exp
372+ wide_exp = wide_exp
371373 . checked_sub ( exp_adj)
372374 . ok_or_else ( || Error :: decimal128 ( Decimal128ErrorKind :: Underflow { } ) ) ?;
373375 joined_str = format ! ( "{}{}" , pre, post) ;
@@ -386,16 +388,17 @@ impl std::str::FromStr for ParsedDecimal128 {
386388 let exp_adj = ( len - decimal_str. len ( ) )
387389 . try_into ( )
388390 . map_err ( |_| Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
389- exp = exp
391+ wide_exp = wide_exp
390392 . checked_add ( exp_adj)
391393 . ok_or_else ( || Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
392394 }
393395 }
394396
395397 // Check exponent limits
396- if exp < Exponent :: TINY {
398+ const TINY : i128 = Exponent :: TINY as i128 ;
399+ if wide_exp < TINY {
397400 if decimal_str != "0" {
398- let delta = ( Exponent :: TINY - exp )
401+ let delta = ( TINY - wide_exp )
399402 . try_into ( )
400403 . map_err ( |_| Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
401404 let new_precision = decimal_str
@@ -404,12 +407,13 @@ impl std::str::FromStr for ParsedDecimal128 {
404407 . ok_or_else ( || Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
405408 decimal_str = round_decimal_str ( decimal_str, new_precision) ?;
406409 }
407- exp = Exponent :: TINY ;
410+ wide_exp = Exponent :: TINY . into ( ) ;
408411 }
409412 let padded_str;
410- if exp > Exponent :: MAX {
413+ const MAX : i128 = Exponent :: MAX as i128 ;
414+ if wide_exp > MAX {
411415 if decimal_str != "0" {
412- let delta = ( exp - Exponent :: MAX )
416+ let delta = ( wide_exp - MAX )
413417 . try_into ( )
414418 . map_err ( |_| Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
415419 if decimal_str
@@ -423,10 +427,13 @@ impl std::str::FromStr for ParsedDecimal128 {
423427 padded_str = format ! ( "{}{}" , decimal_str, "0" . repeat( delta) ) ;
424428 decimal_str = & padded_str;
425429 }
426- exp = Exponent :: MAX ;
430+ wide_exp = Exponent :: MAX . into ( ) ;
427431 }
428432
429433 // Assemble the final value
434+ let exp: i16 = wide_exp
435+ . try_into ( )
436+ . map_err ( |_| Error :: decimal128 ( Decimal128ErrorKind :: Overflow { } ) ) ?;
430437 let exponent = Exponent :: from_native ( exp) ;
431438 let coeff: u128 = decimal_str. parse ( ) . map_err ( |e : ParseIntError | {
432439 Error :: decimal128 ( Decimal128ErrorKind :: InvalidCoefficient { } ) . with_message ( e)
0 commit comments