@@ -37,7 +37,6 @@ export type WriteProtocolMessageType = OpQueryRequest | OpMsgRequest;
37
37
export interface OpQueryOptions extends CommandOptions {
38
38
socketTimeoutMS ?: number ;
39
39
session ?: ClientSession ;
40
- documentsReturnedIn ?: string ;
41
40
numberToSkip ?: number ;
42
41
numberToReturn ?: number ;
43
42
returnFieldSelector ?: Document ;
@@ -53,9 +52,6 @@ export interface OpQueryOptions extends CommandOptions {
53
52
exhaustAllowed ?: boolean ;
54
53
}
55
54
56
- /**************************************************************
57
- * QUERY
58
- **************************************************************/
59
55
/** @internal */
60
56
export class OpQueryRequest {
61
57
ns : string ;
@@ -284,16 +280,11 @@ export interface MessageHeader {
284
280
}
285
281
286
282
/** @internal */
287
- export interface OpResponseOptions extends BSONSerializeOptions {
288
- documentsReturnedIn ?: string | null ;
289
- }
290
-
291
- /** @internal */
292
- export class OpQueryResponse {
283
+ export class OpReply {
293
284
parsed : boolean ;
294
285
raw : Buffer ;
295
286
data : Buffer ;
296
- opts : OpResponseOptions ;
287
+ opts : BSONSerializeOptions ;
297
288
length : number ;
298
289
requestId : number ;
299
290
responseTo : number ;
@@ -303,7 +294,6 @@ export class OpQueryResponse {
303
294
cursorId ?: Long ;
304
295
startingFrom ?: number ;
305
296
numberReturned ?: number ;
306
- documents : ( Document | Buffer ) [ ] = new Array ( 0 ) ;
307
297
cursorNotFound ?: boolean ;
308
298
queryFailure ?: boolean ;
309
299
shardConfigStale ?: boolean ;
@@ -313,7 +303,8 @@ export class OpQueryResponse {
313
303
promoteValues : boolean ;
314
304
promoteBuffers : boolean ;
315
305
bsonRegExp ?: boolean ;
316
- index ?: number ;
306
+ index = 0 ;
307
+ sections : Uint8Array [ ] = [ ] ;
317
308
318
309
/** moreToCome is an OP_MSG only concept */
319
310
moreToCome = false ;
@@ -322,7 +313,7 @@ export class OpQueryResponse {
322
313
message : Buffer ,
323
314
msgHeader : MessageHeader ,
324
315
msgBody : Buffer ,
325
- opts ?: OpResponseOptions
316
+ opts ?: BSONSerializeOptions
326
317
) {
327
318
this . parsed = false ;
328
319
this . raw = message ;
@@ -356,29 +347,9 @@ export class OpQueryResponse {
356
347
return this . parsed ;
357
348
}
358
349
359
- parse ( options : OpResponseOptions ) : void {
350
+ parse ( ) : Uint8Array {
360
351
// 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
- } ;
352
+ if ( this . parsed ) return this . sections [ 0 ] ;
382
353
383
354
// Position within OP_REPLY at which documents start
384
355
// (See https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/#wire-op-reply)
@@ -390,8 +361,11 @@ export class OpQueryResponse {
390
361
this . startingFrom = this . data . readInt32LE ( 12 ) ;
391
362
this . numberReturned = this . data . readInt32LE ( 16 ) ;
392
363
393
- // Preallocate document array
394
- this . documents = new Array ( this . numberReturned ) ;
364
+ if ( this . numberReturned < 0 || this . numberReturned > 2 ** 32 - 1 ) {
365
+ throw new RangeError (
366
+ `OP_REPLY numberReturned is an invalid array length ${ this . numberReturned } `
367
+ ) ;
368
+ }
395
369
396
370
this . cursorNotFound = ( this . responseFlags & CURSOR_NOT_FOUND ) !== 0 ;
397
371
this . queryFailure = ( this . responseFlags & QUERY_FAILURE ) !== 0 ;
@@ -400,67 +374,26 @@ export class OpQueryResponse {
400
374
401
375
// Parse Body
402
376
for ( let i = 0 ; i < this . numberReturned ; i ++ ) {
403
- bsonSize =
377
+ const bsonSize =
404
378
this . data [ this . index ] |
405
379
( this . data [ this . index + 1 ] << 8 ) |
406
380
( this . data [ this . index + 2 ] << 16 ) |
407
381
( this . data [ this . index + 3 ] << 24 ) ;
408
382
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
- }
383
+ const section = this . data . subarray ( this . index , this . index + bsonSize ) ;
384
+ this . sections . push ( section ) ;
418
385
419
386
// Adjust the index
420
387
this . index = this . index + bsonSize ;
421
388
}
422
389
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
390
// Set parsed
433
391
this . parsed = true ;
392
+
393
+ return this . sections [ 0 ] ;
434
394
}
435
395
}
436
396
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
397
// Msg Flags
465
398
const OPTS_CHECKSUM_PRESENT = 1 ;
466
399
const OPTS_MORE_TO_COME = 2 ;
@@ -587,7 +520,7 @@ export class OpMsgResponse {
587
520
parsed : boolean ;
588
521
raw : Buffer ;
589
522
data : Buffer ;
590
- opts : OpResponseOptions ;
523
+ opts : BSONSerializeOptions ;
591
524
length : number ;
592
525
requestId : number ;
593
526
responseTo : number ;
@@ -603,14 +536,14 @@ export class OpMsgResponse {
603
536
promoteValues : boolean ;
604
537
promoteBuffers : boolean ;
605
538
bsonRegExp : boolean ;
606
- documents : ( Document | Buffer ) [ ] ;
607
- index ?: number ;
539
+ index = 0 ;
540
+ sections : Uint8Array [ ] = [ ] ;
608
541
609
542
constructor (
610
543
message : Buffer ,
611
544
msgHeader : MessageHeader ,
612
545
msgBody : Buffer ,
613
- opts ?: OpResponseOptions
546
+ opts ?: BSONSerializeOptions
614
547
) {
615
548
this . parsed = false ;
616
549
this . raw = message ;
@@ -642,47 +575,26 @@ export class OpMsgResponse {
642
575
this . promoteBuffers =
643
576
typeof this . opts . promoteBuffers === 'boolean' ? this . opts . promoteBuffers : false ;
644
577
this . bsonRegExp = typeof this . opts . bsonRegExp === 'boolean' ? this . opts . bsonRegExp : false ;
645
-
646
- this . documents = [ ] ;
647
578
}
648
579
649
580
isParsed ( ) : boolean {
650
581
return this . parsed ;
651
582
}
652
583
653
- parse ( options : OpResponseOptions ) : void {
584
+ parse ( ) : Uint8Array {
654
585
// Don't parse again if not needed
655
- if ( this . parsed ) return ;
656
- options = options ?? { } ;
586
+ if ( this . parsed ) return this . sections [ 0 ] ;
657
587
658
588
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
589
680
590
while ( this . index < this . data . length ) {
681
591
const payloadType = this . data . readUInt8 ( this . index ++ ) ;
682
592
if ( payloadType === 0 ) {
683
593
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 ) ) ;
594
+ const bin = this . data . subarray ( this . index , this . index + bsonSize ) ;
595
+
596
+ this . sections . push ( bin ) ;
597
+
686
598
this . index += bsonSize ;
687
599
} else if ( payloadType === 1 ) {
688
600
// It was decided that no driver makes use of payload type 1
@@ -692,25 +604,9 @@ export class OpMsgResponse {
692
604
}
693
605
}
694
606
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
607
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
608
713
- return { utf8 : { writeErrors : false } } ;
609
+ return this . sections [ 0 ] ;
714
610
}
715
611
}
716
612
0 commit comments