{"version":3,"sources":["../src/binary-reader.ts","../src/puz.ts"],"names":[],"mappings":"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","file":"chunk-YDXBFJGM.mjs","sourcesContent":["/**\n * Generic binary reader for parsing binary file formats\n */\n\nimport { BinaryParseError } from './errors';\n\n/**\n * A utility class for reading binary data from buffers with automatic offset tracking.\n */\nexport class BinaryReader {\n  private _buffer: Buffer;\n  private _offset: number;\n\n  constructor(data: Buffer | ArrayBuffer | Uint8Array) {\n    if (data instanceof ArrayBuffer) {\n      this._buffer = Buffer.from(data);\n    } else if (data instanceof Uint8Array) {\n      this._buffer = Buffer.from(data);\n    } else {\n      this._buffer = data;\n    }\n    this._offset = 0;\n  }\n\n  /**\n   * Read an unsigned 8-bit integer and advance the offset\n   */\n  readUInt8(): number {\n    if (this._offset + 1 > this._buffer.length) {\n      throw new BinaryParseError(\n        `Cannot read byte at offset ${this._offset}: buffer too short (length: ${this._buffer.length})`,\n      );\n    }\n    const value = this._buffer.readUInt8(this._offset);\n    this._offset += 1;\n    return value;\n  }\n\n  /**\n   * Read an unsigned 16-bit integer (little-endian) and advance the offset\n   */\n  readUInt16LE(): number {\n    if (this._offset + 2 > this._buffer.length) {\n      throw new BinaryParseError(\n        `Cannot read 16-bit value at offset ${this._offset}: buffer too short (length: ${this._buffer.length})`,\n      );\n    }\n    const value = this._buffer.readUInt16LE(this._offset);\n    this._offset += 2;\n    return value;\n  }\n\n  /**\n   * Read a specified number of bytes and advance the offset\n   */\n  readBytes(length: number): Buffer {\n    if (this._offset + length > this._buffer.length) {\n      throw new BinaryParseError(\n        `Cannot read ${length} bytes at offset ${this._offset}: buffer too short (length: ${this._buffer.length})`,\n      );\n    }\n    const value = this._buffer.slice(this._offset, this._offset + length);\n    this._offset += length;\n    return value;\n  }\n\n  /**\n   * Read a string of specified length with optional null trimming\n   * @param length Number of bytes to read\n   * @param trimNull Whether to trim at first null byte (default: true)\n   * @param encoding Character encoding (default: 'latin1')\n   */\n  readString(\n    length: number,\n    trimNull: boolean = true,\n    encoding: BufferEncoding = 'latin1',\n  ): string {\n    const bytes = this.readBytes(length);\n    if (trimNull) {\n      // Remove trailing nulls\n      let end = bytes.indexOf(0);\n      if (end === -1) end = length;\n      return bytes.toString(encoding, 0, end);\n    }\n    return bytes.toString(encoding);\n  }\n\n  /**\n   * Read a null-terminated string and advance past the null terminator\n   * @param encoding Character encoding (default: 'latin1')\n   */\n  readNullTerminatedString(encoding: BufferEncoding = 'latin1'): string {\n    const start = this._offset;\n    while (this._offset < this._buffer.length && this._buffer[this._offset] !== 0) {\n      this._offset++;\n    }\n    if (this._offset >= this._buffer.length) {\n      throw new BinaryParseError(\n        `Cannot read null-terminated string at offset ${start}: buffer ended without null terminator`,\n      );\n    }\n    const str = this._buffer.toString(encoding, start, this._offset);\n    this._offset++; // Skip null terminator\n    return str;\n  }\n\n  /**\n   * Move the read position to a specific offset\n   */\n  seek(position: number): void {\n    if (position < 0 || position > this._buffer.length) {\n      throw new BinaryParseError(\n        `Cannot seek to position ${position}: out of bounds (buffer length: ${this._buffer.length})`,\n      );\n    }\n    this._offset = position;\n  }\n\n  /**\n   * Get the current read position\n   */\n  get position(): number {\n    return this._offset;\n  }\n\n  /**\n   * Get the total length of the buffer\n   */\n  get length(): number {\n    return this._buffer.length;\n  }\n\n  /**\n   * Get the underlying buffer\n   */\n  get buffer(): Buffer {\n    return this._buffer;\n  }\n\n  /**\n   * Check if there's more data to read\n   */\n  hasMore(): boolean {\n    return this._offset < this._buffer.length;\n  }\n\n  /**\n   * Get the number of bytes remaining to read\n   */\n  get remaining(): number {\n    return this._buffer.length - this._offset;\n  }\n}\n","/**\n * Parser for PUZ crossword format (Across Lite)\n * Based on reverse-engineered specification\n */\n\nimport { InvalidFileError, PuzParseError, BinaryParseError } from './errors';\nimport { ErrorCode } from './types';\nimport type { Puzzle, Grid, Cell as UnifiedCell, Clues, ParseOptions } from './types';\nimport { BinaryReader } from './binary-reader';\nimport {\n  MAX_GRID_WIDTH,\n  MAX_GRID_HEIGHT,\n  PUZ_MAGIC_STRING,\n  PUZ_HEADER_SIZE,\n  PUZ_SECTION_GRBS,\n  PUZ_SECTION_RTBL,\n  PUZ_SECTION_GEXT,\n  PUZ_SECTION_LTIM,\n  PUZ_CIRCLED_CELL_FLAG,\n} from './constants';\n\nexport interface PuzMetadata {\n  title?: string;\n  author?: string;\n  copyright?: string;\n  notes?: string;\n}\n\nexport interface PuzClue {\n  number: number;\n  text: string;\n}\n\nexport interface PuzCell {\n  solution?: string;\n  playerState?: string;\n  isBlack: boolean;\n  isCircled?: boolean;\n  hasRebus?: boolean;\n  rebusKey?: number;\n}\n\nexport interface PuzPuzzle {\n  width: number;\n  height: number;\n  metadata: PuzMetadata;\n  grid: PuzCell[][];\n  across: PuzClue[];\n  down: PuzClue[];\n  rebusTable?: Map<number, string>;\n  isScrambled?: boolean;\n  timer?: {\n    elapsed: number;\n    running: boolean;\n  };\n}\n\n// PUZ file header structure\ninterface PuzHeader {\n  checksum: number;\n  magic: string;\n  cibChecksum: number;\n  maskedLowChecksum: number;\n  maskedHighChecksum: number;\n  version: string;\n  reserved1: number;\n  scrambledChecksum: number;\n  reserved2: Buffer;\n  width: number;\n  height: number;\n  numClues: number;\n  puzzleType: number;\n  scrambledTag: number;\n}\n\nfunction readHeader(reader: BinaryReader): PuzHeader {\n  // Search for the magic string \"ACROSS&DOWN\" in the file\n  const magicBytes = Buffer.from(PUZ_MAGIC_STRING, 'latin1');\n  let magicOffset = -1;\n\n  // Search for the magic string in the buffer\n  for (let i = 0; i <= reader.length - magicBytes.length; i++) {\n    let found = true;\n    for (let j = 0; j < magicBytes.length; j++) {\n      if (reader.buffer[i + j] !== magicBytes[j]) {\n        found = false;\n        break;\n      }\n    }\n    if (found) {\n      magicOffset = i;\n      break;\n    }\n  }\n\n  if (magicOffset === -1) {\n    throw new PuzParseError(\n      `Invalid PUZ file: magic string \"${PUZ_MAGIC_STRING}\" not found`,\n      ErrorCode.PUZ_INVALID_HEADER,\n    );\n  }\n\n  // Position reader at the start of the actual PUZ data (2 bytes before magic string)\n  const headerStart = magicOffset - 2;\n  if (headerStart < 0) {\n    throw new PuzParseError(\n      'Invalid PUZ file: magic string found too early in file',\n      ErrorCode.PUZ_INVALID_HEADER,\n    );\n  }\n\n  // Ensure there's enough data for the full header\n  if (headerStart + PUZ_HEADER_SIZE > reader.length) {\n    throw new PuzParseError(\n      'Invalid PUZ file: insufficient data for header',\n      ErrorCode.PUZ_INVALID_HEADER,\n    );\n  }\n\n  reader.seek(headerStart);\n\n  // Read header fields according to PUZ specification\n  const checksum = reader.readUInt16LE(); // 0x00-0x01\n  const magic = reader.readString(12, true, 'latin1'); // 0x02-0x0D\n  const cibChecksum = reader.readUInt16LE(); // 0x0E-0x0F\n  const maskedLowChecksum = reader.readUInt16LE(); // 0x10-0x11\n  const maskedHighChecksum = reader.readUInt16LE(); // 0x12-0x13\n  const version = reader.readString(4, true, 'latin1'); // 0x14-0x17\n  const reserved1 = reader.readUInt16LE(); // 0x18-0x19\n  const scrambledChecksum = reader.readUInt16LE(); // 0x1A-0x1B\n  const reserved2 = reader.readBytes(12); // 0x1C-0x27\n  reader.readBytes(4); // 0x28-0x2B (skip unknown bytes)\n  const width = reader.readUInt8(); // 0x2C\n  const height = reader.readUInt8(); // 0x2D\n  const numClues = reader.readUInt16LE(); // 0x2E-0x2F\n  const puzzleType = reader.readUInt16LE(); // 0x30-0x31\n  const scrambledTag = reader.readUInt16LE(); // 0x32-0x33\n\n  const header: PuzHeader = {\n    checksum,\n    magic,\n    cibChecksum,\n    maskedLowChecksum,\n    maskedHighChecksum,\n    version,\n    reserved1,\n    scrambledChecksum,\n    reserved2,\n    width,\n    height,\n    numClues,\n    puzzleType,\n    scrambledTag,\n  };\n\n  // Verify we read the magic string correctly\n  if (header.magic !== PUZ_MAGIC_STRING) {\n    throw new InvalidFileError(\n      'PUZ',\n      `magic string mismatch after positioning. Expected \"${PUZ_MAGIC_STRING}\", got \"${header.magic}\"`,\n    );\n  }\n\n  return header;\n}\n\nfunction parseGrid(\n  solution: string,\n  playerState: string,\n  width: number,\n  height: number,\n): PuzCell[][] {\n  const grid: PuzCell[][] = [];\n\n  for (let row = 0; row < height; row++) {\n    const cells: PuzCell[] = [];\n    for (let col = 0; col < width; col++) {\n      const index = row * width + col;\n      const solutionChar = solution[index];\n      const playerChar = playerState[index];\n\n      cells.push({\n        solution: solutionChar === '.' ? undefined : solutionChar,\n        playerState: playerChar === '-' || playerChar === '.' ? undefined : playerChar,\n        isBlack: solutionChar === '.',\n      });\n    }\n    grid.push(cells);\n  }\n\n  return grid;\n}\n\nfunction assignClueNumbers(grid: PuzCell[][]): Map<string, number> {\n  const cluePositions = new Map<string, number>();\n  let clueNumber = 1;\n  const height = grid.length;\n  const width = grid[0]?.length || 0;\n\n  for (let row = 0; row < height; row++) {\n    for (let col = 0; col < width; col++) {\n      if (grid[row]?.[col]?.isBlack) continue;\n\n      const hasAcross =\n        (col === 0 || grid[row]?.[col - 1]?.isBlack) &&\n        col < width - 1 &&\n        !grid[row]?.[col + 1]?.isBlack;\n\n      const hasDown =\n        (row === 0 || grid[row - 1]?.[col]?.isBlack) &&\n        row < height - 1 &&\n        !grid[row + 1]?.[col]?.isBlack;\n\n      if (hasAcross || hasDown) {\n        if (hasAcross) {\n          cluePositions.set(`A${row},${col}`, clueNumber);\n        }\n        if (hasDown) {\n          cluePositions.set(`D${row},${col}`, clueNumber);\n        }\n        clueNumber++;\n      }\n    }\n  }\n\n  return cluePositions;\n}\n\nfunction parseClues(\n  clueStrings: string[],\n  cluePositions: Map<string, number>,\n): { across: PuzClue[]; down: PuzClue[] } {\n  const across: PuzClue[] = [];\n  const down: PuzClue[] = [];\n  let clueIndex = 0;\n\n  // Sort positions to ensure correct clue assignment\n  const sortedPositions = Array.from(cluePositions.entries()).sort((a, b) => {\n    const [aType, aPos] = a[0].split(',');\n    const [bType, bPos] = b[0].split(',');\n    const aRow = parseInt(aType?.substring(1) || '0');\n    const bRow = parseInt(bType?.substring(1) || '0');\n    const aCol = parseInt(aPos || '0');\n    const bCol = parseInt(bPos || '0');\n\n    if (aRow !== bRow) return aRow - bRow;\n    return aCol - bCol;\n  });\n\n  // First pass: collect all across clues\n  for (const [key, number] of sortedPositions) {\n    if (key.startsWith('A') && clueIndex < clueStrings.length) {\n      across.push({\n        number,\n        text: clueStrings[clueIndex++] || '',\n      });\n    }\n  }\n\n  // Second pass: collect all down clues\n  for (const [key, number] of sortedPositions) {\n    if (key.startsWith('D') && clueIndex < clueStrings.length) {\n      down.push({\n        number,\n        text: clueStrings[clueIndex++] || '',\n      });\n    }\n  }\n\n  return { across, down };\n}\n\nfunction parseExtraSections(\n  reader: BinaryReader,\n  grid: PuzCell[][],\n): {\n  rebusTable?: Map<number, string>;\n  timer?: { elapsed: number; running: boolean };\n} {\n  const result: {\n    rebusTable?: Map<number, string>;\n    timer?: { elapsed: number; running: boolean };\n  } = {};\n\n  while (reader.hasMore()) {\n    // Check if we have enough bytes for a section header\n    if (reader.position + 8 > reader.length) break;\n\n    // Skip null padding bytes between sections\n    while (reader.hasMore() && reader.buffer[reader.position] === 0) {\n      reader.readUInt8();\n    }\n\n    // Check again after skipping padding\n    if (reader.position + 8 > reader.length) break;\n\n    const sectionTitle = reader.readString(4, true, 'latin1');\n    const dataLength = reader.readUInt16LE();\n    reader.readUInt16LE(); // checksum (unused)\n\n    // Skip if not a valid section\n    if (dataLength > reader.length - reader.position) break;\n\n    const sectionData = reader.readBytes(dataLength);\n\n    switch (sectionTitle) {\n      case PUZ_SECTION_GRBS: {\n        // Rebus grid - one byte per square\n        const height = grid.length;\n        const width = grid[0]?.length || 0;\n        for (let row = 0; row < height; row++) {\n          for (let col = 0; col < width; col++) {\n            const index = row * width + col;\n            if (index < sectionData.length) {\n              const rebusKey = sectionData[index];\n              if (rebusKey && rebusKey > 0 && grid[row]?.[col]) {\n                grid[row]![col]!.hasRebus = true;\n                grid[row]![col]!.rebusKey = rebusKey - 1;\n              }\n            }\n          }\n        }\n        break;\n      }\n\n      case PUZ_SECTION_RTBL: {\n        // Rebus table - semicolon-separated values with key:value pairs\n        const tableStr = sectionData.toString('latin1');\n        const entries = tableStr.split(';');\n        result.rebusTable = new Map();\n\n        for (const entry of entries) {\n          if (entry.includes(':')) {\n            const [key, value] = entry.split(':');\n            const keyNum = Number.parseInt(key || '0', 10);\n            if (!Number.isNaN(keyNum)) {\n              result.rebusTable.set(keyNum, value || '');\n            }\n          }\n        }\n        break;\n      }\n\n      case PUZ_SECTION_GEXT: {\n        // Grid extras - circled squares, etc.\n        const height = grid.length;\n        const width = grid[0]?.length || 0;\n        for (let row = 0; row < height; row++) {\n          for (let col = 0; col < width; col++) {\n            const index = row * width + col;\n            if (index < sectionData.length && grid[row]?.[col]) {\n              const flags = sectionData[index];\n              if (flags && flags & PUZ_CIRCLED_CELL_FLAG) {\n                grid[row]![col]!.isCircled = true;\n              }\n            }\n          }\n        }\n        break;\n      }\n\n      case PUZ_SECTION_LTIM: {\n        // Timer data\n        const timerStr = sectionData.toString('latin1');\n        const [elapsed, running] = timerStr.split(',');\n        result.timer = {\n          elapsed: parseInt(elapsed || '0') || 0,\n          running: running === '0' ? false : true,\n        };\n        break;\n      }\n    }\n  }\n\n  return result;\n}\n\n/**\n * Parse a PUZ format crossword puzzle.\n *\n * @param data - The PUZ binary data as Buffer, ArrayBuffer, Uint8Array, or string\n * @param options - Optional parsing options\n * @param options.maxGridSize - Maximum allowed grid dimensions\n * @returns A PuzPuzzle object containing all puzzle data\n * @throws {PuzParseError} When the content is not valid PUZ format\n * @throws {InvalidFileError} When the file is corrupted or has invalid checksums\n *\n * @example\n * ```typescript\n * import { parsePuz } from 'xword-parser';\n * import { readFileSync } from 'fs';\n *\n * const puzData = readFileSync('puzzle.puz');\n * const puzzle = parsePuz(puzData);\n * ```\n */\nexport function parsePuz(\n  data: Buffer | ArrayBuffer | Uint8Array | string,\n  options?: ParseOptions,\n): PuzPuzzle {\n  let buffer: Buffer;\n\n  if (typeof data === 'string') {\n    // If string is passed, assume it's base64 encoded\n    buffer = Buffer.from(data, 'base64');\n  } else if (data instanceof Buffer) {\n    buffer = data;\n  } else {\n    buffer = Buffer.from(data as ArrayBuffer);\n  }\n\n  try {\n    const reader = new BinaryReader(buffer);\n    const header = readHeader(reader);\n\n    // Validate dimensions\n    if (header.width <= 0 || header.height <= 0) {\n      throw new PuzParseError(\n        `Invalid puzzle dimensions: width=${header.width}, height=${header.height}`,\n        ErrorCode.PUZ_INVALID_GRID,\n      );\n    }\n\n    // Check against maxGridSize if provided, otherwise use defaults\n    const maxWidth = options?.maxGridSize?.width ?? MAX_GRID_WIDTH;\n    const maxHeight = options?.maxGridSize?.height ?? MAX_GRID_HEIGHT;\n    if (header.width > maxWidth || header.height > maxHeight) {\n      throw new PuzParseError(\n        `Grid dimensions too large: ${header.width}x${header.height}. Maximum supported size is ${maxWidth}x${maxHeight}`,\n        ErrorCode.PUZ_INVALID_GRID,\n      );\n    }\n\n    // Read puzzle data\n    const gridSize = header.width * header.height;\n    const solution = reader.readString(gridSize, true, 'latin1');\n    const playerState = reader.readString(gridSize, true, 'latin1');\n\n    // Read strings\n    const title = reader.readNullTerminatedString('latin1');\n    const author = reader.readNullTerminatedString('latin1');\n    const copyright = reader.readNullTerminatedString('latin1');\n\n    // Read clues\n    const clueStrings: string[] = [];\n    for (let i = 0; i < header.numClues; i++) {\n      clueStrings.push(reader.readNullTerminatedString('latin1'));\n    }\n\n    const notes = reader.readNullTerminatedString('latin1');\n\n    // Parse grid\n    const grid = parseGrid(solution, playerState, header.width, header.height);\n\n    // Assign clue numbers and parse clues\n    const cluePositions = assignClueNumbers(grid);\n    const { across, down } = parseClues(clueStrings, cluePositions);\n\n    // Parse extra sections\n    const extras = parseExtraSections(reader, grid);\n\n    return {\n      width: header.width,\n      height: header.height,\n      metadata: {\n        title: title || undefined,\n        author: author || undefined,\n        copyright: copyright || undefined,\n        notes: notes || undefined,\n      },\n      grid,\n      across,\n      down,\n      rebusTable: extras.rebusTable,\n      isScrambled: header.scrambledTag !== 0,\n      timer: extras.timer,\n    };\n  } catch (error) {\n    // Convert BinaryParseError to PuzParseError\n    if (error instanceof BinaryParseError) {\n      throw new PuzParseError(error.message, ErrorCode.PUZ_PARSE_ERROR);\n    }\n    // Re-throw other errors as-is\n    throw error;\n  }\n}\n\n/**\n * Convert a PUZ puzzle to the unified Puzzle format.\n *\n * @param puzzle - The PuzPuzzle object to convert\n * @returns A unified Puzzle object\n *\n * @example\n * ```typescript\n * import { parsePuz, convertPuzToUnified } from 'xword-parser';\n * const puzPuzzle = parsePuz(puzData);\n * const unifiedPuzzle = convertPuzToUnified(puzPuzzle);\n * ```\n */\nexport function convertPuzToUnified(puzzle: PuzPuzzle): Puzzle {\n  const grid: Grid = {\n    width: puzzle.width,\n    height: puzzle.height,\n    cells: [],\n  };\n\n  // Convert grid and assign numbers\n  let cellNumber = 1;\n  for (let y = 0; y < puzzle.height; y++) {\n    const row: UnifiedCell[] = [];\n    for (let x = 0; x < puzzle.width; x++) {\n      const puzCell = puzzle.grid[y]?.[x];\n\n      // Determine if this cell should have a number\n      let number: number | undefined;\n      if (puzCell && !puzCell.isBlack) {\n        const needsNumber =\n          // Start of across word\n          ((x === 0 || puzzle.grid[y]?.[x - 1]?.isBlack) &&\n            x < puzzle.width - 1 &&\n            !puzzle.grid[y]?.[x + 1]?.isBlack) ||\n          // Start of down word\n          ((y === 0 || puzzle.grid[y - 1]?.[x]?.isBlack) &&\n            y < puzzle.height - 1 &&\n            !puzzle.grid[y + 1]?.[x]?.isBlack);\n\n        if (needsNumber) {\n          number = cellNumber++;\n        }\n      }\n\n      const cell: UnifiedCell = {\n        solution: puzCell?.solution,\n        number,\n        isBlack: puzCell?.isBlack || false,\n      };\n\n      // Add cell-specific metadata\n      if (puzCell?.isCircled) {\n        cell.isCircled = true;\n      }\n      if (puzCell?.hasRebus) {\n        cell.hasRebus = true;\n        if (puzCell.rebusKey !== undefined) {\n          cell.rebusKey = puzCell.rebusKey;\n        }\n      }\n\n      row.push(cell);\n    }\n    grid.cells.push(row);\n  }\n\n  // Convert clues\n  const clues: Clues = {\n    across: puzzle.across.map((c) => ({\n      number: c.number,\n      text: c.text,\n    })),\n    down: puzzle.down.map((c) => ({\n      number: c.number,\n      text: c.text,\n    })),\n  };\n\n  const result: Puzzle = {\n    title: puzzle.metadata.title,\n    author: puzzle.metadata.author,\n    copyright: puzzle.metadata.copyright,\n    notes: puzzle.metadata.notes,\n    grid,\n    clues,\n    rebusTable: puzzle.rebusTable,\n  };\n\n  // Add puzzle-level metadata if present\n  const additionalProps: Record<string, unknown> = {};\n  if (puzzle.isScrambled) {\n    additionalProps.isScrambled = puzzle.isScrambled;\n  }\n  if (puzzle.timer) {\n    additionalProps.timer = puzzle.timer;\n  }\n\n  if (Object.keys(additionalProps).length > 0) {\n    result.additionalProperties = additionalProps;\n  }\n\n  return result;\n}\n"]}