You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					479 lines
				
				19 KiB
			
		
		
			
		
	
	
					479 lines
				
				19 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | Object.defineProperty(exports, "__esModule", { value: true }); | ||
|  | exports.BinMsg = exports.Msg = exports.Response = exports.Query = void 0; | ||
|  | const BSON = require("../bson"); | ||
|  | const error_1 = require("../error"); | ||
|  | const read_preference_1 = require("../read_preference"); | ||
|  | const utils_1 = require("../utils"); | ||
|  | const constants_1 = require("./wire_protocol/constants"); | ||
|  | // Incrementing request id
 | ||
|  | let _requestId = 0; | ||
|  | // Query flags
 | ||
|  | const OPTS_TAILABLE_CURSOR = 2; | ||
|  | const OPTS_SECONDARY = 4; | ||
|  | const OPTS_OPLOG_REPLAY = 8; | ||
|  | const OPTS_NO_CURSOR_TIMEOUT = 16; | ||
|  | const OPTS_AWAIT_DATA = 32; | ||
|  | const OPTS_EXHAUST = 64; | ||
|  | const OPTS_PARTIAL = 128; | ||
|  | // Response flags
 | ||
|  | const CURSOR_NOT_FOUND = 1; | ||
|  | const QUERY_FAILURE = 2; | ||
|  | const SHARD_CONFIG_STALE = 4; | ||
|  | const AWAIT_CAPABLE = 8; | ||
|  | /************************************************************** | ||
|  |  * QUERY | ||
|  |  **************************************************************/ | ||
|  | /** @internal */ | ||
|  | class Query { | ||
|  |     constructor(ns, query, options) { | ||
|  |         // Basic options needed to be passed in
 | ||
|  |         // TODO(NODE-3483): Replace with MongoCommandError
 | ||
|  |         if (ns == null) | ||
|  |             throw new error_1.MongoRuntimeError('Namespace must be specified for query'); | ||
|  |         // TODO(NODE-3483): Replace with MongoCommandError
 | ||
|  |         if (query == null) | ||
|  |             throw new error_1.MongoRuntimeError('A query document must be specified for query'); | ||
|  |         // Validate that we are not passing 0x00 in the collection name
 | ||
|  |         if (ns.indexOf('\x00') !== -1) { | ||
|  |             // TODO(NODE-3483): Use MongoNamespace static method
 | ||
|  |             throw new error_1.MongoRuntimeError('Namespace cannot contain a null character'); | ||
|  |         } | ||
|  |         // Basic options
 | ||
|  |         this.ns = ns; | ||
|  |         this.query = query; | ||
|  |         // Additional options
 | ||
|  |         this.numberToSkip = options.numberToSkip || 0; | ||
|  |         this.numberToReturn = options.numberToReturn || 0; | ||
|  |         this.returnFieldSelector = options.returnFieldSelector || undefined; | ||
|  |         this.requestId = Query.getRequestId(); | ||
|  |         // special case for pre-3.2 find commands, delete ASAP
 | ||
|  |         this.pre32Limit = options.pre32Limit; | ||
|  |         // Serialization option
 | ||
|  |         this.serializeFunctions = | ||
|  |             typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false; | ||
|  |         this.ignoreUndefined = | ||
|  |             typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : false; | ||
|  |         this.maxBsonSize = options.maxBsonSize || 1024 * 1024 * 16; | ||
|  |         this.checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false; | ||
|  |         this.batchSize = this.numberToReturn; | ||
|  |         // Flags
 | ||
|  |         this.tailable = false; | ||
|  |         this.secondaryOk = typeof options.secondaryOk === 'boolean' ? options.secondaryOk : false; | ||
|  |         this.oplogReplay = false; | ||
|  |         this.noCursorTimeout = false; | ||
|  |         this.awaitData = false; | ||
|  |         this.exhaust = false; | ||
|  |         this.partial = false; | ||
|  |     } | ||
|  |     /** Assign next request Id. */ | ||
|  |     incRequestId() { | ||
|  |         this.requestId = _requestId++; | ||
|  |     } | ||
|  |     /** Peek next request Id. */ | ||
|  |     nextRequestId() { | ||
|  |         return _requestId + 1; | ||
|  |     } | ||
|  |     /** Increment then return next request Id. */ | ||
|  |     static getRequestId() { | ||
|  |         return ++_requestId; | ||
|  |     } | ||
|  |     // Uses a single allocated buffer for the process, avoiding multiple memory allocations
 | ||
|  |     toBin() { | ||
|  |         const buffers = []; | ||
|  |         let projection = null; | ||
|  |         // Set up the flags
 | ||
|  |         let flags = 0; | ||
|  |         if (this.tailable) { | ||
|  |             flags |= OPTS_TAILABLE_CURSOR; | ||
|  |         } | ||
|  |         if (this.secondaryOk) { | ||
|  |             flags |= OPTS_SECONDARY; | ||
|  |         } | ||
|  |         if (this.oplogReplay) { | ||
|  |             flags |= OPTS_OPLOG_REPLAY; | ||
|  |         } | ||
|  |         if (this.noCursorTimeout) { | ||
|  |             flags |= OPTS_NO_CURSOR_TIMEOUT; | ||
|  |         } | ||
|  |         if (this.awaitData) { | ||
|  |             flags |= OPTS_AWAIT_DATA; | ||
|  |         } | ||
|  |         if (this.exhaust) { | ||
|  |             flags |= OPTS_EXHAUST; | ||
|  |         } | ||
|  |         if (this.partial) { | ||
|  |             flags |= OPTS_PARTIAL; | ||
|  |         } | ||
|  |         // If batchSize is different to this.numberToReturn
 | ||
|  |         if (this.batchSize !== this.numberToReturn) | ||
|  |             this.numberToReturn = this.batchSize; | ||
|  |         // Allocate write protocol header buffer
 | ||
|  |         const header = Buffer.alloc(4 * 4 + // Header
 | ||
|  |             4 + // Flags
 | ||
|  |             Buffer.byteLength(this.ns) + | ||
|  |             1 + // namespace
 | ||
|  |             4 + // numberToSkip
 | ||
|  |             4 // numberToReturn
 | ||
|  |         ); | ||
|  |         // Add header to buffers
 | ||
|  |         buffers.push(header); | ||
|  |         // Serialize the query
 | ||
|  |         const query = BSON.serialize(this.query, { | ||
|  |             checkKeys: this.checkKeys, | ||
|  |             serializeFunctions: this.serializeFunctions, | ||
|  |             ignoreUndefined: this.ignoreUndefined | ||
|  |         }); | ||
|  |         // Add query document
 | ||
|  |         buffers.push(query); | ||
|  |         if (this.returnFieldSelector && Object.keys(this.returnFieldSelector).length > 0) { | ||
|  |             // Serialize the projection document
 | ||
|  |             projection = BSON.serialize(this.returnFieldSelector, { | ||
|  |                 checkKeys: this.checkKeys, | ||
|  |                 serializeFunctions: this.serializeFunctions, | ||
|  |                 ignoreUndefined: this.ignoreUndefined | ||
|  |             }); | ||
|  |             // Add projection document
 | ||
|  |             buffers.push(projection); | ||
|  |         } | ||
|  |         // Total message size
 | ||
|  |         const totalLength = header.length + query.length + (projection ? projection.length : 0); | ||
|  |         // Set up the index
 | ||
|  |         let index = 4; | ||
|  |         // Write total document length
 | ||
|  |         header[3] = (totalLength >> 24) & 0xff; | ||
|  |         header[2] = (totalLength >> 16) & 0xff; | ||
|  |         header[1] = (totalLength >> 8) & 0xff; | ||
|  |         header[0] = totalLength & 0xff; | ||
|  |         // Write header information requestId
 | ||
|  |         header[index + 3] = (this.requestId >> 24) & 0xff; | ||
|  |         header[index + 2] = (this.requestId >> 16) & 0xff; | ||
|  |         header[index + 1] = (this.requestId >> 8) & 0xff; | ||
|  |         header[index] = this.requestId & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Write header information responseTo
 | ||
|  |         header[index + 3] = (0 >> 24) & 0xff; | ||
|  |         header[index + 2] = (0 >> 16) & 0xff; | ||
|  |         header[index + 1] = (0 >> 8) & 0xff; | ||
|  |         header[index] = 0 & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Write header information OP_QUERY
 | ||
|  |         header[index + 3] = (constants_1.OP_QUERY >> 24) & 0xff; | ||
|  |         header[index + 2] = (constants_1.OP_QUERY >> 16) & 0xff; | ||
|  |         header[index + 1] = (constants_1.OP_QUERY >> 8) & 0xff; | ||
|  |         header[index] = constants_1.OP_QUERY & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Write header information flags
 | ||
|  |         header[index + 3] = (flags >> 24) & 0xff; | ||
|  |         header[index + 2] = (flags >> 16) & 0xff; | ||
|  |         header[index + 1] = (flags >> 8) & 0xff; | ||
|  |         header[index] = flags & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Write collection name
 | ||
|  |         index = index + header.write(this.ns, index, 'utf8') + 1; | ||
|  |         header[index - 1] = 0; | ||
|  |         // Write header information flags numberToSkip
 | ||
|  |         header[index + 3] = (this.numberToSkip >> 24) & 0xff; | ||
|  |         header[index + 2] = (this.numberToSkip >> 16) & 0xff; | ||
|  |         header[index + 1] = (this.numberToSkip >> 8) & 0xff; | ||
|  |         header[index] = this.numberToSkip & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Write header information flags numberToReturn
 | ||
|  |         header[index + 3] = (this.numberToReturn >> 24) & 0xff; | ||
|  |         header[index + 2] = (this.numberToReturn >> 16) & 0xff; | ||
|  |         header[index + 1] = (this.numberToReturn >> 8) & 0xff; | ||
|  |         header[index] = this.numberToReturn & 0xff; | ||
|  |         index = index + 4; | ||
|  |         // Return the buffers
 | ||
|  |         return buffers; | ||
|  |     } | ||
|  | } | ||
|  | exports.Query = Query; | ||
|  | /** @internal */ | ||
|  | class Response { | ||
|  |     constructor(message, msgHeader, msgBody, opts) { | ||
|  |         this.documents = new Array(0); | ||
|  |         this.parsed = false; | ||
|  |         this.raw = message; | ||
|  |         this.data = msgBody; | ||
|  |         this.opts = opts ?? { | ||
|  |             promoteLongs: true, | ||
|  |             promoteValues: true, | ||
|  |             promoteBuffers: false, | ||
|  |             bsonRegExp: false | ||
|  |         }; | ||
|  |         // Read the message header
 | ||
|  |         this.length = msgHeader.length; | ||
|  |         this.requestId = msgHeader.requestId; | ||
|  |         this.responseTo = msgHeader.responseTo; | ||
|  |         this.opCode = msgHeader.opCode; | ||
|  |         this.fromCompressed = msgHeader.fromCompressed; | ||
|  |         // Flag values
 | ||
|  |         this.promoteLongs = typeof this.opts.promoteLongs === 'boolean' ? this.opts.promoteLongs : true; | ||
|  |         this.promoteValues = | ||
|  |             typeof this.opts.promoteValues === 'boolean' ? this.opts.promoteValues : true; | ||
|  |         this.promoteBuffers = | ||
|  |             typeof this.opts.promoteBuffers === 'boolean' ? this.opts.promoteBuffers : false; | ||
|  |         this.bsonRegExp = typeof this.opts.bsonRegExp === 'boolean' ? this.opts.bsonRegExp : false; | ||
|  |     } | ||
|  |     isParsed() { | ||
|  |         return this.parsed; | ||
|  |     } | ||
|  |     parse(options) { | ||
|  |         // Don't parse again if not needed
 | ||
|  |         if (this.parsed) | ||
|  |             return; | ||
|  |         options = options ?? {}; | ||
|  |         // Allow the return of raw documents instead of parsing
 | ||
|  |         const raw = options.raw || false; | ||
|  |         const documentsReturnedIn = options.documentsReturnedIn || null; | ||
|  |         const promoteLongs = options.promoteLongs ?? this.opts.promoteLongs; | ||
|  |         const promoteValues = options.promoteValues ?? this.opts.promoteValues; | ||
|  |         const promoteBuffers = options.promoteBuffers ?? this.opts.promoteBuffers; | ||
|  |         const bsonRegExp = options.bsonRegExp ?? this.opts.bsonRegExp; | ||
|  |         let bsonSize; | ||
|  |         // Set up the options
 | ||
|  |         const _options = { | ||
|  |             promoteLongs, | ||
|  |             promoteValues, | ||
|  |             promoteBuffers, | ||
|  |             bsonRegExp | ||
|  |         }; | ||
|  |         // Position within OP_REPLY at which documents start
 | ||
|  |         // (See https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/#wire-op-reply)
 | ||
|  |         this.index = 20; | ||
|  |         // Read the message body
 | ||
|  |         this.responseFlags = this.data.readInt32LE(0); | ||
|  |         this.cursorId = new BSON.Long(this.data.readInt32LE(4), this.data.readInt32LE(8)); | ||
|  |         this.startingFrom = this.data.readInt32LE(12); | ||
|  |         this.numberReturned = this.data.readInt32LE(16); | ||
|  |         // Preallocate document array
 | ||
|  |         this.documents = new Array(this.numberReturned); | ||
|  |         this.cursorNotFound = (this.responseFlags & CURSOR_NOT_FOUND) !== 0; | ||
|  |         this.queryFailure = (this.responseFlags & QUERY_FAILURE) !== 0; | ||
|  |         this.shardConfigStale = (this.responseFlags & SHARD_CONFIG_STALE) !== 0; | ||
|  |         this.awaitCapable = (this.responseFlags & AWAIT_CAPABLE) !== 0; | ||
|  |         // Parse Body
 | ||
|  |         for (let i = 0; i < this.numberReturned; i++) { | ||
|  |             bsonSize = | ||
|  |                 this.data[this.index] | | ||
|  |                     (this.data[this.index + 1] << 8) | | ||
|  |                     (this.data[this.index + 2] << 16) | | ||
|  |                     (this.data[this.index + 3] << 24); | ||
|  |             // If we have raw results specified slice the return document
 | ||
|  |             if (raw) { | ||
|  |                 this.documents[i] = this.data.slice(this.index, this.index + bsonSize); | ||
|  |             } | ||
|  |             else { | ||
|  |                 this.documents[i] = BSON.deserialize(this.data.slice(this.index, this.index + bsonSize), _options); | ||
|  |             } | ||
|  |             // Adjust the index
 | ||
|  |             this.index = this.index + bsonSize; | ||
|  |         } | ||
|  |         if (this.documents.length === 1 && documentsReturnedIn != null && raw) { | ||
|  |             const fieldsAsRaw = {}; | ||
|  |             fieldsAsRaw[documentsReturnedIn] = true; | ||
|  |             _options.fieldsAsRaw = fieldsAsRaw; | ||
|  |             const doc = BSON.deserialize(this.documents[0], _options); | ||
|  |             this.documents = [doc]; | ||
|  |         } | ||
|  |         // Set parsed
 | ||
|  |         this.parsed = true; | ||
|  |     } | ||
|  | } | ||
|  | exports.Response = Response; | ||
|  | // Implementation of OP_MSG spec:
 | ||
