UNPKG

@dashevo/dashcore-lib

Version:

A pure and powerful JavaScript Dash library.

284 lines (259 loc) 6.37 kB
/* eslint-disable */ // TODO: Remove previous line and work through linting issues at next edit 'use strict'; var _ = require('lodash'); var $ = require('../util/preconditions'); var BufferUtil = require('../util/buffer'); var BN = require('../crypto/bn'); /** * * @param buf * @returns {BufferReader} * @constructor */ var BufferReader = function BufferReader(buf) { if (!(this instanceof BufferReader)) { return new BufferReader(buf); } if (_.isUndefined(buf)) { return; } if (Buffer.isBuffer(buf)) { this.set({ buf: buf, }); } else if (_.isString(buf)) { this.set({ buf: Buffer.from(buf, 'hex'), }); } else if (_.isObject(buf)) { var obj = buf; this.set(obj); } else { throw new TypeError('Unrecognized argument for BufferReader'); } }; BufferReader.prototype.set = function (obj) { this.buf = obj.buf || this.buf || undefined; this.pos = obj.pos || this.pos || 0; return this; }; BufferReader.prototype.eof = function () { return this.pos >= this.buf.length; }; BufferReader.prototype.finished = BufferReader.prototype.eof; BufferReader.prototype.read = function (len) { $.checkArgument(!_.isUndefined(len), 'Must specify a length'); var buf = this.buf.slice(this.pos, this.pos + len); this.pos = this.pos + len; return buf; }; /** * Return the whole buffer * @return {Buffer} */ BufferReader.prototype.readAll = function () { var buf = this.buf.slice(this.pos, this.buf.length); this.pos = this.buf.length; return buf; }; /** * Read the next UInt8 * @return {number} */ BufferReader.prototype.readUInt8 = function () { var val = this.buf.readUInt8(this.pos); this.pos = this.pos + 1; return val; }; /** * Read the next UInt16BE * @return {number} */ BufferReader.prototype.readUInt16BE = function () { var val = this.buf.readUInt16BE(this.pos); this.pos = this.pos + 2; return val; }; /** * Read the next UInt16LE * @return {number} */ BufferReader.prototype.readUInt16LE = function () { var val = this.buf.readUInt16LE(this.pos); this.pos = this.pos + 2; return val; }; /** * Read the next UInt32BE * @return {number} */ BufferReader.prototype.readUInt32BE = function () { var val = this.buf.readUInt32BE(this.pos); this.pos = this.pos + 4; return val; }; /** * Read the next UInt32LE * @return {number} */ BufferReader.prototype.readUInt32LE = function () { var val = this.buf.readUInt32LE(this.pos); this.pos = this.pos + 4; return val; }; /** * Read the next Int32LE * @return {number} */ BufferReader.prototype.readInt32LE = function () { var val = this.buf.readInt32LE(this.pos); this.pos = this.pos + 4; return val; }; /** * Read the next UInt64BEBN * @return {number} */ BufferReader.prototype.readUInt64BEBN = function () { var buf = this.buf.slice(this.pos, this.pos + 8); var bn = BN.fromBuffer(buf); this.pos = this.pos + 8; return bn; }; /** * Read the next Int16LE * * @return {number} */ BufferReader.prototype.readInt16LE = function () { var val = this.buf.readInt16LE(this.pos); this.pos = this.pos + 2; return val; } /** * Read the next UInt64LEBN * @return {number} */ BufferReader.prototype.readUInt64LEBN = function () { var second = this.buf.readUInt32LE(this.pos); var first = this.buf.readUInt32LE(this.pos + 4); var combined = first * 0x100000000 + second; // Instantiating an instance of BN with a number is faster than with an // array or string. However, the maximum safe number for a double precision // floating point is 2 ^ 52 - 1 (0x1fffffffffffff), thus we can safely use // non-floating point numbers less than this amount (52 bits). And in the case // that the number is larger, we can instatiate an instance of BN by passing // an array from the buffer (slower) and specifying the endianness. var bn; if (combined <= 0x1fffffffffffff) { bn = new BN(combined); } else { var data = Array.prototype.slice.call(this.buf, this.pos, this.pos + 8); bn = new BN(data, 10, 'le'); } this.pos = this.pos + 8; return bn; }; /** * Read the next VarintNum * @return {number} */ BufferReader.prototype.readVarintNum = function () { var first = this.readUInt8(); switch (first) { case 0xfd: return this.readUInt16LE(); case 0xfe: return this.readUInt32LE(); case 0xff: var bn = this.readUInt64LEBN(); var n = bn.toNumber(); if (n <= Math.pow(2, 53)) { return n; } else { throw new Error( 'number too large to retain precision - use readVarintBN' ); } break; default: return first; } }; /** * reads a length prepended buffer * @return {Buffer} */ BufferReader.prototype.readVarLengthBuffer = function () { var len = this.readVarintNum(); var buf = this.read(len); $.checkState( buf.length === len, 'Invalid length while reading varlength buffer. ' + 'Expected to read: ' + len + ' and read ' + buf.length ); return buf; }; /** * Read the next VarIntBuffer * @return {Buffer} */ BufferReader.prototype.readVarintBuf = function () { var first = this.buf.readUInt8(this.pos); switch (first) { case 0xfd: return this.read(1 + 2); case 0xfe: return this.read(1 + 4); case 0xff: return this.read(1 + 8); default: return this.read(1); } }; /** * Read the next VarintBN * @return {BN} */ BufferReader.prototype.readVarintBN = function () { var first = this.readUInt8(); switch (first) { case 0xfd: return new BN(this.readUInt16LE()); case 0xfe: return new BN(this.readUInt32LE()); case 0xff: return this.readUInt64LEBN(); default: return new BN(first); } }; /** * Reverse buffer locally * @return {BufferReader} */ BufferReader.prototype.reverse = function () { var buf = Buffer.alloc(this.buf.length); for (var i = 0; i < buf.length; i++) { buf[i] = this.buf[this.buf.length - 1 - i]; } this.buf = buf; return this; }; /** * Read all and reverse * @return {Buffer} */ BufferReader.prototype.readReverse = function (len) { if (_.isUndefined(len)) { len = this.buf.length; } var buf = this.buf.slice(this.pos, this.pos + len); this.pos = this.pos + len; return BufferUtil.reverse(buf); }; module.exports = BufferReader;