{"version":3,"sources":["../src/olefile.ts","../src/utils.ts"],"sourcesContent":["/**\n * Minimal OLE2 / Microsoft Compound File Binary (CFB) reader.\n *\n * Direct TypeScript port of the read-only subset of `olefile.py` (Philippe\n * Lagadec) needed by msoffcrypto: header parsing, FAT/MiniFAT/DIFAT loading,\n * directory tree walking, and stream extraction. Encrypted OOXML containers,\n * and legacy XLS/DOC/PPT files, expose their data through this layer.\n *\n * Original Python: https://www.decalage.info/olefile (BSD-2-Clause-like)\n */\n\nimport { readU16LE, readU32LE, utf16leDecode } from \"./utils.js\";\n\nexport const MAGIC = new Uint8Array([\n  0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1,\n]);\n\nexport const MAXREGSECT = 0xfffffffa;\nexport const DIFSECT = 0xfffffffc;\nexport const FATSECT = 0xfffffffd;\nexport const ENDOFCHAIN = 0xfffffffe;\nexport const FREESECT = 0xffffffff;\n\nexport const NOSTREAM = 0xffffffff;\nexport const UNKNOWN_SIZE = 0x7fffffff;\n\nexport const STGTY_EMPTY = 0;\nexport const STGTY_STORAGE = 1;\nexport const STGTY_STREAM = 2;\nexport const STGTY_LOCKBYTES = 3;\nexport const STGTY_PROPERTY = 4;\nexport const STGTY_ROOT = 5;\n\nexport const MINIMAL_OLEFILE_SIZE = 1536;\n\nexport class OleFileError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"OleFileError\";\n  }\n}\n\nexport class NotOleFileError extends OleFileError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"NotOleFileError\";\n  }\n}\n\n/**\n * Test if `data` looks like an OLE2 compound file by checking the magic bytes\n * at the start. Mirrors `olefile.isOleFile`.\n */\nexport function isOleFile(data: Uint8Array): boolean {\n  if (data.length < MAGIC.length) return false;\n  for (let i = 0; i < MAGIC.length; i++) {\n    if (data[i] !== MAGIC[i]) return false;\n  }\n  return true;\n}\n\n/**\n * Directory entry as parsed from the 128-byte directory record.\n * Field names match the AAF/MS-CFB specification.\n */\nexport interface OleDirectoryEntry {\n  sid: number;\n  name: string;\n  entryType: number;\n  color: number;\n  sidLeft: number;\n  sidRight: number;\n  sidChild: number;\n  clsid: string;\n  stateBits: number;\n  createTime: bigint;\n  modifyTime: bigint;\n  isectStart: number;\n  size: number;\n  isMinifat: boolean;\n  kids: OleDirectoryEntry[];\n  used: boolean;\n}\n\n/**\n * Read-only view of a single OLE stream. Returns the materialized bytes once;\n * the .py implementation eagerly assembles the sector chain into a BytesIO,\n * and we mirror that.\n */\nexport class OleStream {\n  private _buf: Uint8Array;\n  private _pos = 0;\n\n  constructor(buf: Uint8Array) {\n    this._buf = buf;\n  }\n\n  get size(): number {\n    return this._buf.length;\n  }\n\n  tell(): number {\n    return this._pos;\n  }\n\n  seek(offset: number, whence: 0 | 1 | 2 = 0): number {\n    if (whence === 0) this._pos = offset;\n    else if (whence === 1) this._pos += offset;\n    else this._pos = this._buf.length + offset;\n    if (this._pos < 0) this._pos = 0;\n    return this._pos;\n  }\n\n  read(size?: number): Uint8Array {\n    const remaining = this._buf.length - this._pos;\n    const n = size === undefined ? remaining : Math.min(size, remaining);\n    const out = this._buf.subarray(this._pos, this._pos + n);\n    this._pos += n;\n    return out;\n  }\n\n  /** Whole stream contents (does not move position). */\n  getValue(): Uint8Array {\n    return this._buf;\n  }\n}\n\ntype ParsedDirEntry = OleDirectoryEntry;\n\n/**\n * Read-only OLE/CFB compound file accessor.\n *\n * Constructed from a raw `Uint8Array`. After construction, use `openstream`\n * to read named streams or `listdir` to enumerate them.\n */\nexport class OleFileIO {\n  // Header values\n  private dllVersion = 0;\n  private byteOrder = 0;\n  private sectorShift = 0;\n  private miniSectorShift = 0;\n  private firstDirSector = 0;\n  private miniStreamCutoffSize = 0;\n  private firstMiniFatSector = 0;\n  private numMiniFatSectors = 0;\n  private firstDifatSector = 0;\n  private numDifatSectors = 0;\n\n  private sectorSize = 0;\n  private miniSectorSize = 0;\n  private nbSect = 0;\n  private filesize = 0;\n\n  private fp: Uint8Array;\n  private fat: number[] = [];\n  private minifat: number[] | null = null;\n  private ministream: Uint8Array | null = null;\n  private writable = false;\n\n  private direntries: ParsedDirEntry[] = [];\n  public root!: ParsedDirEntry;\n\n  constructor(input: Uint8Array | ArrayBuffer) {\n    const buf = input instanceof ArrayBuffer ? new Uint8Array(input) : input;\n    this.fp = buf;\n    this.filesize = buf.length;\n    this.parseHeader();\n    this.loadFat();\n    this.loadDirectory();\n  }\n\n  /**\n   * Return the underlying file bytes. After `writeStream` calls, this reflects\n   * the modified container.\n   */\n  getBuffer(): Uint8Array {\n    return this.fp;\n  }\n\n  /**\n   * Make sure `this.fp` is a private writable copy. Called before any\n   * `writeStream` mutation.\n   */\n  private ensureWritable(): void {\n    if (this.writable) return;\n    const copy = new Uint8Array(this.fp.length);\n    copy.set(this.fp, 0);\n    this.fp = copy;\n    this.writable = true;\n  }\n\n  // ---- Header parsing ----\n\n  private parseHeader(): void {\n    if (this.filesize < MINIMAL_OLEFILE_SIZE) {\n      throw new NotOleFileError(\"File too small to be an OLE file\");\n    }\n    const header = this.fp.subarray(0, 512);\n    for (let i = 0; i < MAGIC.length; i++) {\n      if (header[i] !== MAGIC[i]) {\n        throw new NotOleFileError(\"Not an OLE2 structured storage file\");\n      }\n    }\n\n    this.dllVersion = readU16LE(header, 0x1a);\n    this.byteOrder = readU16LE(header, 0x1c);\n    this.sectorShift = readU16LE(header, 0x1e);\n    this.miniSectorShift = readU16LE(header, 0x20);\n    // 0x22..0x27: reserved (6 bytes)\n    // 0x28: numDirSectors (only used for 4K sector files; we don't validate)\n    // 0x2c: numFatSectors (validation only — DIFAT walk handles overflow)\n    this.firstDirSector = readU32LE(header, 0x30);\n    // 0x34: transactionSignatureNumber\n    this.miniStreamCutoffSize = readU32LE(header, 0x38);\n    this.firstMiniFatSector = readU32LE(header, 0x3c);\n    this.numMiniFatSectors = readU32LE(header, 0x40);\n    this.firstDifatSector = readU32LE(header, 0x44);\n    this.numDifatSectors = readU32LE(header, 0x48);\n\n    if (this.byteOrder !== 0xfffe) {\n      throw new OleFileError(\"Unsupported byte order in OLE header\");\n    }\n    if (this.dllVersion !== 3 && this.dllVersion !== 4) {\n      throw new OleFileError(\"Unsupported DLL version in OLE header\");\n    }\n    this.sectorSize = 1 << this.sectorShift;\n    this.miniSectorSize = 1 << this.miniSectorShift;\n    if (this.sectorSize !== 512 && this.sectorSize !== 4096) {\n      throw new OleFileError(\n        `Unsupported sector size: ${this.sectorSize}`,\n      );\n    }\n    if (this.miniSectorSize !== 64) {\n      throw new OleFileError(\n        `Unsupported mini sector size: ${this.miniSectorSize}`,\n      );\n    }\n    this.nbSect =\n      Math.floor((this.filesize + this.sectorSize - 1) / this.sectorSize) - 1;\n  }\n\n  // ---- Sector access ----\n\n  /** Read a full sector by index (from the file allocation space). */\n  private getSect(sect: number): Uint8Array {\n    const off = this.sectorSize * (sect + 1);\n    if (off + this.sectorSize > this.fp.length) {\n      // Some OLE files terminate without a fully padded final sector. Return\n      // whatever bytes remain (the caller already trims to declared size).\n      return this.fp.subarray(off, this.fp.length);\n    }\n    return this.fp.subarray(off, off + this.sectorSize);\n  }\n\n  // ---- FAT / DIFAT loading ----\n\n  private sectorToU32Array(sect: Uint8Array): number[] {\n    const n = sect.length >> 2;\n    const out = new Array<number>(n);\n    for (let i = 0; i < n; i++) {\n      out[i] = readU32LE(sect, i * 4);\n    }\n    return out;\n  }\n\n  /**\n   * Walk through one DIFAT-style array of FAT sector pointers and append the\n   * referenced FAT sectors to `this.fat`.\n   */\n  private loadFatSect(values: number[]): number {\n    let isect = ENDOFCHAIN;\n    for (const raw of values) {\n      isect = raw >>> 0;\n      if (isect === ENDOFCHAIN || isect === FREESECT) break;\n      const sectorBytes = this.getSect(isect);\n      const next = this.sectorToU32Array(sectorBytes);\n      for (const v of next) this.fat.push(v >>> 0);\n    }\n    return isect;\n  }\n\n  private loadFat(): void {\n    // The first 109 FAT sector pointers live in the header itself,\n    // starting at offset 0x4C (76).\n    const headerSlice = this.fp.subarray(76, 512);\n    const headerFatRefs = this.sectorToU32Array(headerSlice);\n    this.loadFatSect(headerFatRefs);\n\n    if (this.numDifatSectors !== 0) {\n      const slotsPerSector = (this.sectorSize >> 2) - 1;\n      let isect = this.firstDifatSector >>> 0;\n      for (let i = 0; i < this.numDifatSectors; i++) {\n        const sectorBytes = this.getSect(isect);\n        const difat = this.sectorToU32Array(sectorBytes);\n        this.loadFatSect(difat.slice(0, slotsPerSector));\n        isect = difat[slotsPerSector] >>> 0;\n        if (isect === ENDOFCHAIN || isect === FREESECT) break;\n      }\n    }\n\n    if (this.fat.length > this.nbSect) {\n      this.fat.length = this.nbSect;\n    }\n  }\n\n  private loadMinifat(): void {\n    if (this.minifat !== null) return;\n    const streamSize = this.numMiniFatSectors * this.sectorSize;\n    const data = this.openByChain(\n      this.firstMiniFatSector,\n      streamSize,\n      /*forceFat=*/ true,\n    );\n    const arr = this.sectorToU32Array(data);\n    const nbMinisectors = Math.floor(\n      (this.root.size + this.miniSectorSize - 1) / this.miniSectorSize,\n    );\n    this.minifat = arr.slice(0, nbMinisectors).map((v) => v >>> 0);\n  }\n\n  private getMinistream(): Uint8Array {\n    if (this.ministream !== null) return this.ministream;\n    this.ministream = this.openByChain(\n      this.root.isectStart,\n      this.root.size,\n      /*forceFat=*/ true,\n    );\n    return this.ministream;\n  }\n\n  /**\n   * Read a full sector chain and return the joined bytes (truncated to size,\n   * if known). This is the workhorse used by both stream loading and FAT\n   * sub-stream extraction.\n   */\n  private openByChain(\n    start: number,\n    size: number,\n    forceFat: boolean,\n  ): Uint8Array {\n    const useMinifat = !forceFat && size < this.miniStreamCutoffSize;\n    let sectorSize: number;\n    let fat: number[];\n    let storage: Uint8Array;\n    let offset: number;\n\n    if (useMinifat) {\n      this.loadMinifat();\n      const ministream = this.getMinistream();\n      sectorSize = this.miniSectorSize;\n      fat = this.minifat!;\n      storage = ministream;\n      offset = 0;\n    } else {\n      sectorSize = this.sectorSize;\n      fat = this.fat;\n      storage = this.fp;\n      offset = this.sectorSize; // FAT sectors are 1-indexed relative to file start\n    }\n\n    let unknownSize = false;\n    if (size === UNKNOWN_SIZE) {\n      size = fat.length * sectorSize;\n      unknownSize = true;\n    }\n\n    const nbSectors = Math.floor((size + (sectorSize - 1)) / sectorSize);\n    const parts: Uint8Array[] = [];\n    let sect = start >>> 0;\n\n    for (let i = 0; i < nbSectors; i++) {\n      if (sect === ENDOFCHAIN) {\n        if (unknownSize) break;\n        throw new OleFileError(\"Incomplete OLE stream (early ENDOFCHAIN)\");\n      }\n      if (sect >= fat.length) {\n        throw new OleFileError(\n          `Incorrect OLE FAT sector index ${sect.toString(16)}`,\n        );\n      }\n      const sliceStart = offset + sectorSize * sect;\n      const sliceEnd = Math.min(sliceStart + sectorSize, storage.length);\n      parts.push(storage.subarray(sliceStart, sliceEnd));\n      sect = fat[sect] >>> 0;\n    }\n\n    let total = 0;\n    for (const p of parts) total += p.length;\n    const joined = new Uint8Array(total);\n    {\n      let off = 0;\n      for (const p of parts) {\n        joined.set(p, off);\n        off += p.length;\n      }\n    }\n    if (joined.length >= size) return joined.subarray(0, size);\n    return joined;\n  }\n\n  // ---- Directory parsing ----\n\n  private parseDirEntry(buf: Uint8Array, sid: number): ParsedDirEntry {\n    // 64s name_raw + H namelength + B type + B color + I left + I right + I child\n    // + 16s clsid + I stateBits + Q createTime + Q modifyTime + I isectStart\n    // + I sizeLow + I sizeHigh\n    const nameRaw = buf.subarray(0, 64);\n    const nameLength = readU16LE(buf, 64);\n    const entryType = buf[66];\n    const color = buf[67];\n    const sidLeft = readU32LE(buf, 68);\n    const sidRight = readU32LE(buf, 72);\n    const sidChild = readU32LE(buf, 76);\n\n    const clsidBytes = buf.subarray(80, 96);\n    const stateBits = readU32LE(buf, 96);\n    const createTime = bytesToBigUint64LE(buf, 100);\n    const modifyTime = bytesToBigUint64LE(buf, 108);\n    const isectStart = readU32LE(buf, 116);\n    const sizeLow = readU32LE(buf, 120);\n    const sizeHigh = readU32LE(buf, 124);\n\n    const safeNameLen = Math.max(0, Math.min(nameLength, 64) - 2);\n    const name = utf16leDecode(nameRaw.subarray(0, safeNameLen));\n\n    let size: number;\n    if (this.sectorSize === 512) {\n      size = sizeLow;\n    } else {\n      // Up to 2^53 — JS number is fine here, real-world streams aren't anywhere near that.\n      size = sizeLow + sizeHigh * 0x100000000;\n    }\n\n    const isMinifat =\n      entryType === STGTY_STREAM &&\n      size > 0 &&\n      size < this.miniStreamCutoffSize;\n\n    return {\n      sid,\n      name,\n      entryType,\n      color,\n      sidLeft,\n      sidRight,\n      sidChild,\n      clsid: formatClsid(clsidBytes),\n      stateBits,\n      createTime,\n      modifyTime,\n      isectStart,\n      size,\n      isMinifat,\n      kids: [],\n      used: false,\n    };\n  }\n\n  private loadDirectory(): void {\n    const dirData = this.openByChain(\n      this.firstDirSector,\n      UNKNOWN_SIZE,\n      /*forceFat=*/ true,\n    );\n    const maxEntries = Math.floor(dirData.length / 128);\n    this.direntries = new Array(maxEntries);\n\n    // Lazily fault entries in as the storage tree is walked.\n    const loadEntry = (sid: number): ParsedDirEntry => {\n      if (sid < 0 || sid >= maxEntries) {\n        throw new OleFileError(\n          `OLE directory index out of range: ${sid}`,\n        );\n      }\n      const cached = this.direntries[sid];\n      if (cached) return cached;\n      const entry = this.parseDirEntry(\n        dirData.subarray(sid * 128, (sid + 1) * 128),\n        sid,\n      );\n      this.direntries[sid] = entry;\n      return entry;\n    };\n\n    const root = loadEntry(0);\n    if (root.entryType !== STGTY_ROOT) {\n      throw new OleFileError(\"First directory entry is not the root entry\");\n    }\n    this.root = root;\n\n    // Walk the red-black tree in-order to collect children. Per the spec, the\n    // tree contains storage and stream entries; visit left, self, right and\n    // recurse into storages.\n    const appendKids = (parent: ParsedDirEntry, childSid: number): void => {\n      if (childSid === NOSTREAM) return;\n      const child = loadEntry(childSid);\n      if (child.used) {\n        throw new OleFileError(\"OLE entry referenced more than once\");\n      }\n      child.used = true;\n      appendKids(parent, child.sidLeft);\n      parent.kids.push(child);\n      appendKids(parent, child.sidRight);\n      if (child.sidChild !== NOSTREAM) {\n        appendKids(child, child.sidChild);\n        child.kids.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n      }\n    };\n\n    if (root.sidChild !== NOSTREAM) {\n      appendKids(root, root.sidChild);\n      root.kids.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n    }\n  }\n\n  // ---- Public API ----\n\n  /**\n   * Find a directory entry by case-insensitive path. Path may be a string with\n   * '/' separators or an array of names.\n   */\n  private find(filename: string | string[]): ParsedDirEntry {\n    const parts =\n      typeof filename === \"string\" ? filename.split(\"/\") : filename;\n    let node: ParsedDirEntry = this.root;\n    for (const name of parts) {\n      const lower = name.toLowerCase();\n      const next = node.kids.find((k) => k.name.toLowerCase() === lower);\n      if (!next) {\n        throw new OleFileError(`Stream not found: ${parts.join(\"/\")}`);\n      }\n      node = next;\n    }\n    return node;\n  }\n\n  /** Return true if the named stream/storage exists in the file. */\n  exists(filename: string | string[]): boolean {\n    try {\n      this.find(filename);\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  /** Get the size of a named stream. */\n  getSize(filename: string | string[]): number {\n    return this.find(filename).size;\n  }\n\n  /**\n   * Open a named stream and return a read-only `OleStream` that exposes\n   * `seek/tell/read`. Mirrors `olefile.openstream`.\n   */\n  openstream(filename: string | string[]): OleStream {\n    const entry = this.find(filename);\n    if (entry.entryType !== STGTY_STREAM) {\n      throw new OleFileError(`Not a stream: ${filename}`);\n    }\n    if (entry.size === 0) return new OleStream(new Uint8Array(0));\n    const data =\n      entry.isMinifat && entry.size < this.miniStreamCutoffSize\n        ? this.openByChain(entry.isectStart, entry.size, false)\n        : this.openByChain(entry.isectStart, entry.size, true);\n    return new OleStream(data);\n  }\n\n  /**\n   * Overwrite the contents of an existing stream with `data`. The new data\n   * MUST be exactly the same size as the original — this keeps the FAT chain\n   * untouched, which is all we need for the legacy decrypt-in-place flow.\n   *\n   * Handles both FAT and MiniFAT-allocated streams.\n   */\n  writeStream(filename: string | string[], data: Uint8Array): void {\n    const entry = this.find(filename);\n    if (entry.entryType !== STGTY_STREAM) {\n      throw new OleFileError(`Not a stream: ${filename}`);\n    }\n    if (data.length !== entry.size) {\n      throw new OleFileError(\n        `writeStream requires same-sized data (expected ${entry.size}, got ${data.length})`,\n      );\n    }\n    this.ensureWritable();\n\n    if (entry.isMinifat && entry.size < this.miniStreamCutoffSize) {\n      this.writeStreamMiniFat(entry, data);\n    } else {\n      this.writeStreamFat(entry, data);\n    }\n  }\n\n  /** Walk the FAT chain for a stream and overwrite each sector. */\n  private writeStreamFat(entry: OleDirectoryEntry, data: Uint8Array): void {\n    let sect = entry.isectStart >>> 0;\n    let off = 0;\n    const sectorSize = this.sectorSize;\n    while (off < data.length) {\n      if (sect === ENDOFCHAIN || sect >= this.fat.length) {\n        throw new OleFileError(\"FAT chain ended unexpectedly during write\");\n      }\n      const fileOffset = this.sectorSize + sect * sectorSize;\n      const remaining = data.length - off;\n      const chunk = data.subarray(off, off + Math.min(sectorSize, remaining));\n      this.fp.set(chunk, fileOffset);\n      off += chunk.length;\n      sect = this.fat[sect] >>> 0;\n    }\n  }\n\n  /**\n   * Mini-streams live inside the root entry's stream (which itself follows the\n   * regular FAT). Walk the MiniFAT chain to compute mini-sector positions, map\n   * those into FAT positions, and write.\n   */\n  private writeStreamMiniFat(\n    entry: OleDirectoryEntry,\n    data: Uint8Array,\n  ): void {\n    this.loadMinifat();\n    const minifat = this.minifat!;\n    const ministreamSize = this.root.size;\n\n    // The ministream itself is allocated on the FAT — collect its sectors.\n    const ministreamFatSectors: number[] = [];\n    let sect = this.root.isectStart >>> 0;\n    const fatSectorCount = Math.ceil(ministreamSize / this.sectorSize);\n    for (let i = 0; i < fatSectorCount; i++) {\n      if (sect === ENDOFCHAIN || sect >= this.fat.length) break;\n      ministreamFatSectors.push(sect);\n      sect = this.fat[sect] >>> 0;\n    }\n\n    // For each mini-sector, find its position inside the ministream, then map\n    // that to (fatSectorIndex, offsetInsideFatSector).\n    let miniSect = entry.isectStart >>> 0;\n    let off = 0;\n    while (off < data.length) {\n      if (miniSect === ENDOFCHAIN || miniSect >= minifat.length) {\n        throw new OleFileError(\"MiniFAT chain ended unexpectedly during write\");\n      }\n      const ministreamOffset = miniSect * this.miniSectorSize;\n      const fatSectorIdx = Math.floor(ministreamOffset / this.sectorSize);\n      const offsetInFatSector = ministreamOffset % this.sectorSize;\n      const fileOffset =\n        this.sectorSize +\n        ministreamFatSectors[fatSectorIdx] * this.sectorSize +\n        offsetInFatSector;\n      const remaining = data.length - off;\n      const chunk = data.subarray(\n        off,\n        off + Math.min(this.miniSectorSize, remaining),\n      );\n      this.fp.set(chunk, fileOffset);\n      off += chunk.length;\n      miniSect = minifat[miniSect] >>> 0;\n    }\n\n    // Invalidate the cached ministream so next reads pick up fresh data.\n    this.ministream = null;\n  }\n\n  /** List all stream paths in the file (depth-first walk). */\n  listdir(streams = true, storages = false): string[][] {\n    const out: string[][] = [];\n    const walk = (node: ParsedDirEntry, prefix: string[]) => {\n      for (const kid of node.kids) {\n        const path = [...prefix, kid.name];\n        if (kid.entryType === STGTY_STORAGE) {\n          if (storages) out.push(path);\n          walk(kid, path);\n        } else if (kid.entryType === STGTY_STREAM) {\n          if (streams) out.push(path);\n        }\n      }\n    };\n    walk(this.root, []);\n    return out;\n  }\n}\n\nfunction bytesToBigUint64LE(b: Uint8Array, o = 0): bigint {\n  const lo = BigInt(readU32LE(b, o));\n  const hi = BigInt(readU32LE(b, o + 4));\n  return (hi << 32n) | lo;\n}\n\nfunction formatClsid(b: Uint8Array): string {\n  let allZero = true;\n  for (const byte of b) if (byte !== 0) { allZero = false; break; }\n  if (allZero) return \"\";\n  const hex2 = (n: number) => n.toString(16).padStart(2, \"0\").toUpperCase();\n  const hex4 = (n: number) => n.toString(16).padStart(4, \"0\").toUpperCase();\n  const hex8 = (n: number) => n.toString(16).padStart(8, \"0\").toUpperCase();\n  const a = hex8(readU32LE(b, 0));\n  const c = hex4(readU16LE(b, 4));\n  const d = hex4(readU16LE(b, 6));\n  let tail = \"\";\n  for (let i = 8; i < 16; i++) tail += hex2(b[i]);\n  return `${a}-${c}-${d}-${tail.slice(0, 4)}-${tail.slice(4)}`;\n}\n","/**\n * Utility helpers: byte/struct manipulation, UTF-16 encoding, BytesIO equivalent.\n */\n\nexport function concatBytes(...parts: Uint8Array[]): Uint8Array {\n  let total = 0;\n  for (const p of parts) total += p.length;\n  const out = new Uint8Array(total);\n  let off = 0;\n  for (const p of parts) {\n    out.set(p, off);\n    off += p.length;\n  }\n  return out;\n}\n\nexport function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n  if (a.length !== b.length) return false;\n  let diff = 0;\n  for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];\n  return diff === 0;\n}\n\nexport function utf16leEncode(s: string): Uint8Array {\n  const out = new Uint8Array(s.length * 2);\n  for (let i = 0; i < s.length; i++) {\n    const c = s.charCodeAt(i);\n    out[i * 2] = c & 0xff;\n    out[i * 2 + 1] = (c >>> 8) & 0xff;\n  }\n  return out;\n}\n\nexport function utf16leDecode(b: Uint8Array): string {\n  let s = \"\";\n  for (let i = 0; i + 1 < b.length; i += 2) {\n    const c = b[i] | (b[i + 1] << 8);\n    s += String.fromCharCode(c);\n  }\n  return s;\n}\n\nexport function utf8Encode(s: string): Uint8Array {\n  return new TextEncoder().encode(s);\n}\n\nexport function utf8Decode(b: Uint8Array): string {\n  return new TextDecoder().decode(b);\n}\n\nexport function hexToBytes(hex: string): Uint8Array {\n  const clean = hex.replace(/[^0-9a-fA-F]/g, \"\");\n  const out = new Uint8Array(clean.length / 2);\n  for (let i = 0; i < out.length; i++) {\n    out[i] = parseInt(clean.substr(i * 2, 2), 16);\n  }\n  return out;\n}\n\nexport function bytesToHex(b: Uint8Array): string {\n  let s = \"\";\n  for (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, \"0\");\n  return s;\n}\n\nconst B64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nexport function base64Encode(b: Uint8Array): string {\n  // Use globalThis.btoa if available, else manual encode.\n  let s = \"\";\n  for (let i = 0; i < b.length; i += 3) {\n    const a = b[i];\n    const c = i + 1 < b.length ? b[i + 1] : 0;\n    const d = i + 2 < b.length ? b[i + 2] : 0;\n    const n = (a << 16) | (c << 8) | d;\n    s +=\n      B64_CHARS[(n >> 18) & 63] +\n      B64_CHARS[(n >> 12) & 63] +\n      (i + 1 < b.length ? B64_CHARS[(n >> 6) & 63] : \"=\") +\n      (i + 2 < b.length ? B64_CHARS[n & 63] : \"=\");\n  }\n  return s;\n}\n\nexport function base64Decode(s: string): Uint8Array {\n  const clean = s.replace(/\\s+/g, \"\");\n  const raw = clean.replace(/=+$/, \"\");\n  // Output length: every 4 input chars become 3 bytes, plus partial groups\n  // (2 chars → 1 byte, 3 chars → 2 bytes).\n  const fullGroups = Math.floor(raw.length / 4);\n  const remainder = raw.length % 4;\n  const outLen =\n    fullGroups * 3 + (remainder === 2 ? 1 : remainder === 3 ? 2 : 0);\n  const out = new Uint8Array(outLen);\n  let oi = 0;\n  for (let i = 0; i < raw.length; i += 4) {\n    const a = B64_CHARS.indexOf(raw[i]);\n    const b = B64_CHARS.indexOf(raw[i + 1]);\n    const c = i + 2 < raw.length ? B64_CHARS.indexOf(raw[i + 2]) : 0;\n    const d = i + 3 < raw.length ? B64_CHARS.indexOf(raw[i + 3]) : 0;\n    const n = (a << 18) | (b << 12) | (c << 6) | d;\n    out[oi++] = (n >> 16) & 0xff;\n    if (i + 2 < raw.length) out[oi++] = (n >> 8) & 0xff;\n    if (i + 3 < raw.length) out[oi++] = n & 0xff;\n  }\n  return out;\n}\n\n/**\n * Pack 32-bit unsigned little-endian.\n */\nexport function packU32LE(n: number): Uint8Array {\n  const b = new Uint8Array(4);\n  b[0] = n & 0xff;\n  b[1] = (n >>> 8) & 0xff;\n  b[2] = (n >>> 16) & 0xff;\n  b[3] = (n >>> 24) & 0xff;\n  return b;\n}\n\nexport function packU16LE(n: number): Uint8Array {\n  const b = new Uint8Array(2);\n  b[0] = n & 0xff;\n  b[1] = (n >>> 8) & 0xff;\n  return b;\n}\n\nexport function packU64LE(n: bigint | number): Uint8Array {\n  const v = typeof n === \"bigint\" ? n : BigInt(n);\n  const b = new Uint8Array(8);\n  const lo = Number(v & 0xffffffffn);\n  const hi = Number((v >> 32n) & 0xffffffffn);\n  b[0] = lo & 0xff;\n  b[1] = (lo >>> 8) & 0xff;\n  b[2] = (lo >>> 16) & 0xff;\n  b[3] = (lo >>> 24) & 0xff;\n  b[4] = hi & 0xff;\n  b[5] = (hi >>> 8) & 0xff;\n  b[6] = (hi >>> 16) & 0xff;\n  b[7] = (hi >>> 24) & 0xff;\n  return b;\n}\n\n/**\n * Read helpers (little-endian).\n */\nexport function readU16LE(b: Uint8Array, o = 0): number {\n  return b[o] | (b[o + 1] << 8);\n}\nexport function readU32LE(b: Uint8Array, o = 0): number {\n  return (\n    (b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24)) >>> 0\n  );\n}\nexport function readU64LE(b: Uint8Array, o = 0): bigint {\n  const lo = BigInt(readU32LE(b, o));\n  const hi = BigInt(readU32LE(b, o + 4));\n  return (hi << 32n) | lo;\n}\nexport function readI32LE(b: Uint8Array, o = 0): number {\n  return b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24);\n}\n\n/**\n * Minimal stream-reader interface — both `BytesIO` and the read-only\n * `OleStream` satisfy this. Used by the `read{U16,U32,U64}` stream helpers\n * below so callers don't have to write `readU32LE(s.read(4), 0)` everywhere.\n */\nexport interface Readable {\n  read(size?: number): Uint8Array;\n}\n\nexport function readU16(s: Readable): number {\n  return readU16LE(s.read(2), 0);\n}\nexport function readU32(s: Readable): number {\n  return readU32LE(s.read(4), 0);\n}\nexport function readU64(s: Readable): bigint {\n  return readU64LE(s.read(8), 0);\n}\n\n/**\n * Append-style bytes builder. Replaces the `parts.push(packU32LE(...))` +\n * concat dance used by the various `pack*` helpers in the format/ folder.\n */\nexport class ByteWriter {\n  private chunks: Uint8Array[] = [];\n  private len = 0;\n\n  bytes(b: Uint8Array): this {\n    this.chunks.push(b);\n    this.len += b.length;\n    return this;\n  }\n  u8(v: number): this {\n    this.chunks.push(new Uint8Array([v & 0xff]));\n    this.len += 1;\n    return this;\n  }\n  u16(v: number): this {\n    return this.bytes(packU16LE(v));\n  }\n  u32(v: number): this {\n    return this.bytes(packU32LE(v >>> 0));\n  }\n  u64(v: bigint | number): this {\n    return this.bytes(packU64LE(v));\n  }\n  zeros(n: number): this {\n    return this.bytes(new Uint8Array(n));\n  }\n\n  get length(): number {\n    return this.len;\n  }\n\n  build(): Uint8Array {\n    const out = new Uint8Array(this.len);\n    let off = 0;\n    for (const c of this.chunks) {\n      out.set(c, off);\n      off += c.length;\n    }\n    return out;\n  }\n}\n\n/**\n * Bit-field helpers for the legacy formats (FibBase, RecordHeader, etc.).\n */\nexport function getBit(bits: number, i: number): number {\n  return (bits >>> i) & 1;\n}\nexport function getBitSlice(bits: number, i: number, w: number): number {\n  return (bits >>> i) & ((1 << w) - 1);\n}\nexport function setBit(bits: number, i: number, v: number): number {\n  return v ? bits | (1 << i) : bits & ~(1 << i);\n}\nexport function setBitSlice(\n  bits: number,\n  i: number,\n  w: number,\n  v: number,\n): number {\n  const mask = ((1 << w) - 1) << i;\n  return (bits & ~mask) | ((v & ((1 << w) - 1)) << i);\n}\n\n/**\n * Stream-like wrapper around a Uint8Array providing seek/tell/read.\n * Mirrors `io.BytesIO` semantics enough for the rest of the library.\n */\nexport class BytesIO {\n  private _buf: Uint8Array;\n  private _pos = 0;\n\n  constructor(initial?: Uint8Array | ArrayBuffer | number) {\n    if (initial === undefined) {\n      this._buf = new Uint8Array(0);\n    } else if (typeof initial === \"number\") {\n      this._buf = new Uint8Array(initial);\n    } else if (initial instanceof ArrayBuffer) {\n      this._buf = new Uint8Array(initial);\n    } else {\n      this._buf = initial;\n    }\n  }\n\n  get length(): number {\n    return this._buf.length;\n  }\n\n  tell(): number {\n    return this._pos;\n  }\n\n  seek(offset: number, whence: 0 | 1 | 2 = 0): number {\n    if (whence === 0) this._pos = offset;\n    else if (whence === 1) this._pos += offset;\n    else this._pos = this._buf.length + offset;\n    if (this._pos < 0) this._pos = 0;\n    return this._pos;\n  }\n\n  read(size?: number): Uint8Array {\n    const remaining = this._buf.length - this._pos;\n    const n = size === undefined ? remaining : Math.min(size, remaining);\n    const out = this._buf.subarray(this._pos, this._pos + n);\n    this._pos += n;\n    return out;\n  }\n\n  /** Returns the entire underlying buffer (does not move position). */\n  getValue(): Uint8Array {\n    return this._buf;\n  }\n\n  /**\n   * Writes data at the current position, growing the buffer if needed.\n   */\n  write(data: Uint8Array): number {\n    const needed = this._pos + data.length;\n    if (needed > this._buf.length) {\n      const next = new Uint8Array(needed);\n      next.set(this._buf, 0);\n      this._buf = next;\n    }\n    this._buf.set(data, this._pos);\n    this._pos += data.length;\n    return data.length;\n  }\n}\n\n/**\n * Coerce input (Uint8Array | ArrayBuffer | BytesIO) into BytesIO.\n */\nexport function toBytesIO(\n  src: Uint8Array | ArrayBuffer | BytesIO,\n): BytesIO {\n  if (src instanceof BytesIO) return src;\n  return new BytesIO(src);\n}\n"],"mappings":"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","names":[]}