UNPKG

nxkit

Version:

This is a collection of tools, independent of any other libraries

606 lines (605 loc) 22 kB
"use strict"; /* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * * Copyright (c) 2015, xuewen.chu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, self list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, self list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of xuewen.chu nor the * names of its contributors may be used to endorse or promote products * derived from self software without specific prior written permission. * * self SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL xuewen.chu BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF self * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ Object.defineProperty(exports, "__esModule", { value: true }); // Temporary buffers to convert numbers. const float32Array = new Float32Array(1); const uInt8Float32Array = new Uint8Array(float32Array.buffer); const float64Array = new Float64Array(1); const uInt8Float64Array = new Uint8Array(float64Array.buffer); var _bigint = null; var _readBigUIntBE; var _writeBigIntLE; function readBigUIntBE(self, offset, end) { validateNumber(offset, 'offset'); validateNumber(end, 'end'); if (end > self.length) boundsError(offset, self.length - (end - offset), 'end'); return _readBigUIntBE(self, offset, end); } function writeBigIntLE(bytes, bigint) { return _writeBigIntLE(bytes, bigint); } if (!!globalThis.BigInt) { (function (ok, ...args) { if (globalThis.document) { // webpack amd import('./_bigint.js').then((e) => ok(e)); // bigint syntax, webpack delay load } else { // node cjs ok(args[0]('./_bigint')); } })(function (bigint) { _bigint = bigint; _bigint._set(checkInt); _readBigUIntBE = _bigint._readBigUIntBE; _writeBigIntLE = _bigint._writeBigIntLE; }, require); } // Check endianness. float32Array[0] = -1; // 0xBF800000 // Either it is [0, 0, 128, 191] or [191, 128, 0, 0]. It is not possible to // check self with `os.endianness()` because that is determined at compile time. const bigEndian = uInt8Float32Array[3] === 0; function ERR_BUFFER_OUT_OF_BOUNDS(name) { if (name) { return new RangeError(`"${name}" is outside of buffer bounds`); } return new RangeError('Attempt to access memory outside buffer bounds'); } exports.ERR_BUFFER_OUT_OF_BOUNDS = ERR_BUFFER_OUT_OF_BOUNDS; function ERR_OUT_OF_RANGE(str, range, input) { return new RangeError(`ERR_OUT_OF_RANGE ${str}, ${range}, ${input}`); } exports.ERR_OUT_OF_RANGE = ERR_OUT_OF_RANGE; function ERR_INVALID_ARG_TYPE(value, types, arg = '') { if (!Array.isArray(types)) types = [types]; return new TypeError(`ERR_INVALID_ARG_TYPE ${arg} [${types.join('|')}] ${value}`); } exports.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE; function validateNumber(value, name) { if (typeof value !== 'number') throw ERR_INVALID_ARG_TYPE(value, 'number', name); // throw new TypeError(`ERR_INVALID_ARG_TYPE ${name} number ${value}`); } exports.validateNumber = validateNumber; function checkBounds(buf, offset, byteLength) { validateNumber(offset, 'offset'); if (buf[offset] === undefined || buf[offset + byteLength] === undefined) boundsError(offset, buf.length - (byteLength + 1)); } function checkInt(value, min, max, buf, offset, byteLength) { if (value > max || value < min) { const n = typeof min === 'bigint' ? 'n' : ''; let range; if (byteLength > 3) { if (min == 0) { range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`; } else { range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + `${(byteLength + 1) * 8 - 1}${n}`; } } else { range = `>= ${min}${n} and <= ${max}${n}`; } throw ERR_OUT_OF_RANGE('value', range, value); } checkBounds(buf, offset, byteLength); } function boundsError(value, length, type) { if (Math.floor(value) !== value) { validateNumber(value, type); throw ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value); } if (length < 0) throw ERR_BUFFER_OUT_OF_BOUNDS(); throw ERR_OUT_OF_RANGE(type || 'offset', `>= ${type ? 1 : 0} and <= ${length}`, value); } // Read integers. function readUInt8(self, offset = 0) { validateNumber(offset, 'offset'); const val = self[offset]; if (val === undefined) boundsError(offset, self.length - 1); return val; } function readInt8(self, offset = 0) { validateNumber(offset, 'offset'); const val = self[offset]; if (val === undefined) boundsError(offset, self.length - 1); return val | (val & 2 ** 7) * 0x1fffffe; } function readInt16BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 1]; if (first === undefined || last === undefined) boundsError(offset, self.length - 2); const val = first * 2 ** 8 + last; return val | (val & 2 ** 15) * 0x1fffe; } function readUInt16BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 1]; if (first === undefined || last === undefined) boundsError(offset, self.length - 2); return first * 2 ** 8 + last; } function readInt24BE(buf, offset = 0) { validateNumber(offset, 'offset'); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) boundsError(offset, buf.length - 3); const val = first * 2 ** 16 + buf[++offset] * 2 ** 8 + last; return val | (val & 2 ** 23) * 0x1fe; } function readUInt24BE(buf, offset = 0) { validateNumber(offset, 'offset'); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) boundsError(offset, buf.length - 3); return first * 2 ** 16 + buf[++offset] * 2 ** 8 + last; } function readInt32BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 3]; if (first === undefined || last === undefined) boundsError(offset, self.length - 4); return (first << 24) + // Overflow self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readUInt32BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 3]; if (first === undefined || last === undefined) boundsError(offset, self.length - 4); return first * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readInt40BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 4]; if (first === undefined || last === undefined) boundsError(offset, self.length - 5); return (first | (first & 2 ** 7) * 0x1fffffe) * 2 ** 32 + self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readUInt40BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 4]; if (first === undefined || last === undefined) boundsError(offset, self.length - 5); return first * 2 ** 32 + self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readInt48BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 5]; if (first === undefined || last === undefined) boundsError(offset, self.length - 6); const val = self[++offset] + first * 2 ** 8; return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 + self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readUInt48BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 5]; if (first === undefined || last === undefined) boundsError(offset, self.length - 6); return (first * 2 ** 8 + self[++offset]) * 2 ** 32 + self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; } function readBigInt64BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); if (_bigint) { return _bigint._readBigInt64BE(self, offset); } throw new Error('Not support bigint'); } function readBigUInt64BE(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); if (_bigint) { return _bigint._readBigUInt64BE(self, offset); } throw new Error('Not support bigint'); } function readBigInt64BE_Compatible(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); if (_bigint) { return _bigint._readBigInt64BE(self, offset); } const hi = (first << 24) + // Overflow self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + self[++offset]; const lo = self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; return hi * 2 ** 32 + lo; } function readBigUInt64BE_Compatible(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); if (_bigint) { return _bigint._readBigUInt64BE(self, offset); } const hi = first * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + self[++offset]; const lo = self[++offset] * 2 ** 24 + self[++offset] * 2 ** 16 + self[++offset] * 2 ** 8 + last; return hi * 2 ** 32 + lo; } function readIntBE(self, offset = 0, byteLength = 4) { validateNumber(offset, 'offset'); if (byteLength === 6) return readInt48BE(self, offset); if (byteLength === 5) return readInt40BE(self, offset); if (byteLength === 4) return readInt32BE(self, offset); if (byteLength === 3) return readInt24BE(self, offset); if (byteLength === 2) return readInt16BE(self, offset); if (byteLength === 1) return readInt8(self, offset); boundsError(byteLength, 6, 'byteLength'); return 0; } function readUIntBE(self, offset = 0, byteLength = 4) { validateNumber(offset, 'offset'); if (byteLength === 6) return readUInt48BE(self, offset); if (byteLength === 5) return readUInt40BE(self, offset); if (byteLength === 4) return readUInt32BE(self, offset); if (byteLength === 3) return readUInt24BE(self, offset); if (byteLength === 2) return readUInt16BE(self, offset); if (byteLength === 1) return readUInt8(self, offset); boundsError(byteLength, 6, 'byteLength'); return 0; } // Read floats function readFloatBackwards(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 3]; if (first === undefined || last === undefined) boundsError(offset, self.length - 4); uInt8Float32Array[3] = first; uInt8Float32Array[2] = self[++offset]; uInt8Float32Array[1] = self[++offset]; uInt8Float32Array[0] = last; return float32Array[0]; } function readFloatForwards(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 3]; if (first === undefined || last === undefined) boundsError(offset, self.length - 4); uInt8Float32Array[0] = first; uInt8Float32Array[1] = self[++offset]; uInt8Float32Array[2] = self[++offset]; uInt8Float32Array[3] = last; return float32Array[0]; } function readDoubleBackwards(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); uInt8Float64Array[7] = first; uInt8Float64Array[6] = self[++offset]; uInt8Float64Array[5] = self[++offset]; uInt8Float64Array[4] = self[++offset]; uInt8Float64Array[3] = self[++offset]; uInt8Float64Array[2] = self[++offset]; uInt8Float64Array[1] = self[++offset]; uInt8Float64Array[0] = last; return float64Array[0]; } function readDoubleForwards(self, offset = 0) { validateNumber(offset, 'offset'); const first = self[offset]; const last = self[offset + 7]; if (first === undefined || last === undefined) boundsError(offset, self.length - 8); uInt8Float64Array[0] = first; uInt8Float64Array[1] = self[++offset]; uInt8Float64Array[2] = self[++offset]; uInt8Float64Array[3] = self[++offset]; uInt8Float64Array[4] = self[++offset]; uInt8Float64Array[5] = self[++offset]; uInt8Float64Array[6] = self[++offset]; uInt8Float64Array[7] = last; return float64Array[0]; } // Write integers. function writeU_Int8(buf, value, offset, min, max) { value = +value; // `checkInt()` can not be used here because it checks two entries. validateNumber(offset, 'offset'); if (value > max || value < min) { throw ERR_OUT_OF_RANGE('value', `>= ${min} and <= ${max}`, value); } if (buf[offset] === undefined) boundsError(offset, buf.length - 1); buf[offset] = value; return offset + 1; } function writeU_Int16BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 1); buf[offset++] = (value >>> 8); buf[offset++] = value; return offset; } function writeU_Int32BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3); buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4; } function writeU_Int24BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 2); buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 3; } function writeU_Int40BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 4); buf[offset++] = Math.floor(value * 2 ** -32); buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4; } function writeU_Int48BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 5); const newVal = Math.floor(value * 2 ** -32); buf[offset++] = (newVal >>> 8); buf[offset++] = newVal; buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4; } function writeInt8(self, value, offset = 0) { return writeU_Int8(self, value, offset, -0x80, 0x7f); } function writeUInt8(self, value, offset = 0) { return writeU_Int8(self, value, offset, 0, 0xff); } function writeInt16BE(self, value, offset = 0) { return writeU_Int16BE(self, value, offset, -0x8000, 0x7fff); } function writeUInt16BE(self, value, offset = 0) { return writeU_Int16BE(self, value, offset, 0, 0xffff); } function writeInt32BE(self, value, offset = 0) { return writeU_Int32BE(self, value, offset, -0x80000000, 0x7fffffff); } function writeUInt32BE(self, value, offset = 0) { return writeU_Int32BE(self, value, offset, 0, 0xffffffff); } function writeInt48BE(self, value, offset = 0) { return writeU_Int48BE(self, value, offset, -0x800000000000, 0x7fffffffffff); } function writeUInt48BE(self, value, offset = 0) { return writeU_Int48BE(self, value, offset, 0, 0xffffffffffffff); } function writeBigInt64BE(self, value, offset = 0) { return _bigint._writeBigInt64BE(self, value, offset); } function writeBigUInt64BE(self, value, offset = 0) { return _bigint._writeBigUInt64BE(self, value, offset); } function writeIntBE(self, value, offset = 0, byteLength = 4) { if (byteLength === 6) return writeU_Int48BE(self, value, offset, -0x800000000000, 0x7fffffffffff); if (byteLength === 5) return writeU_Int40BE(self, value, offset, -0x8000000000, 0x7fffffffff); if (byteLength === 3) return writeU_Int24BE(self, value, offset, -0x800000, 0x7fffff); if (byteLength === 4) return writeU_Int32BE(self, value, offset, -0x80000000, 0x7fffffff); if (byteLength === 2) return writeU_Int16BE(self, value, offset, -0x8000, 0x7fff); if (byteLength === 1) return writeU_Int8(self, value, offset, -0x80, 0x7f); boundsError(byteLength, 6, 'byteLength'); return 0; } function writeUIntBE(self, value, offset = 0, byteLength = 4) { if (byteLength === 6) return writeU_Int48BE(self, value, offset, 0, 0xffffffffffffff); if (byteLength === 5) return writeU_Int40BE(self, value, offset, 0, 0xffffffffff); if (byteLength === 3) return writeU_Int24BE(self, value, offset, 0, 0xffffff); if (byteLength === 4) return writeU_Int32BE(self, value, offset, 0, 0xffffffff); if (byteLength === 2) return writeU_Int16BE(self, value, offset, 0, 0xffff); if (byteLength === 1) return writeU_Int8(self, value, offset, 0, 0xff); boundsError(byteLength, 6, 'byteLength'); return 0; } // Write floats. function writeFloatForwards(self, val, offset = 0) { val = +val; checkBounds(self, offset, 3); float32Array[0] = val; self[offset++] = uInt8Float32Array[0]; self[offset++] = uInt8Float32Array[1]; self[offset++] = uInt8Float32Array[2]; self[offset++] = uInt8Float32Array[3]; return offset; } function writeFloatBackwards(self, val, offset = 0) { val = +val; checkBounds(self, offset, 3); float32Array[0] = val; self[offset++] = uInt8Float32Array[3]; self[offset++] = uInt8Float32Array[2]; self[offset++] = uInt8Float32Array[1]; self[offset++] = uInt8Float32Array[0]; return offset; } function writeDoubleForwards(self, val, offset = 0) { val = +val; checkBounds(self, offset, 7); float64Array[0] = val; self[offset++] = uInt8Float64Array[0]; self[offset++] = uInt8Float64Array[1]; self[offset++] = uInt8Float64Array[2]; self[offset++] = uInt8Float64Array[3]; self[offset++] = uInt8Float64Array[4]; self[offset++] = uInt8Float64Array[5]; self[offset++] = uInt8Float64Array[6]; self[offset++] = uInt8Float64Array[7]; return offset; } function writeDoubleBackwards(self, val, offset = 0) { val = +val; checkBounds(self, offset, 7); float64Array[0] = val; self[offset++] = uInt8Float64Array[7]; self[offset++] = uInt8Float64Array[6]; self[offset++] = uInt8Float64Array[5]; self[offset++] = uInt8Float64Array[4]; self[offset++] = uInt8Float64Array[3]; self[offset++] = uInt8Float64Array[2]; self[offset++] = uInt8Float64Array[1]; self[offset++] = uInt8Float64Array[0]; return offset; } var readFloatBE = bigEndian ? readFloatForwards : readFloatBackwards; var readDoubleBE = bigEndian ? readDoubleForwards : readDoubleBackwards; var writeFloatBE = bigEndian ? writeFloatForwards : writeFloatBackwards; var writeDoubleBE = bigEndian ? writeDoubleForwards : writeDoubleBackwards; exports.default = { get isBigInt() { return !!globalThis.BigInt; }, // read readInt8, readUInt8, readInt16BE, readUInt16BE, readInt32BE, readUInt32BE, readInt40BE, readUInt40BE, readInt48BE, readUInt48BE, readBigInt64BE, readBigUInt64BE, readBigInt64BE_Compatible, readBigUInt64BE_Compatible, readIntBE, readUIntBE, readFloatBE, readDoubleBE, readBigUIntBE, // write writeInt8, writeUInt8, writeInt16BE, writeUInt16BE, writeInt32BE, writeUInt32BE, writeInt48BE, writeUInt48BE, writeBigInt64BE, writeBigUInt64BE, writeIntBE, writeUIntBE, writeFloatBE, writeDoubleBE, writeBigIntLE, };