813 lines
79 KiB
JavaScript
813 lines
79 KiB
JavaScript
|
|
"use strict";
|
||
|
|
|
||
|
|
Object.defineProperty(exports, "__esModule", {
|
||
|
|
value: true
|
||
|
|
});
|
||
|
|
exports.isPLPStream = isPLPStream;
|
||
|
|
exports.readPLPStream = readPLPStream;
|
||
|
|
exports.readValue = readValue;
|
||
|
|
var _metadataParser = require("./metadata-parser");
|
||
|
|
var _dataType = require("./data-type");
|
||
|
|
var _iconvLite = _interopRequireDefault(require("iconv-lite"));
|
||
|
|
var _sprintfJs = require("sprintf-js");
|
||
|
|
var _guidParser = require("./guid-parser");
|
||
|
|
var _helpers = require("./token/helpers");
|
||
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
const NULL = (1 << 16) - 1;
|
||
|
|
const MAX = (1 << 16) - 1;
|
||
|
|
const THREE_AND_A_THIRD = 3 + 1 / 3;
|
||
|
|
const MONEY_DIVISOR = 10000;
|
||
|
|
const PLP_NULL = 0xFFFFFFFFFFFFFFFFn;
|
||
|
|
const UNKNOWN_PLP_LEN = 0xFFFFFFFFFFFFFFFEn;
|
||
|
|
const DEFAULT_ENCODING = 'utf8';
|
||
|
|
function readTinyInt(buf, offset) {
|
||
|
|
return (0, _helpers.readUInt8)(buf, offset);
|
||
|
|
}
|
||
|
|
function readSmallInt(buf, offset) {
|
||
|
|
return (0, _helpers.readInt16LE)(buf, offset);
|
||
|
|
}
|
||
|
|
function readInt(buf, offset) {
|
||
|
|
return (0, _helpers.readInt32LE)(buf, offset);
|
||
|
|
}
|
||
|
|
function readBigInt(buf, offset) {
|
||
|
|
let value;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readBigInt64LE)(buf, offset));
|
||
|
|
return new _helpers.Result(value.toString(), offset);
|
||
|
|
}
|
||
|
|
function readReal(buf, offset) {
|
||
|
|
return (0, _helpers.readFloatLE)(buf, offset);
|
||
|
|
}
|
||
|
|
function readFloat(buf, offset) {
|
||
|
|
return (0, _helpers.readDoubleLE)(buf, offset);
|
||
|
|
}
|
||
|
|
function readSmallMoney(buf, offset) {
|
||
|
|
let value;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readInt32LE)(buf, offset));
|
||
|
|
return new _helpers.Result(value / MONEY_DIVISOR, offset);
|
||
|
|
}
|
||
|
|
function readMoney(buf, offset) {
|
||
|
|
let high;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: high
|
||
|
|
} = (0, _helpers.readInt32LE)(buf, offset));
|
||
|
|
let low;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: low
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
return new _helpers.Result((low + 0x100000000 * high) / MONEY_DIVISOR, offset);
|
||
|
|
}
|
||
|
|
function readBit(buf, offset) {
|
||
|
|
let value;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
return new _helpers.Result(!!value, offset);
|
||
|
|
}
|
||
|
|
function readValue(buf, offset, metadata, options) {
|
||
|
|
const type = metadata.type;
|
||
|
|
switch (type.name) {
|
||
|
|
case 'Null':
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 'TinyInt':
|
||
|
|
{
|
||
|
|
return readTinyInt(buf, offset);
|
||
|
|
}
|
||
|
|
case 'SmallInt':
|
||
|
|
{
|
||
|
|
return readSmallInt(buf, offset);
|
||
|
|
}
|
||
|
|
case 'Int':
|
||
|
|
{
|
||
|
|
return readInt(buf, offset);
|
||
|
|
}
|
||
|
|
case 'BigInt':
|
||
|
|
{
|
||
|
|
return readBigInt(buf, offset);
|
||
|
|
}
|
||
|
|
case 'IntN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 1:
|
||
|
|
return readTinyInt(buf, offset);
|
||
|
|
case 2:
|
||
|
|
return readSmallInt(buf, offset);
|
||
|
|
case 4:
|
||
|
|
return readInt(buf, offset);
|
||
|
|
case 8:
|
||
|
|
return readBigInt(buf, offset);
|
||
|
|
default:
|
||
|
|
throw new Error('Unsupported dataLength ' + dataLength + ' for IntN');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'Real':
|
||
|
|
{
|
||
|
|
return readReal(buf, offset);
|
||
|
|
}
|
||
|
|
case 'Float':
|
||
|
|
{
|
||
|
|
return readFloat(buf, offset);
|
||
|
|
}
|
||
|
|
case 'FloatN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 4:
|
||
|
|
return readReal(buf, offset);
|
||
|
|
case 8:
|
||
|
|
return readFloat(buf, offset);
|
||
|
|
default:
|
||
|
|
throw new Error('Unsupported dataLength ' + dataLength + ' for FloatN');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'SmallMoney':
|
||
|
|
{
|
||
|
|
return readSmallMoney(buf, offset);
|
||
|
|
}
|
||
|
|
case 'Money':
|
||
|
|
return readMoney(buf, offset);
|
||
|
|
case 'MoneyN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 4:
|
||
|
|
return readSmallMoney(buf, offset);
|
||
|
|
case 8:
|
||
|
|
return readMoney(buf, offset);
|
||
|
|
default:
|
||
|
|
throw new Error('Unsupported dataLength ' + dataLength + ' for MoneyN');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'Bit':
|
||
|
|
{
|
||
|
|
return readBit(buf, offset);
|
||
|
|
}
|
||
|
|
case 'BitN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 1:
|
||
|
|
return readBit(buf, offset);
|
||
|
|
default:
|
||
|
|
throw new Error('Unsupported dataLength ' + dataLength + ' for BitN');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'VarChar':
|
||
|
|
case 'Char':
|
||
|
|
{
|
||
|
|
const codepage = metadata.collation.codepage;
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
if (dataLength === NULL) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readChars(buf, offset, dataLength, codepage);
|
||
|
|
}
|
||
|
|
case 'NVarChar':
|
||
|
|
case 'NChar':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
if (dataLength === NULL) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readNChars(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
case 'VarBinary':
|
||
|
|
case 'Binary':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
if (dataLength === NULL) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readBinary(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
case 'Text':
|
||
|
|
{
|
||
|
|
let textPointerLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: textPointerLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (textPointerLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Textpointer
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, textPointerLength));
|
||
|
|
|
||
|
|
// Timestamp
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, 8));
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
return readChars(buf, offset, dataLength, metadata.collation.codepage);
|
||
|
|
}
|
||
|
|
case 'NText':
|
||
|
|
{
|
||
|
|
let textPointerLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: textPointerLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (textPointerLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Textpointer
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, textPointerLength));
|
||
|
|
|
||
|
|
// Timestamp
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, 8));
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
return readNChars(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
case 'Image':
|
||
|
|
{
|
||
|
|
let textPointerLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: textPointerLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (textPointerLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Textpointer
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, textPointerLength));
|
||
|
|
|
||
|
|
// Timestamp
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, 8));
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
return readBinary(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
case 'SmallDateTime':
|
||
|
|
{
|
||
|
|
return readSmallDateTime(buf, offset, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTime':
|
||
|
|
{
|
||
|
|
return readDateTime(buf, offset, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTimeN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 4:
|
||
|
|
return readSmallDateTime(buf, offset, options.useUTC);
|
||
|
|
case 8:
|
||
|
|
return readDateTime(buf, offset, options.useUTC);
|
||
|
|
default:
|
||
|
|
throw new Error('Unsupported dataLength ' + dataLength + ' for DateTimeN');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'Time':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readTime(buf, offset, dataLength, metadata.scale, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'Date':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readDate(buf, offset, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTime2':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readDateTime2(buf, offset, dataLength, metadata.scale, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTimeOffset':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readDateTimeOffset(buf, offset, dataLength, metadata.scale);
|
||
|
|
}
|
||
|
|
case 'NumericN':
|
||
|
|
case 'DecimalN':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readNumeric(buf, offset, dataLength, metadata.precision, metadata.scale);
|
||
|
|
}
|
||
|
|
case 'UniqueIdentifier':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
switch (dataLength) {
|
||
|
|
case 0:
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
case 0x10:
|
||
|
|
return readUniqueIdentifier(buf, offset, options);
|
||
|
|
default:
|
||
|
|
throw new Error((0, _sprintfJs.sprintf)('Unsupported guid size %d', dataLength - 1));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
case 'Variant':
|
||
|
|
{
|
||
|
|
let dataLength;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: dataLength
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
if (dataLength === 0) {
|
||
|
|
return new _helpers.Result(null, offset);
|
||
|
|
}
|
||
|
|
return readVariant(buf, offset, options, dataLength);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
throw new Error('Invalid type!');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function isPLPStream(metadata) {
|
||
|
|
switch (metadata.type.name) {
|
||
|
|
case 'VarChar':
|
||
|
|
case 'NVarChar':
|
||
|
|
case 'VarBinary':
|
||
|
|
{
|
||
|
|
return metadata.dataLength === MAX;
|
||
|
|
}
|
||
|
|
case 'Xml':
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
case 'UDT':
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function readUniqueIdentifier(buf, offset, options) {
|
||
|
|
let data;
|
||
|
|
({
|
||
|
|
value: data,
|
||
|
|
offset
|
||
|
|
} = readBinary(buf, offset, 0x10));
|
||
|
|
return new _helpers.Result(options.lowerCaseGuids ? (0, _guidParser.bufferToLowerCaseGuid)(data) : (0, _guidParser.bufferToUpperCaseGuid)(data), offset);
|
||
|
|
}
|
||
|
|
function readNumeric(buf, offset, dataLength, _precision, scale) {
|
||
|
|
let sign;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: sign
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
sign = sign === 1 ? 1 : -1;
|
||
|
|
let value;
|
||
|
|
if (dataLength === 5) {
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
} else if (dataLength === 9) {
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readUNumeric64LE)(buf, offset));
|
||
|
|
} else if (dataLength === 13) {
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readUNumeric96LE)(buf, offset));
|
||
|
|
} else if (dataLength === 17) {
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value
|
||
|
|
} = (0, _helpers.readUNumeric128LE)(buf, offset));
|
||
|
|
} else {
|
||
|
|
throw new Error((0, _sprintfJs.sprintf)('Unsupported numeric dataLength %d', dataLength));
|
||
|
|
}
|
||
|
|
return new _helpers.Result(value * sign / Math.pow(10, scale), offset);
|
||
|
|
}
|
||
|
|
function readVariant(buf, offset, options, dataLength) {
|
||
|
|
let baseType;
|
||
|
|
({
|
||
|
|
value: baseType,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
const type = _dataType.TYPE[baseType];
|
||
|
|
let propBytes;
|
||
|
|
({
|
||
|
|
value: propBytes,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
dataLength = dataLength - propBytes - 2;
|
||
|
|
switch (type.name) {
|
||
|
|
case 'UniqueIdentifier':
|
||
|
|
return readUniqueIdentifier(buf, offset, options);
|
||
|
|
case 'Bit':
|
||
|
|
return readBit(buf, offset);
|
||
|
|
case 'TinyInt':
|
||
|
|
return readTinyInt(buf, offset);
|
||
|
|
case 'SmallInt':
|
||
|
|
return readSmallInt(buf, offset);
|
||
|
|
case 'Int':
|
||
|
|
return readInt(buf, offset);
|
||
|
|
case 'BigInt':
|
||
|
|
return readBigInt(buf, offset);
|
||
|
|
case 'SmallDateTime':
|
||
|
|
return readSmallDateTime(buf, offset, options.useUTC);
|
||
|
|
case 'DateTime':
|
||
|
|
return readDateTime(buf, offset, options.useUTC);
|
||
|
|
case 'Real':
|
||
|
|
return readReal(buf, offset);
|
||
|
|
case 'Float':
|
||
|
|
return readFloat(buf, offset);
|
||
|
|
case 'SmallMoney':
|
||
|
|
return readSmallMoney(buf, offset);
|
||
|
|
case 'Money':
|
||
|
|
return readMoney(buf, offset);
|
||
|
|
case 'Date':
|
||
|
|
return readDate(buf, offset, options.useUTC);
|
||
|
|
case 'Time':
|
||
|
|
{
|
||
|
|
let scale;
|
||
|
|
({
|
||
|
|
value: scale,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
return readTime(buf, offset, dataLength, scale, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTime2':
|
||
|
|
{
|
||
|
|
let scale;
|
||
|
|
({
|
||
|
|
value: scale,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
return readDateTime2(buf, offset, dataLength, scale, options.useUTC);
|
||
|
|
}
|
||
|
|
case 'DateTimeOffset':
|
||
|
|
{
|
||
|
|
let scale;
|
||
|
|
({
|
||
|
|
value: scale,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
return readDateTimeOffset(buf, offset, dataLength, scale);
|
||
|
|
}
|
||
|
|
case 'VarBinary':
|
||
|
|
case 'Binary':
|
||
|
|
{
|
||
|
|
// maxLength (unused?)
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
return readBinary(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
case 'NumericN':
|
||
|
|
case 'DecimalN':
|
||
|
|
{
|
||
|
|
let precision;
|
||
|
|
({
|
||
|
|
value: precision,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
let scale;
|
||
|
|
({
|
||
|
|
value: scale,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt8)(buf, offset));
|
||
|
|
return readNumeric(buf, offset, dataLength, precision, scale);
|
||
|
|
}
|
||
|
|
case 'VarChar':
|
||
|
|
case 'Char':
|
||
|
|
{
|
||
|
|
// maxLength (unused?)
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
let collation;
|
||
|
|
({
|
||
|
|
value: collation,
|
||
|
|
offset
|
||
|
|
} = (0, _metadataParser.readCollation)(buf, offset));
|
||
|
|
return readChars(buf, offset, dataLength, collation.codepage);
|
||
|
|
}
|
||
|
|
case 'NVarChar':
|
||
|
|
case 'NChar':
|
||
|
|
{
|
||
|
|
// maxLength (unused?)
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
|
||
|
|
// collation (unused?)
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = (0, _metadataParser.readCollation)(buf, offset));
|
||
|
|
return readNChars(buf, offset, dataLength);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
throw new Error('Invalid type!');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function readBinary(buf, offset, dataLength) {
|
||
|
|
if (buf.length < offset + dataLength) {
|
||
|
|
throw new _helpers.NotEnoughDataError(offset + dataLength);
|
||
|
|
}
|
||
|
|
return new _helpers.Result(buf.slice(offset, offset + dataLength), offset + dataLength);
|
||
|
|
}
|
||
|
|
function readChars(buf, offset, dataLength, codepage) {
|
||
|
|
if (buf.length < offset + dataLength) {
|
||
|
|
throw new _helpers.NotEnoughDataError(offset + dataLength);
|
||
|
|
}
|
||
|
|
return new _helpers.Result(_iconvLite.default.decode(buf.slice(offset, offset + dataLength), codepage ?? DEFAULT_ENCODING), offset + dataLength);
|
||
|
|
}
|
||
|
|
function readNChars(buf, offset, dataLength) {
|
||
|
|
if (buf.length < offset + dataLength) {
|
||
|
|
throw new _helpers.NotEnoughDataError(offset + dataLength);
|
||
|
|
}
|
||
|
|
return new _helpers.Result(buf.toString('ucs2', offset, offset + dataLength), offset + dataLength);
|
||
|
|
}
|
||
|
|
async function readPLPStream(parser) {
|
||
|
|
while (parser.buffer.length < parser.position + 8) {
|
||
|
|
await parser.waitForChunk();
|
||
|
|
}
|
||
|
|
const expectedLength = parser.buffer.readBigUInt64LE(parser.position);
|
||
|
|
parser.position += 8;
|
||
|
|
if (expectedLength === PLP_NULL) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
const chunks = [];
|
||
|
|
let currentLength = 0;
|
||
|
|
while (true) {
|
||
|
|
while (parser.buffer.length < parser.position + 4) {
|
||
|
|
await parser.waitForChunk();
|
||
|
|
}
|
||
|
|
const chunkLength = parser.buffer.readUInt32LE(parser.position);
|
||
|
|
parser.position += 4;
|
||
|
|
if (!chunkLength) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
while (parser.buffer.length < parser.position + chunkLength) {
|
||
|
|
await parser.waitForChunk();
|
||
|
|
}
|
||
|
|
chunks.push(parser.buffer.slice(parser.position, parser.position + chunkLength));
|
||
|
|
parser.position += chunkLength;
|
||
|
|
currentLength += chunkLength;
|
||
|
|
}
|
||
|
|
if (expectedLength !== UNKNOWN_PLP_LEN) {
|
||
|
|
if (currentLength !== Number(expectedLength)) {
|
||
|
|
throw new Error('Partially Length-prefixed Bytes unmatched lengths : expected ' + expectedLength + ', but got ' + currentLength + ' bytes');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return chunks;
|
||
|
|
}
|
||
|
|
function readSmallDateTime(buf, offset, useUTC) {
|
||
|
|
let days;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: days
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
let minutes;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: minutes
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
let value;
|
||
|
|
if (useUTC) {
|
||
|
|
value = new Date(Date.UTC(1900, 0, 1 + days, 0, minutes));
|
||
|
|
} else {
|
||
|
|
value = new Date(1900, 0, 1 + days, 0, minutes);
|
||
|
|
}
|
||
|
|
return new _helpers.Result(value, offset);
|
||
|
|
}
|
||
|
|
function readDateTime(buf, offset, useUTC) {
|
||
|
|
let days;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: days
|
||
|
|
} = (0, _helpers.readInt32LE)(buf, offset));
|
||
|
|
let threeHundredthsOfSecond;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: threeHundredthsOfSecond
|
||
|
|
} = (0, _helpers.readInt32LE)(buf, offset));
|
||
|
|
const milliseconds = Math.round(threeHundredthsOfSecond * THREE_AND_A_THIRD);
|
||
|
|
let value;
|
||
|
|
if (useUTC) {
|
||
|
|
value = new Date(Date.UTC(1900, 0, 1 + days, 0, 0, 0, milliseconds));
|
||
|
|
} else {
|
||
|
|
value = new Date(1900, 0, 1 + days, 0, 0, 0, milliseconds);
|
||
|
|
}
|
||
|
|
return new _helpers.Result(value, offset);
|
||
|
|
}
|
||
|
|
function readTime(buf, offset, dataLength, scale, useUTC) {
|
||
|
|
let value;
|
||
|
|
switch (dataLength) {
|
||
|
|
case 3:
|
||
|
|
{
|
||
|
|
({
|
||
|
|
value,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt24LE)(buf, offset));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 4:
|
||
|
|
{
|
||
|
|
({
|
||
|
|
value,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt32LE)(buf, offset));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case 5:
|
||
|
|
{
|
||
|
|
({
|
||
|
|
value,
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt40LE)(buf, offset));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
throw new Error('unreachable');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (scale < 7) {
|
||
|
|
for (let i = scale; i < 7; i++) {
|
||
|
|
value *= 10;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
let date;
|
||
|
|
if (useUTC) {
|
||
|
|
date = new Date(Date.UTC(1970, 0, 1, 0, 0, 0, value / 10000));
|
||
|
|
} else {
|
||
|
|
date = new Date(1970, 0, 1, 0, 0, 0, value / 10000);
|
||
|
|
}
|
||
|
|
Object.defineProperty(date, 'nanosecondsDelta', {
|
||
|
|
enumerable: false,
|
||
|
|
value: value % 10000 / Math.pow(10, 7)
|
||
|
|
});
|
||
|
|
return new _helpers.Result(date, offset);
|
||
|
|
}
|
||
|
|
function readDate(buf, offset, useUTC) {
|
||
|
|
let days;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: days
|
||
|
|
} = (0, _helpers.readUInt24LE)(buf, offset));
|
||
|
|
if (useUTC) {
|
||
|
|
return new _helpers.Result(new Date(Date.UTC(2000, 0, days - 730118)), offset);
|
||
|
|
} else {
|
||
|
|
return new _helpers.Result(new Date(2000, 0, days - 730118), offset);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function readDateTime2(buf, offset, dataLength, scale, useUTC) {
|
||
|
|
let time;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: time
|
||
|
|
} = readTime(buf, offset, dataLength - 3, scale, useUTC));
|
||
|
|
let days;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: days
|
||
|
|
} = (0, _helpers.readUInt24LE)(buf, offset));
|
||
|
|
let date;
|
||
|
|
if (useUTC) {
|
||
|
|
date = new Date(Date.UTC(2000, 0, days - 730118, 0, 0, 0, +time));
|
||
|
|
} else {
|
||
|
|
date = new Date(2000, 0, days - 730118, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
|
||
|
|
}
|
||
|
|
Object.defineProperty(date, 'nanosecondsDelta', {
|
||
|
|
enumerable: false,
|
||
|
|
value: time.nanosecondsDelta
|
||
|
|
});
|
||
|
|
return new _helpers.Result(date, offset);
|
||
|
|
}
|
||
|
|
function readDateTimeOffset(buf, offset, dataLength, scale) {
|
||
|
|
let time;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: time
|
||
|
|
} = readTime(buf, offset, dataLength - 5, scale, true));
|
||
|
|
let days;
|
||
|
|
({
|
||
|
|
offset,
|
||
|
|
value: days
|
||
|
|
} = (0, _helpers.readUInt24LE)(buf, offset));
|
||
|
|
|
||
|
|
// time offset?
|
||
|
|
({
|
||
|
|
offset
|
||
|
|
} = (0, _helpers.readUInt16LE)(buf, offset));
|
||
|
|
const date = new Date(Date.UTC(2000, 0, days - 730118, 0, 0, 0, +time));
|
||
|
|
Object.defineProperty(date, 'nanosecondsDelta', {
|
||
|
|
enumerable: false,
|
||
|
|
value: time.nanosecondsDelta
|
||
|
|
});
|
||
|
|
return new _helpers.Result(date, offset);
|
||
|
|
}
|
||
|
|
module.exports.readValue = readValue;
|
||
|
|
module.exports.isPLPStream = isPLPStream;
|
||
|
|
module.exports.readPLPStream = readPLPStream;
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWV0YWRhdGFQYXJzZXIiLCJyZXF1aXJlIiwiX2RhdGFUeXBlIiwiX2ljb252TGl0ZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfc3ByaW50ZkpzIiwiX2d1aWRQYXJzZXIiLCJfaGVscGVycyIsIm9iaiIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiTlVMTCIsIk1BWCIsIlRIUkVFX0FORF9BX1RISVJEIiwiTU9ORVlfRElWSVNPUiIsIlBMUF9OVUxMIiwiVU5LTk9XTl9QTFBfTEVOIiwiREVGQVVMVF9FTkNPRElORyIsInJlYWRUaW55SW50IiwiYnVmIiwib2Zmc2V0IiwicmVhZFVJbnQ4IiwicmVhZFNtYWxsSW50IiwicmVhZEludDE2TEUiLCJyZWFkSW50IiwicmVhZEludDMyTEUiLCJyZWFkQmlnSW50IiwidmFsdWUiLCJyZWFkQmlnSW50NjRMRSIsIlJlc3VsdCIsInRvU3RyaW5nIiwicmVhZFJlYWwiLCJyZWFkRmxvYXRMRSIsInJlYWRGbG9hdCIsInJlYWREb3VibGVMRSIsInJlYWRTbWFsbE1vbmV5IiwicmVhZE1vbmV5IiwiaGlnaCIsImxvdyIsInJlYWRVSW50MzJMRSIsInJlYWRCaXQiLCJyZWFkVmFsdWUiLCJtZXRhZGF0YSIsIm9wdGlvbnMiLCJ0eXBlIiwibmFtZSIsImRhdGFMZW5ndGgiLCJFcnJvciIsImNvZGVwYWdlIiwiY29sbGF0aW9uIiwicmVhZFVJbnQxNkxFIiwicmVhZENoYXJzIiwicmVhZE5DaGFycyIsInJlYWRCaW5hcnkiLCJ0ZXh0UG9pbnRlckxlbmd0aCIsInJlYWRTbWFsbERhdGVUaW1lIiwidXNlVVRDIiwicmVhZERhdGVUaW1lIiwicmVhZFRpbWUiLCJzY2FsZSIsInJlYWREYXRlIiwicmVhZERhdGVUaW1lMiIsInJlYWREYXRlVGltZU9mZnNldCIsInJlYWROdW1lcmljIiwicHJlY2lzaW9uIiwicmVhZFVuaXF1ZUlkZW50aWZpZXIiLCJzcHJpbnRmIiwicmVhZFZhcmlhbnQiLCJpc1BMUFN0cmVhbSIsImRhdGEiLCJsb3dlckNhc2VHdWlkcyIsImJ1ZmZlclRvTG93ZXJDYXNlR3VpZCIsImJ1ZmZlclRvVXBwZXJDYXNlR3VpZCIsIl9wcmVjaXNpb24iLCJzaWduIiwicmVhZFVOdW1lcmljNjRMRSIsInJlYWRVTnVtZXJpYzk2TEUiLCJyZWFkVU51bWVyaWMxMjhMRSIsIk1hdGgiLCJwb3ciLCJiYXNlVHlwZSIsIlRZUEUiLCJwcm9wQnl0ZXMiLCJyZWFkQ29sbGF0aW9uIiwibGVuZ3RoIiwiTm90RW5vdWdoRGF0YUVycm9yIiwic2xpY2UiLCJpY29udiIsImRlY29kZSIsInJlYWRQTFBTdHJlYW0iLCJwYXJzZXIiLCJidWZmZXIiLCJwb3NpdGlvbiIsIndhaXRGb3JDaHVuayIsImV4cGVjdGVkTGVuZ3RoIiwicmVhZEJpZ1VJbnQ2NExFIiwiY2h1bmtzIiwiY3VycmVudExlbmd0aCIsImNodW5rTGVuZ3RoIiwicHVzaCIsIk51bWJlciIsImRheXMiLCJtaW51dGVzIiwiRGF0ZSIsIlVUQyIsInRocmVlSHVuZHJlZHRoc09mU2Vjb25kIiwibWlsbGlzZWNvbmRzIiwicm91bmQiLCJyZWFkVUludDI0TEUiLCJyZWFkVUludDQwTEUiLCJpIiwiZGF0ZSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZW51bWVyYWJsZSIsInRpbWUiLCJnZXRIb3VycyIsImdldE1pbnV0ZXMiLCJnZXRTZWNvbmRzIiwiZ2V0TWlsbGlzZWNvbmRzIiwibmFub3NlY29uZHNEZWx0YSIsIm1vZHVsZSIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi9zcmMvdmFsdWUtcGFyc2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQYXJzZXIsIHsgdHlwZSBQYXJzZXJPcHRpb25zIH0gZnJvbSAnLi90b2tlbi9zdHJlYW0tcGFyc2VyJztcbmltcG9ydCB7IHR5cGUgTWV0YWRhdGEsIHJlYWRDb2xsYXRpb24gfSBmcm9tICcuL21ldGFkYXRhLXBhcnNlcic7XG5pbXBvcnQgeyBUWVBFIH0gZnJvbSAnLi9kYXRhLXR5cGUnO1xuXG5pbXBvcnQgaWNvbnYgZnJvbSAnaWNvbnYtbGl0ZSc7XG5pbXBvcnQgeyBzcHJpbnRmIH0gZnJvbSAnc3ByaW50Zi1qcyc7XG5pbXBvcnQgeyBidWZmZXJUb0xvd2VyQ2FzZUd1aWQsIGJ1ZmZlclRvVXBwZXJDYXNlR3VpZCB9IGZyb20gJy4vZ3VpZC1wYXJzZXInO1xuaW1wb3J0IHsgTm90RW5vdWdoRGF0YUVycm9yLCBSZXN1bHQsIHJlYWRCaWdJbnQ2NExFLCByZWFkRG91YmxlTEUsIHJlYWRGbG9hdExFLCByZWFkSW50MTZMRSwgcmVhZEludDMyTEUsIHJlYWRVSW50MTZMRSwgcmVhZFVJbnQzMkxFLCByZWFkVUludDgsIHJlYWRVSW50MjRMRSwgcmVhZFVJbnQ0MExFLCByZWFkVU51bWVyaWM2NExFLCByZWFkVU51bWVyaWM5NkxFLCByZWFkVU51bWVyaWMxMjhMRSB9IGZyb20gJy4vdG9rZW4vaGVscGVycyc7XG5cbmNvbnN0IE5VTEwgPSAoMSA8PCAxNikgLSAxO1xuY29uc3QgTUFYID0gKDEgPDwgMTYpIC0gMTtcbmNvbnN0IFRIUkVFX0FORF9BX1RISVJEID0gMyArICgxIC8gMyk7XG5jb25zdCBNT05FWV9ESVZJU09SID0gMTAwMDA7XG5jb25zdCBQTFBfTlVMTCA9IDB4RkZGRkZGRkZGRkZGRkZGRm47XG5jb25zdCBVTktOT1dOX1BMUF9MRU4gPSAweEZGRkZGRkZGRkZGRkZGRkVuO1xuY29uc3QgREVGQVVMVF9FTkNPRElORyA9ICd1dGY4JztcblxuZnVuY3Rpb24gcmVhZFRpbnlJbnQoYnVmOiBCdWZmZXIsIG9mZnNldDogbnVtYmVyKTogUmVzdWx0PG51bWJlcj4ge1xuICByZXR1cm4gcmVhZFVJbnQ4KGJ1Ziwgb2Zmc2V0KTtcbn1cblxuZnVuY3Rpb24gcmVhZFNtYWxsSW50KGJ1ZjogQnVmZmVyLCBvZmZzZXQ6IG51bWJlcik6IFJlc3VsdDxudW1iZXI+IHtcbiAgcmV0dXJuIHJlYWRJbnQxNkxFKGJ1Ziwgb2Zmc2V0KTtcbn1cblxuZnVuY3Rpb24gcmVhZEludChidWY6IEJ1ZmZlciwgb2Zmc2V0OiBudW1iZXIpOiBSZXN1bHQ8bnVtYmVyPiB7XG4gIHJldHVybiByZWFkSW50MzJMRShidWYsIG9mZnNldCk7XG59XG5cbmZ1bmN0aW9uIHJlYWRCaWdJbnQoYnVmOiBCdWZmZXIsIG9mZnNldDogbnVtYmVyKTogUmVzdWx0PHN0cmluZz4ge1xuICBsZXQgdmFsdWU7XG4gICh7IG9mZnNldCwgdmFsdWUgfSA9IHJlYWRCaWdJbnQ2NExFKGJ1Ziwgb2Zmc2V0KSk7XG5cbiAgcmV0dXJuIG5ldyBSZXN1bHQodmFsdWUudG9TdHJpbmcoKSwgb2Zmc2V0KTtcbn1cblxuZnVuY3Rpb24gcmVhZFJlYWwoYnVmOiBCdWZmZXIsIG9mZnNldDogbnVtYmVyKTogUmV
|