UNPKG

@iotize/device-client.js

Version:

IoTize Device client for Javascript

383 lines (382 loc) 15 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var kaitai_stream_1 = require("./kaitai-stream"); var KaitaiStreamReader = /** @class */ (function (_super) { __extends(KaitaiStreamReader, _super); /** KaitaiStream is an implementation of Kaitai Struct API for JavaScript. Based on DataStream - https://github.com/kig/DataStream.js @param {ArrayBuffer} arrayBuffer ArrayBuffer to read from. @param {?Number} byteOffset Offset from arrayBuffer beginning for the KaitaiStream. */ function KaitaiStreamReader(arrayBuffer, byteOffset, isBigEndian) { if (byteOffset === void 0) { byteOffset = 0; } if (isBigEndian === void 0) { isBigEndian = true; } return _super.call(this, arrayBuffer, byteOffset, isBigEndian) || this; } KaitaiStreamReader.fromArray = function (array) { // let buffer = new ArrayBuffer(array.length); var stream = new KaitaiStreamReader(array.buffer); return stream; }; KaitaiStreamReader.create = function (packet) { return packet instanceof Uint8Array ? KaitaiStreamReader.fromArray(packet) : packet; }; ; // ======================================================================== // Integer numbers // ======================================================================== // ------------------------------------------------------------------------ // Signed // ------------------------------------------------------------------------ KaitaiStreamReader.prototype.readS = function (size) { return this.read('s', size * 8); }; KaitaiStreamReader.prototype.read = function (type, bitSize, isLittleEndian) { if (isLittleEndian === void 0) { isLittleEndian = this.isLittleEndian; } if (type !== 'b') { bitSize /= 8; } var methodType = "read" + type.toUpperCase() + (type != 'b' ? bitSize : '') + (bitSize > 1 && type != 'b' ? (isLittleEndian ? 'le' : 'be') : ''); if (!(methodType in this)) { throw new Error("Invalid read type: type=" + type + ", size=" + bitSize + ", le=" + isLittleEndian + ". Method name: " + methodType); } // console.debug(`Will ${methodType} (le=${isLittleEndian}, pos=${this.pos}, size=${bitSize}, bitsLeft=${this.bitsLeft})`) var val = this[methodType](bitSize); // console.debug(`\t-Value red ${val}`) return val; }; /** Reads an 8-bit signed int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readS1 = function () { var v = this._dataView.getInt8(this.pos); this.pos += 1; return v; }; ; // ........................................................................ // Big-endian // ........................................................................ /** Reads a 16-bit big-endian signed int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readS2be = function () { var v = this._dataView.getInt16(this.pos); this.pos += 2; return v; }; ; /** Reads a 32-bit big-endian signed int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readS4be = function () { var v = this._dataView.getInt32(this.pos); this.pos += 4; return v; }; ; /** Reads a 64-bit big-endian unsigned int from the stream. Note that JavaScript does not support 64-bit integers natively, so it will automatically upgrade internal representation to use IEEE 754 double precision float. @return {number} The read number. */ KaitaiStreamReader.prototype.readS8be = function () { var v1 = this.readU4be(); var v2 = this.readU4be(); if ((v1 & 0x80000000) != 0) { // negative number return -(0x100000000 * (v1 ^ 0xffffffff) + (v2 ^ 0xffffffff)) - 1; } else { return 0x100000000 * v1 + v2; } }; ; // ........................................................................ // Little-endian // ........................................................................ /** Reads a 16-bit little-endian signed int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readS2le = function () { var v = this._dataView.getInt16(this.pos, true); this.pos += 2; return v; }; ; /** Reads a 32-bit little-endian signed int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readS4le = function () { var v = this._dataView.getInt32(this.pos, true); this.pos += 4; return v; }; ; /** Reads a 64-bit little-endian unsigned int from the stream. Note that JavaScript does not support 64-bit integers natively, so it will automatically upgrade internal representation to use IEEE 754 double precision float. @return {number} The read number. */ KaitaiStreamReader.prototype.readS8le = function () { var v1 = this.readU4le(); var v2 = this.readU4le(); if ((v2 & 0x80000000) != 0) { // negative number return -(0x100000000 * (v2 ^ 0xffffffff) + (v1 ^ 0xffffffff)) - 1; } else { return 0x100000000 * v2 + v1; } }; ; // ------------------------------------------------------------------------ // Unsigned // ------------------------------------------------------------------------ /** * Read unsigned * @param size */ KaitaiStreamReader.prototype.readU = function (size) { return this.read('u', size * 8); }; /** Reads an 8-bit unsigned int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readU1 = function () { var v = this._dataView.getUint8(this.pos); this.pos += 1; return v; }; ; // ........................................................................ // Big-endian // ........................................................................ /** Reads a 16-bit big-endian unsigned int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readU2be = function () { var v = this._dataView.getUint16(this.pos); this.pos += 2; return v; }; ; /** Reads a 32-bit big-endian unsigned int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readU4be = function () { var v = this._dataView.getUint32(this.pos); this.pos += 4; return v; }; ; /** Reads a 64-bit big-endian unsigned int from the stream. Note that JavaScript does not support 64-bit integers natively, so it will automatically upgrade internal representation to use IEEE 754 double precision float. @return {number} The read number. */ KaitaiStreamReader.prototype.readU8be = function () { var v1 = this.readU4be(); var v2 = this.readU4be(); return 0x100000000 * v1 + v2; }; ; // ........................................................................ // Little-endian // ........................................................................ /** Reads a 16-bit little-endian unsigned int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readU2le = function () { var v = this._dataView.getUint16(this.pos, true); this.pos += 2; return v; }; ; /** Reads a 32-bit little-endian unsigned int from the stream. @return {number} The read number. */ KaitaiStreamReader.prototype.readU4le = function () { var v = this._dataView.getUint32(this.pos, true); this.pos += 4; return v; }; ; /** Reads a 64-bit little-endian unsigned int from the stream. Note that JavaScript does not support 64-bit integers natively, so it will automatically upgrade internal representation to use IEEE 754 double precision float. @return {number} The read number. */ KaitaiStreamReader.prototype.readU8le = function () { var v1 = this.readU4le(); var v2 = this.readU4le(); return 0x100000000 * v2 + v1; }; ; // ======================================================================== // Floating point numbers // ======================================================================== // ------------------------------------------------------------------------ // Big endian // ------------------------------------------------------------------------ KaitaiStreamReader.prototype.readF = function (size) { return this.read('f', size * 8); }; KaitaiStreamReader.prototype.readF4be = function () { var v = this._dataView.getFloat32(this.pos); this.pos += 4; return v; }; ; KaitaiStreamReader.prototype.readF8be = function () { var v = this._dataView.getFloat64(this.pos); this.pos += 8; return v; }; ; // ------------------------------------------------------------------------ // Little endian // ------------------------------------------------------------------------ KaitaiStreamReader.prototype.readF4le = function () { var v = this._dataView.getFloat32(this.pos, true); this.pos += 4; return v; }; ; KaitaiStreamReader.prototype.readF8le = function () { var v = this._dataView.getFloat64(this.pos, true); this.pos += 8; return v; }; ; // ------------------------------------------------------------------------ // Unaligned bit values // ------------------------------------------------------------------------ KaitaiStreamReader.prototype.readBitsBoolean = function (n) { return this.readBitsInt(n) !== 0; }; KaitaiStreamReader.prototype.readB = function (n) { return this.readBitsInt(n); }; KaitaiStreamReader.prototype.forwardBits = function (n) { this.readBitsInt(n); return this; }; KaitaiStreamReader.prototype.readBitsInt = function (n) { // console.debug('readBitsInt(' + n + '): bits: ', this.bits, ' | bitsLeft: ', this.bitsLeft, ' | pos:' + this.pos, ' | buffer: ' + FormatHelper.toHexString(this.toBytes)) // JS only supports bit operations on 32 bits if (n > 32) throw new Error("readBitsInt: the maximum supported bit length is 32 (tried to read " + n + " bits)"); var bitsNeeded = n - this.bitsLeft; if (bitsNeeded > 0) { // console.debug(`readBitsInt bitsNeeded ${bitsNeeded} but only ${this.bitsLeft} available`) // 1 bit => 1 byte // 8 bits => 1 byte // 9 bits => 2 bytes var bytesNeeded = Math.ceil(bitsNeeded / 8); var buf = this.readBytes(bytesNeeded); for (var i = 0; i < buf.length; i++) { this.bits <<= 8; this.bits |= buf[i]; this.bitsLeft += 8; } } // raw mask with required number of 1s, starting from lowest bit var mask = n == 32 ? 0xffffffff : (1 << n) - 1; // shift mask to align with highest bits available in this.bits var shiftBits = this.bitsLeft - n; mask <<= shiftBits; // derive reading result var res = (this.bits & mask) >>> shiftBits; // clear top bits that we've just read => AND with 1s this.bitsLeft -= n; mask = (1 << this.bitsLeft) - 1; this.bits &= mask; return res; }; // ======================================================================== // Byte arrays // ======================================================================== KaitaiStreamReader.prototype.readBytes = function (len) { if (len < 0) { len = this.byteLeft + len; } // console.debug('readBytes', len); return this.mapUint8Array(len); }; KaitaiStreamReader.prototype.readBytesFull = function () { return this.mapUint8Array(this.size - this.pos); }; KaitaiStreamReader.prototype.readBytesTerm = function (terminator, include, consume, eosError) { var blen = this.size - this.pos; var u8 = new Uint8Array(this._buffer, this._byteOffset + this.pos); for (var i = 0; i < blen && u8[i] != terminator; i++) ; // find first zero byte if (i == blen) { // we've read all the buffer and haven't found the terminator if (eosError) { throw "End of stream reached, but no terminator " + terminator + " found"; } else { return this.mapUint8Array(i); } } else { var arr; if (include) { arr = this.mapUint8Array(i + 1); } else { arr = this.mapUint8Array(i); } if (consume) { this.pos += 1; } return arr; } }; KaitaiStreamReader.prototype.ensureFixedContents = function (expected) { var actual = this.readBytes(expected.length); if (actual.length !== expected.length) { throw new kaitai_stream_1.UnexpectedDataError(expected, actual); } var actLen = actual.length; for (var i = 0; i < actLen; i++) { if (actual[i] != expected[i]) { throw new kaitai_stream_1.UnexpectedDataError(expected, actual); } } return actual; }; return KaitaiStreamReader; }(kaitai_stream_1.KaitaiStream)); exports.KaitaiStreamReader = KaitaiStreamReader;