UNPKG

libnexa-ts

Version:

A pure and powerful Nexa SDK library.

201 lines (176 loc) 5.29 kB
import ValidationUtils from "../utils/validation.utils"; import BN from "../crypto/bn.extension"; import BufferUtils from "../utils/buffer.utils"; import type { BufferParams } from "../common/interfaces"; export default class BufferReader { public buf: Uint8Array; public pos: number; constructor(buf?: Uint8Array | string | BufferParams) { this.buf = new Uint8Array(); this.pos = 0; if (buf == null) { return; } if (BufferUtils.isBuffer(buf)) { this.set({ buf: buf }); } else if (typeof buf === 'string') { let b = BufferUtils.hexToBuffer(buf); if (b.length * 2 != buf.length) { throw new TypeError('Invalid hex string'); } this.set({ buf: b }); } else if (typeof buf === 'object') { let obj = buf; this.set(obj); } else { throw new TypeError('Unrecognized argument for BufferReader'); } } public set(obj: BufferParams): this { this.buf = obj.buf || this.buf; this.pos = obj.pos || this.pos || 0; return this; } public eof(): boolean { return this.pos >= this.buf.length; } public finished = this.eof; public read(len: number): Uint8Array { ValidationUtils.validateArgument(len != null, 'Must specify a length'); let buf = this.buf.subarray(this.pos, this.pos + len); this.pos = this.pos + len; return buf; } public readAll(): Uint8Array { let buf = this.buf.subarray(this.pos, this.buf.length); this.pos = this.buf.length; return buf; } public readUInt8(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getUint8(this.pos); this.pos += 1; return val; } public readUInt16BE(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getUint16(this.pos); this.pos += 2; return val; } public readUInt16LE(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getUint16(this.pos, true); this.pos += 2; return val; } public readUInt32BE(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getUint32(this.pos); this.pos += 4; return val; } public readUInt32LE(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getUint32(this.pos, true); this.pos += 4; return val; } public readInt32LE(): number { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getInt32(this.pos, true); this.pos += 4; return val; } public readUInt64BEBN(): BN { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getBigUint64(this.pos); this.pos += 8; return BN.fromBigInt(val); } public readUInt64LEBN(): BN { const view = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength); const val = view.getBigUint64(this.pos, true); this.pos += 8; return BN.fromBigInt(val); } public readVarintNum(): number { let first = this.readUInt8(); switch (first) { case 0xFD: return this.readUInt16LE(); case 0xFE: return this.readUInt32LE(); case 0xFF: let bn = this.readUInt64LEBN(); let n = bn.toNumber(); if (n <= Math.pow(2, 53)) { return n; } else { throw new Error('number too large to retain precision - use readVarintBN'); } } return first; } /** * reads a length prepended buffer */ public readVarLengthBuffer(): Uint8Array { let len = this.readVarintNum(); let buf = this.read(len); ValidationUtils.validateState(buf.length === len, 'Invalid length while reading varlength buffer. ' + 'Expected to read: ' + len + ' and read ' + buf.length); return buf; } public readVarintBuf(): Uint8Array { let first = this.buf[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); } } public readVarintBN(): BN { let 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); } } public reverse(): this { let buf = BufferUtils.reverse(this.buf); this.buf = buf; return this; } public readReverse(len?: number): Uint8Array { if (len == null) { len = this.buf.length; } let buf = this.buf.subarray(this.pos, this.pos + len); this.pos = this.pos + len; return BufferUtils.reverse(buf); }; public readCoreVarintNum(): number { let n = 0; while (true) { let chData = this.readUInt8(); n = (n << 7) | (chData & 0x7F); if (chData & 0x80) { n++; } else { return n; } } } }