UNPKG

lotus-sdk

Version:

Central repository for several classes of tools for integrating with, and building for, the Lotusia ecosystem

199 lines (198 loc) 5.78 kB
import { Preconditions } from '../util/preconditions.js'; import { BN } from '../crypto/bn.js'; import { BufferUtil } from '../util/buffer.js'; export class BufferReader { buf; pos = 0; constructor(buf) { if (buf === undefined) { return; } if (Buffer.isBuffer(buf)) { this.set({ buf: buf, }); } else if (typeof buf === 'string') { const b = Buffer.from(buf, 'hex'); if (b.length * 2 !== buf.length) { throw new TypeError('Invalid hex string'); } this.set({ buf: b, }); } else if (typeof buf === 'object' && buf !== null) { const obj = buf; this.set(obj); } else { throw new TypeError('Unrecognized argument for BufferReader'); } } static create(buf) { return new BufferReader(buf); } set(obj) { this.buf = obj.buf || this.buf || undefined; this.pos = obj.pos || this.pos || 0; return this; } eof() { return this.pos >= this.buf.length; } finished() { return this.eof(); } read(len) { Preconditions.checkArgument(len !== undefined, 'len', 'Must specify a length'); const buf = this.buf.slice(this.pos, this.pos + len); this.pos = this.pos + len; return buf; } readAll() { const buf = this.buf.slice(this.pos, this.buf.length); this.pos = this.buf.length; return buf; } readUInt8() { const val = this.buf.readUInt8(this.pos); this.pos = this.pos + 1; return val; } readUInt16BE() { const val = this.buf.readUInt16BE(this.pos); this.pos = this.pos + 2; return val; } readUInt16LE() { const val = this.buf.readUInt16LE(this.pos); this.pos = this.pos + 2; return val; } readUInt32BE() { const val = this.buf.readUInt32BE(this.pos); this.pos = this.pos + 4; return val; } readUInt32LE() { const val = this.buf.readUInt32LE(this.pos); this.pos = this.pos + 4; return val; } readUInt48LE() { const val = this.buf.readUIntLE(this.pos, 6); this.pos = this.pos + 6; return val; } readUInt56LEBN() { const buf = this.buf.slice(this.pos, this.pos + 7); const bn = BN.fromBuffer(buf, { endian: 'little' }); this.pos = this.pos + 7; return bn; } readInt32LE() { const val = this.buf.readInt32LE(this.pos); this.pos = this.pos + 4; return val; } readUInt64BEBN() { const buf = this.buf.slice(this.pos, this.pos + 8); const bn = BN.fromBuffer(buf); this.pos = this.pos + 8; return bn; } readUInt64LEBN() { const second = this.buf.readUInt32LE(this.pos); const first = this.buf.readUInt32LE(this.pos + 4); const combined = first * 0x100000000 + second; let bn; if (combined <= 0x1fffffffffffff) { bn = new BN(combined); } else { const data = Array.prototype.slice.call(this.buf, this.pos, this.pos + 8); bn = new BN(Buffer.from(data), 'le'); } this.pos = this.pos + 8; return bn; } readUInt32LEBN() { const value = this.buf.readUInt32LE(this.pos); this.pos = this.pos + 4; return new BN(value); } readVarintNum() { const first = this.readUInt8(); switch (first) { case 0xfd: return this.readUInt16LE(); case 0xfe: return this.readUInt32LE(); case 0xff: { const bn = this.readUInt64LEBN(); const n = Number(bn); if (n <= Math.pow(2, 53)) { return n; } else { throw new Error('number too large to retain precision - use readVarintBN'); } } default: return first; } } readVarLengthBuffer() { const len = this.readVarintNum(); const buf = this.read(len); Preconditions.checkState(buf.length === len, 'Invalid length while reading varlength buffer. ' + 'Expected to read: ' + len + ' and read ' + buf.length); return buf; } readVarintBuf() { const 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); } } readVarintBN() { const 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() { const buf = Buffer.alloc(this.buf.length); for (let i = 0; i < buf.length; i++) { buf[i] = this.buf[this.buf.length - 1 - i]; } this.buf = buf; return this; } readReverse(len) { if (len === undefined) { len = this.buf.length; } const buf = this.buf.slice(this.pos, this.pos + len); this.pos = this.pos + len; return BufferUtil.reverse(buf); } }