123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- 'use strict';
- const Buffer = require('buffer').Buffer;
- const Map = require('./map');
- const Long = require('./long');
- const Double = require('./double');
- const Timestamp = require('./timestamp');
- const ObjectId = require('./objectid');
- const BSONRegExp = require('./regexp');
- const BSONSymbol = require('./symbol');
- const Int32 = require('./int_32');
- const Code = require('./code');
- const Decimal128 = require('./decimal128');
- const MinKey = require('./min_key');
- const MaxKey = require('./max_key');
- const DBRef = require('./db_ref');
- const Binary = require('./binary');
- const constants = require('./constants');
- const EJSON = require('./extended_json');
- // Parts of the parser
- const internalDeserialize = require('./parser/deserializer');
- const internalSerialize = require('./parser/serializer');
- const internalCalculateObjectSize = require('./parser/calculate_size');
- const ensureBuffer = require('./ensure_buffer');
- /**
- * @ignore
- */
- // Default Max Size
- const MAXSIZE = 1024 * 1024 * 17;
- // Current Internal Temporary Serialization Buffer
- let buffer = Buffer.alloc(MAXSIZE);
- /**
- * Sets the size of the internal serialization buffer.
- *
- * @method
- * @param {number} size The desired size for the internal serialization buffer
- */
- function setInternalBufferSize(size) {
- // Resize the internal serialization buffer if needed
- if (buffer.length < size) {
- buffer = Buffer.alloc(size);
- }
- }
- /**
- * Serialize a Javascript object.
- *
- * @param {Object} object the Javascript object to serialize.
- * @param {Boolean} [options.checkKeys] the serializer will check if keys are valid.
- * @param {Boolean} [options.serializeFunctions=false] serialize the javascript functions **(default:false)**.
- * @param {Boolean} [options.ignoreUndefined=true] ignore undefined fields **(default:true)**.
- * @return {Buffer} returns the Buffer object containing the serialized object.
- */
- function serialize(object, options) {
- options = options || {};
- // Unpack the options
- const checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
- const serializeFunctions =
- typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
- const ignoreUndefined =
- typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
- const minInternalBufferSize =
- typeof options.minInternalBufferSize === 'number' ? options.minInternalBufferSize : MAXSIZE;
- // Resize the internal serialization buffer if needed
- if (buffer.length < minInternalBufferSize) {
- buffer = Buffer.alloc(minInternalBufferSize);
- }
- // Attempt to serialize
- const serializationIndex = internalSerialize(
- buffer,
- object,
- checkKeys,
- 0,
- 0,
- serializeFunctions,
- ignoreUndefined,
- []
- );
- // Create the final buffer
- const finishedBuffer = Buffer.alloc(serializationIndex);
- // Copy into the finished buffer
- buffer.copy(finishedBuffer, 0, 0, finishedBuffer.length);
- // Return the buffer
- return finishedBuffer;
- }
- /**
- * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization.
- *
- * @param {Object} object the Javascript object to serialize.
- * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object.
- * @param {Boolean} [options.checkKeys] the serializer will check if keys are valid.
- * @param {Boolean} [options.serializeFunctions=false] serialize the javascript functions **(default:false)**.
- * @param {Boolean} [options.ignoreUndefined=true] ignore undefined fields **(default:true)**.
- * @param {Number} [options.index] the index in the buffer where we wish to start serializing into.
- * @return {Number} returns the index pointing to the last written byte in the buffer.
- */
- function serializeWithBufferAndIndex(object, finalBuffer, options) {
- options = options || {};
- // Unpack the options
- const checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
- const serializeFunctions =
- typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
- const ignoreUndefined =
- typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
- const startIndex = typeof options.index === 'number' ? options.index : 0;
- // Attempt to serialize
- const serializationIndex = internalSerialize(
- buffer,
- object,
- checkKeys,
- 0,
- 0,
- serializeFunctions,
- ignoreUndefined
- );
- buffer.copy(finalBuffer, startIndex, 0, serializationIndex);
- // Return the index
- return startIndex + serializationIndex - 1;
- }
- /**
- * Deserialize data as BSON.
- *
- * @param {Buffer} buffer the buffer containing the serialized set of BSON documents.
- * @param {Object} [options.evalFunctions=false] evaluate functions in the BSON document scoped to the object deserialized.
- * @param {Object} [options.cacheFunctions=false] cache evaluated functions for reuse.
- * @param {Object} [options.cacheFunctionsCrc32=false] use a crc32 code for caching, otherwise use the string of the function.
- * @param {Object} [options.promoteLongs=true] when deserializing a Long will fit it into a Number if it's smaller than 53 bits
- * @param {Object} [options.promoteBuffers=false] when deserializing a Binary will return it as a node.js Buffer instance.
- * @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
- * @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
- * @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
- * @param {boolean} [options.allowObjectSmallerThanBufferSize=false] allows the buffer to be larger than the parsed BSON object
- * @return {Object} returns the deserialized Javascript Object.
- */
- function deserialize(buffer, options) {
- buffer = ensureBuffer(buffer);
- return internalDeserialize(buffer, options);
- }
- /**
- * Calculate the bson size for a passed in Javascript object.
- *
- * @param {Object} object the Javascript object to calculate the BSON byte size for.
- * @param {Boolean} [options.serializeFunctions=false] serialize the javascript functions **(default:false)**.
- * @param {Boolean} [options.ignoreUndefined=true] ignore undefined fields **(default:true)**.
- * @return {Number} returns the number of bytes the BSON object will take up.
- */
- function calculateObjectSize(object, options) {
- options = options || {};
- const serializeFunctions =
- typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
- const ignoreUndefined =
- typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
- return internalCalculateObjectSize(object, serializeFunctions, ignoreUndefined);
- }
- /**
- * Deserialize stream data as BSON documents.
- *
- * @param {Buffer} data the buffer containing the serialized set of BSON documents.
- * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start.
- * @param {Number} numberOfDocuments number of documents to deserialize.
- * @param {Array} documents an array where to store the deserialized documents.
- * @param {Number} docStartIndex the index in the documents array from where to start inserting documents.
- * @param {Object} [options] additional options used for the deserialization.
- * @param {Object} [options.evalFunctions=false] evaluate functions in the BSON document scoped to the object deserialized.
- * @param {Object} [options.cacheFunctions=false] cache evaluated functions for reuse.
- * @param {Object} [options.cacheFunctionsCrc32=false] use a crc32 code for caching, otherwise use the string of the function.
- * @param {Object} [options.promoteLongs=true] when deserializing a Long will fit it into a Number if it's smaller than 53 bits
- * @param {Object} [options.promoteBuffers=false] when deserializing a Binary will return it as a node.js Buffer instance.
- * @param {Object} [options.promoteValues=false] when deserializing will promote BSON values to their Node.js closest equivalent types.
- * @param {Object} [options.fieldsAsRaw=null] allow to specify if there what fields we wish to return as unserialized raw buffer.
- * @param {Object} [options.bsonRegExp=false] return BSON regular expressions as BSONRegExp instances.
- * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents.
- */
- function deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options) {
- options = Object.assign({ allowObjectSmallerThanBufferSize: true }, options);
- data = ensureBuffer(data);
- let index = startIndex;
- // Loop over all documents
- for (let i = 0; i < numberOfDocuments; i++) {
- // Find size of the document
- const size =
- data[index] | (data[index + 1] << 8) | (data[index + 2] << 16) | (data[index + 3] << 24);
- // Update options with index
- options.index = index;
- // Parse the document at this point
- documents[docStartIndex + i] = internalDeserialize(data, options);
- // Adjust index by the document size
- index = index + size;
- }
- // Return object containing end index of parsing and list of documents
- return index;
- }
- module.exports = {
- // constants
- // NOTE: this is done this way because rollup can't resolve an `Object.assign`ed export
- BSON_INT32_MAX: constants.BSON_INT32_MAX,
- BSON_INT32_MIN: constants.BSON_INT32_MIN,
- BSON_INT64_MAX: constants.BSON_INT64_MAX,
- BSON_INT64_MIN: constants.BSON_INT64_MIN,
- JS_INT_MAX: constants.JS_INT_MAX,
- JS_INT_MIN: constants.JS_INT_MIN,
- BSON_DATA_NUMBER: constants.BSON_DATA_NUMBER,
- BSON_DATA_STRING: constants.BSON_DATA_STRING,
- BSON_DATA_OBJECT: constants.BSON_DATA_OBJECT,
- BSON_DATA_ARRAY: constants.BSON_DATA_ARRAY,
- BSON_DATA_BINARY: constants.BSON_DATA_BINARY,
- BSON_DATA_UNDEFINED: constants.BSON_DATA_UNDEFINED,
- BSON_DATA_OID: constants.BSON_DATA_OID,
- BSON_DATA_BOOLEAN: constants.BSON_DATA_BOOLEAN,
- BSON_DATA_DATE: constants.BSON_DATA_DATE,
- BSON_DATA_NULL: constants.BSON_DATA_NULL,
- BSON_DATA_REGEXP: constants.BSON_DATA_REGEXP,
- BSON_DATA_DBPOINTER: constants.BSON_DATA_DBPOINTER,
- BSON_DATA_CODE: constants.BSON_DATA_CODE,
- BSON_DATA_SYMBOL: constants.BSON_DATA_SYMBOL,
- BSON_DATA_CODE_W_SCOPE: constants.BSON_DATA_CODE_W_SCOPE,
- BSON_DATA_INT: constants.BSON_DATA_INT,
- BSON_DATA_TIMESTAMP: constants.BSON_DATA_TIMESTAMP,
- BSON_DATA_LONG: constants.BSON_DATA_LONG,
- BSON_DATA_DECIMAL128: constants.BSON_DATA_DECIMAL128,
- BSON_DATA_MIN_KEY: constants.BSON_DATA_MIN_KEY,
- BSON_DATA_MAX_KEY: constants.BSON_DATA_MAX_KEY,
- BSON_BINARY_SUBTYPE_DEFAULT: constants.BSON_BINARY_SUBTYPE_DEFAULT,
- BSON_BINARY_SUBTYPE_FUNCTION: constants.BSON_BINARY_SUBTYPE_FUNCTION,
- BSON_BINARY_SUBTYPE_BYTE_ARRAY: constants.BSON_BINARY_SUBTYPE_BYTE_ARRAY,
- BSON_BINARY_SUBTYPE_UUID: constants.BSON_BINARY_SUBTYPE_UUID,
- BSON_BINARY_SUBTYPE_MD5: constants.BSON_BINARY_SUBTYPE_MD5,
- BSON_BINARY_SUBTYPE_USER_DEFINED: constants.BSON_BINARY_SUBTYPE_USER_DEFINED,
- // wrapped types
- Code,
- Map,
- BSONSymbol,
- DBRef,
- Binary,
- ObjectId,
- Long,
- Timestamp,
- Double,
- Int32,
- MinKey,
- MaxKey,
- BSONRegExp,
- Decimal128,
- // methods
- serialize,
- serializeWithBufferAndIndex,
- deserialize,
- calculateObjectSize,
- deserializeStream,
- setInternalBufferSize,
- // legacy support
- ObjectID: ObjectId,
- // Extended JSON
- EJSON
- };
|