@@ -14,7 +14,8 @@ import { ObjectId } from '../objectid';
14
14
import { BSONRegExp } from '../regexp' ;
15
15
import { BSONSymbol } from '../symbol' ;
16
16
import { Timestamp } from '../timestamp' ;
17
- import { BSONDataView , ByteUtils } from '../utils/byte_utils' ;
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 } ` ) ;
@@ -204,8 +201,8 @@ function deserializeObject(
204
201
if ( buffer . length < 5 ) throw new BSONError ( 'corrupt bson message < 5 bytes long' ) ;
205
202
206
203
// Read the document size
207
- const size =
208
- buffer [ index ++ ] | ( buffer [ index ++ ] << 8 ) | ( buffer [ index ++ ] << 16 ) | ( buffer [ index ++ ] << 24 ) ;
204
+ const size = NumberUtils . getInt32LE ( buffer , index ) ;
205
+ index += 4 ;
209
206
210
207
// Ensure buffer is valid size
211
208
if ( size < 5 || size > buffer . length ) throw new BSONError ( 'corrupt bson message' ) ;
@@ -218,8 +215,6 @@ function deserializeObject(
218
215
219
216
let isPossibleDBRef = isArray ? false : null ;
220
217
221
- let dataView ;
222
-
223
218
// While we have more left data left keep parsing
224
219
while ( ! done ) {
225
220
// Read the type
@@ -257,11 +252,8 @@ function deserializeObject(
257
252
index = i + 1 ;
258
253
259
254
if ( elementType === constants . BSON_DATA_STRING ) {
260
- const stringSize =
261
- buffer [ index ++ ] |
262
- ( buffer [ index ++ ] << 8 ) |
263
- ( buffer [ index ++ ] << 16 ) |
264
- ( buffer [ index ++ ] << 24 ) ;
255
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
256
+ index += 4 ;
265
257
if (
266
258
stringSize <= 0 ||
267
259
stringSize > buffer . length - index ||
@@ -277,34 +269,19 @@ function deserializeObject(
277
269
value = new ObjectId ( oid ) ;
278
270
index = index + 12 ;
279
271
} else if ( elementType === constants . BSON_DATA_INT && promoteValues === false ) {
280
- value = new Int32 (
281
- buffer [ index ++ ] | ( buffer [ index ++ ] << 8 ) | ( buffer [ index ++ ] << 16 ) | ( buffer [ index ++ ] << 24 )
282
- ) ;
272
+ value = new Int32 ( NumberUtils . getInt32LE ( buffer , index ) ) ;
273
+ index += 4 ;
283
274
} else if ( elementType === constants . BSON_DATA_INT ) {
284
- value =
285
- buffer [ index ++ ] |
286
- ( buffer [ index ++ ] << 8 ) |
287
- ( buffer [ index ++ ] << 16 ) |
288
- ( buffer [ index ++ ] << 24 ) ;
289
- } else if ( elementType === constants . BSON_DATA_NUMBER && promoteValues === false ) {
290
- dataView ??= new DataView ( buffer . buffer , buffer . byteOffset , buffer . byteLength ) ;
291
- value = new Double ( dataView . getFloat64 ( index , true ) ) ;
292
- index = index + 8 ;
275
+ value = NumberUtils . getInt32LE ( buffer , index ) ;
276
+ index += 4 ;
293
277
} else if ( elementType === constants . BSON_DATA_NUMBER ) {
294
- dataView ??= new DataView ( buffer . buffer , buffer . byteOffset , buffer . byteLength ) ;
295
- value = dataView . getFloat64 ( index , true ) ;
296
- index = index + 8 ;
278
+ value = NumberUtils . getFloat64LE ( buffer , index ) ;
279
+ index += 8 ;
280
+ if ( promoteValues === false ) value = new Double ( value ) ;
297
281
} else if ( elementType === constants . BSON_DATA_DATE ) {
298
- const lowBits =
299
- buffer [ index ++ ] |
300
- ( buffer [ index ++ ] << 8 ) |
301
- ( buffer [ index ++ ] << 16 ) |
302
- ( buffer [ index ++ ] << 24 ) ;
303
- const highBits =
304
- buffer [ index ++ ] |
305
- ( buffer [ index ++ ] << 8 ) |
306
- ( buffer [ index ++ ] << 16 ) |
307
- ( buffer [ index ++ ] << 24 ) ;
282
+ const lowBits = NumberUtils . getInt32LE ( buffer , index ) ;
283
+ const highBits = NumberUtils . getInt32LE ( buffer , index + 4 ) ;
284
+ index += 8 ;
308
285
309
286
value = new Date ( new Long ( lowBits , highBits ) . toNumber ( ) ) ;
310
287
} else if ( elementType === constants . BSON_DATA_BOOLEAN ) {
@@ -313,11 +290,8 @@ function deserializeObject(
313
290
value = buffer [ index ++ ] === 1 ;
314
291
} else if ( elementType === constants . BSON_DATA_OBJECT ) {
315
292
const _index = index ;
316
- const objectSize =
317
- buffer [ index ] |
318
- ( buffer [ index + 1 ] << 8 ) |
319
- ( buffer [ index + 2 ] << 16 ) |
320
- ( buffer [ index + 3 ] << 24 ) ;
293
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
294
+
321
295
if ( objectSize <= 0 || objectSize > buffer . length - index )
322
296
throw new BSONError ( 'bad embedded document length in bson' ) ;
323
297
@@ -335,11 +309,7 @@ function deserializeObject(
335
309
index = index + objectSize ;
336
310
} else if ( elementType === constants . BSON_DATA_ARRAY ) {
337
311
const _index = index ;
338
- const objectSize =
339
- buffer [ index ] |
340
- ( buffer [ index + 1 ] << 8 ) |
341
- ( buffer [ index + 2 ] << 16 ) |
342
- ( buffer [ index + 3 ] << 24 ) ;
312
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
343
313
let arrayOptions : DeserializeOptions = options ;
344
314
345
315
// Stop index
@@ -363,30 +333,25 @@ function deserializeObject(
363
333
} else if ( elementType === constants . BSON_DATA_NULL ) {
364
334
value = null ;
365
335
} else if ( elementType === constants . BSON_DATA_LONG ) {
366
- // Unpack the low and high bits
367
- const dataview = BSONDataView . fromUint8Array ( buffer . subarray ( index , index + 8 ) ) ;
368
-
369
- const lowBits =
370
- buffer [ index ++ ] |
371
- ( buffer [ index ++ ] << 8 ) |
372
- ( buffer [ index ++ ] << 16 ) |
373
- ( buffer [ index ++ ] << 24 ) ;
374
- const highBits =
375
- buffer [ index ++ ] |
376
- ( buffer [ index ++ ] << 8 ) |
377
- ( buffer [ index ++ ] << 16 ) |
378
- ( buffer [ index ++ ] << 24 ) ;
379
- const long = new Long ( lowBits , highBits ) ;
380
336
if ( useBigInt64 ) {
381
- value = dataview . getBigInt64 ( 0 , true ) ;
382
- } else if ( promoteLongs && promoteValues === true ) {
383
- // Promote the long if possible
384
- value =
385
- long . lessThanOrEqual ( JS_INT_MAX_LONG ) && long . greaterThanOrEqual ( JS_INT_MIN_LONG )
386
- ? long . toNumber ( )
387
- : long ;
337
+ value = NumberUtils . getBigInt64LE ( buffer , index ) ;
338
+ index += 8 ;
388
339
} else {
389
- value = long ;
340
+ // Unpack the low and high bits
341
+ const lowBits = NumberUtils . getInt32LE ( buffer , index ) ;
342
+ const highBits = NumberUtils . getInt32LE ( buffer , index + 4 ) ;
343
+ index += 8 ;
344
+
345
+ const long = new Long ( lowBits , highBits ) ;
346
+ // Promote the long if possible
347
+ if ( promoteLongs && promoteValues === true ) {
348
+ value =
349
+ long . lessThanOrEqual ( JS_INT_MAX_LONG ) && long . greaterThanOrEqual ( JS_INT_MIN_LONG )
350
+ ? long . toNumber ( )
351
+ : long ;
352
+ } else {
353
+ value = long ;
354
+ }
390
355
}
391
356
} else if ( elementType === constants . BSON_DATA_DECIMAL128 ) {
392
357
// Buffer to contain the decimal bytes
@@ -398,11 +363,8 @@ function deserializeObject(
398
363
// Assign the new Decimal128 value
399
364
value = new Decimal128 ( bytes ) ;
400
365
} else if ( elementType === constants . BSON_DATA_BINARY ) {
401
- let binarySize =
402
- buffer [ index ++ ] |
403
- ( buffer [ index ++ ] << 8 ) |
404
- ( buffer [ index ++ ] << 16 ) |
405
- ( buffer [ index ++ ] << 24 ) ;
366
+ let binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
367
+ index += 4 ;
406
368
const totalBinarySize = binarySize ;
407
369
const subType = buffer [ index ++ ] ;
408
370
@@ -417,11 +379,8 @@ function deserializeObject(
417
379
if ( buffer [ 'slice' ] != null ) {
418
380
// If we have subtype 2 skip the 4 bytes for the size
419
381
if ( subType === Binary . SUBTYPE_BYTE_ARRAY ) {
420
- binarySize =
421
- buffer [ index ++ ] |
422
- ( buffer [ index ++ ] << 8 ) |
423
- ( buffer [ index ++ ] << 16 ) |
424
- ( buffer [ index ++ ] << 24 ) ;
382
+ binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
383
+ index += 4 ;
425
384
if ( binarySize < 0 )
426
385
throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
427
386
if ( binarySize > totalBinarySize - 4 )
@@ -442,11 +401,8 @@ function deserializeObject(
442
401
const _buffer = ByteUtils . allocate ( binarySize ) ;
443
402
// If we have subtype 2 skip the 4 bytes for the size
444
403
if ( subType === Binary . SUBTYPE_BYTE_ARRAY ) {
445
- binarySize =
446
- buffer [ index ++ ] |
447
- ( buffer [ index ++ ] << 8 ) |
448
- ( buffer [ index ++ ] << 16 ) |
449
- ( buffer [ index ++ ] << 24 ) ;
404
+ binarySize = NumberUtils . getInt32LE ( buffer , index ) ;
405
+ index += 4 ;
450
406
if ( binarySize < 0 )
451
407
throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
452
408
if ( binarySize > totalBinarySize - 4 )
@@ -545,11 +501,8 @@ function deserializeObject(
545
501
// Set the object
546
502
value = new BSONRegExp ( source , regExpOptions ) ;
547
503
} else if ( elementType === constants . BSON_DATA_SYMBOL ) {
548
- const stringSize =
549
- buffer [ index ++ ] |
550
- ( buffer [ index ++ ] << 8 ) |
551
- ( buffer [ index ++ ] << 16 ) |
552
- ( buffer [ index ++ ] << 24 ) ;
504
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
505
+ index += 4 ;
553
506
if (
554
507
stringSize <= 0 ||
555
508
stringSize > buffer . length - index ||
@@ -561,31 +514,18 @@ function deserializeObject(
561
514
value = promoteValues ? symbol : new BSONSymbol ( symbol ) ;
562
515
index = index + stringSize ;
563
516
} else if ( elementType === constants . BSON_DATA_TIMESTAMP ) {
564
- // We intentionally **do not** use bit shifting here
565
- // Bit shifting in javascript coerces numbers to **signed** int32s
566
- // We need to keep i, and t unsigned
567
- const i =
568
- buffer [ index ++ ] +
569
- buffer [ index ++ ] * ( 1 << 8 ) +
570
- buffer [ index ++ ] * ( 1 << 16 ) +
571
- buffer [ index ++ ] * ( 1 << 24 ) ;
572
- const t =
573
- buffer [ index ++ ] +
574
- buffer [ index ++ ] * ( 1 << 8 ) +
575
- buffer [ index ++ ] * ( 1 << 16 ) +
576
- buffer [ index ++ ] * ( 1 << 24 ) ;
577
-
578
- 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 ;
579
522
} else if ( elementType === constants . BSON_DATA_MIN_KEY ) {
580
523
value = new MinKey ( ) ;
581
524
} else if ( elementType === constants . BSON_DATA_MAX_KEY ) {
582
525
value = new MaxKey ( ) ;
583
526
} else if ( elementType === constants . BSON_DATA_CODE ) {
584
- const stringSize =
585
- buffer [ index ++ ] |
586
- ( buffer [ index ++ ] << 8 ) |
587
- ( buffer [ index ++ ] << 16 ) |
588
- ( buffer [ index ++ ] << 24 ) ;
527
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
528
+ index += 4 ;
589
529
if (
590
530
stringSize <= 0 ||
591
531
stringSize > buffer . length - index ||
@@ -605,23 +545,17 @@ function deserializeObject(
605
545
// Update parse index position
606
546
index = index + stringSize ;
607
547
} else if ( elementType === constants . BSON_DATA_CODE_W_SCOPE ) {
608
- const totalSize =
609
- buffer [ index ++ ] |
610
- ( buffer [ index ++ ] << 8 ) |
611
- ( buffer [ index ++ ] << 16 ) |
612
- ( buffer [ index ++ ] << 24 ) ;
548
+ const totalSize = NumberUtils . getInt32LE ( buffer , index ) ;
549
+ index += 4 ;
613
550
614
551
// Element cannot be shorter than totalSize + stringSize + documentSize + terminator
615
552
if ( totalSize < 4 + 4 + 4 + 1 ) {
616
553
throw new BSONError ( 'code_w_scope total size shorter minimum expected length' ) ;
617
554
}
618
555
619
556
// Get the code string size
620
- const stringSize =
621
- buffer [ index ++ ] |
622
- ( buffer [ index ++ ] << 8 ) |
623
- ( buffer [ index ++ ] << 16 ) |
624
- ( buffer [ index ++ ] << 24 ) ;
557
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
558
+ index += 4 ;
625
559
// Check if we have a valid string
626
560
if (
627
561
stringSize <= 0 ||
@@ -643,11 +577,7 @@ function deserializeObject(
643
577
// Parse the element
644
578
const _index = index ;
645
579
// Decode the size of the object document
646
- const objectSize =
647
- buffer [ index ] |
648
- ( buffer [ index + 1 ] << 8 ) |
649
- ( buffer [ index + 2 ] << 16 ) |
650
- ( buffer [ index + 3 ] << 24 ) ;
580
+ const objectSize = NumberUtils . getInt32LE ( buffer , index ) ;
651
581
// Decode the scope object
652
582
const scopeObject = deserializeObject ( buffer , _index , options , false ) ;
653
583
// Adjust the index
@@ -666,11 +596,8 @@ function deserializeObject(
666
596
value = new Code ( functionString , scopeObject ) ;
667
597
} else if ( elementType === constants . BSON_DATA_DBPOINTER ) {
668
598
// Get the code string size
669
- const stringSize =
670
- buffer [ index ++ ] |
671
- ( buffer [ index ++ ] << 8 ) |
672
- ( buffer [ index ++ ] << 16 ) |
673
- ( buffer [ index ++ ] << 24 ) ;
599
+ const stringSize = NumberUtils . getInt32LE ( buffer , index ) ;
600
+ index += 4 ;
674
601
// Check if we have a valid string
675
602
if (
676
603
stringSize <= 0 ||
0 commit comments