@@ -53,9 +53,6 @@ export interface OpQueryOptions extends CommandOptions {
53
53
exhaustAllowed ?: boolean ;
54
54
}
55
55
56
- /**************************************************************
57
- * QUERY
58
- **************************************************************/
59
56
/** @internal */
60
57
export class OpQueryRequest {
61
58
ns : string ;
@@ -289,7 +286,7 @@ export interface OpResponseOptions extends BSONSerializeOptions {
289
286
}
290
287
291
288
/** @internal */
292
- export class OpQueryResponse {
289
+ export class OpReply {
293
290
parsed : boolean ;
294
291
raw : Buffer ;
295
292
data : Buffer ;
@@ -303,7 +300,6 @@ export class OpQueryResponse {
303
300
cursorId ?: Long ;
304
301
startingFrom ?: number ;
305
302
numberReturned ?: number ;
306
- documents : ( Document | Buffer ) [ ] = new Array ( 0 ) ;
307
303
cursorNotFound ?: boolean ;
308
304
queryFailure ?: boolean ;
309
305
shardConfigStale ?: boolean ;
@@ -313,7 +309,8 @@ export class OpQueryResponse {
313
309
promoteValues : boolean ;
314
310
promoteBuffers : boolean ;
315
311
bsonRegExp ?: boolean ;
316
- index ?: number ;
312
+ index = 0 ;
313
+ sections : Uint8Array [ ] = [ ] ;
317
314
318
315
/** moreToCome is an OP_MSG only concept */
319
316
moreToCome = false ;
@@ -356,29 +353,9 @@ export class OpQueryResponse {
356
353
return this . parsed ;
357
354
}
358
355
359
- parse ( options : OpResponseOptions ) : void {
356
+ parse ( ) : Uint8Array {
360
357
// Don't parse again if not needed
361
- if ( this . parsed ) return ;
362
- options = options ?? { } ;
363
-
364
- // Allow the return of raw documents instead of parsing
365
- const raw = options . raw || false ;
366
- const documentsReturnedIn = options . documentsReturnedIn || null ;
367
- const useBigInt64 = options . useBigInt64 ?? this . opts . useBigInt64 ;
368
- const promoteLongs = options . promoteLongs ?? this . opts . promoteLongs ;
369
- const promoteValues = options . promoteValues ?? this . opts . promoteValues ;
370
- const promoteBuffers = options . promoteBuffers ?? this . opts . promoteBuffers ;
371
- const bsonRegExp = options . bsonRegExp ?? this . opts . bsonRegExp ;
372
- let bsonSize ;
373
-
374
- // Set up the options
375
- const _options : BSONSerializeOptions = {
376
- useBigInt64,
377
- promoteLongs,
378
- promoteValues,
379
- promoteBuffers,
380
- bsonRegExp
381
- } ;
358
+ if ( this . parsed ) return this . sections [ 0 ] ;
382
359
383
360
// Position within OP_REPLY at which documents start
384
361
// (See https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/#wire-op-reply)
@@ -390,8 +367,11 @@ export class OpQueryResponse {
390
367
this . startingFrom = this . data . readInt32LE ( 12 ) ;
391
368
this . numberReturned = this . data . readInt32LE ( 16 ) ;
392
369
393
- // Preallocate document array
394
- this . documents = new Array ( this . numberReturned ) ;
370
+ if ( this . numberReturned < 0 || this . numberReturned > 2 ** 32 - 1 ) {
371
+ throw new RangeError (
372
+ `OP_REPLY numberReturned is an invalid array length ${ this . numberReturned } `
373
+ ) ;
374
+ }
395
375
396
376
this . cursorNotFound = ( this . responseFlags & CURSOR_NOT_FOUND ) !== 0 ;
397
377
this . queryFailure = ( this . responseFlags & QUERY_FAILURE ) !== 0 ;
@@ -400,67 +380,26 @@ export class OpQueryResponse {
400
380
401
381
// Parse Body
402
382
for ( let i = 0 ; i < this . numberReturned ; i ++ ) {
403
- bsonSize =
383
+ const bsonSize =
404
384
this . data [ this . index ] |
405
385
( this . data [ this . index + 1 ] << 8 ) |
406
386
( this . data [ this . index + 2 ] << 16 ) |
407
387
( this . data [ this . index + 3 ] << 24 ) ;
408
388
409
- // If we have raw results specified slice the return document
410
- if ( raw ) {
411
- this . documents [ i ] = this . data . slice ( this . index , this . index + bsonSize ) ;
412
- } else {
413
- this . documents [ i ] = BSON . deserialize (
414
- this . data . slice ( this . index , this . index + bsonSize ) ,
415
- _options
416
- ) ;
417
- }
389
+ const section = this . data . subarray ( this . index , this . index + bsonSize ) ;
390
+ this . sections . push ( section ) ;
418
391
419
392
// Adjust the index
420
393
this . index = this . index + bsonSize ;
421
394
}
422
395
423
- if ( this . documents . length === 1 && documentsReturnedIn != null && raw ) {
424
- const fieldsAsRaw : Document = { } ;
425
- fieldsAsRaw [ documentsReturnedIn ] = true ;
426
- _options . fieldsAsRaw = fieldsAsRaw ;
427
-
428
- const doc = BSON . deserialize ( this . documents [ 0 ] as Buffer , _options ) ;
429
- this . documents = [ doc ] ;
430
- }
431
-
432
396
// Set parsed
433
397
this . parsed = true ;
398
+
399
+ return this . sections [ 0 ] ;
434
400
}
435
401
}
436
402
437
- // Implementation of OP_MSG spec:
438
- // https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst
439
- //
440
- // struct Section {
441
- // uint8 payloadType;
442
- // union payload {
443
- // document document; // payloadType == 0
444
- // struct sequence { // payloadType == 1
445
- // int32 size;
446
- // cstring identifier;
447
- // document* documents;
448
- // };
449
- // };
450
- // };
451
-
452
- // struct OP_MSG {
453
- // struct MsgHeader {
454
- // int32 messageLength;
455
- // int32 requestID;
456
- // int32 responseTo;
457
- // int32 opCode = 2013;
458
- // };
459
- // uint32 flagBits;
460
- // Section+ sections;
461
- // [uint32 checksum;]
462
- // };
463
-
464
403
// Msg Flags
465
404
const OPTS_CHECKSUM_PRESENT = 1 ;
466
405
const OPTS_MORE_TO_COME = 2 ;
@@ -603,8 +542,8 @@ export class OpMsgResponse {
603
542
promoteValues : boolean ;
604
543
promoteBuffers : boolean ;
605
544
bsonRegExp : boolean ;
606
- documents : ( Document | Buffer ) [ ] ;
607
- index ?: number ;
545
+ index = 0 ;
546
+ sections : Uint8Array [ ] = [ ] ;
608
547
609
548
constructor (
610
549
message : Buffer ,
@@ -642,47 +581,26 @@ export class OpMsgResponse {
642
581
this . promoteBuffers =
643
582
typeof this . opts . promoteBuffers === 'boolean' ? this . opts . promoteBuffers : false ;
644
583
this . bsonRegExp = typeof this . opts . bsonRegExp === 'boolean' ? this . opts . bsonRegExp : false ;
645
-
646
- this . documents = [ ] ;
647
584
}
648
585
649
586
isParsed ( ) : boolean {
650
587
return this . parsed ;
651
588
}
652
589
653
- parse ( options : OpResponseOptions ) : void {
590
+ parse ( ) : Uint8Array {
654
591
// Don't parse again if not needed
655
- if ( this . parsed ) return ;
656
- options = options ?? { } ;
592
+ if ( this . parsed ) return this . sections [ 0 ] ;
657
593
658
594
this . index = 4 ;
659
- // Allow the return of raw documents instead of parsing
660
- const raw = options . raw || false ;
661
- const documentsReturnedIn = options . documentsReturnedIn || null ;
662
- const useBigInt64 = options . useBigInt64 ?? this . opts . useBigInt64 ;
663
- const promoteLongs = options . promoteLongs ?? this . opts . promoteLongs ;
664
- const promoteValues = options . promoteValues ?? this . opts . promoteValues ;
665
- const promoteBuffers = options . promoteBuffers ?? this . opts . promoteBuffers ;
666
- const bsonRegExp = options . bsonRegExp ?? this . opts . bsonRegExp ;
667
- const validation = this . parseBsonSerializationOptions ( options ) ;
668
-
669
- // Set up the options
670
- const bsonOptions : BSONSerializeOptions = {
671
- useBigInt64,
672
- promoteLongs,
673
- promoteValues,
674
- promoteBuffers,
675
- bsonRegExp,
676
- validation
677
- // Due to the strictness of the BSON libraries validation option we need this cast
678
- } as BSONSerializeOptions & { validation : { utf8 : { writeErrors : boolean } } } ;
679
595
680
596
while ( this . index < this . data . length ) {
681
597
const payloadType = this . data . readUInt8 ( this . index ++ ) ;
682
598
if ( payloadType === 0 ) {
683
599
const bsonSize = this . data . readUInt32LE ( this . index ) ;
684
- const bin = this . data . slice ( this . index , this . index + bsonSize ) ;
685
- this . documents . push ( raw ? bin : BSON . deserialize ( bin , bsonOptions ) ) ;
600
+ const bin = this . data . subarray ( this . index , this . index + bsonSize ) ;
601
+
602
+ this . sections . push ( bin ) ;
603
+
686
604
this . index += bsonSize ;
687
605
} else if ( payloadType === 1 ) {
688
606
// It was decided that no driver makes use of payload type 1
@@ -692,25 +610,9 @@ export class OpMsgResponse {
692
610
}
693
611
}
694
612
695
- if ( this . documents . length === 1 && documentsReturnedIn != null && raw ) {
696
- const fieldsAsRaw : Document = { } ;
697
- fieldsAsRaw [ documentsReturnedIn ] = true ;
698
- bsonOptions . fieldsAsRaw = fieldsAsRaw ;
699
- const doc = BSON . deserialize ( this . documents [ 0 ] as Buffer , bsonOptions ) ;
700
- this . documents = [ doc ] ;
701
- }
702
-
703
613
this . parsed = true ;
704
- }
705
-
706
- parseBsonSerializationOptions ( { enableUtf8Validation } : BSONSerializeOptions ) : {
707
- utf8 : { writeErrors : false } | false ;
708
- } {
709
- if ( enableUtf8Validation === false ) {
710
- return { utf8 : false } ;
711
- }
712
614
713
- return { utf8 : { writeErrors : false } } ;
615
+ return this . sections [ 0 ] ;
714
616
}
715
617
}
716
618
0 commit comments