@@ -741,72 +741,53 @@ fn parse_e_notation<T: DecimalType>(
741741 let mut exp: i16 = 0 ;
742742 let base = T :: Native :: usize_as ( 10 ) ;
743743
744- let mut exp_start: bool = false ;
745744 // e has a plus sign
746745 let mut pos_shift_direction: bool = true ;
747746
748- // skip to point or exponent index
749- let mut bs;
750- if fractionals > 0 {
751- // it's a fraction, so the point index needs to be skipped, so +1
752- bs = s. as_bytes ( ) . iter ( ) . skip ( index + fractionals as usize + 1 ) ;
753- } else {
754- // it's actually an integer that is already written into the result, so let's skip on to e
755- bs = s. as_bytes ( ) . iter ( ) . skip ( index) ;
756- }
747+ // skip to the exponent index directly or just after any processed fractionals
748+ let mut bs = s. as_bytes ( ) . iter ( ) . skip ( index + fractionals as usize ) ;
757749
758- while let Some ( b) = bs. next ( ) {
750+ // complete parsing of any unprocessed fractionals up to the exponent
751+ for b in bs. by_ref ( ) {
759752 match b {
760753 b'0' ..=b'9' => {
761754 result = result. mul_wrapping ( base) ;
762755 result = result. add_wrapping ( T :: Native :: usize_as ( ( b - b'0' ) as usize ) ) ;
763- if fractionals > 0 {
764- fractionals += 1 ;
765- }
756+ fractionals += 1 ;
766757 digits += 1 ;
767758 }
768- & b'e' | & b'E' => {
769- exp_start = true ;
759+ b'e' | b'E' => {
760+ break ;
770761 }
771762 _ => {
772763 return Err ( ArrowError :: ParseError ( format ! (
773764 "can't parse the string value {s} to decimal"
774765 ) ) ) ;
775766 }
776767 } ;
768+ }
777769
778- if exp_start {
779- pos_shift_direction = match bs. next ( ) {
780- Some ( & b'-' ) => false ,
781- Some ( & b'+' ) => true ,
782- Some ( b) => {
783- if !b. is_ascii_digit ( ) {
784- return Err ( ArrowError :: ParseError ( format ! (
785- "can't parse the string value {s} to decimal"
786- ) ) ) ;
787- }
788-
789- exp *= 10 ;
790- exp += ( b - b'0' ) as i16 ;
791-
792- true
793- }
794- None => {
795- return Err ( ArrowError :: ParseError ( format ! (
796- "can't parse the string value {s} to decimal"
797- ) ) ) ;
798- }
799- } ;
800-
801- for b in bs. by_ref ( ) {
802- if !b. is_ascii_digit ( ) {
803- return Err ( ArrowError :: ParseError ( format ! (
804- "can't parse the string value {s} to decimal"
805- ) ) ) ;
806- }
770+ // parse the exponent itself
771+ let mut signed = false ;
772+ for b in bs {
773+ match b {
774+ b'-' if !signed => {
775+ pos_shift_direction = false ;
776+ signed = true ;
777+ }
778+ b'+' if !signed => {
779+ pos_shift_direction = true ;
780+ signed = true ;
781+ }
782+ b if b. is_ascii_digit ( ) => {
807783 exp *= 10 ;
808784 exp += ( b - b'0' ) as i16 ;
809785 }
786+ _ => {
787+ return Err ( ArrowError :: ParseError ( format ! (
788+ "can't parse the string value {s} to decimal"
789+ ) ) ) ;
790+ }
810791 }
811792 }
812793
@@ -903,7 +884,7 @@ pub fn parse_decimal<T: DecimalType>(
903884 digits as u16 ,
904885 fractionals as i16 ,
905886 result,
906- point_index,
887+ point_index + 1 ,
907888 precision as u16 ,
908889 scale as i16 ,
909890 ) ?;
@@ -916,7 +897,7 @@ pub fn parse_decimal<T: DecimalType>(
916897 "can't parse the string value {s} to decimal"
917898 ) ) ) ;
918899 }
919- if fractionals == scale && scale != 0 {
900+ if fractionals == scale {
920901 // We have processed all the digits that we need. All that
921902 // is left is to validate that the rest of the string contains
922903 // valid digits.
@@ -933,7 +914,7 @@ pub fn parse_decimal<T: DecimalType>(
933914 }
934915
935916 // Fail on "."
936- if digits == 0 {
917+ if digits == 0 && scale != 0 {
937918 return Err ( ArrowError :: ParseError ( format ! (
938919 "can't parse the string value {s} to decimal"
939920 ) ) ) ;
@@ -963,14 +944,6 @@ pub fn parse_decimal<T: DecimalType>(
963944 }
964945
965946 if !is_e_notation {
966- if scale == 0 && fractionals > 0 {
967- // The input string contained some fractional digits after the decimal point despite
968- // the scale being zero. Eject all the fractional digits from the number.
969- result = result. div_wrapping ( base. pow_wrapping ( fractionals as _ ) ) ;
970- digits -= fractionals as u8 ;
971- fractionals = 0 ;
972- }
973-
974947 if fractionals < scale {
975948 let exp = scale - fractionals;
976949 if exp as u8 + digits > precision {
@@ -2763,20 +2736,31 @@ mod tests {
27632736 }
27642737
27652738 let zero_scale_tests = [
2766- ( "0.123" , 0 ) ,
2767- ( "1.0" , 1 ) ,
2768- ( "1.2" , 1 ) ,
2769- ( "1.00" , 1 ) ,
2770- ( "1.23" , 1 ) ,
2771- ( "1.000" , 1 ) ,
2772- ( "1.123" , 1 ) ,
2773- ( "123.0" , 123 ) ,
2774- ( "123.4" , 123 ) ,
2775- ( "123.00" , 123 ) ,
2776- ( "123.45" , 123 ) ,
2739+ ( "0.123" , 0 , 3 ) ,
2740+ ( "1.0" , 1 , 3 ) ,
2741+ ( "1.2" , 1 , 3 ) ,
2742+ ( "1.00" , 1 , 3 ) ,
2743+ ( "1.23" , 1 , 3 ) ,
2744+ ( "1.000" , 1 , 3 ) ,
2745+ ( "1.123" , 1 , 3 ) ,
2746+ ( "123.0" , 123 , 3 ) ,
2747+ ( "123.4" , 123 , 3 ) ,
2748+ ( "123.00" , 123 , 3 ) ,
2749+ ( "123.45" , 123 , 3 ) ,
2750+ ( "123.000000000000000000004" , 123 , 3 ) ,
2751+ ( "0.123e2" , 12 , 3 ) ,
2752+ ( "0.123e4" , 1230 , 10 ) ,
2753+ ( "1.23e4" , 12300 , 10 ) ,
2754+ ( "12.3e4" , 123000 , 10 ) ,
2755+ ( "123e4" , 1230000 , 10 ) ,
2756+ (
2757+ "20000000000000000000000000000000000002.0" ,
2758+ 20000000000000000000000000000000000002 ,
2759+ 38 ,
2760+ ) ,
27772761 ] ;
2778- for ( s, i) in zero_scale_tests {
2779- let result_128 = parse_decimal :: < Decimal128Type > ( s, 3 , 0 ) . unwrap ( ) ;
2762+ for ( s, i, precision ) in zero_scale_tests {
2763+ let result_128 = parse_decimal :: < Decimal128Type > ( s, precision , 0 ) . unwrap ( ) ;
27802764 assert_eq ! ( i, result_128) ;
27812765 }
27822766 }
0 commit comments