@@ -15,6 +15,7 @@ import { BSONRegExp } from '../regexp';
15
15
import { BSONSymbol } from '../symbol' ;
16
16
import { Timestamp } from '../timestamp' ;
17
17
import { ByteUtils } from '../utils/byte_utils' ;
18
+ import { NumberUtils } from '../utils/number_utils' ;
18
19
import { validateUtf8 } from '../validate_utf8' ;
19
20
20
21
/** @public */
@@ -91,11 +92,7 @@ export function internalDeserialize(
91
92
options = options == null ? { } : options ;
92
93
const index = options && options . index ? options . index : 0 ;
93
94
// Read the document size
94
- const size =
95
- buffer [ index ] |
96
- ( buffer [ index + 1 ] << 8 ) |
97
- ( buffer [ index + 2 ] << 16 ) |
98
- ( buffer [ index + 3 ] << 24 ) ;
95
+ const size = NumberUtils . getInt32LE ( buffer , index ) ;
99
96
100
97
if ( size < 5 ) {
101
98
throw new BSONError ( `bson size must be >= 5, is ${ size } ` ) ;
@@ -128,9 +125,6 @@ export function internalDeserialize(
128
125
129
126
const allowedDBRefKeys = / ^ \$ r e f $ | ^ \$ i d $ | ^ \$ d b $ / ;
130
127
131
- const FLOAT_READ = new Float64Array ( 1 ) ;
132
- const FLOAT_WRITE_BYTES = new Uint8Array ( FLOAT_READ . buffer , 0 , 8 ) ;
133
-
134
128
function deserializeObject (
135
129
buffer : Uint8Array ,
136
130
index : number ,
@@ -207,8 +201,8 @@ function deserializeObject(
207
201
if ( buffer . length < 5 ) throw new BSONError ( 'corrupt bson message < 5 bytes long' ) ;
208
202
209
203
// Read the document size
210
- const size =
211
- buffer [ index ++ ] | ( buffer [ index ++ ] << 8 ) | ( buffer [ index ++ ] << 16 ) | ( buffer [ index ++ ] << 24 ) ;
204
+ const size = NumberUtils . getInt32LE ( buffer , index ) ;
205
+ index += 4 ;
212
206
213
207
// Ensure buffer is valid size
214
208
if ( size < 5 || size > buffer . length ) throw new BSONError ( 'corrupt bson message' ) ;
@@ -258,11 +252,8 @@ function deserializeObject(
258
252
index = i + 1 ;
259
253
260
254
if ( elementType === constants . BSON_DATA_STRING ) {
261
- const stringSize =
262
- buffer [ index ++ ] |
263
- ( buffer [ index ++ ] << 8 ) |
264
- ( buffer [ index ++ ] << 16 ) |
265
- ( buffer [ index ++ ] << 24 ) ;
255
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
256
+ index += 4 ;
266
257
if (
267
258
stringSize <= 0 ||
268
259
stringSize > buffer . length - index ||
@@ -278,37 +269,19 @@ function deserializeObject(
278
269
value = new ObjectId ( oid ) ;
279
270
index = index + 12 ;
280
271
} else if ( elementType === constants . BSON_DATA_INT && promoteValues === false ) {
281
- value = new Int32 (
282
- buffer [ index ++ ] | ( buffer [ index ++ ] << 8 ) | ( buffer [ index ++ ] << 16 ) | ( buffer [ index ++ ] << 24 )
283
- ) ;
272
+ value = new Int32 ( NumberUtils . getInt32LE ( buffer , index ) ) ;
273
+ index += 4 ;
284
274
} else if ( elementType === constants . BSON_DATA_INT ) {
285
- value =
286
- buffer [ index ++ ] |
287
- ( buffer [ index ++ ] << 8 ) |
288
- ( buffer [ index ++ ] << 16 ) |
289
- ( buffer [ index ++ ] << 24 ) ;
275
+ value = NumberUtils . getInt32LE ( buffer , index ) ;
276
+ index += 4 ;
290
277
} else if ( elementType === constants . BSON_DATA_NUMBER ) {
291
- FLOAT_WRITE_BYTES [ 0 ] = buffer [ index ++ ] ;
292
- FLOAT_WRITE_BYTES [ 1 ] = buffer [ index ++ ] ;
293
- FLOAT_WRITE_BYTES [ 2 ] = buffer [ index ++ ] ;
294
- FLOAT_WRITE_BYTES [ 3 ] = buffer [ index ++ ] ;
295
- FLOAT_WRITE_BYTES [ 4 ] = buffer [ index ++ ] ;
296
- FLOAT_WRITE_BYTES [ 5 ] = buffer [ index ++ ] ;
297
- FLOAT_WRITE_BYTES [ 6 ] = buffer [ index ++ ] ;
298
- FLOAT_WRITE_BYTES [ 7 ] = buffer [ index ++ ] ;
299
- value = FLOAT_READ [ 0 ] ;
278
+ value = NumberUtils . getFloat64LE ( buffer , index ) ;
279
+ index += 8 ;
300
280
if ( promoteValues === false ) value = new Double ( value ) ;
301
281
} else if ( elementType === constants . BSON_DATA_DATE ) {
302
- const lowBits =
303
- buffer [ index ++ ] |
304
- ( buffer [ index ++ ] << 8 ) |
305
- ( buffer [ index ++ ] << 16 ) |
306
- ( buffer [ index ++ ] << 24 ) ;
307
- const highBits =
308
- buffer [ index ++ ] |
309
- ( buffer [ index ++ ] << 8 ) |
310
- ( buffer [ index ++ ] << 16 ) |
311
- ( buffer [ index ++ ] << 24 ) ;
282
+ const lowBits = NumberUtils . getInt32LE ( buffer , index ) ;
283
+ const highBits = NumberUtils . getInt32LE ( buffer , index + 4 ) ;
284
+ index += 8 ;
312
285
313
286
value = new Date ( new Long ( lowBits , highBits ) . toNumber ( ) ) ;
314
287
} else if ( elementType === constants . BSON_DATA_BOOLEAN ) {
@@ -317,11 +290,8 @@ function deserializeObject(
317
290
value = buffer [ index ++ ] === 1 ;
318
291
} else if ( elementType === constants . BSON_DATA_OBJECT ) {
319
292
const _index = index ;
320
- const objectSize =
321
- buffer [ index ] |
322
- ( buffer [ index + 1 ] << 8 ) |
323
- ( buffer [ index + 2 ] << 16 ) |
324
- ( buffer [ index + 3 ] << 24 ) ;
293
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
294
+
325
295
if ( objectSize <= 0 || objectSize > buffer . length - index )
326
296
throw new BSONError ( 'bad embedded document length in bson' ) ;
327
297
@@ -339,11 +309,7 @@ function deserializeObject(
339
309
index = index + objectSize ;
340
310
} else if ( elementType === constants . BSON_DATA_ARRAY ) {
341
311
const _index = index ;
342
- const objectSize =
343
- buffer [ index ] |
344
- ( buffer [ index + 1 ] << 8 ) |
345
- ( buffer [ index + 2 ] << 16 ) |
346
- ( buffer [ index + 3 ] << 24 ) ;
312
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
347
313
let arrayOptions : DeserializeOptions = options ;
348
314
349
315
// Stop index
@@ -368,32 +334,14 @@ function deserializeObject(
368
334
value = null ;
369
335
} else if ( elementType === constants . BSON_DATA_LONG ) {
370
336
if ( useBigInt64 ) {
371
- const lo =
372
- buffer [ index ] +
373
- buffer [ index + 1 ] * 2 ** 8 +
374
- buffer [ index + 2 ] * 2 ** 16 +
375
- buffer [ index + 3 ] * 2 ** 24 ;
376
- const hi =
377
- buffer [ index + 4 ] +
378
- buffer [ index + 5 ] * 2 ** 8 +
379
- buffer [ index + 6 ] * 2 ** 16 +
380
- ( buffer [ index + 7 ] << 24 ) ; // Overflow
381
-
382
- /* eslint-disable-next-line no-restricted-globals -- This is allowed here as useBigInt64=true */
383
- value = ( BigInt ( hi ) << BigInt ( 32 ) ) + BigInt ( lo ) ;
337
+ value = NumberUtils . getBigInt64LE ( buffer , index ) ;
384
338
index += 8 ;
385
339
} else {
386
340
// Unpack the low and high bits
387
- const lowBits =
388
- buffer [ index ++ ] |
389
- ( buffer [ index ++ ] << 8 ) |
390
- ( buffer [ index ++ ] << 16 ) |
391
- ( buffer [ index ++ ] << 24 ) ;
392
- const highBits =
393
- buffer [ index ++ ] |
394
- ( buffer [ index ++ ] << 8 ) |
395
- ( buffer [ index ++ ] << 16 ) |
396
- ( buffer [ index ++ ] << 24 ) ;
341
+ const lowBits = NumberUtils . getInt32LE ( buffer , index ) ;
342
+ const highBits = NumberUtils . getInt32LE ( buffer , index + 4 ) ;
343
+ index += 8 ;
344
+
397
345
const long = new Long ( lowBits , highBits ) ;
398
346
// Promote the long if possible
399
347
if ( promoteLongs && promoteValues === true ) {
@@ -415,11 +363,8 @@ function deserializeObject(
415
363
// Assign the new Decimal128 value
416
364
value = new Decimal128 ( bytes ) ;
417
365
} else if ( elementType === constants . BSON_DATA_BINARY ) {
418
- let binarySize =
419
- buffer [ index ++ ] |
420
- ( buffer [ index ++ ] << 8 ) |
421
- ( buffer [ index ++ ] << 16 ) |
422
- ( buffer [ index ++ ] << 24 ) ;
366
+ let binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
367
+ index += 4 ;
423
368
const totalBinarySize = binarySize ;
424
369
const subType = buffer [ index ++ ] ;
425
370
@@ -434,11 +379,8 @@ function deserializeObject(
434
379
if ( buffer [ 'slice' ] != null ) {
435
380
// If we have subtype 2 skip the 4 bytes for the size
436
381
if ( subType === Binary . SUBTYPE_BYTE_ARRAY ) {
437
- binarySize =
438
- buffer [ index ++ ] |
439
- ( buffer [ index ++ ] << 8 ) |
440
- ( buffer [ index ++ ] << 16 ) |
441
- ( buffer [ index ++ ] << 24 ) ;
382
+ binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
383
+ index += 4 ;
442
384
if ( binarySize < 0 )
443
385
throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
444
386
if ( binarySize > totalBinarySize - 4 )
@@ -459,11 +401,8 @@ function deserializeObject(
459
401
const _buffer = ByteUtils . allocate ( binarySize ) ;
460
402
// If we have subtype 2 skip the 4 bytes for the size
461
403
if ( subType === Binary . SUBTYPE_BYTE_ARRAY ) {
462
- binarySize =
463
- buffer [ index ++ ] |
464
- ( buffer [ index ++ ] << 8 ) |
465
- ( buffer [ index ++ ] << 16 ) |
466
- ( buffer [ index ++ ] << 24 ) ;
404
+ binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
405
+ index += 4 ;
467
406
if ( binarySize < 0 )
468
407
throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
469
408
if ( binarySize > totalBinarySize - 4 )
@@ -562,11 +501,8 @@ function deserializeObject(
562
501
// Set the object
563
502
value = new BSONRegExp ( source , regExpOptions ) ;
564
503
} else if ( elementType === constants . BSON_DATA_SYMBOL ) {
565
- const stringSize =
566
- buffer [ index ++ ] |
567
- ( buffer [ index ++ ] << 8 ) |
568
- ( buffer [ index ++ ] << 16 ) |
569
- ( buffer [ index ++ ] << 24 ) ;
504
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
505
+ index += 4 ;
570
506
if (
571
507
stringSize <= 0 ||
572
508
stringSize > buffer . length - index ||
@@ -578,31 +514,18 @@ function deserializeObject(
578
514
value = promoteValues ? symbol : new BSONSymbol ( symbol ) ;
579
515
index = index + stringSize ;
580
516
} else if ( elementType === constants . BSON_DATA_TIMESTAMP ) {
581
- // We intentionally **do not** use bit shifting here
582
- // Bit shifting in javascript coerces numbers to **signed** int32s
583
- // We need to keep i, and t unsigned
584
- const i =
585
- buffer [ index ++ ] +
586
- buffer [ index ++ ] * ( 1 << 8 ) +
587
- buffer [ index ++ ] * ( 1 << 16 ) +
588
- buffer [ index ++ ] * ( 1 << 24 ) ;
589
- const t =
590
- buffer [ index ++ ] +
591
- buffer [ index ++ ] * ( 1 << 8 ) +
592
- buffer [ index ++ ] * ( 1 << 16 ) +
593
- buffer [ index ++ ] * ( 1 << 24 ) ;
594
-
595
- value = new Timestamp ( { i, t } ) ;
517
+ value = new Timestamp ( {
518
+ i : NumberUtils . getUint32LE ( buffer , index ) ,
519
+ t : NumberUtils . getUint32LE ( buffer , index + 4 )
520
+ } ) ;
521
+ index += 8 ;
596
522
} else if ( elementType === constants . BSON_DATA_MIN_KEY ) {
597
523
value = new MinKey ( ) ;
598
524
} else if ( elementType === constants . BSON_DATA_MAX_KEY ) {
599
525
value = new MaxKey ( ) ;
600
526
} else if ( elementType === constants . BSON_DATA_CODE ) {
601
- const stringSize =
602
- buffer [ index ++ ] |
603
- ( buffer [ index ++ ] << 8 ) |
604
- ( buffer [ index ++ ] << 16 ) |
605
- ( buffer [ index ++ ] << 24 ) ;
527
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
528
+ index += 4 ;
606
529
if (
607
530
stringSize <= 0 ||
608
531
stringSize > buffer . length - index ||
@@ -622,23 +545,17 @@ function deserializeObject(
622
545
// Update parse index position
623
546
index = index + stringSize ;
624
547
} else if ( elementType === constants . BSON_DATA_CODE_W_SCOPE ) {
625
- const totalSize =
626
- buffer [ index ++ ] |
627
- ( buffer [ index ++ ] << 8 ) |
628
- ( buffer [ index ++ ] << 16 ) |
629
- ( buffer [ index ++ ] << 24 ) ;
548
+ const totalSize = NumberUtils . getInt32LE ( buffer , index ) ;
549
+ index += 4 ;
630
550
631
551
// Element cannot be shorter than totalSize + stringSize + documentSize + terminator
632
552
if ( totalSize < 4 + 4 + 4 + 1 ) {
633
553
throw new BSONError ( 'code_w_scope total size shorter minimum expected length' ) ;
634
554
}
635
555
636
556
// Get the code string size
637
- const stringSize =
638
- buffer [ index ++ ] |
639
- ( buffer [ index ++ ] << 8 ) |
640
- ( buffer [ index ++ ] << 16 ) |
641
- ( buffer [ index ++ ] << 24 ) ;
557
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
558
+ index += 4 ;
642
559
// Check if we have a valid string
643
560
if (
644
561
stringSize <= 0 ||
@@ -660,11 +577,7 @@ function deserializeObject(
660
577
// Parse the element
661
578
const _index = index ;
662
579
// Decode the size of the object document
663
- const objectSize =
664
- buffer [ index ] |
665
- ( buffer [ index + 1 ] << 8 ) |
666
- ( buffer [ index + 2 ] << 16 ) |
667
- ( buffer [ index + 3 ] << 24 ) ;
580
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
668
581
// Decode the scope object
669
582
const scopeObject = deserializeObject ( buffer , _index , options , false ) ;
670
583
// Adjust the index
@@ -683,11 +596,8 @@ function deserializeObject(
683
596
value = new Code ( functionString , scopeObject ) ;
684
597
} else if ( elementType === constants . BSON_DATA_DBPOINTER ) {
685
598
// Get the code string size
686
- const stringSize =
687
- buffer [ index ++ ] |
688
- ( buffer [ index ++ ] << 8 ) |
689
- ( buffer [ index ++ ] << 16 ) |
690
- ( buffer [ index ++ ] << 24 ) ;
599
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
600
+ index += 4 ;
691
601
// Check if we have a valid string
692
602
if (
693
603
stringSize <= 0 ||
0 commit comments