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.
386 lines
12 KiB
386 lines
12 KiB
'use strict';
|
|
|
|
var Map = require('./map'),
|
|
Long = require('./long'),
|
|
Double = require('./double'),
|
|
Timestamp = require('./timestamp'),
|
|
ObjectID = require('./objectid'),
|
|
BSONRegExp = require('./regexp'),
|
|
Symbol = require('./symbol'),
|
|
Int32 = require('./int_32'),
|
|
Code = require('./code'),
|
|
Decimal128 = require('./decimal128'),
|
|
MinKey = require('./min_key'),
|
|
MaxKey = require('./max_key'),
|
|
DBRef = require('./db_ref'),
|
|
Binary = require('./binary');
|
|
|
|
// Parts of the parser
|
|
var deserialize = require('./parser/deserializer'),
|
|
serializer = require('./parser/serializer'),
|
|
calculateObjectSize = require('./parser/calculate_size'),
|
|
utils = require('./parser/utils');
|
|
|
|
/**
|
|
* @ignore
|
|
* @api private
|
|
*/
|
|
// Default Max Size
|
|
var MAXSIZE = 1024 * 1024 * 17;
|
|
|
|
// Current Internal Temporary Serialization Buffer
|
|
var buffer = utils.allocBuffer(MAXSIZE);
|
|
|
|
var BSON = function() {};
|
|
|
|
/**
|
|
* 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)**.
|
|
* @param {Number} [options.minInternalBufferSize=1024*1024*17] minimum size of the internal temporary serialization buffer **(default:1024*1024*17)**.
|
|
* @return {Buffer} returns the Buffer object containing the serialized object.
|
|
* @api public
|
|
*/
|
|
BSON.prototype.serialize = function serialize(object, options) {
|
|
options = options || {};
|
|
// Unpack the options
|
|
var checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
|
|
var serializeFunctions =
|
|
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
|
|
var ignoreUndefined =
|
|
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
|
|
var minInternalBufferSize =
|
|
typeof options.minInternalBufferSize === 'number' ? options.minInternalBufferSize : MAXSIZE;
|
|
|
|
// Resize the internal serialization buffer if needed
|
|
if (buffer.length < minInternalBufferSize) {
|
|
buffer = utils.allocBuffer(minInternalBufferSize);
|
|
}
|
|
|
|
// Attempt to serialize
|
|
var serializationIndex = serializer(
|
|
buffer,
|
|
object,
|
|
checkKeys,
|
|
0,
|
|
0,
|
|
serializeFunctions,
|
|
ignoreUndefined,
|
|
[]
|
|
);
|
|
// Create the final buffer
|
|
var finishedBuffer = utils.allocBuffer(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.
|
|
* @api public
|
|
*/
|
|
BSON.prototype.serializeWithBufferAndIndex = function(object, finalBuffer, options) {
|
|
options = options || {};
|
|
// Unpack the options
|
|
var checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;
|
|
var serializeFunctions =
|
|
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
|
|
var ignoreUndefined =
|
|
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
|
|
var startIndex = typeof options.index === 'number' ? options.index : 0;
|
|
|
|
// Attempt to serialize
|
|
var serializationIndex = serializer(
|
|
finalBuffer,
|
|
object,
|
|
checkKeys,
|
|
startIndex || 0,
|
|
0,
|
|
serializeFunctions,
|
|
ignoreUndefined
|
|
);
|
|
|
|
// Return the index
|
|
return 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.
|
|
* @return {Object} returns the deserialized Javascript Object.
|
|
* @api public
|
|
*/
|
|
BSON.prototype.deserialize = function(buffer, options) {
|
|
return deserialize(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.
|
|
* @api public
|
|
*/
|
|
BSON.prototype.calculateObjectSize = function(object, options) {
|
|
options = options || {};
|
|
|
|
var serializeFunctions =
|
|
typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
|
|
var ignoreUndefined =
|
|
typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
|
|
|
|
return calculateObjectSize(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.
|
|
* @api public
|
|
*/
|
|
BSON.prototype.deserializeStream = function(
|
|
data,
|
|
startIndex,
|
|
numberOfDocuments,
|
|
documents,
|
|
docStartIndex,
|
|
options
|
|
) {
|
|
options = options != null ? options : {};
|
|
var index = startIndex;
|
|
// Loop over all documents
|
|
for (var i = 0; i < numberOfDocuments; i++) {
|
|
// Find size of the document
|
|
var 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] = this.deserialize(data, options);
|
|
// Adjust index by the document size
|
|
index = index + size;
|
|
}
|
|
|
|
// Return object containing end index of parsing and list of documents
|
|
return index;
|
|
};
|
|
|
|
/**
|
|
* @ignore
|
|
* @api private
|
|
*/
|
|
// BSON MAX VALUES
|
|
BSON.BSON_INT32_MAX = 0x7fffffff;
|
|
BSON.BSON_INT32_MIN = -0x80000000;
|
|
|
|
BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
|
|
BSON.BSON_INT64_MIN = -Math.pow(2, 63);
|
|
|
|
// JS MAX PRECISE VALUES
|
|
BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
|
|
BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
|
|
|
|
// Internal long versions
|
|
// var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
|
|
// var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
|
|
|
|
/**
|
|
* Number BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_NUMBER
|
|
**/
|
|
BSON.BSON_DATA_NUMBER = 1;
|
|
/**
|
|
* String BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_STRING
|
|
**/
|
|
BSON.BSON_DATA_STRING = 2;
|
|
/**
|
|
* Object BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_OBJECT
|
|
**/
|
|
BSON.BSON_DATA_OBJECT = 3;
|
|
/**
|
|
* Array BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_ARRAY
|
|
**/
|
|
BSON.BSON_DATA_ARRAY = 4;
|
|
/**
|
|
* Binary BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_BINARY
|
|
**/
|
|
BSON.BSON_DATA_BINARY = 5;
|
|
/**
|
|
* ObjectID BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_OID
|
|
**/
|
|
BSON.BSON_DATA_OID = 7;
|
|
/**
|
|
* Boolean BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_BOOLEAN
|
|
**/
|
|
BSON.BSON_DATA_BOOLEAN = 8;
|
|
/**
|
|
* Date BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_DATE
|
|
**/
|
|
BSON.BSON_DATA_DATE = 9;
|
|
/**
|
|
* null BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_NULL
|
|
**/
|
|
BSON.BSON_DATA_NULL = 10;
|
|
/**
|
|
* RegExp BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_REGEXP
|
|
**/
|
|
BSON.BSON_DATA_REGEXP = 11;
|
|
/**
|
|
* Code BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_CODE
|
|
**/
|
|
BSON.BSON_DATA_CODE = 13;
|
|
/**
|
|
* Symbol BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_SYMBOL
|
|
**/
|
|
BSON.BSON_DATA_SYMBOL = 14;
|
|
/**
|
|
* Code with Scope BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_CODE_W_SCOPE
|
|
**/
|
|
BSON.BSON_DATA_CODE_W_SCOPE = 15;
|
|
/**
|
|
* 32 bit Integer BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_INT
|
|
**/
|
|
BSON.BSON_DATA_INT = 16;
|
|
/**
|
|
* Timestamp BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_TIMESTAMP
|
|
**/
|
|
BSON.BSON_DATA_TIMESTAMP = 17;
|
|
/**
|
|
* Long BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_LONG
|
|
**/
|
|
BSON.BSON_DATA_LONG = 18;
|
|
/**
|
|
* MinKey BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_MIN_KEY
|
|
**/
|
|
BSON.BSON_DATA_MIN_KEY = 0xff;
|
|
/**
|
|
* MaxKey BSON Type
|
|
*
|
|
* @classconstant BSON_DATA_MAX_KEY
|
|
**/
|
|
BSON.BSON_DATA_MAX_KEY = 0x7f;
|
|
|
|
/**
|
|
* Binary Default Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_DEFAULT
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
|
|
/**
|
|
* Binary Function Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_FUNCTION
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
|
|
/**
|
|
* Binary Byte Array Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
|
|
/**
|
|
* Binary UUID Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_UUID
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_UUID = 3;
|
|
/**
|
|
* Binary MD5 Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_MD5
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
|
|
/**
|
|
* Binary User Defined Type
|
|
*
|
|
* @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
|
|
**/
|
|
BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
|
|
|
|
// Return BSON
|
|
module.exports = BSON;
|
|
module.exports.Code = Code;
|
|
module.exports.Map = Map;
|
|
module.exports.Symbol = Symbol;
|
|
module.exports.BSON = BSON;
|
|
module.exports.DBRef = DBRef;
|
|
module.exports.Binary = Binary;
|
|
module.exports.ObjectID = ObjectID;
|
|
module.exports.Long = Long;
|
|
module.exports.Timestamp = Timestamp;
|
|
module.exports.Double = Double;
|
|
module.exports.Int32 = Int32;
|
|
module.exports.MinKey = MinKey;
|
|
module.exports.MaxKey = MaxKey;
|
|
module.exports.BSONRegExp = BSONRegExp;
|
|
module.exports.Decimal128 = Decimal128;
|
|
|