123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /*!
- * Module dependencies.
- */
- 'use strict';
- const Binary = require('../driver').get().Binary;
- const utils = require('../utils');
- /**
- * Mongoose Buffer constructor.
- *
- * Values always have to be passed to the constructor to initialize.
- *
- * @param {Buffer} value
- * @param {String} encode
- * @param {Number} offset
- * @api private
- * @inherits Buffer
- * @see https://bit.ly/f6CnZU
- */
- function MongooseBuffer(value, encode, offset) {
- let val = value;
- if (value == null) {
- val = 0;
- }
- let encoding;
- let path;
- let doc;
- if (Array.isArray(encode)) {
- // internal casting
- path = encode[0];
- doc = encode[1];
- } else {
- encoding = encode;
- }
- let buf;
- if (typeof val === 'number' || val instanceof Number) {
- buf = Buffer.alloc(val);
- } else { // string, array or object { type: 'Buffer', data: [...] }
- buf = Buffer.from(val, encoding, offset);
- }
- utils.decorate(buf, MongooseBuffer.mixin);
- buf.isMongooseBuffer = true;
- // make sure these internal props don't show up in Object.keys()
- buf[MongooseBuffer.pathSymbol] = path;
- buf[parentSymbol] = doc;
- buf._subtype = 0;
- return buf;
- }
- const pathSymbol = Symbol.for('mongoose#Buffer#_path');
- const parentSymbol = Symbol.for('mongoose#Buffer#_parent');
- MongooseBuffer.pathSymbol = pathSymbol;
- /*!
- * Inherit from Buffer.
- */
- MongooseBuffer.mixin = {
- /**
- * Default subtype for the Binary representing this Buffer
- *
- * @api private
- * @property _subtype
- * @receiver MongooseBuffer
- */
- _subtype: undefined,
- /**
- * Marks this buffer as modified.
- *
- * @api private
- * @method _markModified
- * @receiver MongooseBuffer
- */
- _markModified: function() {
- const parent = this[parentSymbol];
- if (parent) {
- parent.markModified(this[MongooseBuffer.pathSymbol]);
- }
- return this;
- },
- /**
- * Writes the buffer.
- *
- * @api public
- * @method write
- * @receiver MongooseBuffer
- */
- write: function() {
- const written = Buffer.prototype.write.apply(this, arguments);
- if (written > 0) {
- this._markModified();
- }
- return written;
- },
- /**
- * Copies the buffer.
- *
- * #### Note:
- *
- * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this.
- *
- * @return {Number} The number of bytes copied.
- * @param {Buffer} target
- * @method copy
- * @receiver MongooseBuffer
- */
- copy: function(target) {
- const ret = Buffer.prototype.copy.apply(this, arguments);
- if (target && target.isMongooseBuffer) {
- target._markModified();
- }
- return ret;
- }
- };
- /*!
- * Compile other Buffer methods marking this buffer as modified.
- */
- (
- // node < 0.5
- ('writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
- 'writeFloat writeDouble fill ' +
- 'utf8Write binaryWrite asciiWrite set ' +
- // node >= 0.5
- 'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
- 'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' + 'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE')
- ).split(' ').forEach(function(method) {
- if (!Buffer.prototype[method]) {
- return;
- }
- MongooseBuffer.mixin[method] = function() {
- const ret = Buffer.prototype[method].apply(this, arguments);
- this._markModified();
- return ret;
- };
- });
- /**
- * Converts this buffer to its Binary type representation.
- *
- * ####SubTypes:
- *
- * const bson = require('bson')
- * bson.BSON_BINARY_SUBTYPE_DEFAULT
- * bson.BSON_BINARY_SUBTYPE_FUNCTION
- * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
- * bson.BSON_BINARY_SUBTYPE_UUID
- * bson.BSON_BINARY_SUBTYPE_MD5
- * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
- *
- * doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
- *
- * @see https://bsonspec.org/#/specification
- * @param {Hex} [subtype]
- * @return {Binary}
- * @api public
- * @method toObject
- * @receiver MongooseBuffer
- */
- MongooseBuffer.mixin.toObject = function(options) {
- const subtype = typeof options === 'number'
- ? options
- : (this._subtype || 0);
- return new Binary(Buffer.from(this), subtype);
- };
- MongooseBuffer.mixin.$toObject = MongooseBuffer.mixin.toObject;
- /**
- * Converts this buffer for storage in MongoDB, including subtype
- *
- * @return {Binary}
- * @api public
- * @method toBSON
- * @receiver MongooseBuffer
- */
- MongooseBuffer.mixin.toBSON = function() {
- return new Binary(this, this._subtype || 0);
- };
- /**
- * Determines if this buffer is equals to `other` buffer
- *
- * @param {Buffer} other
- * @return {Boolean}
- * @method equals
- * @receiver MongooseBuffer
- */
- MongooseBuffer.mixin.equals = function(other) {
- if (!Buffer.isBuffer(other)) {
- return false;
- }
- if (this.length !== other.length) {
- return false;
- }
- for (let i = 0; i < this.length; ++i) {
- if (this[i] !== other[i]) {
- return false;
- }
- }
- return true;
- };
- /**
- * Sets the subtype option and marks the buffer modified.
- *
- * ####SubTypes:
- *
- * const bson = require('bson')
- * bson.BSON_BINARY_SUBTYPE_DEFAULT
- * bson.BSON_BINARY_SUBTYPE_FUNCTION
- * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
- * bson.BSON_BINARY_SUBTYPE_UUID
- * bson.BSON_BINARY_SUBTYPE_MD5
- * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
- *
- * doc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);
- *
- * @see https://bsonspec.org/#/specification
- * @param {Hex} subtype
- * @api public
- * @method subtype
- * @receiver MongooseBuffer
- */
- MongooseBuffer.mixin.subtype = function(subtype) {
- if (typeof subtype !== 'number') {
- throw new TypeError('Invalid subtype. Expected a number');
- }
- if (this._subtype !== subtype) {
- this._markModified();
- }
- this._subtype = subtype;
- };
- /*!
- * Module exports.
- */
- MongooseBuffer.Binary = Binary;
- module.exports = MongooseBuffer;
|