@vuept/loopback-connector-mssql
Version:
Microsoft SQL Server connector for LoopBack
315 lines (292 loc) • 9.18 kB
JavaScript
'use strict';
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var bigint = require('./bigint');
var SHIFT_LEFT_32 = (1 << 16) * (1 << 16);
var SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
var UNKNOWN_PLP_LEN = new Buffer([0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
var ZERO_LENGTH_BUFFER = new Buffer(0);
/*
A Buffer-like class that tracks position.
As values are written, the position advances by the size of the written data.
When writing, automatically allocates new buffers if there's not enough space.
*/
module.exports = function () {
function WritableTrackingBuffer(initialSize, encoding, doubleSizeGrowth) {
(0, _classCallCheck3.default)(this, WritableTrackingBuffer);
this.initialSize = initialSize;
this.encoding = encoding || 'ucs2';
this.doubleSizeGrowth = doubleSizeGrowth || false;
this.buffer = new Buffer(this.initialSize).fill(0);
this.compositeBuffer = new Buffer(0);
this.position = 0;
}
// $FlowFixMe: Flow does not like getter/setters that have side-effects.
(0, _createClass3.default)(WritableTrackingBuffer, [{
key: 'copyFrom',
value: function copyFrom(buffer) {
var length = buffer.length;
this.makeRoomFor(length);
buffer.copy(this.buffer, this.position);
this.position += length;
}
}, {
key: 'makeRoomFor',
value: function makeRoomFor(requiredLength) {
if (this.buffer.length - this.position < requiredLength) {
if (this.doubleSizeGrowth) {
var size = Math.max(128, this.buffer.length * 2);
while (size < requiredLength) {
size *= 2;
}
this.newBuffer(size);
} else {
this.newBuffer(requiredLength);
}
}
}
}, {
key: 'newBuffer',
value: function newBuffer(size) {
var buffer = this.buffer.slice(0, this.position);
this.compositeBuffer = Buffer.concat([this.compositeBuffer, buffer]);
this.buffer = size === 0 ? ZERO_LENGTH_BUFFER : new Buffer(size).fill(0);
this.position = 0;
}
}, {
key: 'writeUInt8',
value: function writeUInt8(value) {
var length = 1;
this.makeRoomFor(length);
this.buffer.writeUInt8(value, this.position);
this.position += length;
}
}, {
key: 'writeUInt16LE',
value: function writeUInt16LE(value) {
var length = 2;
this.makeRoomFor(length);
this.buffer.writeUInt16LE(value, this.position);
this.position += length;
}
}, {
key: 'writeUShort',
value: function writeUShort(value) {
this.writeUInt16LE(value);
}
}, {
key: 'writeUInt16BE',
value: function writeUInt16BE(value) {
var length = 2;
this.makeRoomFor(length);
this.buffer.writeUInt16BE(value, this.position);
this.position += length;
}
}, {
key: 'writeUInt24LE',
value: function writeUInt24LE(value) {
var length = 3;
this.makeRoomFor(length);
this.buffer[this.position + 2] = value >>> 16 & 0xff;
this.buffer[this.position + 1] = value >>> 8 & 0xff;
this.buffer[this.position] = value & 0xff;
this.position += length;
}
}, {
key: 'writeUInt32LE',
value: function writeUInt32LE(value) {
var length = 4;
this.makeRoomFor(length);
this.buffer.writeUInt32LE(value, this.position);
this.position += length;
}
}, {
key: 'writeInt64LE',
value: function writeInt64LE(value) {
var buf = bigint.numberToInt64LE(value);
this.copyFrom(buf);
}
}, {
key: 'writeUInt32BE',
value: function writeUInt32BE(value) {
var length = 4;
this.makeRoomFor(length);
this.buffer.writeUInt32BE(value, this.position);
this.position += length;
}
}, {
key: 'writeUInt40LE',
value: function writeUInt40LE(value) {
// inspired by https://github.com/dpw/node-buffer-more-ints
this.writeInt32LE(value & -1);
this.writeUInt8(Math.floor(value * SHIFT_RIGHT_32));
}
}, {
key: 'writeUInt64LE',
value: function writeUInt64LE(value) {
this.writeInt32LE(value & -1);
this.writeUInt32LE(Math.floor(value * SHIFT_RIGHT_32));
}
}, {
key: 'writeInt8',
value: function writeInt8(value) {
var length = 1;
this.makeRoomFor(length);
this.buffer.writeInt8(value, this.position);
this.position += length;
}
}, {
key: 'writeInt16LE',
value: function writeInt16LE(value) {
var length = 2;
this.makeRoomFor(length);
this.buffer.writeInt16LE(value, this.position);
this.position += length;
}
}, {
key: 'writeInt16BE',
value: function writeInt16BE(value) {
var length = 2;
this.makeRoomFor(length);
this.buffer.writeInt16BE(value, this.position);
this.position += length;
}
}, {
key: 'writeInt32LE',
value: function writeInt32LE(value) {
var length = 4;
this.makeRoomFor(length);
this.buffer.writeInt32LE(value, this.position);
this.position += length;
}
}, {
key: 'writeInt32BE',
value: function writeInt32BE(value) {
var length = 4;
this.makeRoomFor(length);
this.buffer.writeInt32BE(value, this.position);
this.position += length;
}
}, {
key: 'writeFloatLE',
value: function writeFloatLE(value) {
var length = 4;
this.makeRoomFor(length);
this.buffer.writeFloatLE(value, this.position);
this.position += length;
}
}, {
key: 'writeDoubleLE',
value: function writeDoubleLE(value) {
var length = 8;
this.makeRoomFor(length);
this.buffer.writeDoubleLE(value, this.position);
this.position += length;
}
}, {
key: 'writeString',
value: function writeString(value, encoding) {
if (encoding == undefined) {
encoding = this.encoding;
}
var length = Buffer.byteLength(value, encoding);
this.makeRoomFor(length);
// $FlowFixMe https://github.com/facebook/flow/pull/5398
this.buffer.write(value, this.position, encoding);
this.position += length;
}
}, {
key: 'writeBVarchar',
value: function writeBVarchar(value, encoding) {
this.writeUInt8(value.length);
this.writeString(value, encoding);
}
}, {
key: 'writeUsVarchar',
value: function writeUsVarchar(value, encoding) {
this.writeUInt16LE(value.length);
this.writeString(value, encoding);
}
// TODO: Figure out what types are passed in other than `Buffer`
}, {
key: 'writeUsVarbyte',
value: function writeUsVarbyte(value, encoding) {
if (encoding == undefined) {
encoding = this.encoding;
}
var length = void 0;
if (value instanceof Buffer) {
length = value.length;
} else {
value = value.toString();
length = Buffer.byteLength(value, encoding);
}
this.writeUInt16LE(length);
if (value instanceof Buffer) {
this.writeBuffer(value);
} else {
this.makeRoomFor(length);
// $FlowFixMe https://github.com/facebook/flow/pull/5398
this.buffer.write(value, this.position, encoding);
this.position += length;
}
}
}, {
key: 'writePLPBody',
value: function writePLPBody(value, encoding) {
if (encoding == null) {
encoding = this.encoding;
}
var length = void 0;
if (value instanceof Buffer) {
length = value.length;
} else {
value = value.toString();
length = Buffer.byteLength(value, encoding);
}
// Length of all chunks.
// this.writeUInt64LE(length);
// unknown seems to work better here - might revisit later.
this.writeBuffer(UNKNOWN_PLP_LEN);
// In the UNKNOWN_PLP_LEN case, the data is represented as a series of zero or more chunks.
if (length > 0) {
// One chunk.
this.writeUInt32LE(length);
if (value instanceof Buffer) {
this.writeBuffer(value);
} else {
this.makeRoomFor(length);
// $FlowFixMe https://github.com/facebook/flow/pull/5398
this.buffer.write(value, this.position, encoding);
this.position += length;
}
}
// PLP_TERMINATOR (no more chunks).
this.writeUInt32LE(0);
}
}, {
key: 'writeBuffer',
value: function writeBuffer(value) {
var length = value.length;
this.makeRoomFor(length);
value.copy(this.buffer, this.position);
this.position += length;
}
}, {
key: 'writeMoney',
value: function writeMoney(value) {
this.writeInt32LE(Math.floor(value * SHIFT_RIGHT_32));
this.writeInt32LE(value & -1);
}
}, {
key: 'data',
get: function get() {
this.newBuffer(0);
return this.compositeBuffer;
}
}]);
return WritableTrackingBuffer;
}();