@@ -11,6 +11,7 @@ use bigdecimal::{
11
11
BigDecimal ,
12
12
num_bigint:: { BigInt , BigUint , Sign } ,
13
13
} ;
14
+ use num_traits:: FromPrimitive ;
14
15
use num_traits:: Signed ;
15
16
use num_traits:: ToPrimitive ;
16
17
use num_traits:: Zero ;
@@ -166,22 +167,26 @@ impl ExtendedParser for u64 {
166
167
let ( digits, scale) = bd. into_bigint_and_scale ( ) ;
167
168
if scale == 0 {
168
169
let negative = digits. sign ( ) == Sign :: Minus ;
169
- match u64:: try_from ( digits) {
170
+
171
+ match u64:: try_from ( digits. clone ( ) ) {
170
172
Ok ( i) => Ok ( i) ,
171
- _ => Err ( ExtendedParserError :: Overflow ( if negative {
172
- // TODO: We should wrap around here #7488
173
- 0
174
- } else {
175
- u64:: MAX
176
- } ) ) ,
173
+ _ => {
174
+ if negative {
175
+ match u64:: try_from ( digits. into_parts ( ) . 1 ) {
176
+ Ok ( i) => Ok ( !i + 1 ) , // two's complement representation
177
+ _ => Err ( ExtendedParserError :: Overflow ( u64:: MAX ) ) ,
178
+ }
179
+ } else {
180
+ Err ( ExtendedParserError :: Overflow ( u64:: MAX ) )
181
+ }
182
+ }
177
183
}
178
184
} else {
179
185
// Should not happen.
180
186
Err ( ExtendedParserError :: NotNumeric )
181
187
}
182
188
}
183
- // TODO: Handle -0 too #7488
184
- // No other case should not happen.
189
+ ExtendedBigDecimal :: MinusZero => Ok ( 0 ) ,
185
190
_ => Err ( ExtendedParserError :: NotNumeric ) ,
186
191
}
187
192
}
@@ -500,10 +505,28 @@ mod tests {
500
505
fn test_decimal_u64 ( ) {
501
506
assert_eq ! ( Ok ( 123 ) , u64 :: extended_parse( "123" ) ) ;
502
507
assert_eq ! ( Ok ( u64 :: MAX ) , u64 :: extended_parse( & format!( "{}" , u64 :: MAX ) ) ) ;
503
- // TODO: We should wrap around here #7488
508
+ assert_eq ! ( Ok ( 0 ) , u64 :: extended_parse( "-0" ) ) ;
509
+ assert_eq ! ( Ok ( u64 :: MAX ) , u64 :: extended_parse( "-1" ) ) ;
510
+ assert_eq ! (
511
+ Ok ( u64 :: MAX / 2 + 1 ) ,
512
+ u64 :: extended_parse( "-9223372036854775808" ) // i64::MIN
513
+ ) ;
514
+ assert_eq ! (
515
+ Ok ( 1123372036854675616 ) ,
516
+ u64 :: extended_parse( "-17323372036854876000" ) // 2*i64::MIN
517
+ ) ;
518
+ assert_eq ! ( Ok ( 1 ) , u64 :: extended_parse( "-18446744073709551615" ) ) ; // -u64::MAX
519
+ assert ! ( matches!(
520
+ u64 :: extended_parse( "-18446744073709551616" ) , // -u64::MAX - 1
521
+ Err ( ExtendedParserError :: Overflow ( u64 :: MAX ) )
522
+ ) ) ;
523
+ assert ! ( matches!(
524
+ u64 :: extended_parse( "-92233720368547758150" ) ,
525
+ Err ( ExtendedParserError :: Overflow ( u64 :: MAX ) )
526
+ ) ) ;
504
527
assert ! ( matches!(
505
- u64 :: extended_parse( "-123 " ) ,
506
- Err ( ExtendedParserError :: Overflow ( 0 ) )
528
+ u64 :: extended_parse( "-170141183460469231731687303715884105729 " ) ,
529
+ Err ( ExtendedParserError :: Overflow ( u64 :: MAX ) )
507
530
) ) ;
508
531
assert ! ( matches!(
509
532
u64 :: extended_parse( "" ) ,
0 commit comments