@@ -15,6 +15,7 @@ import { BSONRegExp } from '../regexp';
1515import { BSONSymbol } from '../symbol' ;
1616import { Timestamp } from '../timestamp' ;
1717import { ByteUtils } from '../utils/byte_utils' ;
18+ import { NumberUtils } from '../utils/number_utils' ;
1819import { validateUtf8 } from '../validate_utf8' ;
1920
2021/** @public */
@@ -91,11 +92,7 @@ export function internalDeserialize(
9192 options = options == null ? { } : options ;
9293 const index = options && options . index ? options . index : 0 ;
9394 // 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 ) ;
9996
10097 if ( size < 5 ) {
10198 throw new BSONError ( `bson size must be >= 5, is ${ size } ` ) ;
@@ -128,9 +125,6 @@ export function internalDeserialize(
128125
129126const allowedDBRefKeys = / ^ \$ r e f $ | ^ \$ i d $ | ^ \$ d b $ / ;
130127
131- const FLOAT_READ = new Float64Array ( 1 ) ;
132- const FLOAT_WRITE_BYTES = new Uint8Array ( FLOAT_READ . buffer , 0 , 8 ) ;
133-
134128function deserializeObject (
135129 buffer : Uint8Array ,
136130 index : number ,
@@ -207,8 +201,8 @@ function deserializeObject(
207201 if ( buffer . length < 5 ) throw new BSONError ( 'corrupt bson message < 5 bytes long' ) ;
208202
209203 // 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 ;
212206
213207 // Ensure buffer is valid size
214208 if ( size < 5 || size > buffer . length ) throw new BSONError ( 'corrupt bson message' ) ;
@@ -258,11 +252,8 @@ function deserializeObject(
258252 index = i + 1 ;
259253
260254 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 ;
266257 if (
267258 stringSize <= 0 ||
268259 stringSize > buffer . length - index ||
@@ -278,37 +269,19 @@ function deserializeObject(
278269 value = new ObjectId ( oid ) ;
279270 index = index + 12 ;
280271 } 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 ;
284274 } 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 ;
290277 } 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 ;
300280 if ( promoteValues === false ) value = new Double ( value ) ;
301281 } 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 ;
312285
313286 value = new Date ( new Long ( lowBits , highBits ) . toNumber ( ) ) ;
314287 } else if ( elementType === constants . BSON_DATA_BOOLEAN ) {
@@ -317,11 +290,8 @@ function deserializeObject(
317290 value = buffer [ index ++ ] === 1 ;
318291 } else if ( elementType === constants . BSON_DATA_OBJECT ) {
319292 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+
325295 if ( objectSize <= 0 || objectSize > buffer . length - index )
326296 throw new BSONError ( 'bad embedded document length in bson' ) ;
327297
@@ -339,11 +309,7 @@ function deserializeObject(
339309 index = index + objectSize ;
340310 } else if ( elementType === constants . BSON_DATA_ARRAY ) {
341311 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 ) ;
347313 let arrayOptions : DeserializeOptions = options ;
348314
349315 // Stop index
@@ -368,32 +334,14 @@ function deserializeObject(
368334 value = null ;
369335 } else if ( elementType === constants . BSON_DATA_LONG ) {
370336 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 ) ;
384338 index += 8 ;
385339 } else {
386340 // 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+
397345 const long = new Long ( lowBits , highBits ) ;
398346 // Promote the long if possible
399347 if ( promoteLongs && promoteValues === true ) {
@@ -415,11 +363,8 @@ function deserializeObject(
415363 // Assign the new Decimal128 value
416364 value = new Decimal128 ( bytes ) ;
417365 } 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 ;
423368 const totalBinarySize = binarySize ;
424369 const subType = buffer [ index ++ ] ;
425370
@@ -434,11 +379,8 @@ function deserializeObject(
434379 if ( buffer [ 'slice' ] != null ) {
435380 // If we have subtype 2 skip the 4 bytes for the size
436381 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 ;
442384 if ( binarySize < 0 )
443385 throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
444386 if ( binarySize > totalBinarySize - 4 )
@@ -459,11 +401,8 @@ function deserializeObject(
459401 const _buffer = ByteUtils . allocate ( binarySize ) ;
460402 // If we have subtype 2 skip the 4 bytes for the size
461403 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 ;
467406 if ( binarySize < 0 )
468407 throw new BSONError ( 'Negative binary type element size found for subtype 0x02' ) ;
469408 if ( binarySize > totalBinarySize - 4 )
@@ -562,11 +501,8 @@ function deserializeObject(
562501 // Set the object
563502 value = new BSONRegExp ( source , regExpOptions ) ;
564503 } 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 ;
570506 if (
571507 stringSize <= 0 ||
572508 stringSize > buffer . length - index ||
@@ -578,31 +514,18 @@ function deserializeObject(
578514 value = promoteValues ? symbol : new BSONSymbol ( symbol ) ;
579515 index = index + stringSize ;
580516 } 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 ;
596522 } else if ( elementType === constants . BSON_DATA_MIN_KEY ) {
597523 value = new MinKey ( ) ;
598524 } else if ( elementType === constants . BSON_DATA_MAX_KEY ) {
599525 value = new MaxKey ( ) ;
600526 } 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 ;
606529 if (
607530 stringSize <= 0 ||
608531 stringSize > buffer . length - index ||
@@ -622,23 +545,17 @@ function deserializeObject(
622545 // Update parse index position
623546 index = index + stringSize ;
624547 } 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 ;
630550
631551 // Element cannot be shorter than totalSize + stringSize + documentSize + terminator
632552 if ( totalSize < 4 + 4 + 4 + 1 ) {
633553 throw new BSONError ( 'code_w_scope total size shorter minimum expected length' ) ;
634554 }
635555
636556 // 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 ;
642559 // Check if we have a valid string
643560 if (
644561 stringSize <= 0 ||
@@ -660,11 +577,7 @@ function deserializeObject(
660577 // Parse the element
661578 const _index = index ;
662579 // 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 ) ;
668581 // Decode the scope object
669582 const scopeObject = deserializeObject ( buffer , _index , options , false ) ;
670583 // Adjust the index
@@ -683,11 +596,8 @@ function deserializeObject(
683596 value = new Code ( functionString , scopeObject ) ;
684597 } else if ( elementType === constants . BSON_DATA_DBPOINTER ) {
685598 // 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 ;
691601 // Check if we have a valid string
692602 if (
693603 stringSize <= 0 ||
0 commit comments