|  | // https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst
 | ||
|  | //
 | ||
|  | // struct Section {
 | ||
|  | //   uint8 payloadType;
 | ||
|  | //   union payload {
 | ||
|  | //       document  document; // payloadType == 0
 | ||
|  | //       struct sequence { // payloadType == 1
 | ||
|  | //           int32      size;
 | ||
|  | //           cstring    identifier;
 | ||
|  | //           document*  documents;
 | ||
|  | //       };
 | ||
|  | //   };
 | ||
|  | // };
 | ||
|  | // struct OP_MSG {
 | ||
|  | //   struct MsgHeader {
 | ||
|  | //       int32  messageLength;
 | ||
|  | //       int32  requestID;
 | ||
|  | //       int32  responseTo;
 | ||
|  | //       int32  opCode = 2013;
 | ||
|  | //   };
 | ||
|  | //   uint32      flagBits;
 | ||
|  | //   Section+    sections;
 | ||
|  | //   [uint32     checksum;]
 | ||
|  | // };
 | ||
|  | // Msg Flags
 | ||
|  | const OPTS_CHECKSUM_PRESENT = 1; | ||
|  | const OPTS_MORE_TO_COME = 2; | ||
|  | const OPTS_EXHAUST_ALLOWED = 1 << 16; | ||
|  | /** @internal */ | ||
|  | class Msg { | ||
|  |     constructor(ns, command, options) { | ||
|  |         // Basic options needed to be passed in
 | ||
|  |         if (command == null) | ||
|  |             throw new error_1.MongoInvalidArgumentError('Query document must be specified for query'); | ||
|  |         // Basic options
 | ||
|  |         this.ns = ns; | ||
|  |         this.command = command; | ||
|  |         this.command.$db = (0, utils_1.databaseNamespace)(ns); | ||
|  |         if (options.readPreference && options.readPreference.mode !== read_preference_1.ReadPreference.PRIMARY) { | ||
|  |             this.command.$readPreference = options.readPreference.toJSON(); | ||
|  |         } | ||
|  |         // Ensure empty options
 | ||
|  |         this.options = options ?? {}; | ||
|  |         // Additional options
 | ||
|  |         this.requestId = options.requestId ? options.requestId : Msg.getRequestId(); | ||
|  |         // Serialization option
 | ||
|  |         this.serializeFunctions = | ||
|  |             typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false; | ||
|  |         this.ignoreUndefined = | ||
|  |             typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : false; | ||
|  |         this.checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false; | ||
|  |         this.maxBsonSize = options.maxBsonSize || 1024 * 1024 * 16; | ||
|  |         // flags
 | ||
|  |         this.checksumPresent = false; | ||
|  |         this.moreToCome = options.moreToCome || false; | ||
|  |         this.exhaustAllowed = | ||
|  |             typeof options.exhaustAllowed === 'boolean' ? options.exhaustAllowed : false; | ||
|  |     } | ||
|  |     toBin() { | ||
|  |         const buffers = []; | ||
|  |         let flags = 0; | ||
|  |         if (this.checksumPresent) { | ||
|  |             flags |= OPTS_CHECKSUM_PRESENT; | ||
|  |         } | ||
|  |         if (this.moreToCome) { | ||
|  |             flags |= OPTS_MORE_TO_COME; | ||
|  |         } | ||
|  |         if (this.exhaustAllowed) { | ||
|  |             flags |= OPTS_EXHAUST_ALLOWED; | ||
|  |         } | ||
|  |         const header = Buffer.alloc(4 * 4 + // Header
 | ||
|  |             4 // Flags
 | ||
|  |         ); | ||
|  |         buffers.push(header); | ||
|  |         let totalLength = header.length; | ||
|  |         const command = this.command; | ||
|  |         totalLength += this.makeDocumentSegment(buffers, command); | ||
|  |         header.writeInt32LE(totalLength, 0); // messageLength
 | ||
|  |         header.writeInt32LE(this.requestId, 4); // requestID
 | ||
|  |         header.writeInt32LE(0, 8); // responseTo
 | ||
|  |         header.writeInt32LE(constants_1.OP_MSG, 12); // opCode
 | ||
|  |         header.writeUInt32LE(flags, 16); // flags
 | ||
|  |         return buffers; | ||
|  |     } | ||
|  |     makeDocumentSegment(buffers, document) { | ||
|  |         const payloadTypeBuffer = Buffer.alloc(1); | ||
|  |         payloadTypeBuffer[0] = 0; | ||
|  |         const documentBuffer = this.serializeBson(document); | ||
|  |         buffers.push(payloadTypeBuffer); | ||
|  |         buffers.push(documentBuffer); | ||
|  |         return payloadTypeBuffer.length + documentBuffer.length; | ||
|  |     } | ||
|  |     serializeBson(document) { | ||
|  |         return BSON.serialize(document, { | ||
|  |             checkKeys: this.checkKeys, | ||
|  |             serializeFunctions: this.serializeFunctions, | ||
|  |             ignoreUndefined: this.ignoreUndefined | ||
|  |         }); | ||
|  |     } | ||
|  |     static getRequestId() { | ||
|  |         _requestId = (_requestId + 1) & 0x7fffffff; | ||
|  |         return _requestId; | ||
|  |     } | ||
|  | } | ||
|  | exports.Msg = Msg; | ||
|  | /** @internal */ | ||
|  | class BinMsg { | ||
|  |     constructor(message, msgHeader, msgBody, opts) { | ||
|  |         this.parsed = false; | ||
|  |         this.raw = message; | ||
|  |         this.data = msgBody; | ||
|  |         this.opts = opts ?? { | ||
|  |             promoteLongs: true, | ||
|  |             promoteValues: true, | ||
|  |             promoteBuffers: false, | ||
|  |             bsonRegExp: false | ||
|  |         }; | ||
|  |         // Read the message header
 | ||
|  |         this.length = msgHeader.length; | ||
|  |         this.requestId = msgHeader.requestId; | ||
|  |         this.responseTo = msgHeader.responseTo; | ||
|  |         this.opCode = msgHeader.opCode; | ||
|  |         this.fromCompressed = msgHeader.fromCompressed; | ||
|  |         // Read response flags
 | ||
|  |         this.responseFlags = msgBody.readInt32LE(0); | ||
|  |         this.checksumPresent = (this.responseFlags & OPTS_CHECKSUM_PRESENT) !== 0; | ||
|  |         this.moreToCome = (this.responseFlags & OPTS_MORE_TO_COME) !== 0; | ||
|  |         this.exhaustAllowed = (this.responseFlags & OPTS_EXHAUST_ALLOWED) !== 0; | ||
|  |         this.promoteLongs = typeof this.opts.promoteLongs === 'boolean' ? this.opts.promoteLongs : true; | ||
|  |         this.promoteValues = | ||
|  |             typeof this.opts.promoteValues === 'boolean' ? this.opts.promoteValues : true; | ||
|  |         this.promoteBuffers = | ||
|  |             typeof this.opts.promoteBuffers === 'boolean' ? this.opts.promoteBuffers : false; | ||
|  |         this.bsonRegExp = typeof this.opts.bsonRegExp === 'boolean' ? this.opts.bsonRegExp : false; | ||
|  |         this.documents = []; | ||
|  |     } | ||
|  |     isParsed() { | ||
|  |         return this.parsed; | ||
|  |     } | ||
|  |     parse(options) { | ||
|  |         // Don't parse again if not needed
 | ||
|  |         if (this.parsed) | ||
|  |             return; | ||
|  |         options = options ?? {}; | ||
|  |         this.index = 4; | ||
|  |         // Allow the return of raw documents instead of parsing
 | ||
|  |         const raw = options.raw || false; | ||
|  |         const documentsReturnedIn = options.documentsReturnedIn || null; | ||
|  |         const promoteLongs = options.promoteLongs ?? this.opts.promoteLongs; | ||
|  |         const promoteValues = options.promoteValues ?? this.opts.promoteValues; | ||
|  |         const promoteBuffers = options.promoteBuffers ?? this.opts.promoteBuffers; | ||
|  |         const bsonRegExp = options.bsonRegExp ?? this.opts.bsonRegExp; | ||
|  |         const validation = this.parseBsonSerializationOptions(options); | ||
|  |         // Set up the options
 | ||
|  |         const bsonOptions = { | ||
|  |             promoteLongs, | ||
|  |             promoteValues, | ||
|  |             promoteBuffers, | ||
|  |             bsonRegExp, | ||
|  |             validation | ||
|  |             // Due to the strictness of the BSON libraries validation option we need this cast
 | ||
|  |         }; | ||
|  |         while (this.index < this.data.length) { | ||
|  |             const payloadType = this.data.readUInt8(this.index++); | ||
|  |             if (payloadType === 0) { | ||
|  |                 const bsonSize = this.data.readUInt32LE(this.index); | ||
|  |                 const bin = this.data.slice(this.index, this.index + bsonSize); | ||
|  |                 this.documents.push(raw ? bin : BSON.deserialize(bin, bsonOptions)); | ||
|  |                 this.index += bsonSize; | ||
|  |             } | ||
|  |             else if (payloadType === 1) { | ||
|  |                 // It was decided that no driver makes use of payload type 1
 | ||
|  |                 // TODO(NODE-3483): Replace with MongoDeprecationError
 | ||
|  |                 throw new error_1.MongoRuntimeError('OP_MSG Payload Type 1 detected unsupported protocol'); | ||
|  |             } | ||
|  |         } | ||
|  |         if (this.documents.length === 1 && documentsReturnedIn != null && raw) { | ||
|  |             const fieldsAsRaw = {}; | ||
|  |             fieldsAsRaw[documentsReturnedIn] = true; | ||
|  |             bsonOptions.fieldsAsRaw = fieldsAsRaw; | ||
|  |             const doc = BSON.deserialize(this.documents[0], bsonOptions); | ||
|  |             this.documents = [doc]; | ||
|  |         } | ||
|  |         this.parsed = true; | ||
|  |     } | ||
|  |     parseBsonSerializationOptions({ enableUtf8Validation }) { | ||
|  |         if (enableUtf8Validation === false) { | ||
|  |             return { utf8: false }; | ||
|  |         } | ||
|  |         return { utf8: { writeErrors: false } }; | ||
|  |     } | ||
|  | } | ||
|  | exports.BinMsg = BinMsg; | ||
|  | //# sourceMappingURL=commands.js.map
 |