import type { IReadable } from "@mcap/core"; import type { FileHandle } from "node:fs/promises"; /** * IReadable implementation for FileHandle. */ export class FileHandleReadable implements IReadable { #handle: FileHandle; #buffer = new ArrayBuffer(4096); constructor(handle: FileHandle) { this.#handle = handle; } async size(): Promise { return BigInt((await this.#handle.stat()).size); } async read(offset: bigint, length: bigint): Promise { if (offset > Number.MAX_SAFE_INTEGER || length > Number.MAX_SAFE_INTEGER) { throw new Error(`Read too large: offset ${offset}, length ${length}`); } if (length > this.#buffer.byteLength) { this.#buffer = new ArrayBuffer(Number(length * 2n)); } const result = await this.#handle.read({ buffer: new DataView(this.#buffer, 0, Number(length)), position: Number(offset), }); if (result.bytesRead !== Number(length)) { throw new Error( `Read only ${result.bytesRead} bytes from offset ${offset}, expected ${length}`, ); } return new Uint8Array(result.buffer.buffer, result.buffer.byteOffset, result.bytesRead); } }