1+ #[ cfg( feature = "num-bigint" ) ]
12use num_bigint:: BigInt ;
3+ #[ cfg( feature = "num-bigint" ) ]
24use num_traits:: cast:: ToPrimitive ;
5+
36use std:: ops:: Range ;
47
58use lexical_parse_float:: { format as lexical_format, FromLexicalWithOptions , Options as ParseFloatOptions } ;
@@ -16,13 +19,15 @@ pub trait AbstractNumberDecoder {
1619#[ derive( Debug , Clone , PartialEq ) ]
1720pub enum NumberInt {
1821 Int ( i64 ) ,
22+ #[ cfg( feature = "num-bigint" ) ]
1923 BigInt ( BigInt ) ,
2024}
2125
2226impl From < NumberInt > for f64 {
2327 fn from ( num : NumberInt ) -> Self {
2428 match num {
2529 NumberInt :: Int ( int) => int as f64 ,
30+ #[ cfg( feature = "num-bigint" ) ]
2631 NumberInt :: BigInt ( big_int) => big_int. to_f64 ( ) . unwrap_or ( f64:: NAN ) ,
2732 }
2833 }
@@ -118,6 +123,7 @@ impl pyo3::ToPyObject for NumberAny {
118123 fn to_object ( & self , py : pyo3:: Python < ' _ > ) -> pyo3:: PyObject {
119124 match self {
120125 Self :: Int ( NumberInt :: Int ( int) ) => int. to_object ( py) ,
126+ #[ cfg( feature = "num-bigint" ) ]
121127 Self :: Int ( NumberInt :: BigInt ( big_int) ) => big_int. to_object ( py) ,
122128 Self :: Float ( float) => float. to_object ( py) ,
123129 }
@@ -220,8 +226,8 @@ impl IntParse {
220226 index += 1 ;
221227 let ( chunk, new_index) = IntChunk :: parse_small ( data, index, first_value) ;
222228
223- let mut big_value : BigInt = match chunk {
224- IntChunk :: Ongoing ( value) => value. into ( ) ,
229+ let ongoing : u64 = match chunk {
230+ IntChunk :: Ongoing ( value) => value,
225231 IntChunk :: Done ( value) => {
226232 let mut value_i64 = value as i64 ;
227233 if !positive {
@@ -231,62 +237,76 @@ impl IntParse {
231237 }
232238 IntChunk :: Float => return Ok ( ( Self :: Float , new_index) ) ,
233239 } ;
234- index = new_index;
235240
236- // number is too big for i64, we need ot use a big int
237- loop {
238- let ( chunk, new_index) = IntChunk :: parse_big ( data, index) ;
239- if ( new_index - start) > 4300 {
240- return json_err ! ( NumberOutOfRange , start + 4301 ) ;
241- }
242- match chunk {
243- IntChunk :: Ongoing ( value) => {
244- big_value *= ONGOING_CHUNK_MULTIPLIER ;
245- big_value += value;
246- index = new_index;
241+ // number is too big for i64, we need to use a BigInt,
242+ // or error out if num-bigint is not enabled
243+
244+ #[ cfg( not( feature = "num-bigint" ) ) ]
245+ {
246+ // silence unused variable warning
247+ let _ = ( ongoing, start) ;
248+ return json_err ! ( NumberOutOfRange , index) ;
249+ }
250+
251+ #[ cfg( feature = "num-bigint" ) ]
252+ {
253+ #[ cfg( target_arch = "aarch64" ) ]
254+ // in aarch64 we use a 128 bit registers - 16 bytes
255+ const ONGOING_CHUNK_MULTIPLIER : u64 = 10u64 . pow ( 16 ) ;
256+ #[ cfg( not( target_arch = "aarch64" ) ) ]
257+ // decode_int_chunk_fallback - we parse 18 bytes when the number is ongoing
258+ const ONGOING_CHUNK_MULTIPLIER : u64 = 10u64 . pow ( 18 ) ;
259+
260+ const POW_10 : [ u64 ; 18 ] = [
261+ 10u64 . pow ( 0 ) ,
262+ 10u64 . pow ( 1 ) ,
263+ 10u64 . pow ( 2 ) ,
264+ 10u64 . pow ( 3 ) ,
265+ 10u64 . pow ( 4 ) ,
266+ 10u64 . pow ( 5 ) ,
267+ 10u64 . pow ( 6 ) ,
268+ 10u64 . pow ( 7 ) ,
269+ 10u64 . pow ( 8 ) ,
270+ 10u64 . pow ( 9 ) ,
271+ 10u64 . pow ( 10 ) ,
272+ 10u64 . pow ( 11 ) ,
273+ 10u64 . pow ( 12 ) ,
274+ 10u64 . pow ( 13 ) ,
275+ 10u64 . pow ( 14 ) ,
276+ 10u64 . pow ( 15 ) ,
277+ 10u64 . pow ( 16 ) ,
278+ 10u64 . pow ( 17 ) ,
279+ ] ;
280+
281+ let mut big_value: BigInt = ongoing. into ( ) ;
282+ index = new_index;
283+
284+ loop {
285+ let ( chunk, new_index) = IntChunk :: parse_big ( data, index) ;
286+ if ( new_index - start) > 4300 {
287+ return json_err ! ( NumberOutOfRange , start + 4301 ) ;
247288 }
248- IntChunk :: Done ( value) => {
249- big_value *= POW_10 [ new_index - index] ;
250- big_value += value;
251- if !positive {
252- big_value = -big_value;
289+ match chunk {
290+ IntChunk :: Ongoing ( value) => {
291+ big_value *= ONGOING_CHUNK_MULTIPLIER ;
292+ big_value += value;
293+ index = new_index;
294+ }
295+ IntChunk :: Done ( value) => {
296+ big_value *= POW_10 [ new_index - index] ;
297+ big_value += value;
298+ if !positive {
299+ big_value = -big_value;
300+ }
301+ return Ok ( ( Self :: Int ( NumberInt :: BigInt ( big_value) ) , new_index) ) ;
253302 }
254- return Ok ( ( Self :: Int ( NumberInt :: BigInt ( big_value ) ) , new_index) ) ;
303+ IntChunk :: Float => return Ok ( ( Self :: Float , new_index) ) ,
255304 }
256- IntChunk :: Float => return Ok ( ( Self :: Float , new_index) ) ,
257305 }
258306 }
259307 }
260308}
261309
262- static POW_10 : [ u64 ; 18 ] = [
263- 10u64 . pow ( 0 ) ,
264- 10u64 . pow ( 1 ) ,
265- 10u64 . pow ( 2 ) ,
266- 10u64 . pow ( 3 ) ,
267- 10u64 . pow ( 4 ) ,
268- 10u64 . pow ( 5 ) ,
269- 10u64 . pow ( 6 ) ,
270- 10u64 . pow ( 7 ) ,
271- 10u64 . pow ( 8 ) ,
272- 10u64 . pow ( 9 ) ,
273- 10u64 . pow ( 10 ) ,
274- 10u64 . pow ( 11 ) ,
275- 10u64 . pow ( 12 ) ,
276- 10u64 . pow ( 13 ) ,
277- 10u64 . pow ( 14 ) ,
278- 10u64 . pow ( 15 ) ,
279- 10u64 . pow ( 16 ) ,
280- 10u64 . pow ( 17 ) ,
281- ] ;
282-
283- #[ cfg( target_arch = "aarch64" ) ]
284- // in aarch64 we use a 128 bit registers - 16 bytes
285- static ONGOING_CHUNK_MULTIPLIER : u64 = 10u64 . pow ( 16 ) ;
286- #[ cfg( not( target_arch = "aarch64" ) ) ]
287- // decode_int_chunk_fallback - we parse 18 bytes when the number is ongoing
288- static ONGOING_CHUNK_MULTIPLIER : u64 = 10u64 . pow ( 18 ) ;
289-
290310pub ( crate ) enum IntChunk {
291311 Ongoing ( u64 ) ,
292312 Done ( u64 ) ,
@@ -362,6 +382,8 @@ pub(crate) static INT_CHAR_MAP: [bool; 256] = {
362382
363383pub struct NumberRange {
364384 pub range : Range < usize > ,
385+ // in some cfg configurations, this field is never read.
386+ #[ allow( dead_code) ]
365387 pub is_int : bool ,
366388}
367389
0 commit comments