@@ -37,7 +37,6 @@ export type WriteProtocolMessageType = OpQueryRequest | OpMsgRequest;
3737export interface OpQueryOptions extends CommandOptions {
3838 socketTimeoutMS ?: number ;
3939 session ?: ClientSession ;
40- documentsReturnedIn ?: string ;
4140 numberToSkip ?: number ;
4241 numberToReturn ?: number ;
4342 returnFieldSelector ?: Document ;
@@ -53,9 +52,6 @@ export interface OpQueryOptions extends CommandOptions {
5352 exhaustAllowed ?: boolean ;
5453}
5554
56- /**************************************************************
57- * QUERY
58- **************************************************************/
5955/** @internal */
6056export class OpQueryRequest {
6157 ns : string ;
@@ -284,16 +280,11 @@ export interface MessageHeader {
284280}
285281
286282/** @internal */
287- export interface OpResponseOptions extends BSONSerializeOptions {
288- documentsReturnedIn ?: string | null ;
289- }
290-
291- /** @internal */
292- export class OpQueryResponse {
283+ export class OpReply {
293284 parsed : boolean ;
294285 raw : Buffer ;
295286 data : Buffer ;
296- opts : OpResponseOptions ;
287+ opts : BSONSerializeOptions ;
297288 length : number ;
298289 requestId : number ;
299290 responseTo : number ;
@@ -303,7 +294,6 @@ export class OpQueryResponse {
303294 cursorId ?: Long ;
304295 startingFrom ?: number ;
305296 numberReturned ?: number ;
306- documents : ( Document | Buffer ) [ ] = new Array ( 0 ) ;
307297 cursorNotFound ?: boolean ;
308298 queryFailure ?: boolean ;
309299 shardConfigStale ?: boolean ;
@@ -313,7 +303,8 @@ export class OpQueryResponse {
313303 promoteValues : boolean ;
314304 promoteBuffers : boolean ;
315305 bsonRegExp ?: boolean ;
316- index ?: number ;
306+ index = 0 ;
307+ sections : Uint8Array [ ] = [ ] ;
317308
318309 /** moreToCome is an OP_MSG only concept */
319310 moreToCome = false ;
@@ -322,7 +313,7 @@ export class OpQueryResponse {
322313 message : Buffer ,
323314 msgHeader : MessageHeader ,
324315 msgBody : Buffer ,
325- opts ?: OpResponseOptions
316+ opts ?: BSONSerializeOptions
326317 ) {
327318 this . parsed = false ;
328319 this . raw = message ;
@@ -356,29 +347,9 @@ export class OpQueryResponse {
356347 return this . parsed ;
357348 }
358349
359- parse ( options : OpResponseOptions ) : void {
350+ parse ( ) : Uint8Array {
360351 // 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 ] ;
382353
383354 // Position within OP_REPLY at which documents start
384355 // (See https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/#wire-op-reply)
@@ -390,8 +361,11 @@ export class OpQueryResponse {
390361 this . startingFrom = this . data . readInt32LE ( 12 ) ;
391362 this . numberReturned = this . data . readInt32LE ( 16 ) ;
392363
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+ }
395369
396370 this . cursorNotFound = ( this . responseFlags & CURSOR_NOT_FOUND ) !== 0 ;
397371 this . queryFailure = ( this . responseFlags & QUERY_FAILURE ) !== 0 ;
@@ -400,67 +374,26 @@ export class OpQueryResponse {
400374
401375 // Parse Body
402376 for ( let i = 0 ; i < this . numberReturned ; i ++ ) {
403- bsonSize =
377+ const bsonSize =
404378 this . data [ this . index ] |
405379 ( this . data [ this . index + 1 ] << 8 ) |
406380 ( this . data [ this . index + 2 ] << 16 ) |
407381 ( this . data [ this . index + 3 ] << 24 ) ;
408382
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 ) ;
418385
419386 // Adjust the index
420387 this . index = this . index + bsonSize ;
421388 }
422389
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-
432390 // Set parsed
433391 this . parsed = true ;
392+
393+ return this . sections [ 0 ] ;
434394 }
435395}
436396
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-
464397// Msg Flags
465398const OPTS_CHECKSUM_PRESENT = 1 ;
466399const OPTS_MORE_TO_COME = 2 ;
@@ -587,7 +520,7 @@ export class OpMsgResponse {
587520 parsed : boolean ;
588521 raw : Buffer ;
589522 data : Buffer ;
590- opts : OpResponseOptions ;
523+ opts : BSONSerializeOptions ;
591524 length : number ;
592525 requestId : number ;
593526 responseTo : number ;
@@ -603,14 +536,14 @@ export class OpMsgResponse {
603536 promoteValues : boolean ;
604537 promoteBuffers : boolean ;
605538 bsonRegExp : boolean ;
606- documents : ( Document | Buffer ) [ ] ;
607- index ?: number ;
539+ index = 0 ;
540+ sections : Uint8Array [ ] = [ ] ;
608541
609542 constructor (
610543 message : Buffer ,
611544 msgHeader : MessageHeader ,
612545 msgBody : Buffer ,
613- opts ?: OpResponseOptions
546+ opts ?: BSONSerializeOptions
614547 ) {
615548 this . parsed = false ;
616549 this . raw = message ;
@@ -642,47 +575,26 @@ export class OpMsgResponse {
642575 this . promoteBuffers =
643576 typeof this . opts . promoteBuffers === 'boolean' ? this . opts . promoteBuffers : false ;
644577 this . bsonRegExp = typeof this . opts . bsonRegExp === 'boolean' ? this . opts . bsonRegExp : false ;
645-
646- this . documents = [ ] ;
647578 }
648579
649580 isParsed ( ) : boolean {
650581 return this . parsed ;
651582 }
652583
653- parse ( options : OpResponseOptions ) : void {
584+ parse ( ) : Uint8Array {
654585 // Don't parse again if not needed
655- if ( this . parsed ) return ;
656- options = options ?? { } ;
586+ if ( this . parsed ) return this . sections [ 0 ] ;
657587
658588 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 } } } ;
679589
680590 while ( this . index < this . data . length ) {
681591 const payloadType = this . data . readUInt8 ( this . index ++ ) ;
682592 if ( payloadType === 0 ) {
683593 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+
686598 this . index += bsonSize ;
687599 } else if ( payloadType === 1 ) {
688600 // It was decided that no driver makes use of payload type 1
@@ -692,25 +604,9 @@ export class OpMsgResponse {
692604 }
693605 }
694606
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-
703607 this . parsed = true ;
704- }
705-
706- parseBsonSerializationOptions ( { enableUtf8Validation } : BSONSerializeOptions ) : {
707- utf8 : { writeErrors : false } | false ;
708- } {
709- if ( enableUtf8Validation === false ) {
710- return { utf8 : false } ;
711- }
712608
713- return { utf8 : { writeErrors : false } } ;
609+ return this . sections [ 0 ] ;
714610 }
715611}
716612
0 commit comments