import { Utils } from "../.."; /** Utility class to sequentially fetch data from byte array. EOF checks included. */ export class SequentialDataReader { private bytes: Uint8Array; private offset: number; constructor(bytes: Uint8Array) { this.bytes = bytes; this.offset = 0; } /** Check available bytes bytes and throw exception if EOF met */ private willRead(count: number) { // console.log(`willRead ${count} (offset becomes ${this.offset+count} / ${this.bytes.length})`) if (this.offset + count > this.bytes.length) { throw new Error("Tried to read too much data"); } } /** Skip bytes */ skip(len: number): void { this.willRead(len); this.offset += len; } /** Read fixed length bytes */ readBytes(len: number): Uint8Array { this.willRead(len); const part = this.bytes.slice(this.offset, this.offset + len); this.offset += len; return part; } /** Read variable length bytes */ readVBytes(): Uint8Array { let len = this.readI8(); let part: Uint8Array = this.readBytes(len); return part; } /** Read variable length string */ readVString(): string { let part: Uint8Array = this.readVBytes(); return Utils.u8ArrayToString(part); } /** Read 8 bit int (big endian) */ readI8(): number { this.willRead(1); const result = this.bytes[this.offset]; this.offset += 1; return result; } /** Read 16 bit int (big endian) */ readI16(): number { this.willRead(2); const part = this.bytes.slice(this.offset, this.offset + 2); this.offset += 2; return Utils.bytesToI16(part); } /** Check EOF condition */ end() { if (this.offset != this.bytes.length) { throw new Error("Extra data left"); } } }