UNPKG

blitflash

Version:

A JavaScript implementation of the 32blit flash tools

123 lines (122 loc) 5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReadBuffer = void 0; const INITIAL_CAPACITY = 1024; class PendingPromise { constructor(dataLength, resolve, reject) { this.dataLength = dataLength; this.resolve = resolve; this.reject = reject; } } class ReadBuffer { constructor(initialCapacity = INITIAL_CAPACITY) { this.pendingPromises = []; this._size = 0; this.decoder = new TextDecoder(); this.buffer = new Uint8Array(new ArrayBuffer(initialCapacity)); } read(numBytes) { return __awaiter(this, void 0, void 0, function* () { // If we don't have any Promises pending ahead of this and have enough data we respond straight // away. if (this.pendingPromises.length === 0 && this.size() >= numBytes) { return yield this.internalRead(numBytes); } // Otherwise, we append a Promise to our list of pending promises. return new Promise((resolve, reject) => { this.pendingPromises.push(new PendingPromise(numBytes, resolve, reject)); }); }); } readUint8() { return __awaiter(this, void 0, void 0, function* () { const data = yield this.read(1); return new DataView(data.buffer).getUint8(0); }); } readUint16(littleEndian) { return __awaiter(this, void 0, void 0, function* () { const data = yield this.read(2); return new DataView(data.buffer).getUint16(0, littleEndian); }); } readUint32(littleEndian) { return __awaiter(this, void 0, void 0, function* () { const data = yield this.read(4); return new DataView(data.buffer).getUint32(0, littleEndian); }); } readString(size) { return __awaiter(this, void 0, void 0, function* () { const data = yield this.read(size); let end = data.findIndex((value) => value === 0); if (end === -1) { end = size - 1; } return this.decoder.decode(data.slice(0, end + 1)); }); } append(data) { if (this.size() + data.byteLength > this.buffer.byteLength) { this.extendBuffer(); } this.buffer.set(data, this.size()); this._size += data.byteLength; this.tryResolvePendingPromises(); } failPendingPromises(error) { while (this.pendingPromises.length > 0) { this.pendingPromises.shift().reject(error); } } size() { return this._size; } capacity() { return this.buffer.byteLength; } /** * Reads `numBytes` from the internal buffer. throws an {Error} if there's not enough data in the * Buffer. * * @param numBytes number of bytes to read. * @returns A @{Promise<Uint8Array>} which resolves if the data is successfully read and rejects * if the buffer doesn't have enough data. */ internalRead(numBytes) { return __awaiter(this, void 0, void 0, function* () { if (this.size() < numBytes) { throw new Error(`Internal buffer has ${this.size} bytes, but tried to read ${numBytes}.`); } this._size -= numBytes; const array = new Uint8Array(this.buffer.subarray(0, numBytes)); this.buffer.copyWithin(0, numBytes, numBytes + this.size()); return array; }); } tryResolvePendingPromises() { return __awaiter(this, void 0, void 0, function* () { while (this.pendingPromises.length > 0 && this.pendingPromises[0].dataLength <= this.size()) { const pendingPromise = this.pendingPromises.shift(); const result = yield this.internalRead(pendingPromise.dataLength); pendingPromise.resolve(result); } }); } extendBuffer() { const newBuffer = new Uint8Array(new ArrayBuffer(this.buffer.byteLength * 2)); newBuffer.set(this.buffer); this.buffer = newBuffer; } } exports.ReadBuffer = ReadBuffer;