qvdjs 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -35
- package/dist/index.cjs +84 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +84 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/QvdErrors.js","../src/QvdSymbol.js","../src/util/validatePath.js","../src/QvdFileWriter.js","../src/util/bitUtils.js","../src/util/memoryUtils.js","../src/util/validationUtils.js","../src/util/symbolParser.js","../src/QvdFileReader.js","../src/QvdDataFrame.js","../src/index.js"],"names":["QvdError","QvdParseError","QvdValidationError","QvdIOError","QvdCorruptedError","QvdSecurityError","QvdSymbol","path","fs","QvdFileWriter","assert","crypto","xml","v8","os","QvdFileReader","QvdDataFrame"],"mappings":"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","file":"index.cjs","sourcesContent":["// @ts-check\n\n/**\n * Base error class for all QVD-related errors.\n * Provides structured error information with error codes and context.\n */\nexport class QvdError extends Error {\n /**\n * Constructs a new QVD error.\n *\n * @param {string} message The error message.\n * @param {string} code The error code.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, code, context = {}) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.context = context;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Error thrown when parsing a QVD file fails.\n * Used for issues during XML header parsing, symbol table parsing, or index table parsing.\n */\nexport class QvdParseError extends QvdError {\n /**\n * Constructs a new QVD parse error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_PARSE_ERROR', context);\n }\n}\n\n/**\n * Error thrown when input validation fails.\n * Used for invalid parameters, out of bounds access, or missing required data.\n */\nexport class QvdValidationError extends QvdError {\n /**\n * Constructs a new QVD validation error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_VALIDATION_ERROR', context);\n }\n}\n\n/**\n * Error thrown when file system operations fail.\n * Used for issues reading or writing QVD files.\n */\nexport class QvdIOError extends QvdError {\n /**\n * Constructs a new QVD IO error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_IO_ERROR', context);\n }\n}\n\n/**\n * Error thrown when a QVD file is corrupted or malformed.\n * Used for missing headers, invalid data structures, or corrupted data.\n */\nexport class QvdCorruptedError extends QvdError {\n /**\n * Constructs a new QVD corrupted error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_CORRUPTED_ERROR', context);\n }\n}\n\n/**\n * Error thrown when security violations occur.\n * Used for path traversal attempts, XXE attacks, or other security issues.\n */\nexport class QvdSecurityError extends QvdError {\n /**\n * Constructs a new QVD security error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_SECURITY_ERROR', context);\n }\n}\n","// @ts-check\n\nimport {QvdValidationError} from './QvdErrors.js';\n\n/**\n * Represents a Qlik symbol/value, stored in a QVD file.\n */\nexport class QvdSymbol {\n /**\n * Constructs a new QVD symbol.\n *\n * @param {number|null} intValue The integer value.\n * @param {number|null} doubleValue The double value.\n * @param {string|null} stringValue The string value.\n */\n constructor(intValue, doubleValue, stringValue) {\n this._intValue = intValue;\n\n this._doubleValue = doubleValue;\n\n this._stringValue = stringValue;\n }\n\n /**\n * Returns the integer value of this symbol.\n *\n * @return {number|null} The integer value.\n */\n get intValue() {\n return this._intValue;\n }\n\n /**\n * Returns the double value of this symbol.\n *\n * @return {number|null} The double value.\n */\n get doubleValue() {\n return this._doubleValue;\n }\n\n /**\n * Returns the string value of this symbol.\n *\n * @return {string|null} The string value.\n */\n get stringValue() {\n return this._stringValue;\n }\n\n /**\n * Retrieves the primary value of this symbol. The primary value is descriptive raw value.\n * It is either the string value, the integer value or the double value, prioritized in this order.\n *\n * @return {number|string|null} The primary value.\n */\n toPrimaryValue() {\n if (null != this._stringValue) {\n return this._stringValue;\n } else if (null != this._intValue) {\n return this._intValue;\n } else if (null != this._doubleValue) {\n return this._doubleValue;\n } else {\n return null;\n }\n }\n\n /**\n * Converts the symbol to its byte representation.\n *\n * @return {Buffer} The byte representation of the symbol.\n */\n toByteRepresentation() {\n if (this._intValue !== null && this._stringValue !== null) {\n const intBuffer = Buffer.alloc(4);\n intBuffer.writeInt32LE(this._intValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n const stringBuffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([5]), intBuffer, stringBuffer]);\n } else if (this._doubleValue !== null && this._stringValue !== null) {\n const floatBuffer = Buffer.alloc(8);\n floatBuffer.writeDoubleLE(this._doubleValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n const stringBuffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([6]), floatBuffer, stringBuffer]);\n } else if (this._intValue !== null) {\n const buffer = Buffer.alloc(4);\n buffer.writeInt32LE(this._intValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([1]), buffer]);\n } else if (this._doubleValue !== null) {\n const buffer = Buffer.alloc(8);\n buffer.writeDoubleLE(this._doubleValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([2]), buffer]);\n } else if (this._stringValue !== null) {\n // @ts-ignore - Buffer.concat type compatibility\n const buffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([4]), buffer]);\n } else {\n throw new QvdValidationError('The symbol does not contain any value.', {\n intValue: this._intValue,\n doubleValue: this._doubleValue,\n stringValue: this._stringValue,\n });\n }\n }\n\n /**\n * Checks if this symbol is equal to another symbol.\n *\n * @param {*} value The object to compare with.\n * @return {boolean} True if the objects are equal, false otherwise.\n */\n equals(value) {\n if (!(value instanceof QvdSymbol)) {\n return false;\n }\n\n return (\n this._intValue === value.intValue &&\n this._doubleValue === value.doubleValue &&\n this._stringValue === value.stringValue\n );\n }\n\n /**\n * Constructs a pure integer value symbol.\n *\n * @param {number} intValue The integer value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromIntValue(intValue) {\n return new QvdSymbol(intValue, null, null);\n }\n\n /**\n * Constructs a pure double value symbol.\n *\n * @param {number} doubleValue The double value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDoubleValue(doubleValue) {\n return new QvdSymbol(null, doubleValue, null);\n }\n\n /**\n * Constructs a pure string value symbol.\n *\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromStringValue(stringValue) {\n return new QvdSymbol(null, null, stringValue);\n }\n\n /**\n * Constructs a dual value symbol from an integer and a string value.\n *\n * @param {number} intValue The integer value.\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDualIntValue(intValue, stringValue) {\n return new QvdSymbol(intValue, null, stringValue);\n }\n\n /**\n * Constructs a dual value symbol from a double and a string value.\n *\n * @param {number} doubleValue The double value.\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDualDoubleValue(doubleValue, stringValue) {\n return new QvdSymbol(null, doubleValue, stringValue);\n }\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport path from 'path';\nimport {QvdSecurityError, QvdValidationError} from '../QvdErrors.js';\n\n/**\n * Determines whether a resolved path is contained within a resolved base directory, using only\n * string comparison.\n *\n * This is the fallback for when the filesystem cannot answer the question - in practice, when\n * allowedDir does not exist. It cannot see through symlinks and has to guess at case\n * sensitivity, which is exactly why it is not the primary check.\n *\n * Uses path.relative() rather than a string prefix test, so that filesystem roots\n * ('/', 'C:\\', '\\\\server\\share\\') and base directories with a trailing separator are\n * handled correctly. A prefix test appends path.sep to the base, which produces '//'\n * for a root and therefore matches nothing.\n *\n * @param {string} resolvedBaseDir Absolute, resolved base directory.\n * @param {string} resolvedPath Absolute, resolved candidate path.\n * @return {boolean} True if the path is the base directory itself or lies beneath it.\n */\nfunction isWithinDirectoryLexically(resolvedBaseDir, resolvedPath) {\n // Folding is applied on Windows only. It used to cover darwin as well, on the assumption that\n // macOS is always case-insensitive, but macOS supports case-sensitive APFS and HFS+ volumes on\n // which two names differing only in case are genuinely different directories - so folding there\n // let a sibling directory pass the check. The on-disk comparison below settles case correctly\n // by asking the filesystem, which is why this fallback no longer needs to guess for darwin.\n const isCaseInsensitiveFS = process.platform === 'win32';\n const base = isCaseInsensitiveFS ? resolvedBaseDir.toLowerCase() : resolvedBaseDir;\n const target = isCaseInsensitiveFS ? resolvedPath.toLowerCase() : resolvedPath;\n\n const relative = path.relative(base, target);\n\n // '' means the path IS the base directory. A relative path that starts with '..' escapes\n // the base, and an absolute result means the two are on different roots/drives.\n if (relative === '') {\n return true;\n }\n if (path.isAbsolute(relative)) {\n return false;\n }\n return relative !== '..' && !relative.startsWith(`..${path.sep}`);\n}\n\n/**\n * Resolves the deepest ancestor of a path that actually exists, following symlinks.\n *\n * A path being written to does not exist yet, and neither may some of its parent directories, so\n * realpath() on the full path would simply fail. Walking up to the first component that does\n * exist gives the deepest point the filesystem can vouch for; anything below it is a name that\n * will be created inside that directory.\n *\n * @param {string} target Absolute, lexically resolved path.\n * @return {string|null} Canonical path of the deepest existing ancestor, or null if it could not\n * be determined.\n */\nfunction resolveDeepestExisting(target) {\n let current = target;\n\n for (;;) {\n try {\n return fs.realpathSync(current);\n } catch (error) {\n const code = /** @type {{code?: string}} */ (error)?.code;\n\n // ENOENT: this component does not exist. ENOTDIR: an ancestor is a file, so nothing below\n // it can exist either. Both mean \"keep walking up\". Anything else (EACCES, ELOOP) means the\n // filesystem cannot answer, and the caller falls back to the lexical test - which is safe,\n // because an open() on the same path is about to fail for the same reason.\n if (code !== 'ENOENT' && code !== 'ENOTDIR') {\n return null;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n }\n}\n\n/**\n * Determines whether a path is contained within a base directory by asking the filesystem.\n *\n * Both sides are resolved through symlinks and then compared by identity - device and inode -\n * rather than by name, walking up from the target until the base is found or the root is reached.\n * That settles two questions a string comparison cannot:\n *\n * - Symlinks. A link inside allowedDir pointing outside it resolves to its target, so it is\n * rejected. A lexical check sees only the link's own name, still under allowedDir, and lets it\n * through - which meant arbitrary read via the reader and arbitrary overwrite via the writer.\n * - Case. On a case-insensitive volume 'Qvd' and 'qvd' are one directory and share an inode; on a\n * case-sensitive volume they are two directories with different inodes. Comparing identity gets\n * both right without inferring anything from process.platform, which is what the old code did\n * and got wrong on case-sensitive macOS volumes.\n *\n * This is a check on the path, so it is inherently subject to a race: a symlink swapped in\n * between this call and the subsequent open would defeat it. Closing that would require opening\n * with O_NOFOLLOW and verifying the descriptor, which is a larger change to the reader and\n * writer than this function can make on its own.\n *\n * @param {string} resolvedBaseDir Absolute, lexically resolved base directory.\n * @param {string} resolvedPath Absolute, lexically resolved candidate path.\n * @return {boolean|null} True or false when the filesystem could answer, null when it could not.\n */\nfunction isWithinDirectoryOnDisk(resolvedBaseDir, resolvedPath) {\n /** @type {import('fs').Stats} */\n let baseStat;\n\n try {\n // The base has to exist to be identified. If it does not, there is nothing on disk to compare\n // against and the lexical fallback is all that is left.\n baseStat = fs.statSync(fs.realpathSync(resolvedBaseDir));\n } catch {\n return null;\n }\n\n let current = resolveDeepestExisting(resolvedPath);\n if (current === null) {\n return null;\n }\n\n // realpathSync() returns a fully canonical path, so every ancestor of it is canonical too and\n // walking up with dirname() cannot step through a symlink.\n for (;;) {\n let stat;\n try {\n stat = fs.statSync(current);\n } catch {\n return null;\n }\n\n if (stat.dev === baseStat.dev && stat.ino === baseStat.ino) {\n return true;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return false;\n }\n current = parent;\n }\n}\n\n/**\n * Validates that a file path stays inside the allowed directory.\n *\n * Containment is decided by the filesystem wherever it can be: both paths are resolved through\n * symlinks and compared by device and inode. That covers symlink escapes and case sensitivity,\n * neither of which a string comparison can get right. When the base directory does not exist,\n * there is nothing to compare against and a lexical check is used instead.\n *\n * To permit access to an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on\n * Windows). There is deliberately no separate \"disable the check\" value: a null or empty\n * allowedDir falls back to the current working directory, so a caller that accidentally\n * passes one still gets the restriction rather than silently losing it.\n *\n * @param {string} filePath The path to validate.\n * @param {string|null} [allowedDir] Optional allowed directory path. Defaults to the current\n * working directory to prevent path traversal attacks.\n * @throws {QvdValidationError} If filePath is not a non-empty string, or allowedDir is not a\n * string, null or undefined.\n * @throws {QvdSecurityError} If path traversal is detected.\n * @return {string} The resolved absolute path. This is the lexically resolved path, not the\n * canonical one, so callers see the path they asked for.\n */\nexport function validatePath(filePath, allowedDir) {\n // Validate argument types up front, so callers get a typed error instead of a bare TypeError\n // from deep inside the function (e.g. 'filePath.includes is not a function').\n if (typeof filePath !== 'string' || filePath.length === 0) {\n throw new QvdValidationError('filePath must be a non-empty string', {\n provided: filePath,\n type: typeof filePath,\n });\n }\n\n if (allowedDir !== undefined && allowedDir !== null && typeof allowedDir !== 'string') {\n throw new QvdValidationError('allowedDir must be a string, null or undefined', {\n provided: allowedDir,\n type: typeof allowedDir,\n });\n }\n\n // Check for null bytes which can be used in path traversal attacks\n if (filePath.includes('\\0')) {\n throw new QvdSecurityError('Path traversal detected: Null byte in path', {\n path: filePath,\n reason: 'null_byte',\n });\n }\n\n const resolvedPath = path.resolve(filePath);\n\n // Default to the current working directory when no allowed directory is specified. This\n // prevents path traversal attacks by ensuring files can only be accessed within the CWD\n // or a more restrictive allowed directory.\n //\n // null and '' deliberately fall back to the CWD rather than meaning \"no restriction\":\n // callers routinely produce them from optional config or a JSON round trip, and silently\n // dropping the sandbox in that case would be a security hole. A caller that genuinely wants\n // an entire volume passes its root ('/' or 'C:\\\\'), which the containment test supports.\n const baseDir = allowedDir || process.cwd();\n const resolvedBaseDir = path.resolve(baseDir);\n\n const onDisk = isWithinDirectoryOnDisk(resolvedBaseDir, resolvedPath);\n const contained = onDisk === null ? isWithinDirectoryLexically(resolvedBaseDir, resolvedPath) : onDisk;\n\n if (!contained) {\n throw new QvdSecurityError('Path traversal detected: Access denied', {\n path: filePath,\n resolvedPath,\n allowedDir: resolvedBaseDir,\n reason: 'outside_allowed_directory',\n // Says which check refused, so a rejection of a path that looks contained is traceable to\n // a symlink or a case difference rather than looking like a bug.\n check: onDisk === null ? 'lexical' : 'filesystem',\n });\n }\n\n return resolvedPath;\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport xml from 'xml2js';\nimport assert from 'assert';\nimport {QvdSymbol} from './QvdSymbol.js';\nimport {validatePath} from './util/validatePath.js';\n\n/**\n * @typedef {import('./QvdDataFrame.js').QvdDataFrame} QvdDataFrame\n */\n\n/**\n * Persists a QVD file to disk.\n */\nexport class QvdFileWriter {\n /**\n * Constructs a new QVD file writer.\n *\n * @param {string} filePath The path to the QVD file to write.\n * @param {QvdDataFrame} df The data frame to write to the QVD file.\n * @param {Object} [options={}] Options for the writer.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file\n * path must be within this directory, with symlinks resolved first, so a link inside it that\n * points outside it is rejected. Defaults to the current working directory. To permit\n * an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or\n * empty value falls back to the working directory rather than removing the restriction.\n * @param {Function} [options.onProgress] Optional progress callback function.\n */\n constructor(filePath, df, options = {}) {\n const {allowedDir, onProgress} = options;\n this._path = validatePath(filePath, allowedDir);\n this._df = df;\n this._onProgress = onProgress;\n this._header = null;\n this._symbolBuffer = null;\n /** @type {Array<Array<import('./QvdSymbol.js').QvdSymbol>>|null} */\n this._symbolTable = null;\n /** @type {Array<any>|null} */\n this._symbolTableMetadata = null;\n this._indexBuffer = null;\n /** @type {Array<any>|null} */\n this._indexTable = null;\n /** @type {Array<any>|null} */\n this._indexTableMetadata = null;\n this._recordByteSize = null;\n }\n\n /**\n * Emits a progress event if a callback is registered.\n *\n * @param {string} stage The current stage of the operation.\n * @param {number} current The current progress value.\n * @param {number} total The total progress value.\n */\n _emitProgress(stage, current, total) {\n if (this._onProgress) {\n const percent = total > 0 ? Math.round((current / total) * 100) : 100;\n this._onProgress({\n stage,\n current,\n total,\n percent,\n });\n }\n }\n\n /**\n * Writes the data to the QVD file.\n */\n async _writeData() {\n assert(this._header, 'The QVD file header has not been parsed.');\n assert(this._symbolBuffer, 'The QVD file symbol table has not been parsed.');\n assert(this._indexBuffer, 'The QVD file index table has not been parsed.');\n\n this._emitProgress('write', 0, 1);\n\n // @ts-ignore - Buffer.concat type compatibility\n const headerBuffer = Buffer.concat([Buffer.from(this._header, 'utf-8'), Buffer.from([0])]);\n\n let fd;\n try {\n fd = await fs.promises.open(this._path, 'w');\n await fd.write(headerBuffer, 0, headerBuffer.length, 0);\n await fd.write(this._symbolBuffer, 0, this._symbolBuffer.length, headerBuffer.length);\n await fd.write(this._indexBuffer, 0, this._indexBuffer.length, headerBuffer.length + this._symbolBuffer.length);\n this._emitProgress('write', 1, 1);\n } finally {\n if (fd) {\n await fd.close();\n }\n }\n }\n\n /**\n * Builds the XML header of the QVD file.\n */\n _buildHeader() {\n this._emitProgress('header', 0, 1);\n const creationDate = new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '');\n /** @type {import('./QvdDataFrame.js').QvdMetadata|null} */\n const existingMetadata = this._df.metadata;\n\n // Use existing metadata if available, otherwise create default values\n const baseMetadata = existingMetadata\n ? {\n QvBuildNo: existingMetadata.QvBuildNo || 50667,\n CreatorDoc: existingMetadata.CreatorDoc || crypto.randomUUID(),\n CreateUtcTime: existingMetadata.CreateUtcTime || creationDate,\n SourceCreateUtcTime: existingMetadata.SourceCreateUtcTime || '',\n SourceFileUtcTime: existingMetadata.SourceFileUtcTime || '',\n SourceFileSize: existingMetadata.SourceFileSize || -1,\n StaleUtcTime: existingMetadata.StaleUtcTime || '',\n TableName: existingMetadata.TableName || path.basename(this._path, path.extname(this._path)),\n Compression: existingMetadata.Compression || '',\n Comment: existingMetadata.Comment || '',\n EncryptionInfo: existingMetadata.EncryptionInfo || '',\n TableTags: existingMetadata.TableTags || '',\n ProfilingData: existingMetadata.ProfilingData || '',\n Lineage: existingMetadata.Lineage || {\n LineageInfo: {\n Discriminator: 'INLINE;',\n Statement: '',\n },\n },\n }\n : {\n QvBuildNo: 50667,\n CreatorDoc: crypto.randomUUID(),\n CreateUtcTime: creationDate,\n SourceCreateUtcTime: '',\n SourceFileUtcTime: '',\n SourceFileSize: -1,\n StaleUtcTime: '',\n TableName: path.basename(this._path, path.extname(this._path)),\n Compression: '',\n Comment: '',\n EncryptionInfo: '',\n TableTags: '',\n ProfilingData: '',\n Lineage: {\n LineageInfo: {\n Discriminator: 'INLINE;',\n Statement: '',\n },\n },\n };\n\n // Get existing field metadata if available\n /** @type {any[]} */\n let existingFields = [];\n if (existingMetadata && existingMetadata.Fields && existingMetadata.Fields.QvdFieldHeader) {\n existingFields = Array.isArray(existingMetadata.Fields.QvdFieldHeader)\n ? existingMetadata.Fields.QvdFieldHeader\n : [existingMetadata.Fields.QvdFieldHeader];\n }\n\n const xmlObject = {\n QvdTableHeader: {\n ...baseMetadata,\n Fields: {\n QvdFieldHeader: this._df.columns.map((/** @type {any} */ column, /** @type {number} */ index) => {\n // Find existing field metadata for this column\n const existingField = existingFields.find((/** @type {any} */ f) => f.FieldName === column);\n\n return {\n FieldName: column,\n BitOffset: this._indexTableMetadata?.[index][0],\n BitWidth: this._indexTableMetadata?.[index][1],\n Bias: this._indexTableMetadata?.[index][2],\n NoOfSymbols: this._symbolTable?.[index].length,\n Offset: this._symbolTableMetadata?.[index][0],\n Length: this._symbolTableMetadata?.[index][1],\n Comment: existingField?.Comment || '',\n NumberFormat: existingField?.NumberFormat || {\n Type: 'UNKNOWN',\n nDec: '0',\n UseThou: '0',\n Fmt: '',\n Dec: '',\n Thou: '',\n },\n Tags: existingField?.Tags || {},\n };\n }),\n },\n NoOfRecords: this._indexTable?.length,\n RecordByteSize: this._recordByteSize,\n Offset:\n this._symbolTableMetadata && this._symbolTableMetadata.length > 0\n ? this._symbolTableMetadata[this._symbolTableMetadata.length - 1][0] +\n this._symbolTableMetadata[this._symbolTableMetadata.length - 1][1]\n : 0,\n Length: this._indexBuffer?.length,\n },\n };\n\n const builder = new xml.Builder({\n renderOpts: {\n pretty: true,\n newline: '\\r\\n',\n indent: ' ',\n },\n });\n this._header = builder.buildObject(xmlObject) + '\\r\\n';\n this._emitProgress('header', 1, 1);\n }\n\n /**\n * Builds the symbol table of the QVD file.\n *\n * PERFORMANCE OPTIMIZATION: This method uses a single-pass algorithm to build\n * symbol tables for all columns simultaneously. This reduces time complexity from\n * O(n×m×s) to O(n×m) where n=rows, m=columns, s=symbols per column.\n *\n * Algorithm:\n * 1. Initialize a Set for each column to collect unique values\n * 2. Single pass through all data rows, adding values to corresponding Sets\n * 3. Convert Sets to arrays and create QvdSymbol instances\n * 4. Serialize symbols to binary format and update metadata\n *\n * This approach provides:\n * - 80-90% performance improvement for large datasets (100K+ rows)\n * - Better cache locality (process all columns in one data traversal)\n * - Lower memory pressure (no intermediate arrays per column)\n *\n * @private\n */\n _buildSymbolTable() {\n this._symbolTable = [];\n this._symbolTableMetadata = [];\n this._symbolBuffer = Buffer.alloc(0);\n\n const numColumns = this._df.columns.length;\n\n this._emitProgress('symbol-table', 0, numColumns);\n\n // Initialize a Set for each column to track unique values\n // Sets provide O(1) add and automatic deduplication\n const uniqueValuesSets = this._df.columns.map(() => new Set());\n\n // Single pass through all data to collect unique values for all columns\n // This is the key optimization: process all columns together instead of\n // iterating through data once per column\n this._df.data.forEach((row) => {\n this._df.columns.forEach((column, columnIndex) => {\n const value = row[columnIndex];\n uniqueValuesSets[columnIndex].add(value);\n });\n });\n\n // Process each column's unique values\n this._df.columns.forEach((column, columnIndex) => {\n const uniqueValuesSet = uniqueValuesSets[columnIndex];\n const uniqueValues = Array.from(uniqueValuesSet);\n const containsNull = uniqueValues.includes(null) || uniqueValues.includes(undefined);\n const symbols = uniqueValues\n .filter((value) => value !== null && value !== undefined)\n .map((value) => QvdFileWriter._convertRawToSymbol(value));\n\n // @ts-ignore:next-line sd\n const currentSymbolBuffer = Buffer.concat(symbols.map((symbol) => symbol.toByteRepresentation()));\n this._symbolBuffer = this._symbolBuffer\n ? Buffer.concat([this._symbolBuffer, currentSymbolBuffer])\n : currentSymbolBuffer;\n\n const symbolsLength = currentSymbolBuffer.length;\n const symbolsOffset = this._symbolBuffer.length - symbolsLength;\n\n this._symbolTableMetadata?.push([symbolsOffset, symbolsLength, containsNull]);\n // @ts-ignore - Symbol array type compatibility\n this._symbolTable?.push(symbols);\n\n this._emitProgress('symbol-table', columnIndex + 1, numColumns);\n });\n }\n\n /**\n * Builds the index table of the QVD file.\n *\n * PERFORMANCE OPTIMIZATION: Uses Map-based lookups for O(1) symbol index retrieval\n * instead of Array.findIndex() which is O(n). For columns with many unique values,\n * this provides significant performance improvements.\n *\n * Algorithm:\n * 1. Build Map<symbol, index> for each column (O(m) where m=unique values)\n * 2. For each data row, lookup indices in maps (O(1) per value)\n * 3. Convert indices to bit-packed binary format\n *\n * Bit Packing:\n * - Calculates minimum bits needed: ceil(log2(numSymbols))\n * - Packs indices into binary string, then converts to bytes\n * - Reduces file size significantly for columns with few unique values\n *\n * Example: Column with 10 unique values needs only 4 bits per value\n * instead of 32 bits (full integer), saving 87.5% space.\n *\n * @private\n */\n _buildIndexTable() {\n this._indexTable = [];\n this._indexTableMetadata = [];\n this._indexBuffer = Buffer.alloc(0);\n\n const numRows = this._df.data.length;\n this._emitProgress('index-table', 0, numRows);\n\n // Build symbol-to-index lookup maps for O(1) lookups\n // This is crucial for performance: findIndex() on large arrays is O(n)\n // while Map.get() is O(1)\n // This converts the O(n×m×s) findIndex operations to O(n×m)\n const symbolIndexMaps = this._symbolTable?.map((symbols) => {\n const map = new Map();\n symbols.forEach((symbol, idx) => {\n // Create a unique key for each symbol based on its values\n const key = `${symbol.intValue}|${symbol.doubleValue}|${symbol.stringValue}`;\n map.set(key, idx);\n });\n return map;\n });\n\n let processedRows = 0;\n const progressInterval = Math.max(1, Math.floor(numRows / 100)); // Report progress every 1%\n\n this._df.data.forEach((/** @type {any} */ row) => {\n // Convert the raw values to indices referring to the symbol table\n const indices = this._df.columns.map((/** @type {any} */ column, columnIndex) => {\n const value = row[columnIndex];\n const symbol = QvdFileWriter._convertRawToSymbol(value);\n const fieldContainsNull = this._symbolTableMetadata?.[columnIndex][2];\n\n // None values are represented by bias shifted negative indices\n if (symbol === null) {\n return 0;\n } else {\n // Use the Map for O(1) lookup instead of findIndex\n const key = `${symbol.intValue}|${symbol.doubleValue}|${symbol.stringValue}`;\n const symbolIndex = symbolIndexMaps?.[columnIndex].get(key);\n // In order to represent None values, the indices are shifted by the bias value of the column\n return fieldContainsNull ? (symbolIndex ?? 0) + 2 : (symbolIndex ?? 0);\n }\n });\n\n // Convert the integer indices to binary representation\n /** @type {string[]} */\n const stringIndices = indices.map((/** @type {number} */ index) => {\n const bits = QvdFileWriter._convertInt32ToBits(index, 32);\n let bitString = bits.join('');\n bitString = bitString.replace(/^0+/, '') || '0';\n return bitString;\n });\n\n // @ts-ignore - Index array type compatibility\n this._indexTable?.push(stringIndices);\n\n // Report progress periodically\n processedRows++;\n if (processedRows % progressInterval === 0 || processedRows === numRows) {\n this._emitProgress('index-table', processedRows, numRows);\n }\n });\n\n // Normalize the bit representation of the indices by padding with zeros\n this._df.columns.forEach((column, columnIndex) => {\n // Bit offset is the sum of the bit widths of all previous columns\n const bitOffset = this._indexTableMetadata?.slice(0, columnIndex).reduce((sum, metadata) => sum + metadata[1], 0);\n\n assert(this._indexTable, 'The QVD file header has not been parsed.');\n\n const fieldContainsNull = this._symbolTableMetadata?.[columnIndex][2];\n const bias = fieldContainsNull ? -2 : 0;\n\n // Bit width is derived from the number of symbols rather than by scanning every row.\n //\n // The largest stored index is (symbolCount - 1), shifted by 2 when the column contains\n // NULLs (index 0 denotes NULL and indices start at 2, which is what Bias=-2 encodes).\n //\n // Deriving it this way is O(1) per column instead of O(rows), and it avoids\n // Math.max(...oneArgumentPerRow), which overflows the call stack somewhere around\n // 120k rows and made toQvd() unusable for realistic table sizes.\n const symbolCount = this._symbolTable?.[columnIndex].length ?? 0;\n const maxStoredIndex = symbolCount === 0 ? 0 : symbolCount - 1 + (fieldContainsNull ? 2 : 0);\n // A single distinct value needs no bits at all, which matches what Qlik emits.\n const bitWidth = maxStoredIndex === 0 ? 0 : 32 - Math.clz32(maxStoredIndex);\n\n this._indexTableMetadata?.push([bitOffset, bitWidth, bias]);\n\n // Pad the bit representation of the indices with zeros to match the bit width.\n //\n // The assertion restores the self-correcting property of the old Math.max() approach,\n // which measured the actual bit strings and so absorbed any mismatch between the symbol\n // table and the indices built from it. Deriving the width instead makes such a mismatch\n // silent: padStart() never truncates, so an over-wide index would make the record wider\n // than BitWidth declares and misalign every field after it in every subsequent row.\n this._indexTable.forEach((/** @type{string[]} */ indices) => {\n const bitString = indices[columnIndex];\n // '0' is the stored index 0, which needs no bits and is written as an empty string\n // when bitWidth is 0; every other value must fit inside the derived width.\n assert(\n bitString === '0' || bitString.length <= bitWidth,\n `Stored index for column '${column}' needs ${bitString.length} bits, ` +\n `but BitWidth was derived as ${bitWidth} from ${symbolCount} symbols. ` +\n `The symbol table and the index table are out of sync.`,\n );\n indices[columnIndex] = bitWidth === 0 ? '' : bitString.padStart(bitWidth, '0');\n });\n });\n\n // Concatenate the bit representation of the indices of each row to a single binary string per row\n // @ts-ignore - Buffer.concat type compatibility\n this._indexBuffer = Buffer.concat(\n // @ts-ignore - Buffer array type compatibility\n this._indexTable.map((/** @type{string[]} */ indices) => {\n indices.reverse();\n const bits = indices.join('');\n\n // Every column may have a bit width of 0 (each holds a single distinct value or only\n // NULLs), leaving no bits at all. Qlik still uses a one-byte record in that situation,\n // and a zero-byte record would be rejected on read, so emit a single zero byte.\n if (bits.length === 0) {\n return Buffer.from(Uint8Array.from([0]));\n }\n\n const paddingWidth = (8 - (bits.length % 8)) % 8;\n const paddedBits = bits.padStart(bits.length + paddingWidth, '0');\n const bytes = paddedBits.match(/.{1,8}/g)?.map((byte) => parseInt(byte, 2));\n bytes?.reverse();\n\n assert(bytes, 'Byte conversion of bit indices failed.');\n\n return Buffer.from(Uint8Array.from(bytes));\n }),\n );\n\n // For empty data, set record byte size to 1 (matching Qlik Sense behavior)\n // instead of 0 or NaN/Infinity\n this._recordByteSize = this._indexTable.length > 0 ? this._indexBuffer.length / this._indexTable.length : 1;\n }\n\n /**\n * Converts a raw value/literal to a QVD symbol.\n *\n * @param {any} raw The raw value/literal to convert.\n * @return {QvdSymbol|null} The converted QVD symbol.\n */\n static _convertRawToSymbol(raw) {\n if (raw === null || raw === undefined) {\n return null;\n }\n\n const INT32_MIN = -2147483648;\n const INT32_MAX = 2147483647;\n\n const isInteger = typeof raw === 'number' && Number.isInteger(raw);\n const isFloat = typeof raw === 'number' && !Number.isInteger(raw);\n const isWithinInt32Range = typeof raw === 'number' && raw >= INT32_MIN && raw <= INT32_MAX;\n\n if (isInteger && isWithinInt32Range) {\n return QvdSymbol.fromDualIntValue(raw, raw.toString());\n } else if (isFloat || (isInteger && !isWithinInt32Range)) {\n return QvdSymbol.fromDualDoubleValue(raw, raw.toString());\n } else {\n return QvdSymbol.fromStringValue(raw);\n }\n }\n\n /**\n * Converts an integer to a list of bits.\n *\n * @param {number} value The integer value to convert.\n * @param {number} width The width of the bit list.\n * @return {Array<number>} The list of bits.\n */\n static _convertInt32ToBits(value, width) {\n return value\n .toString(2)\n .split('')\n .map((bit) => parseInt(bit))\n .reverse()\n .concat(new Array(width).fill(0))\n .slice(0, width)\n .reverse();\n }\n\n /**\n * Persists the data frame to a QVD file.\n */\n async save() {\n this._buildSymbolTable();\n this._buildIndexTable();\n this._buildHeader();\n await this._writeData();\n }\n}\n","// @ts-check\n\n/**\n * Converts a bit array to an integer value.\n *\n * @param {Array<number>} bits The bit array\n * @return {number} The integer value\n */\nexport function convertBitsToInt32(bits) {\n if (bits.length === 0) {\n return 0;\n }\n\n return bits.reduce((value, bit, index) => (value += bit * Math.pow(2, index)), 0);\n}\n","// @ts-check\n\nimport os from 'os';\nimport v8 from 'v8';\nimport {QvdValidationError} from '../QvdErrors.js';\n\n/**\n * Gets the configured V8 heap size limit for the current Node.js process.\n * This respects the --max-old-space-size flag if set.\n *\n * @returns {number} Heap size limit in bytes\n */\nexport function getHeapLimit() {\n return v8.getHeapStatistics().heap_size_limit;\n}\n\n/**\n * Estimates the memory usage for loading a QVD file with given parameters.\n * Takes into account Phase 2.5 optimization which skips parsing unused symbols.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @returns {number} Estimated memory usage in bytes\n */\nexport function estimateMemoryUsage(symbolTableSize, maxRows, totalRows) {\n // Memory overhead multipliers based on empirical testing\n const FULL_PARSE_OVERHEAD = 6.0; // Baseline: JavaScript objects have 6x overhead\n const MINIMAL_OVERHEAD = 0.01; // Skipped symbols: minimal null placeholder overhead\n\n if (maxRows === null || maxRows >= totalRows) {\n // Loading all rows - need all symbols, no filtering benefit\n return symbolTableSize * FULL_PARSE_OVERHEAD;\n }\n\n // Estimate what percentage of symbols we'll need\n // Symbol usage grows slower than linear (diminishing returns as you add rows)\n // Use square root scaling as empirical approximation\n const rowPercentage = maxRows / totalRows;\n const symbolPercentage = Math.sqrt(rowPercentage);\n\n // Calculate memory for kept symbols (full overhead) + skipped symbols (minimal overhead)\n const keptSymbolsMemory = symbolTableSize * symbolPercentage * FULL_PARSE_OVERHEAD;\n const skippedSymbolsMemory = symbolTableSize * (1 - symbolPercentage) * MINIMAL_OVERHEAD;\n\n return keptSymbolsMemory + skippedSymbolsMemory;\n}\n\n/**\n * Validates that there is sufficient memory available to load a QVD file safely.\n * Considers both available system RAM and the configured V8 heap limit.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number} [safetyFactor=0.3] Percentage of available memory to use (0.0-1.0)\n * @throws {QvdValidationError} If insufficient memory is available\n */\nexport function validateMemoryAvailability(symbolTableSize, maxRows, totalRows, filePath, safetyFactor = 0.3) {\n if (typeof safetyFactor !== 'number' || safetyFactor < 0 || safetyFactor > 1) {\n throw new QvdValidationError('safetyFactor must be a number between 0.0 and 1.0', {safetyFactor});\n }\n\n const availableMemory = os.freemem();\n const heapLimit = getHeapLimit();\n const estimatedMemory = estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n\n // Use the smaller of available RAM or heap limit to determine max allowed memory\n // This ensures we don't try to allocate more than V8 can handle\n const effectiveLimit = Math.min(availableMemory, heapLimit);\n const maxAllowedMemory = effectiveLimit * safetyFactor;\n\n if (estimatedMemory > maxAllowedMemory) {\n // Calculate how many rows would be safe to load\n // Reverse the square root formula: symbolPercentage = sqrt(rowPercentage)\n const safeSymbolPercentage = maxAllowedMemory / (symbolTableSize * 6.0);\n const safeRowPercentage = Math.pow(safeSymbolPercentage, 2);\n const recommendedMaxRows = Math.max(1, Math.floor(totalRows * safeRowPercentage));\n\n const sizeMB = Math.round(symbolTableSize / 1024 / 1024);\n const estimatedMB = Math.round(estimatedMemory / 1024 / 1024);\n const availableMB = Math.round(maxAllowedMemory / 1024 / 1024);\n const heapLimitMB = Math.round(heapLimit / 1024 / 1024);\n const availableRamMB = Math.round(availableMemory / 1024 / 1024);\n\n // Determine which limit was hit\n const limitingFactor = heapLimit < availableMemory ? 'V8 heap limit' : 'available RAM';\n\n throw new QvdValidationError(\n `Insufficient memory to load file safely. ` +\n `Symbol table: ${sizeMB}MB, Estimated memory needed: ${estimatedMB}MB, Available: ${availableMB}MB (limited by ${limitingFactor}: ${heapLimitMB}MB heap / ${availableRamMB}MB RAM). ` +\n `Try loading fewer rows using the maxRows parameter (recommended: ${recommendedMaxRows.toLocaleString()} rows or less).`,\n {\n file: filePath,\n symbolTableSize,\n symbolTableSizeMB: sizeMB,\n estimatedMemoryMB: estimatedMB,\n availableMemoryMB: availableMB,\n heapLimitMB,\n availableRamMB,\n limitingFactor,\n totalRows,\n maxRows,\n recommendedMaxRows,\n },\n );\n }\n}\n\n/**\n * Emits a warning for large symbol tables when loading all rows.\n * Warning threshold scales with configured heap size (12.5% of heap).\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n */\nexport function warnLargeSymbolTable(symbolTableSize, maxRows, totalRows) {\n // Dynamic warning threshold: 12.5% of configured heap size\n // Examples: 4GB heap = 512MB, 8GB heap = 1GB, 16GB heap = 2GB\n const heapLimit = getHeapLimit();\n const LARGE_SYMBOL_TABLE_WARNING = heapLimit * 0.125;\n\n if (symbolTableSize > LARGE_SYMBOL_TABLE_WARNING && (maxRows === null || maxRows >= totalRows)) {\n const sizeMB = Math.round(symbolTableSize / 1024 / 1024);\n const estimatedMemory = estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n const estimatedMB = Math.round(estimatedMemory / 1024 / 1024);\n const warnMB = Math.round(LARGE_SYMBOL_TABLE_WARNING / 1024 / 1024);\n\n console.warn(\n `⚠️ Large symbol table detected (${sizeMB}MB > ${warnMB}MB threshold). Loading all ${totalRows.toLocaleString()} rows will use ~${estimatedMB}MB RAM. ` +\n `Consider using the maxRows parameter for better performance and lower memory usage.`,\n );\n }\n}\n","// @ts-check\n\nimport {QvdCorruptedError, QvdValidationError} from '../QvdErrors.js';\nimport {getHeapLimit} from './memoryUtils.js';\n\n/**\n * Validates symbol table size during initial file read (early check).\n * This is the first-pass validation in _readData for lazy loading.\n * Limit scales with configured heap size (12.5% of heap).\n *\n * @param {number} symbolTableLength Size of symbol table in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdValidationError} If symbol table exceeds dynamic limit\n */\nexport function validateSymbolTableSizeEarly(symbolTableLength, filePath) {\n // Dynamic limit: 12.5% of configured heap size\n // Examples: 4GB heap = 512MB, 8GB heap = 1GB, 16GB heap = 2GB\n const heapLimit = getHeapLimit();\n const MAX_SYMBOL_TABLE_SIZE = heapLimit * 0.125;\n\n if (symbolTableLength > MAX_SYMBOL_TABLE_SIZE) {\n const sizeMB = Math.round(symbolTableLength / 1024 / 1024);\n const maxMB = Math.round(MAX_SYMBOL_TABLE_SIZE / 1024 / 1024);\n const heapMB = Math.round(heapLimit / 1024 / 1024);\n\n throw new QvdValidationError(\n `Symbol table too large (${sizeMB}MB exceeds ${maxMB}MB limit for lazy loading). ` +\n `This QVD file contains extremely high-cardinality fields. ` +\n `Limit scales with heap size (current: ${heapMB}MB, limit: 12.5% = ${maxMB}MB). ` +\n `Consider: (1) loading the full file without maxRows, (2) increasing heap size with --max-old-space-size, or (3) aggregating high-cardinality fields.`,\n {\n file: filePath,\n symbolTableSize: symbolTableLength,\n symbolTableSizeMB: sizeMB,\n maxAllowed: MAX_SYMBOL_TABLE_SIZE,\n maxAllowedMB: maxMB,\n heapLimitMB: heapMB,\n limitPercentage: 12.5,\n },\n );\n }\n}\n\n/**\n * Validates symbol table size limits to prevent out-of-memory conditions.\n * This is the comprehensive validation in _parseSymbolTable.\n * Absolute ceiling scales with configured heap size (50% of heap).\n *\n * @param {number} symbolTableLength Size of symbol table in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number} totalRows Total number of rows in the file\n * @throws {QvdValidationError} If symbol table exceeds safety limits\n */\nexport function validateSymbolTableSize(symbolTableLength, filePath, totalRows) {\n // Dynamic absolute ceiling: 50% of configured heap size\n // Examples: 4GB heap = 2GB, 8GB heap = 4GB, 16GB heap = 8GB, 32GB heap = 16GB\n const heapLimit = getHeapLimit();\n const ABSOLUTE_MAX_SYMBOL_TABLE = heapLimit * 0.5;\n\n if (symbolTableLength > ABSOLUTE_MAX_SYMBOL_TABLE) {\n const sizeMB = Math.round(symbolTableLength / 1024 / 1024);\n const maxMB = Math.round(ABSOLUTE_MAX_SYMBOL_TABLE / 1024 / 1024);\n const heapMB = Math.round(heapLimit / 1024 / 1024);\n\n throw new QvdValidationError(\n `Symbol table exceeds absolute maximum size (${sizeMB}MB > ${maxMB}MB). ` +\n `This QVD file has pathological cardinality (likely a data modeling issue). ` +\n `Limit scales with heap size (current: ${heapMB}MB, limit: 50% = ${maxMB}MB). ` +\n `Consider: (1) increasing heap size with --max-old-space-size, (2) aggregating high-cardinality fields, (3) splitting the data, or (4) using a different format.`,\n {\n file: filePath,\n symbolTableSize: symbolTableLength,\n symbolTableSizeMB: sizeMB,\n maxAllowed: ABSOLUTE_MAX_SYMBOL_TABLE,\n maxAllowedMB: maxMB,\n heapLimitMB: heapMB,\n limitPercentage: 50,\n totalRows,\n },\n );\n }\n}\n\n/**\n * Validates field metadata before processing to prevent buffer overflow attacks.\n *\n * @param {any} field Field metadata object\n * @param {number} symbolBufferLength Length of the symbol buffer\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdCorruptedError} If field metadata is invalid\n */\nexport function validateFieldMetadata(field, symbolBufferLength, filePath) {\n const symbolsOffset = parseInt(field['Offset'], 10);\n const symbolsLength = parseInt(field['Length'], 10);\n\n // Validate offset is a valid number and within bounds\n if (isNaN(symbolsOffset) || !Number.isSafeInteger(symbolsOffset) || symbolsOffset < 0) {\n throw new QvdCorruptedError('Invalid symbol offset', {\n field: field['FieldName'],\n offset: symbolsOffset,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n // Validate length is a valid number and non-negative\n if (isNaN(symbolsLength) || !Number.isSafeInteger(symbolsLength) || symbolsLength < 0) {\n throw new QvdCorruptedError('Invalid symbol length', {\n field: field['FieldName'],\n length: symbolsLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n // Validate that offset + length doesn't exceed buffer size\n if (symbolsOffset + symbolsLength > symbolBufferLength) {\n throw new QvdCorruptedError('Symbol data extends beyond buffer', {\n field: field['FieldName'],\n offset: symbolsOffset,\n length: symbolsLength,\n bufferSize: symbolBufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n}\n\n/**\n * Validates index table metadata and bounds.\n *\n * @param {number} recordSize Size of a single record in bytes\n * @param {number} totalRows Total number of rows\n * @param {number} indexTableLength Length of the index table\n * @param {number} indexTableOffset Offset to the index table\n * @param {number} bufferLength Length of the buffer\n * @param {number} rowsToLoad Number of rows to load\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number|null} [fileSize] Actual size of the file on disk, when known. Used to detect a\n * header that describes more data than the file contains.\n * @throws {QvdCorruptedError} If index table metadata is invalid\n */\nexport function validateIndexTableMetadata(\n recordSize,\n totalRows,\n indexTableLength,\n indexTableOffset,\n bufferLength,\n rowsToLoad,\n filePath,\n fileSize = null,\n) {\n // Validate recordSize\n if (isNaN(recordSize) || !Number.isSafeInteger(recordSize) || recordSize < 0) {\n throw new QvdCorruptedError('Invalid record byte size', {\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate totalRows\n if (isNaN(totalRows) || !Number.isSafeInteger(totalRows) || totalRows < 0) {\n throw new QvdCorruptedError('Invalid number of records', {\n totalRows,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Allow recordSize of 0 or 1 only when there are no records (empty QVD)\n // Qlik Sense uses recordSize=1 for empty QVDs\n if (recordSize === 0 && totalRows > 0) {\n throw new QvdCorruptedError('Record byte size cannot be zero when records exist', {\n recordSize,\n totalRows,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate recordSize is reasonable (max 1MB per record)\n if (recordSize > 1048576) {\n throw new QvdCorruptedError('Record byte size exceeds maximum', {\n recordSize,\n maxSize: 1048576,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate index table length\n if (isNaN(indexTableLength) || !Number.isSafeInteger(indexTableLength) || indexTableLength < 0) {\n throw new QvdCorruptedError('Invalid index table length', {\n length: indexTableLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate index table start offset doesn't extend beyond buffer\n if (indexTableOffset > bufferLength) {\n throw new QvdCorruptedError('Index table offset beyond buffer', {\n indexTableOffset,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // The index table must be exactly as long as the record count implies. Every QVD produced by\n // Qlik or by this library satisfies this, so a mismatch means the header is inconsistent.\n // Checking it catches corrupt headers that would otherwise decode misaligned rows.\n if (indexTableLength !== totalRows * recordSize) {\n throw new QvdCorruptedError('Index table length inconsistent with record count', {\n indexTableLength,\n expectedLength: totalRows * recordSize,\n totalRows,\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate the index table against the actual file when its size is known.\n //\n // Comparing against the in-memory buffer instead is wrong in both directions: during a lazy\n // load the buffer is deliberately truncated, so valid large files were rejected as corrupt,\n // while a truncated file whose header claims more data was accepted and silently returned\n // fewer rows than the header declares.\n if (fileSize !== null) {\n if (indexTableOffset + indexTableLength > fileSize) {\n throw new QvdCorruptedError('Index table extends beyond the end of the file', {\n indexTableOffset,\n indexTableLength,\n fileSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n }\n\n // Ensure the loaded buffer actually holds the rows we were asked to parse.\n const requiredIndexBytes = rowsToLoad * recordSize;\n if (indexTableOffset + requiredIndexBytes > bufferLength) {\n throw new QvdCorruptedError('Index table truncated', {\n indexTableOffset,\n requiredBytes: requiredIndexBytes,\n availableBytes: Math.max(0, bufferLength - indexTableOffset),\n rowsToLoad,\n recordSize,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Ensure the index table length is sufficient for the number of rows to load\n if (indexTableLength < requiredIndexBytes) {\n throw new QvdCorruptedError('Index table length smaller than required', {\n indexTableLength,\n requiredBytes: requiredIndexBytes,\n rowsToLoad,\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n}\n\n/**\n * Validates field bit offset and bit width for index table parsing.\n *\n * @param {any} field Field metadata object\n * @param {number} recordSize Size of a single record in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdCorruptedError} If field bit metadata is invalid\n */\nexport function validateFieldBitMetadata(field, recordSize, filePath) {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n\n // Validate bitOffset\n if (isNaN(bitOffset) || !Number.isSafeInteger(bitOffset) || bitOffset < 0) {\n throw new QvdCorruptedError('Invalid bit offset', {\n field: field['FieldName'],\n bitOffset,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate bitWidth\n if (isNaN(bitWidth) || !Number.isSafeInteger(bitWidth) || bitWidth < 0) {\n throw new QvdCorruptedError('Invalid bit width', {\n field: field['FieldName'],\n bitWidth,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate bitOffset + bitWidth doesn't exceed record size in bits\n const recordSizeInBits = recordSize * 8;\n if (bitOffset + bitWidth > recordSizeInBits) {\n throw new QvdCorruptedError('Bit field extends beyond record size', {\n field: field['FieldName'],\n bitOffset,\n bitWidth,\n recordSizeInBits,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n}\n","// @ts-check\n\nimport {QvdSymbol} from '../QvdSymbol.js';\nimport {QvdCorruptedError, QvdParseError} from '../QvdErrors.js';\n\n/**\n * Parses an integer symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for an integer\n if (pointer + 4 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading integer symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const byteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 4));\n const value = Buffer.from(byteData).readIntLE(0, byteData.length);\n return {symbol: QvdSymbol.fromIntValue(value), bytesRead: 4};\n}\n\n/**\n * Parses a double symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for a double\n if (pointer + 8 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading double symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const byteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 8));\n const value = Buffer.from(byteData).readDoubleLE(0);\n return {symbol: QvdSymbol.fromDoubleValue(value), bytesRead: 8};\n}\n\n/**\n * Parses a string symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n const startPointer = pointer;\n const maxStringLength = 1048576; // 1MB max string size to prevent memory exhaustion\n let stringLength = 0;\n\n // Find the null terminator\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('String symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n // Ensure we found the null terminator\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('String symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const value = symbolBuffer.subarray(startPointer, pointer).toString('utf-8');\n return {symbol: QvdSymbol.fromStringValue(value), bytesRead: pointer - startPointer + 1};\n}\n\n/**\n * Skips a string symbol in the buffer without parsing it.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {number} Bytes to skip\n */\nexport function skipStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n const startPointer = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('String symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('String symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n return pointer - startPointer + 1;\n}\n\n/**\n * Parses a dual integer symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDualIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for an integer\n if (pointer + 4 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading dual integer symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const intByteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 4));\n const intValue = Buffer.from(intByteData).readIntLE(0, intByteData.length);\n pointer += 4;\n\n // Parse the string portion\n const stringStart = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const stringValue = symbolBuffer.subarray(stringStart, pointer).toString('utf-8');\n return {symbol: QvdSymbol.fromDualIntValue(intValue, stringValue), bytesRead: pointer - (stringStart - 4) + 1};\n}\n\n/**\n * Parses a dual double symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDualDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for a double\n if (pointer + 8 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading dual double symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const doubleByteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 8));\n const doubleValue = Buffer.from(doubleByteData).readDoubleLE(0);\n pointer += 8;\n\n // Parse the string portion\n const stringStart = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const stringValue = symbolBuffer.subarray(stringStart, pointer).toString('utf-8');\n return {\n symbol: QvdSymbol.fromDualDoubleValue(doubleValue, stringValue),\n bytesRead: pointer - (stringStart - 8) + 1,\n };\n}\n\n/**\n * Skips a dual symbol (integer or double) in the buffer without parsing it.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {number} numericBytes Number of bytes for the numeric portion (4 for int, 8 for double)\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {number} Bytes to skip\n */\nexport function skipDualSymbol(symbolBuffer, pointer, bufferLength, numericBytes, fieldName, filePath) {\n if (pointer + numericBytes > bufferLength) {\n throw new QvdCorruptedError(`Buffer overflow reading dual symbol`, {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const startPointer = pointer;\n pointer += numericBytes;\n\n // Skip the string portion\n const maxStringLength = 1048576;\n let stringLength = 0;\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n return pointer - startPointer + 1;\n}\n\n/**\n * Parses a symbol based on the type byte.\n *\n * @param {number} typeByte The type byte\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position (after type byte)\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {boolean} shouldParse Whether to parse the symbol (true) or skip it (false)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol (or null if skipped) and bytes read\n */\nexport function parseSymbol(typeByte, symbolBuffer, pointer, bufferLength, fieldName, filePath, shouldParse) {\n switch (typeByte) {\n case 1: {\n // Integer value (4 Bytes)\n if (shouldParse) {\n return parseIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n return {symbol: null, bytesRead: 4};\n }\n case 2: {\n // Double value (8 Bytes)\n if (shouldParse) {\n return parseDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n return {symbol: null, bytesRead: 8};\n }\n case 4: {\n // String value (0 terminated)\n if (shouldParse) {\n return parseStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n case 5: {\n // Dual (Integer format) value (4 bytes), followed by string format\n if (shouldParse) {\n return parseDualIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipDualSymbol(symbolBuffer, pointer, bufferLength, 4, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n case 6: {\n // Dual (Double format) value (8 bytes), followed by string format\n if (shouldParse) {\n return parseDualDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipDualSymbol(symbolBuffer, pointer, bufferLength, 8, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n default: {\n throw new QvdParseError('Unknown symbol type byte', {\n typeByte: typeByte.toString(16),\n offset: pointer - 1,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n }\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport xml from 'xml2js';\nimport assert from 'assert';\nimport {QvdDataFrame} from './QvdDataFrame.js';\nimport {QvdParseError, QvdValidationError, QvdCorruptedError} from './QvdErrors.js';\nimport {validatePath} from './util/validatePath.js';\nimport {convertBitsToInt32} from './util/bitUtils.js';\nimport {estimateMemoryUsage, validateMemoryAvailability, warnLargeSymbolTable} from './util/memoryUtils.js';\nimport {\n validateSymbolTableSize,\n validateSymbolTableSizeEarly,\n validateFieldMetadata,\n validateIndexTableMetadata,\n validateFieldBitMetadata,\n} from './util/validationUtils.js';\nimport {parseSymbol} from './util/symbolParser.js';\n\n/**\n * Maximum number of bytes searched for the XML header delimiter before giving up.\n * Real QVD headers are a few kilobytes; the largest observed is well under 100KB.\n */\nconst MAX_HEADER_SIZE = 16 * 1024 * 1024;\n\n/**\n * Maximum length of a single fs.read call. Node's fs.read binding requires the length to fit\n * in an Int32: a larger value aborts the process via a C++ assertion instead of throwing.\n */\nconst READ_CHUNK_SIZE = 512 * 1024 * 1024;\n\n/**\n * Parses a QVD file and loads it into memory.\n */\nexport class QvdFileReader {\n /**\n * Constructs a new QVD file parser.\n *\n * @param {string} filePath The path to the QVD file to load.\n * @param {Object} [options={}] Options for the reader.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file\n * path must be within this directory, with symlinks resolved first, so a link inside it that\n * points outside it is rejected. Defaults to the current working directory. To permit\n * an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or\n * empty value falls back to the working directory rather than removing the restriction.\n * @param {number} [options.memorySafetyFactor=0.3] Memory safety factor (0.0-1.0). Determines\n * what percentage of available memory (or V8 heap limit, whichever is smaller) can be used\n * for loading QVD files. Default is 0.3 (30%). Increase for larger heap configurations.\n */\n constructor(filePath, options = {}) {\n const {allowedDir, memorySafetyFactor = 0.3} = options;\n this._path = validatePath(filePath, allowedDir);\n this._memorySafetyFactor = memorySafetyFactor;\n this._buffer = null;\n this._headerOffset = null;\n this._symbolTableOffset = null;\n this._indexTableOffset = null;\n this._header = null;\n /** @type {Array<Array<import('./QvdSymbol.js').QvdSymbol>>|null} */\n this._symbolTable = null;\n /** @type {Array<Array<number>>|null} */\n this._indexTable = null;\n /** @type {number|null} */\n this._fileSize = null;\n }\n\n /**\n * Reads the binary data of the QVD file.\n *\n * LAZY LOADING OPTIMIZATION: When maxRows is specified, this method implements\n * true lazy loading by reading only the necessary portions of the file from disk.\n *\n * For large files (e.g., 5GB), loading only the first 1000 rows can save significant\n * memory and time:\n * - Full load: 5GB in memory, ~30-60s load time\n * - Lazy load (maxRows=1000): ~1.75-2GB in memory, ~2-5s load time\n *\n * Algorithm for Lazy Loading:\n * 1. Stream-read the file until XML header delimiter is found\n * 2. Parse header to determine symbol table and index table locations\n * 3. Calculate bytes needed: header + full symbol table + partial index table\n * 4. Read only those calculated bytes using fs.open/read\n * 5. Rest of parsing proceeds normally with limited data\n *\n * WHY THIS APPROACH:\n * - Symbol table must be fully loaded (contains all unique values)\n * - Index table can be partially loaded (only rows we need)\n * - Streaming for header finding is efficient for unknown header sizes\n * - Direct byte-range reading for remaining data is fastest\n *\n * @param {number|null} maxRows The maximum number of rows to load. If null, all data is loaded.\n * @private\n */\n async _readData(maxRows = null) {\n if (maxRows === null) {\n // Load entire file into memory (original behavior)\n // This is simple and fast for small to medium files\n this._buffer = await fs.promises.readFile(this._path);\n this._fileSize = this._buffer.length;\n return;\n }\n\n const HEADER_DELIMITER = '\\r\\n\\0';\n const CHUNK_SIZE = 64 * 1024; // 64KB chunks - balance between memory and I/O efficiency\n\n // Use streaming to find the header delimiter dynamically\n // We don't know header size in advance, so we must stream-read\n const stream = fs.createReadStream(this._path, {\n highWaterMark: CHUNK_SIZE,\n });\n\n /** @type {Array<Buffer>} */\n const headerChunks = [];\n let headerBytes = 0;\n /** Last (delimiter length - 1) bytes seen so far, carried across chunk boundaries. */\n let tail = Buffer.alloc(0);\n let headerBuffer = Buffer.alloc(0);\n let headerDelimiterIndex = -1;\n\n try {\n // Read chunks until we find the delimiter.\n //\n // Chunks are collected and concatenated once, and each chunk is searched individually\n // (with a small carry-over so a delimiter straddling a chunk boundary is still found).\n // Concatenating the whole accumulated buffer on every chunk and re-scanning it from the\n // start is quadratic: a 200 MB delimiter-less file cost 43 s and 13 GB of memory.\n for await (const chunk of stream) {\n // Search the new chunk prefixed by the bytes already seen, so a delimiter spanning a\n // chunk boundary is not missed.\n //\n // The carry is kept in `tail` across iterations rather than read back off the previous\n // chunk, because a chunk may be shorter than the delimiter. Taking min(bytesSoFar, 2)\n // bytes from a 1-byte previous chunk yields only 1 byte, which both misses a delimiter\n // spread over three chunks and leaves the reported offset short by the difference.\n const chunkStart = headerBytes;\n const searchBuffer = tail.length > 0 ? Buffer.concat([tail, chunk]) : chunk;\n const foundInSearch = searchBuffer.indexOf(HEADER_DELIMITER);\n\n headerChunks.push(chunk);\n headerBytes += chunk.length;\n\n if (foundInSearch !== -1) {\n // searchBuffer starts tail.length bytes before this chunk does.\n headerDelimiterIndex = chunkStart - tail.length + foundInSearch;\n stream.destroy();\n break;\n }\n\n // Copy the carry instead of keeping a subarray view, which would pin the whole chunk.\n tail = Buffer.from(searchBuffer.subarray(-(HEADER_DELIMITER.length - 1)));\n\n // Real QVD headers are a few kilobytes. Without a cap, a non-QVD or corrupt file is\n // read to its end before the error below is raised, which is a denial-of-service\n // vector for any service that accepts uploaded files.\n if (headerBytes > MAX_HEADER_SIZE) {\n stream.destroy();\n throw new QvdCorruptedError(\n `The XML header delimiter was not found within the first ${MAX_HEADER_SIZE / (1024 * 1024)}MB of the file.`,\n {\n file: this._path,\n bytesSearched: headerBytes,\n maxHeaderSize: MAX_HEADER_SIZE,\n stage: 'readData',\n },\n );\n }\n }\n } catch (error) {\n // Destroying the stream once the delimiter is found surfaces as ERR_STREAM_PREMATURE_CLOSE.\n // That one case is expected and ignored; everything else must propagate.\n //\n // The previous condition also required a 'code' property, so any error without one — a\n // TypeError or RangeError raised in the loop body, or a stream error from a source that\n // does not set a code — was swallowed. Execution then fell through to the generic\n // 'header not properly delimited' error below, reporting file corruption for what was\n // actually a bug or an I/O failure.\n const isExpectedEarlyClose =\n headerDelimiterIndex !== -1 &&\n error !== null &&\n typeof error === 'object' &&\n /** @type {{code?: unknown}} */ (error).code === 'ERR_STREAM_PREMATURE_CLOSE';\n\n if (!isExpectedEarlyClose) {\n throw error;\n }\n }\n\n if (headerDelimiterIndex === -1) {\n throw new QvdCorruptedError(\n 'The XML header section does not exist or is not properly delimited from the binary data.',\n {\n file: this._path,\n stage: 'readData',\n },\n );\n }\n\n headerBuffer = Buffer.concat(headerChunks);\n\n const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;\n\n // Parse header to get metadata about symbol and index table locations\n const headerXml = headerBuffer.subarray(0, headerEndIndex).toString();\n const headerObj = await xml.parseStringPromise(headerXml, {explicitArray: false});\n\n if (!headerObj) {\n throw new QvdParseError('The XML header could not be parsed.', {\n file: this._path,\n stage: 'readData',\n });\n }\n\n const symbolTableOffset = headerEndIndex;\n const symbolTableLength = parseInt(headerObj['QvdTableHeader']['Offset'], 10);\n const indexTableOffset = symbolTableOffset + symbolTableLength;\n const recordSize = parseInt(headerObj['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(headerObj['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToLoad = Math.min(maxRows, totalRows);\n\n // SAFETY CHECK: Very large symbol tables (>500MB) are still blocked to prevent OOM\n // Phase 2 filtering can handle up to ~500MB symbol tables efficiently\n validateSymbolTableSizeEarly(symbolTableLength, this._path);\n\n // Validate the header numbers before they are used to size an allocation. Without this,\n // a NaN or negative value reaches Buffer.alloc and surfaces as a raw Node RangeError.\n for (const [name, value] of [\n ['Offset', symbolTableLength],\n ['RecordByteSize', recordSize],\n ['NoOfRecords', totalRows],\n ]) {\n if (!Number.isSafeInteger(value) || Number(value) < 0) {\n throw new QvdCorruptedError(`Invalid header value: ${name}`, {\n name,\n value,\n file: this._path,\n stage: 'readData',\n });\n }\n }\n\n // Calculate how much of the index table we need to read\n const indexTableBytesToRead = rowsToLoad * recordSize;\n\n // Calculate total bytes needed: header + symbol table + partial index table\n const totalBytesToRead = indexTableOffset + indexTableBytesToRead;\n\n // Now read the exact portion we need from the file\n const fd = await fs.promises.open(this._path, 'r');\n try {\n const {size: fileSize} = await fd.stat();\n this._fileSize = fileSize;\n\n // The buffer size is derived entirely from header values, which may not describe the\n // file on disk (truncated download, interrupted copy, file still being written, or a\n // deliberately crafted header). Reading past the end would otherwise leave the tail of\n // the buffer holding whatever memory the allocator handed out, and that memory is then\n // parsed as symbol and index data.\n if (totalBytesToRead > fileSize) {\n throw new QvdCorruptedError('The file is shorter than its header claims.', {\n file: this._path,\n fileSize,\n requiredBytes: totalBytesToRead,\n stage: 'readData',\n });\n }\n\n // Zero-filled rather than allocUnsafe: if any path ever fails to overwrite part of this\n // buffer, the result is zeros instead of leaked process memory.\n this._buffer = Buffer.alloc(totalBytesToRead);\n\n // Read in bounded chunks, checking bytesRead each time. A single fs.read call with a\n // length of 2^31 or more does not throw - it trips a C++ assertion and aborts the whole\n // process, which no try/catch can intercept.\n let position = 0;\n while (position < totalBytesToRead) {\n const length = Math.min(READ_CHUNK_SIZE, totalBytesToRead - position);\n // @ts-ignore - Buffer type compatibility\n const {bytesRead} = await fd.read(this._buffer, position, length, position);\n\n if (bytesRead === 0) {\n throw new QvdCorruptedError('Unexpected end of file while reading QVD data.', {\n file: this._path,\n fileSize,\n bytesRead: position,\n requiredBytes: totalBytesToRead,\n stage: 'readData',\n });\n }\n\n position += bytesRead;\n }\n } finally {\n await fd.close();\n }\n }\n\n /**\n * Parses the XML header of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n */\n async _parseHeader() {\n if (!this._buffer) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseHeader',\n },\n );\n }\n\n const HEADER_DELIMITER = '\\r\\n\\0';\n\n const headerBeginIndex = 0;\n const headerDelimiterIndex = this._buffer.indexOf(HEADER_DELIMITER, headerBeginIndex);\n\n // Check explicitly for -1 (not found) rather than using falsy check (!headerDelimiterIndex)\n // because indexOf() returns 0 when the delimiter is at position 0, which is a valid buffer index.\n // Using !0 would incorrectly treat position 0 as an error.\n if (headerDelimiterIndex === -1) {\n throw new QvdCorruptedError(\n 'The XML header section does not exist or is not properly delimited from the binary data.',\n {\n file: this._path,\n stage: 'parseHeader',\n },\n );\n }\n\n const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;\n const headerBuffer = this._buffer.subarray(headerBeginIndex, headerEndIndex);\n\n /*\n * The following instruction parses the XML header into a JSON object. It is important to\n * note that the object is a plain JavaScript object and not an instance of representative\n * class. Hence, types are not casted, therefore all raw values are strings, and child nodes\n * that contain an array of objects are not represented directly as an array but as an object\n * with a property, named like the array item tag, that is an array of the actual objects. The\n * same applies to child nodes that contain a single object and the root node.\n *\n * The following XML representation of the QVD header for example...\n *\n * <QvdTableHeader>\n * ...\n * <Fields>\n * <QvdFieldHeader>\n * <FieldName>Field1</FieldName>\n * ...\n * </QvdFieldHeader>\n * <QvdFieldHeader>\n * <FieldName>Field1</FieldName>\n * ...\n * </QvdFieldHeader>\n * </Fields>\n * </QvdTableHeader>\n *\n * ...is parsed into the following object:\n *\n * {\n * QvdTableHeader: {\n * ...,\n * Fields: {\n * QvdFieldHeader: [\n * { FieldName: 'Field1', ...},\n * { FieldName: 'Field2', ...}\n * ]\n * }\n * }\n * }\n */\n\n // Note: xml2js (via sax-js) does not support external entity resolution\n // by default, providing inherent protection against XXE attacks.\n this._header = await xml.parseStringPromise(headerBuffer.toString(), {explicitArray: false});\n\n if (!this._header) {\n throw new QvdParseError('The XML header could not be parsed.', {\n file: this._path,\n stage: 'parseHeader',\n });\n }\n\n /*\n * Because the three parts of the QVD file, header, symbol and index table, are seamlessly concatenated,\n * the end of the respective previous part is the beginning of the next part.\n */\n\n this._headerOffset = headerBeginIndex;\n this._symbolTableOffset = headerEndIndex;\n this._indexTableOffset = this._symbolTableOffset + parseInt(this._header['QvdTableHeader']['Offset'], 10);\n }\n\n /**\n * Estimates the memory usage for loading a QVD file with given parameters.\n * Takes into account Phase 2.5 optimization which skips parsing unused symbols.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @returns {number} Estimated memory usage in bytes\n * @private\n */\n _estimateMemoryUsage(symbolTableSize, maxRows, totalRows) {\n return estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n }\n\n /**\n * Analyzes the index table to determine which symbols are actually needed.\n * This is used for two-pass symbol filtering optimization.\n *\n * @param {number} maxRows The maximum number of rows to analyze.\n * @returns {Promise<Map<string, Set<number>>>} Map of field names to Set of needed symbol indices.\n * @private\n */\n async _analyzeIndexTableSymbolUsage(maxRows) {\n if (!this._buffer || !this._header || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'analyzeIndexTableSymbolUsage',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const recordSize = parseInt(this._header['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToAnalyze = Math.min(maxRows, totalRows);\n const indexTableLength = parseInt(this._header['QvdTableHeader']['Length'], 10);\n\n const indexBuffer = this._buffer.subarray(this._indexTableOffset, this._indexTableOffset + indexTableLength + 1);\n\n // Map of field name -> Set of symbol indices needed\n /** @type {Map<string, Set<number>>} */\n const symbolUsage = new Map();\n\n // Initialize sets for each field\n fields.forEach((field) => {\n symbolUsage.set(field['FieldName'], new Set());\n });\n\n // Parse rows to collect symbol indices\n for (\n let pointer = 0, rowCount = 0;\n pointer < indexBuffer.length && rowCount < rowsToAnalyze;\n pointer += recordSize, rowCount++\n ) {\n const bytes = new Int32Array(indexBuffer.subarray(pointer, pointer + recordSize));\n bytes.reverse();\n\n const mask = bytes\n .reduce((bits, byte) => bits + ('00000000' + byte.toString(2)).slice(-8), '')\n .split('')\n .reverse()\n .map((bit) => parseInt(bit));\n\n // Extract symbol index for each field\n fields.forEach((field) => {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n const bias = parseInt(field['Bias'], 10);\n\n let symbolIndex;\n\n if (bitWidth === 0) {\n symbolIndex = 0;\n } else {\n symbolIndex = this._convertBitsToInt32(mask.slice(bitOffset, bitOffset + bitWidth));\n }\n\n // Apply bias. This MUST use the same sign as _parseIndexTable (which adds the bias),\n // otherwise the symbols recorded as \"needed\" here are not the ones the parse pass\n // looks up, and every affected cell silently reads back as undefined. Qlik encodes\n // nullable fields with Bias=-2, so getting this wrong corrupts every nullable column.\n symbolIndex += bias;\n\n // Negative indices denote NULL and reference no symbol, so they never need to be kept.\n if (symbolIndex < 0) {\n return;\n }\n\n // Add to the set of needed symbols for this field\n const fieldName = field['FieldName'];\n symbolUsage.get(fieldName)?.add(symbolIndex);\n });\n }\n\n return symbolUsage;\n }\n\n /**\n * Parses the symbol table of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n *\n * @param {Map<string, Set<number>>|null} symbolsToKeep Optional map of field names to symbol indices to keep.\n * If provided, only these symbols will be parsed (two-pass filtering optimization).\n * @param {number|null} maxRows Optional maximum number of rows being loaded (for memory estimation).\n */\n async _parseSymbolTable(symbolsToKeep = null, maxRows = null) {\n if (!this._buffer || !this._header || !this._symbolTableOffset || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseSymbolTable',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n const symbolBuffer = this._buffer.subarray(this._symbolTableOffset, this._indexTableOffset);\n const symbolTableSize = symbolBuffer.length;\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n\n // SAFETY CHECK 1: Absolute ceiling to prevent pathological cases\n // Phase 2.5 optimization allows much larger symbol tables when using maxRows,\n // but we still need an absolute maximum to prevent truly extreme cases\n validateSymbolTableSize(symbolTableSize, this._path, totalRows);\n\n // SAFETY CHECK 2: Dynamic memory validation\n // Check if we have enough available memory to load this file safely\n validateMemoryAvailability(symbolTableSize, maxRows, totalRows, this._path, this._memorySafetyFactor);\n\n // WARNING ZONE: Large files without maxRows parameter\n // Educate users about best practices but don't block\n warnLargeSymbolTable(symbolTableSize, maxRows, totalRows);\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n /*\n * The symbol table is a contiguous byte array that contains all possible symbols/values of all fields/columns.\n * The symbols/values of one field are stored consecutively in the same order as the fields/columns are defined\n * in the header. The length of the symbol area as well as it's offset, relativ to the begin of the symbol\n * table, are also defined in the header.\n */\n\n // Validate all field metadata before processing to prevent buffer overflow attacks\n for (const field of fields) {\n validateFieldMetadata(field, symbolBuffer.length, this._path);\n }\n\n // Parse all possible symbols of each field/column\n // Phase 2.5 optimization: Skip parsing entirely for symbols we don't need\n this._symbolTable = fields.map((/** @type {any} */ field) => {\n const symbolsOffset = parseInt(field['Offset'], 10); // Offset of the column's symbol area in the symbol table\n const symbolsLength = parseInt(field['Length'], 10); // Length of the column's symbol area in the symbol table\n\n const fieldName = field['FieldName'];\n const neededSymbols = symbolsToKeep ? symbolsToKeep.get(fieldName) : null;\n const filteringEnabled = neededSymbols !== null;\n\n const symbols = [];\n let symbolIndex = 0; // Track current symbol index as we parse\n\n // Parse all possible values of the current field/column\n for (let pointer = symbolsOffset; pointer < symbolsOffset + symbolsLength; pointer++) {\n // Each stored symbol consists of a type byte and the actual value, which length depends on the type\n const typeByte = symbolBuffer[pointer++];\n\n // Check if we should keep this symbol (filtering mode)\n const shouldKeepSymbol = !filteringEnabled || !!(neededSymbols && neededSymbols.has(symbolIndex));\n\n // Use utility function to parse or skip symbol\n const {symbol, bytesRead} = parseSymbol(\n typeByte,\n symbolBuffer,\n pointer,\n symbolBuffer.length,\n fieldName,\n this._path,\n shouldKeepSymbol,\n );\n\n symbols.push(symbol);\n pointer += bytesRead - 1; // -1 because the loop will increment\n symbolIndex++;\n }\n\n return symbols;\n // @ts-ignore - Symbol table type assignment\n });\n }\n\n /**\n * Utility method to convert a bit array to an integer value.\n *\n * @param {Array<number>} bits The bit array\n * @return {Number} The integer value\n */\n _convertBitsToInt32(bits) {\n return convertBitsToInt32(bits);\n }\n\n /**\n * Parses the bit stuffed index table of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n *\n * @param {number|null} maxRows The maximum number of rows to parse. If null, all rows are parsed.\n */\n async _parseIndexTable(maxRows = null) {\n if (!this._buffer || !this._header || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseIndexTable',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n // Size of a single row of the index table in bytes\n const recordSize = parseInt(this._header['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToLoad = maxRows !== null ? Math.min(maxRows, totalRows) : totalRows;\n const indexTableLength = parseInt(this._header['QvdTableHeader']['Length'], 10);\n\n // Validate all index table metadata\n validateIndexTableMetadata(\n recordSize,\n totalRows,\n indexTableLength,\n this._indexTableOffset,\n this._buffer.length,\n rowsToLoad,\n this._path,\n this._fileSize,\n );\n\n const indexBuffer = this._buffer.subarray(this._indexTableOffset, this._indexTableOffset + indexTableLength + 1);\n\n // Validate BitOffset and BitWidth for all fields before processing\n for (const field of fields) {\n validateFieldBitMetadata(field, recordSize, this._path);\n }\n\n this._indexTable = [];\n\n // Parse rows of the index table, each row contains the indices of the symbol table for each field/column\n for (\n let pointer = 0, rowCount = 0;\n pointer < indexBuffer.length && rowCount < rowsToLoad;\n pointer += recordSize, rowCount++\n ) {\n // Validate we have enough bytes for this record\n if (pointer + recordSize > indexBuffer.length) {\n throw new QvdCorruptedError('Buffer overflow reading index table record', {\n pointer,\n recordSize,\n bufferSize: indexBuffer.length,\n file: this._path,\n stage: 'parseIndexTable',\n });\n }\n\n const bytes = new Int32Array(indexBuffer.subarray(pointer, pointer + recordSize));\n bytes.reverse();\n\n // The bit mask contains the bit stuffed indices of the symbol table of the current row\n const mask = bytes\n .reduce((bits, byte) => bits + ('00000000' + byte.toString(2)).slice(-8), '')\n .split('')\n .reverse()\n .map((bit) => parseInt(bit));\n\n /** @type {number[]} */\n const symbolIndices = [];\n\n // Extract the index from the current row's bit mask for each field/column\n fields.forEach((/** @type {any} */ field) => {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n const bias = parseInt(field['Bias'], 10);\n\n let symbolIndex;\n\n if (bitWidth === 0) {\n symbolIndex = 0;\n } else {\n symbolIndex = this._convertBitsToInt32(mask.slice(bitOffset, bitOffset + bitWidth));\n }\n\n symbolIndex += bias;\n symbolIndices.push(symbolIndex);\n });\n\n this._indexTable.push(symbolIndices);\n }\n\n // The loop is bounded by the buffer as well as by rowsToLoad, so a short buffer would\n // otherwise silently yield fewer rows than the header declares.\n if (this._indexTable.length !== rowsToLoad) {\n throw new QvdCorruptedError('Index table contains fewer records than expected', {\n expectedRows: rowsToLoad,\n actualRows: this._indexTable.length,\n totalRows,\n recordSize,\n file: this._path,\n stage: 'parseIndexTable',\n });\n }\n }\n\n /**\n * Loads the QVD file into memory and parses it.\n *\n * @param {number|null} maxRows The maximum number of rows to load. If null, all rows are loaded.\n * Must be a non-negative integer when given.\n * @throws {QvdValidationError} If maxRows is neither null nor a non-negative integer.\n * @return {Promise<QvdDataFrame>} The loaded QVD file.\n */\n async load(maxRows = null) {\n // Validate before any I/O. Every downstream use is Math.min(maxRows, totalRows), which\n // silently accepts nonsense: a negative value yields a negative row count, NaN makes every\n // comparison false, and a fractional value produces a fractional loop bound. Each of those\n // returns a wrong or empty data frame rather than an error, so reject them up front.\n // undefined never reaches here: the default parameter above turns it into null.\n if (maxRows !== null && (typeof maxRows !== 'number' || !Number.isInteger(maxRows) || maxRows < 0)) {\n throw new QvdValidationError('maxRows must be a non-negative integer, or null to load all rows', {\n provided: maxRows,\n type: typeof maxRows,\n file: this._path,\n });\n }\n\n await this._readData(maxRows);\n await this._parseHeader();\n\n // Determine if we should use two-pass symbol filtering\n // This optimization is beneficial for large symbol tables with limited row access\n let symbolsToKeep = null;\n\n if (maxRows !== null && this._header) {\n const symbolTableLength = parseInt(this._header['QvdTableHeader']['Offset'], 10);\n const SYMBOL_FILTERING_THRESHOLD = 50 * 1024 * 1024; // 50MB\n\n // Use two-pass filtering for symbol tables > 50MB when loading limited rows\n if (symbolTableLength > SYMBOL_FILTERING_THRESHOLD) {\n // Pass 1: Analyze which symbols are actually needed\n symbolsToKeep = await this._analyzeIndexTableSymbolUsage(maxRows);\n\n // Log the optimization for visibility\n const totalSymbols = Array.from(symbolsToKeep.values()).reduce((sum, set) => sum + set.size, 0);\n console.log(\n `[Phase 2.5 Optimization] Using stream-and-skip parsing: keeping ${totalSymbols} symbols from ${(symbolTableLength / 1024 / 1024).toFixed(1)}MB symbol table`,\n );\n }\n }\n\n // Pass 2: Parse symbol table (with filtering if enabled)\n await this._parseSymbolTable(symbolsToKeep, maxRows);\n await this._parseIndexTable(maxRows);\n\n assert(this._header, 'The QVD file header has not been parsed.');\n assert(this._symbolTable, 'The QVD file symbol table has not been parsed.');\n assert(this._indexTable, 'The QVD file index table has not been parsed.');\n\n /**\n * Retrieves the values of a specific row of the QVD file. Values are in the same order\n * as the field names.\n *\n * @param {number} index The index of the row.\n * @return {Array<any>} The values of the row.\n */\n const getRow = (index) => {\n if (!this._indexTable || index >= this._indexTable.length) {\n throw new QvdValidationError('Row index out of bounds', {\n index,\n max: this._indexTable ? this._indexTable.length - 1 : -1,\n file: this._path,\n });\n }\n\n return this._indexTable?.[index].map((/** @type {number} */ symbolIndex, /** @type {number} */ fieldIndex) => {\n if (symbolIndex < 0) {\n return null;\n }\n\n const symbol = this._symbolTable?.[fieldIndex]?.[symbolIndex];\n const value = symbol?.toPrimaryValue();\n\n if (typeof value === 'string') {\n // Number('') and Number(' ') are 0, which silently turned every blank cell Qlik\n // stored into the number zero - indistinguishable from a real zero, and persisted as\n // one on the next write. Blank strings are never numeric, so exclude them.\n if (value.trim() !== '' && !isNaN(Number(value))) {\n return Number(value);\n }\n }\n\n return value;\n });\n };\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const columns = fields.map((/** @type {any} */ field) => field['FieldName']);\n const data = this._indexTable.map((_, index) => getRow(index));\n\n // Pass the complete header metadata to the data frame\n const metadata = this._header['QvdTableHeader'];\n\n return new QvdDataFrame(data, columns, metadata);\n }\n}\n","// @ts-check\n\nimport {QvdValidationError} from './QvdErrors.js';\n\n/**\n * @typedef {Object} QvdNumberFormat\n * @property {string} Type - Number format type\n * @property {string} nDec - Number of decimals\n * @property {string} UseThou - Use thousands separator\n * @property {string} Fmt - Format string\n * @property {string} Dec - Decimal separator\n * @property {string} Thou - Thousands separator\n */\n\n/**\n * @typedef {Object} QvdFieldHeader\n * @property {string} FieldName - The name of the field\n * @property {string|number} [BitOffset] - The bit offset\n * @property {string|number} [BitWidth] - The bit width\n * @property {string|number} [Bias] - The bias value\n * @property {string|number} [NoOfSymbols] - Number of symbols\n * @property {string|number} [Offset] - The offset\n * @property {string|number} [Length] - The length\n * @property {string} [Comment] - Field comment\n * @property {QvdNumberFormat|string} [NumberFormat] - Number format\n * @property {Object|string} [Tags] - Field tags\n */\n\n/**\n * @typedef {Object} QvdFields\n * @property {QvdFieldHeader|QvdFieldHeader[]} QvdFieldHeader - Field header(s)\n */\n\n/**\n * @typedef {Object} QvdMetadata\n * @property {string|number} [QvBuildNo] - QlikView build number\n * @property {string} [CreatorDoc] - Creator document\n * @property {string} [CreateUtcTime] - Creation UTC time\n * @property {string} [SourceCreateUtcTime] - Source creation UTC time\n * @property {string} [SourceFileUtcTime] - Source file UTC time\n * @property {string|number} [SourceFileSize] - Source file size\n * @property {string} [StaleUtcTime] - Stale UTC time\n * @property {string} [TableName] - Table name\n * @property {string|number} [NoOfRecords] - Number of records\n * @property {string|number} [RecordByteSize] - Record byte size\n * @property {string|number} [Offset] - Offset\n * @property {string|number} [Length] - Length\n * @property {string} [Compression] - Compression type\n * @property {string} [Comment] - Comment\n * @property {string} [EncryptionInfo] - Encryption info\n * @property {string} [TableTags] - Table tags\n * @property {string} [ProfilingData] - Profiling data\n * @property {Object|string} [Lineage] - Lineage\n * @property {QvdFields} [Fields] - Fields information\n */\n\n/**\n * Represents a loaded QVD file.\n */\nexport class QvdDataFrame {\n /**\n * Represents the data frame stored inside a QVD file.\n * @param {Array<Array<any>>} data The data of the data frame.\n * @param {Array<string>} columns The columns of the data frame.\n * @param {QvdMetadata|null} metadata The metadata from the QVD file header (optional).\n */\n constructor(data, columns, metadata = null) {\n this._data = data;\n this._columns = columns;\n this._metadata = metadata;\n }\n\n /**\n * Returns the data of the data frame.\n */\n get data() {\n return this._data;\n }\n\n /**\n * Returns the columns of the data frame.\n */\n get columns() {\n return this._columns;\n }\n\n /**\n * Returns the shape of the data frame.\n */\n get shape() {\n return [this._data.length, this._columns.length];\n }\n\n /**\n * Returns the complete metadata object from the QVD file header.\n * @return {Object|null} The complete metadata object or null if not available.\n */\n get metadata() {\n return this._metadata;\n }\n\n /**\n * Returns file-level metadata from the QVD header.\n * @return {Object} File-level metadata properties.\n */\n get fileMetadata() {\n if (!this._metadata) {\n return {};\n }\n\n const header = this._metadata;\n return {\n qvBuildNo: header.QvBuildNo,\n creatorDoc: header.CreatorDoc,\n createUtcTime: header.CreateUtcTime,\n sourceCreateUtcTime: header.SourceCreateUtcTime,\n sourceFileUtcTime: header.SourceFileUtcTime,\n sourceFileSize: header.SourceFileSize,\n staleUtcTime: header.StaleUtcTime,\n tableName: header.TableName,\n noOfRecords: header.NoOfRecords,\n recordByteSize: header.RecordByteSize,\n offset: header.Offset,\n length: header.Length,\n compression: header.Compression,\n comment: header.Comment,\n encryptionInfo: header.EncryptionInfo,\n tableTags: header.TableTags,\n profilingData: header.ProfilingData,\n lineage: header.Lineage,\n };\n }\n\n /**\n * Returns field-level metadata for a specific field/column.\n * @param {string} fieldName The name of the field.\n * @return {Object|null} Field metadata or null if field not found.\n */\n getFieldMetadata(fieldName) {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return null;\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const field = fields.find((f) => f.FieldName === fieldName);\n if (!field) {\n return null;\n }\n\n return {\n fieldName: field.FieldName,\n bitOffset: field.BitOffset,\n bitWidth: field.BitWidth,\n bias: field.Bias,\n noOfSymbols: field.NoOfSymbols,\n offset: field.Offset,\n length: field.Length,\n comment: field.Comment,\n numberFormat: field.NumberFormat,\n tags: field.Tags,\n };\n }\n\n /**\n * Returns field-level metadata for all fields.\n * @return {Array<Object>} Array of field metadata objects.\n */\n getAllFieldMetadata() {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return [];\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n return fields.map((field) => ({\n fieldName: field.FieldName,\n bitOffset: field.BitOffset,\n bitWidth: field.BitWidth,\n bias: field.Bias,\n noOfSymbols: field.NoOfSymbols,\n offset: field.Offset,\n length: field.Length,\n comment: field.Comment,\n numberFormat: field.NumberFormat,\n tags: field.Tags,\n }));\n }\n\n /**\n * @typedef {Object} FileMetadataUpdate\n * @property {string|number} [qvBuildNo] - QlikView build number\n * @property {string} [creatorDoc] - Creator document\n * @property {string} [createUtcTime] - Creation UTC time\n * @property {string} [sourceCreateUtcTime] - Source creation UTC time\n * @property {string} [sourceFileUtcTime] - Source file UTC time\n * @property {string|number} [sourceFileSize] - Source file size\n * @property {string} [staleUtcTime] - Stale UTC time\n * @property {string} [tableName] - Table name\n * @property {string} [compression] - Compression type\n * @property {string} [comment] - Comment\n * @property {string} [encryptionInfo] - Encryption info\n * @property {string} [tableTags] - Table tags\n * @property {string} [profilingData] - Profiling data\n * @property {Object|string} [lineage] - Lineage\n */\n\n /**\n * Sets modifiable file-level metadata. Immutable properties related to data storage are ignored.\n * @param {FileMetadataUpdate} metadata Object containing metadata properties to update.\n */\n setFileMetadata(metadata) {\n if (!this._metadata) {\n // Initialize metadata structure if it doesn't exist\n this._metadata = {\n QvBuildNo: 50667,\n CreatorDoc: '',\n CreateUtcTime: '',\n SourceCreateUtcTime: '',\n SourceFileUtcTime: '',\n SourceFileSize: -1,\n StaleUtcTime: '',\n TableName: '',\n Fields: {\n QvdFieldHeader: this._columns.map((column) => ({\n FieldName: column,\n BitOffset: 0,\n BitWidth: 0,\n Bias: 0,\n NoOfSymbols: 0,\n Offset: 0,\n Length: 0,\n Comment: '',\n NumberFormat: {\n Type: 'UNKNOWN',\n nDec: '0',\n UseThou: '0',\n Fmt: '',\n Dec: '',\n Thou: '',\n },\n Tags: {},\n })),\n },\n NoOfRecords: 0,\n RecordByteSize: 0,\n Offset: 0,\n Length: 0,\n Compression: '',\n Comment: '',\n EncryptionInfo: '',\n TableTags: '',\n ProfilingData: '',\n Lineage: {},\n };\n }\n\n // Only allow modification of certain fields (not Offset, Length, NoOfRecords, RecordByteSize)\n const modifiableFields = [\n 'qvBuildNo',\n 'creatorDoc',\n 'createUtcTime',\n 'sourceCreateUtcTime',\n 'sourceFileUtcTime',\n 'sourceFileSize',\n 'staleUtcTime',\n 'tableName',\n 'compression',\n 'comment',\n 'encryptionInfo',\n 'tableTags',\n 'profilingData',\n 'lineage',\n ];\n\n // Map camelCase to XML property names\n const fieldMapping = {\n qvBuildNo: 'QvBuildNo',\n creatorDoc: 'CreatorDoc',\n createUtcTime: 'CreateUtcTime',\n sourceCreateUtcTime: 'SourceCreateUtcTime',\n sourceFileUtcTime: 'SourceFileUtcTime',\n sourceFileSize: 'SourceFileSize',\n staleUtcTime: 'StaleUtcTime',\n tableName: 'TableName',\n compression: 'Compression',\n comment: 'Comment',\n encryptionInfo: 'EncryptionInfo',\n tableTags: 'TableTags',\n profilingData: 'ProfilingData',\n lineage: 'Lineage',\n };\n\n modifiableFields.forEach((field) => {\n // @ts-ignore - Dynamic property access for metadata mapping\n if (metadata[field] !== undefined) {\n // @ts-ignore - Dynamic property access for metadata mapping\n this._metadata[fieldMapping[field]] = metadata[field];\n }\n });\n }\n\n /**\n * @typedef {Object} FieldMetadataUpdate\n * @property {string} [comment] - Field comment\n * @property {QvdNumberFormat|string} [numberFormat] - Number format\n * @property {Object|string} [tags] - Field tags\n */\n\n /**\n * Sets modifiable field-level metadata for a specific field.\n * Immutable properties related to data storage (Offset, Length, BitOffset, etc.) are ignored.\n * @param {string} fieldName The name of the field.\n * @param {FieldMetadataUpdate} metadata Object containing field metadata properties to update.\n */\n setFieldMetadata(fieldName, metadata) {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return;\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n this._metadata.Fields.QvdFieldHeader = fields;\n }\n\n const fieldIndex = fields.findIndex((f) => f.FieldName === fieldName);\n if (fieldIndex === -1) {\n return;\n }\n\n // Only allow modification of Comment, NumberFormat, and Tags (not Offset, Length, BitOffset, etc.)\n if (metadata.comment !== undefined) {\n fields[fieldIndex].Comment = metadata.comment;\n }\n if (metadata.numberFormat !== undefined) {\n fields[fieldIndex].NumberFormat = metadata.numberFormat;\n }\n if (metadata.tags !== undefined) {\n fields[fieldIndex].Tags = metadata.tags;\n }\n }\n\n /**\n * Returns the first n rows of the data frame.\n *\n * @param {number} n The number of rows to return.\n * @return {QvdDataFrame} The first n rows of the data frame.\n * @throws {QvdValidationError} If n is not a non-negative integer.\n */\n head(n = 5) {\n if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) {\n throw new QvdValidationError('head() requires a non-negative integer', {\n provided: n,\n type: typeof n,\n });\n }\n return new QvdDataFrame(this._data.slice(0, n), this._columns, this._metadata);\n }\n\n /**\n * Returns the last n rows of the data frame.\n *\n * @param {number} n The number of rows to return.\n * @return {QvdDataFrame} The first n rows of the data frame.\n * @throws {QvdValidationError} If n is not a non-negative integer.\n */\n tail(n = 5) {\n if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) {\n throw new QvdValidationError('tail() requires a non-negative integer', {\n provided: n,\n type: typeof n,\n });\n }\n return new QvdDataFrame(n === 0 ? [] : this._data.slice(-n), this._columns, this._metadata);\n }\n\n /**\n * Returns the selected rows of the data frame.\n *\n * @param {...number} args The indices of the rows to return.\n * @return {QvdDataFrame} The selected rows of the data frame.\n * @throws {QvdValidationError} If any index is not an integer or is out of bounds.\n */\n rows(...args) {\n for (const index of args) {\n if (typeof index !== 'number' || !Number.isInteger(index)) {\n throw new QvdValidationError('rows() requires integer indices', {\n provided: index,\n type: typeof index,\n });\n }\n if (index < 0 || index >= this._data.length) {\n throw new QvdValidationError(`Row index ${index} out of bounds`, {\n index,\n validRange: [0, this._data.length - 1],\n dataLength: this._data.length,\n });\n }\n }\n return new QvdDataFrame(\n args.map((index) => this._data[index]),\n this._columns,\n this._metadata,\n );\n }\n\n /**\n * Returns the value at the specified row and column.\n *\n * @param {number} row The index of the row.\n * @param {string} column The name of the column.\n * @return {any} The value at the specified row and column.\n * @throws {QvdValidationError} If row is not an integer, out of bounds, or column does not exist.\n */\n at(row, column) {\n if (typeof row !== 'number' || !Number.isInteger(row)) {\n throw new QvdValidationError('Row index must be an integer', {\n provided: row,\n type: typeof row,\n });\n }\n if (row < 0 || row >= this._data.length) {\n throw new QvdValidationError(`Row index ${row} out of bounds`, {\n index: row,\n validRange: [0, this._data.length - 1],\n dataLength: this._data.length,\n });\n }\n if (!this._columns.includes(column)) {\n throw new QvdValidationError(`Column '${column}' does not exist`, {\n column,\n availableColumns: this._columns,\n });\n }\n return this._data[row][this._columns.indexOf(column)];\n }\n\n /**\n * Selects the specified columns from the data frame.\n *\n * @param {...string} args The names of the columns to select.\n * @return {QvdDataFrame} The selected columns of the data frame.\n * @throws {QvdValidationError} If any column name does not exist.\n */\n select(...args) {\n for (const column of args) {\n if (!this._columns.includes(column)) {\n throw new QvdValidationError(`Column '${column}' does not exist`, {\n column,\n availableColumns: this._columns,\n });\n }\n }\n const indices = args.map((arg) => this._columns.indexOf(arg));\n const data = this._data.map((row) => indices.map((index) => row[index]));\n const columns = indices.map((index) => this._columns[index]);\n return new QvdDataFrame(data, columns, this._metadata);\n }\n\n /**\n * Returns the data frame as a dictionary.\n *\n * @return {Promise<{columns: Array<string>, data: Array<Array<any>>}>} The data frame as a dictionary.\n */\n async toDict() {\n return {columns: this._columns, data: this._data};\n }\n\n /**\n * Persists the data frame to a QVD file.\n *\n * @param {string} path The path to the QVD file.\n * @param {Object} [options] Optional writing options.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file path\n * must be within this directory, with symlinks resolved first, so a link inside it that points\n * outside it is rejected. Defaults to the current working directory. To permit an entire\n * volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or empty value falls\n * back to the working directory rather than removing the restriction.\n * @param {Function} [options.onProgress] Optional progress callback function that receives progress updates during write operations.\n */\n async toQvd(path, options = {}) {\n const {QvdFileWriter} = await import('./QvdFileWriter.js');\n const writerOptions = {\n allowedDir: options.allowedDir,\n onProgress: options.onProgress,\n };\n await new QvdFileWriter(path, this, writerOptions).save();\n }\n\n /**\n * Loads a QVD file and returns its data frame.\n *\n * @param {string} path The path to the QVD file.\n * @param {Object} [options] Optional loading options.\n * @param {number|null} [options.maxRows] The maximum number of rows to load. Must be a non-negative\n * integer; if not specified or null, all rows are loaded. Anything else throws a QvdValidationError.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file path\n * must be within this directory, with symlinks resolved first, so a link inside it that points\n * outside it is rejected. Defaults to the current working directory. To permit an entire\n * volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or empty value falls\n * back to the working directory rather than removing the restriction.\n * @param {number} [options.memorySafetyFactor=0.3] Memory safety factor (0.0-1.0). Determines what percentage\n * of available memory (or V8 heap limit, whichever is smaller) can be used. Default is 0.3 (30%).\n * Increase this (e.g., to 0.5 or 0.7) when running with larger heap sizes via --max-old-space-size.\n * @throws {QvdValidationError} If options.maxRows is neither null/undefined nor a non-negative integer.\n * @return {Promise<QvdDataFrame>} The data frame of the QVD file.\n */\n static async fromQvd(path, options = {}) {\n const {QvdFileReader} = await import('./QvdFileReader.js');\n const readerOptions = {\n allowedDir: options.allowedDir,\n memorySafetyFactor: options.memorySafetyFactor,\n };\n return await new QvdFileReader(path, readerOptions).load(options.maxRows !== undefined ? options.maxRows : null);\n }\n\n /**\n * Constructs a data frame from a dictionary.\n *\n * @param {{columns: Array<string>, data: Array<Array<any>>}} data The dictionary to construct the data frame from.\n * @return {Promise<QvdDataFrame>} The constructed data frame.\n */\n static async fromDict(data) {\n if (!data.columns) {\n throw new QvdValidationError('The dictionary to construct the data frame from does not contain any columns.', {\n data,\n });\n }\n if (!data.data) {\n throw new QvdValidationError('The dictionary to construct the data frame from does not contain any data.', {\n data,\n });\n }\n\n return new QvdDataFrame(data.data, data.columns);\n }\n}\n","// @ts-check\n\nexport {QvdSymbol} from './QvdSymbol.js';\nexport {QvdDataFrame} from './QvdDataFrame.js';\nexport {QvdFileReader} from './QvdFileReader.js';\nexport {QvdFileWriter} from './QvdFileWriter.js';\nexport {\n QvdError,\n QvdParseError,\n QvdValidationError,\n QvdIOError,\n QvdCorruptedError,\n QvdSecurityError,\n} from './QvdErrors.js';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/QvdErrors.js","../src/QvdSymbol.js","../src/util/validatePath.js","../src/QvdFileWriter.js","../src/util/bitUtils.js","../src/util/memoryUtils.js","../src/util/validationUtils.js","../src/util/symbolParser.js","../src/QvdFileReader.js","../src/QvdDataFrame.js","../src/index.js"],"names":["QvdError","QvdParseError","QvdValidationError","QvdIOError","QvdCorruptedError","QvdSecurityError","QvdSymbol","path","fs","QvdFileWriter","assert","crypto","xml","v8","os","QvdFileReader","QvdDataFrame"],"mappings":"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","file":"index.cjs","sourcesContent":["// @ts-check\n\n/**\n * Base error class for all QVD-related errors.\n * Provides structured error information with error codes and context.\n */\nexport class QvdError extends Error {\n /**\n * Constructs a new QVD error.\n *\n * @param {string} message The error message.\n * @param {string} code The error code.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, code, context = {}) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.context = context;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Error thrown when parsing a QVD file fails.\n * Used for issues during XML header parsing, symbol table parsing, or index table parsing.\n */\nexport class QvdParseError extends QvdError {\n /**\n * Constructs a new QVD parse error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_PARSE_ERROR', context);\n }\n}\n\n/**\n * Error thrown when input validation fails.\n * Used for invalid parameters, out of bounds access, or missing required data.\n */\nexport class QvdValidationError extends QvdError {\n /**\n * Constructs a new QVD validation error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_VALIDATION_ERROR', context);\n }\n}\n\n/**\n * Error thrown when file system operations fail.\n * Used for issues reading or writing QVD files.\n */\nexport class QvdIOError extends QvdError {\n /**\n * Constructs a new QVD IO error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_IO_ERROR', context);\n }\n}\n\n/**\n * Error thrown when a QVD file is corrupted or malformed.\n * Used for missing headers, invalid data structures, or corrupted data.\n */\nexport class QvdCorruptedError extends QvdError {\n /**\n * Constructs a new QVD corrupted error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_CORRUPTED_ERROR', context);\n }\n}\n\n/**\n * Error thrown when security violations occur.\n * Used for path traversal attempts, XXE attacks, or other security issues.\n */\nexport class QvdSecurityError extends QvdError {\n /**\n * Constructs a new QVD security error.\n *\n * @param {string} message The error message.\n * @param {Object} [context={}] Additional context about the error.\n */\n constructor(message, context = {}) {\n super(message, 'QVD_SECURITY_ERROR', context);\n }\n}\n","// @ts-check\n\nimport {QvdValidationError} from './QvdErrors.js';\n\n/**\n * Represents a Qlik symbol/value, stored in a QVD file.\n */\nexport class QvdSymbol {\n /**\n * Constructs a new QVD symbol.\n *\n * @param {number|null} intValue The integer value.\n * @param {number|null} doubleValue The double value.\n * @param {string|null} stringValue The string value.\n */\n constructor(intValue, doubleValue, stringValue) {\n this._intValue = intValue;\n\n this._doubleValue = doubleValue;\n\n this._stringValue = stringValue;\n }\n\n /**\n * Returns the integer value of this symbol.\n *\n * @return {number|null} The integer value.\n */\n get intValue() {\n return this._intValue;\n }\n\n /**\n * Returns the double value of this symbol.\n *\n * @return {number|null} The double value.\n */\n get doubleValue() {\n return this._doubleValue;\n }\n\n /**\n * Returns the string value of this symbol.\n *\n * @return {string|null} The string value.\n */\n get stringValue() {\n return this._stringValue;\n }\n\n /**\n * Retrieves the primary value of this symbol. The primary value is descriptive raw value.\n * It is either the string value, the integer value or the double value, prioritized in this order.\n *\n * @return {number|string|null} The primary value.\n */\n toPrimaryValue() {\n if (null != this._stringValue) {\n return this._stringValue;\n } else if (null != this._intValue) {\n return this._intValue;\n } else if (null != this._doubleValue) {\n return this._doubleValue;\n } else {\n return null;\n }\n }\n\n /**\n * Converts the symbol to its byte representation.\n *\n * @return {Buffer} The byte representation of the symbol.\n */\n toByteRepresentation() {\n if (this._intValue !== null && this._stringValue !== null) {\n const intBuffer = Buffer.alloc(4);\n intBuffer.writeInt32LE(this._intValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n const stringBuffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([5]), intBuffer, stringBuffer]);\n } else if (this._doubleValue !== null && this._stringValue !== null) {\n const floatBuffer = Buffer.alloc(8);\n floatBuffer.writeDoubleLE(this._doubleValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n const stringBuffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([6]), floatBuffer, stringBuffer]);\n } else if (this._intValue !== null) {\n const buffer = Buffer.alloc(4);\n buffer.writeInt32LE(this._intValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([1]), buffer]);\n } else if (this._doubleValue !== null) {\n const buffer = Buffer.alloc(8);\n buffer.writeDoubleLE(this._doubleValue);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([2]), buffer]);\n } else if (this._stringValue !== null) {\n // @ts-ignore - Buffer.concat type compatibility\n const buffer = Buffer.concat([Buffer.from(this._stringValue, 'utf-8'), Buffer.from([0])]);\n\n // @ts-ignore - Buffer.concat type compatibility\n return Buffer.concat([Buffer.from([4]), buffer]);\n } else {\n throw new QvdValidationError('The symbol does not contain any value.', {\n intValue: this._intValue,\n doubleValue: this._doubleValue,\n stringValue: this._stringValue,\n });\n }\n }\n\n /**\n * Checks if this symbol is equal to another symbol.\n *\n * @param {*} value The object to compare with.\n * @return {boolean} True if the objects are equal, false otherwise.\n */\n equals(value) {\n if (!(value instanceof QvdSymbol)) {\n return false;\n }\n\n return (\n this._intValue === value.intValue &&\n this._doubleValue === value.doubleValue &&\n this._stringValue === value.stringValue\n );\n }\n\n /**\n * Constructs a pure integer value symbol.\n *\n * @param {number} intValue The integer value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromIntValue(intValue) {\n return new QvdSymbol(intValue, null, null);\n }\n\n /**\n * Constructs a pure double value symbol.\n *\n * @param {number} doubleValue The double value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDoubleValue(doubleValue) {\n return new QvdSymbol(null, doubleValue, null);\n }\n\n /**\n * Constructs a pure string value symbol.\n *\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromStringValue(stringValue) {\n return new QvdSymbol(null, null, stringValue);\n }\n\n /**\n * Constructs a dual value symbol from an integer and a string value.\n *\n * @param {number} intValue The integer value.\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDualIntValue(intValue, stringValue) {\n return new QvdSymbol(intValue, null, stringValue);\n }\n\n /**\n * Constructs a dual value symbol from a double and a string value.\n *\n * @param {number} doubleValue The double value.\n * @param {string} stringValue The string value.\n * @return {QvdSymbol} The constructed value symbol.\n */\n static fromDualDoubleValue(doubleValue, stringValue) {\n return new QvdSymbol(null, doubleValue, stringValue);\n }\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport path from 'path';\nimport {QvdSecurityError, QvdValidationError} from '../QvdErrors.js';\n\n/**\n * Determines whether a resolved path is contained within a resolved base directory, using only\n * string comparison.\n *\n * This is the fallback for when the filesystem cannot answer the question - in practice, when\n * allowedDir does not exist. It cannot see through symlinks and has to guess at case\n * sensitivity, which is exactly why it is not the primary check.\n *\n * Uses path.relative() rather than a string prefix test, so that filesystem roots\n * ('/', 'C:\\', '\\\\server\\share\\') and base directories with a trailing separator are\n * handled correctly. A prefix test appends path.sep to the base, which produces '//'\n * for a root and therefore matches nothing.\n *\n * @param {string} resolvedBaseDir Absolute, resolved base directory.\n * @param {string} resolvedPath Absolute, resolved candidate path.\n * @return {boolean} True if the path is the base directory itself or lies beneath it.\n */\nfunction isWithinDirectoryLexically(resolvedBaseDir, resolvedPath) {\n // Folding is applied on Windows only. It used to cover darwin as well, on the assumption that\n // macOS is always case-insensitive, but macOS supports case-sensitive APFS and HFS+ volumes on\n // which two names differing only in case are genuinely different directories - so folding there\n // let a sibling directory pass the check. The on-disk comparison below settles case correctly\n // by asking the filesystem, which is why this fallback no longer needs to guess for darwin.\n const isCaseInsensitiveFS = process.platform === 'win32';\n const base = isCaseInsensitiveFS ? resolvedBaseDir.toLowerCase() : resolvedBaseDir;\n const target = isCaseInsensitiveFS ? resolvedPath.toLowerCase() : resolvedPath;\n\n const relative = path.relative(base, target);\n\n // '' means the path IS the base directory. A relative path that starts with '..' escapes\n // the base, and an absolute result means the two are on different roots/drives.\n if (relative === '') {\n return true;\n }\n if (path.isAbsolute(relative)) {\n return false;\n }\n return relative !== '..' && !relative.startsWith(`..${path.sep}`);\n}\n\n/**\n * Resolves the deepest ancestor of a path that actually exists, following symlinks.\n *\n * A path being written to does not exist yet, and neither may some of its parent directories, so\n * realpath() on the full path would simply fail. Walking up to the first component that does\n * exist gives the deepest point the filesystem can vouch for; anything below it is a name that\n * will be created inside that directory.\n *\n * @param {string} target Absolute, lexically resolved path.\n * @return {string|null} Canonical path of the deepest existing ancestor, or null if it could not\n * be determined.\n */\nfunction resolveDeepestExisting(target) {\n let current = target;\n\n for (;;) {\n try {\n return fs.realpathSync(current);\n } catch (error) {\n const code = /** @type {{code?: string}} */ (error)?.code;\n\n // ENOENT: this component does not exist. ENOTDIR: an ancestor is a file, so nothing below\n // it can exist either. Both mean \"keep walking up\". Anything else (EACCES, ELOOP) means the\n // filesystem cannot answer, and the caller falls back to the lexical test - which is safe,\n // because an open() on the same path is about to fail for the same reason.\n if (code !== 'ENOENT' && code !== 'ENOTDIR') {\n return null;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n }\n}\n\n/**\n * Determines whether a path is contained within a base directory by asking the filesystem.\n *\n * Both sides are resolved through symlinks and then compared by identity - device and inode -\n * rather than by name, walking up from the target until the base is found or the root is reached.\n * That settles two questions a string comparison cannot:\n *\n * - Symlinks. A link inside allowedDir pointing outside it resolves to its target, so it is\n * rejected. A lexical check sees only the link's own name, still under allowedDir, and lets it\n * through - which meant arbitrary read via the reader and arbitrary overwrite via the writer.\n * - Case. On a case-insensitive volume 'Qvd' and 'qvd' are one directory and share an inode; on a\n * case-sensitive volume they are two directories with different inodes. Comparing identity gets\n * both right without inferring anything from process.platform, which is what the old code did\n * and got wrong on case-sensitive macOS volumes.\n *\n * This is a check on the path, so it is inherently subject to a race: a symlink swapped in\n * between this call and the subsequent open would defeat it. Closing that would require opening\n * with O_NOFOLLOW and verifying the descriptor, which is a larger change to the reader and\n * writer than this function can make on its own.\n *\n * @param {string} resolvedBaseDir Absolute, lexically resolved base directory.\n * @param {string} resolvedPath Absolute, lexically resolved candidate path.\n * @return {boolean|null} True or false when the filesystem could answer, null when it could not.\n */\nfunction isWithinDirectoryOnDisk(resolvedBaseDir, resolvedPath) {\n /** @type {import('fs').Stats} */\n let baseStat;\n\n try {\n // The base has to exist to be identified. If it does not, there is nothing on disk to compare\n // against and the lexical fallback is all that is left.\n baseStat = fs.statSync(fs.realpathSync(resolvedBaseDir));\n } catch {\n return null;\n }\n\n let current = resolveDeepestExisting(resolvedPath);\n if (current === null) {\n return null;\n }\n\n // realpathSync() returns a fully canonical path, so every ancestor of it is canonical too and\n // walking up with dirname() cannot step through a symlink.\n for (;;) {\n let stat;\n try {\n stat = fs.statSync(current);\n } catch {\n return null;\n }\n\n if (stat.dev === baseStat.dev && stat.ino === baseStat.ino) {\n return true;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return false;\n }\n current = parent;\n }\n}\n\n/**\n * Validates that a file path stays inside the allowed directory.\n *\n * Containment is decided by the filesystem wherever it can be: both paths are resolved through\n * symlinks and compared by device and inode. That covers symlink escapes and case sensitivity,\n * neither of which a string comparison can get right. When the base directory does not exist,\n * there is nothing to compare against and a lexical check is used instead.\n *\n * To permit access to an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on\n * Windows). There is deliberately no separate \"disable the check\" value: a null or empty\n * allowedDir falls back to the current working directory, so a caller that accidentally\n * passes one still gets the restriction rather than silently losing it.\n *\n * @param {string} filePath The path to validate.\n * @param {string|null} [allowedDir] Optional allowed directory path. Defaults to the current\n * working directory to prevent path traversal attacks.\n * @throws {QvdValidationError} If filePath is not a non-empty string, or allowedDir is not a\n * string, null or undefined.\n * @throws {QvdSecurityError} If path traversal is detected.\n * @return {string} The resolved absolute path. This is the lexically resolved path, not the\n * canonical one, so callers see the path they asked for.\n */\nexport function validatePath(filePath, allowedDir) {\n // Validate argument types up front, so callers get a typed error instead of a bare TypeError\n // from deep inside the function (e.g. 'filePath.includes is not a function').\n if (typeof filePath !== 'string' || filePath.length === 0) {\n throw new QvdValidationError('filePath must be a non-empty string', {\n provided: filePath,\n type: typeof filePath,\n });\n }\n\n if (allowedDir !== undefined && allowedDir !== null && typeof allowedDir !== 'string') {\n throw new QvdValidationError('allowedDir must be a string, null or undefined', {\n provided: allowedDir,\n type: typeof allowedDir,\n });\n }\n\n // Check for null bytes which can be used in path traversal attacks\n if (filePath.includes('\\0')) {\n throw new QvdSecurityError('Path traversal detected: Null byte in path', {\n path: filePath,\n reason: 'null_byte',\n });\n }\n\n const resolvedPath = path.resolve(filePath);\n\n // Default to the current working directory when no allowed directory is specified. This\n // prevents path traversal attacks by ensuring files can only be accessed within the CWD\n // or a more restrictive allowed directory.\n //\n // null and '' deliberately fall back to the CWD rather than meaning \"no restriction\":\n // callers routinely produce them from optional config or a JSON round trip, and silently\n // dropping the sandbox in that case would be a security hole. A caller that genuinely wants\n // an entire volume passes its root ('/' or 'C:\\\\'), which the containment test supports.\n const baseDir = allowedDir || process.cwd();\n const resolvedBaseDir = path.resolve(baseDir);\n\n const onDisk = isWithinDirectoryOnDisk(resolvedBaseDir, resolvedPath);\n const contained = onDisk === null ? isWithinDirectoryLexically(resolvedBaseDir, resolvedPath) : onDisk;\n\n if (!contained) {\n throw new QvdSecurityError('Path traversal detected: Access denied', {\n path: filePath,\n resolvedPath,\n allowedDir: resolvedBaseDir,\n reason: 'outside_allowed_directory',\n // Says which check refused, so a rejection of a path that looks contained is traceable to\n // a symlink or a case difference rather than looking like a bug.\n check: onDisk === null ? 'lexical' : 'filesystem',\n });\n }\n\n return resolvedPath;\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport xml from 'xml2js';\nimport assert from 'assert';\nimport {QvdSymbol} from './QvdSymbol.js';\nimport {validatePath} from './util/validatePath.js';\n\n/**\n * @typedef {import('./QvdDataFrame.js').QvdDataFrame} QvdDataFrame\n */\n\n/**\n * Persists a QVD file to disk.\n */\nexport class QvdFileWriter {\n /**\n * Constructs a new QVD file writer.\n *\n * @param {string} filePath The path to the QVD file to write.\n * @param {QvdDataFrame} df The data frame to write to the QVD file.\n * @param {Object} [options={}] Options for the writer.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file\n * path must be within this directory, with symlinks resolved first, so a link inside it that\n * points outside it is rejected. Defaults to the current working directory. To permit\n * an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or\n * empty value falls back to the working directory rather than removing the restriction.\n * @param {Function} [options.onProgress] Optional progress callback function.\n */\n constructor(filePath, df, options = {}) {\n const {allowedDir, onProgress} = options;\n this._path = validatePath(filePath, allowedDir);\n this._df = df;\n this._onProgress = onProgress;\n this._header = null;\n this._symbolBuffer = null;\n /** @type {Array<Array<import('./QvdSymbol.js').QvdSymbol>>|null} */\n this._symbolTable = null;\n /** @type {Array<any>|null} */\n this._symbolTableMetadata = null;\n this._indexBuffer = null;\n /** @type {Array<any>|null} */\n this._indexTable = null;\n /** @type {Array<any>|null} */\n this._indexTableMetadata = null;\n this._recordByteSize = null;\n }\n\n /**\n * Emits a progress event if a callback is registered.\n *\n * @param {string} stage The current stage of the operation.\n * @param {number} current The current progress value.\n * @param {number} total The total progress value.\n */\n _emitProgress(stage, current, total) {\n if (this._onProgress) {\n const percent = total > 0 ? Math.round((current / total) * 100) : 100;\n this._onProgress({\n stage,\n current,\n total,\n percent,\n });\n }\n }\n\n /**\n * Writes the data to the QVD file.\n */\n async _writeData() {\n assert(this._header, 'The QVD file header has not been parsed.');\n assert(this._symbolBuffer, 'The QVD file symbol table has not been parsed.');\n assert(this._indexBuffer, 'The QVD file index table has not been parsed.');\n\n this._emitProgress('write', 0, 1);\n\n // @ts-ignore - Buffer.concat type compatibility\n const headerBuffer = Buffer.concat([Buffer.from(this._header, 'utf-8'), Buffer.from([0])]);\n\n let fd;\n try {\n fd = await fs.promises.open(this._path, 'w');\n await fd.write(headerBuffer, 0, headerBuffer.length, 0);\n await fd.write(this._symbolBuffer, 0, this._symbolBuffer.length, headerBuffer.length);\n await fd.write(this._indexBuffer, 0, this._indexBuffer.length, headerBuffer.length + this._symbolBuffer.length);\n this._emitProgress('write', 1, 1);\n } finally {\n if (fd) {\n await fd.close();\n }\n }\n }\n\n /**\n * Builds the XML header of the QVD file.\n */\n _buildHeader() {\n this._emitProgress('header', 0, 1);\n const creationDate = new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '');\n /** @type {import('./QvdDataFrame.js').QvdMetadata|null} */\n const existingMetadata = this._df.metadata;\n\n // Use existing metadata if available, otherwise create default values\n const baseMetadata = existingMetadata\n ? {\n QvBuildNo: existingMetadata.QvBuildNo || 50667,\n CreatorDoc: existingMetadata.CreatorDoc || crypto.randomUUID(),\n CreateUtcTime: existingMetadata.CreateUtcTime || creationDate,\n SourceCreateUtcTime: existingMetadata.SourceCreateUtcTime || '',\n SourceFileUtcTime: existingMetadata.SourceFileUtcTime || '',\n SourceFileSize: existingMetadata.SourceFileSize || -1,\n StaleUtcTime: existingMetadata.StaleUtcTime || '',\n TableName: existingMetadata.TableName || path.basename(this._path, path.extname(this._path)),\n Compression: existingMetadata.Compression || '',\n Comment: existingMetadata.Comment || '',\n EncryptionInfo: existingMetadata.EncryptionInfo || '',\n TableTags: existingMetadata.TableTags || '',\n ProfilingData: existingMetadata.ProfilingData || '',\n Lineage: existingMetadata.Lineage || {\n LineageInfo: {\n Discriminator: 'INLINE;',\n Statement: '',\n },\n },\n }\n : {\n QvBuildNo: 50667,\n CreatorDoc: crypto.randomUUID(),\n CreateUtcTime: creationDate,\n SourceCreateUtcTime: '',\n SourceFileUtcTime: '',\n SourceFileSize: -1,\n StaleUtcTime: '',\n TableName: path.basename(this._path, path.extname(this._path)),\n Compression: '',\n Comment: '',\n EncryptionInfo: '',\n TableTags: '',\n ProfilingData: '',\n Lineage: {\n LineageInfo: {\n Discriminator: 'INLINE;',\n Statement: '',\n },\n },\n };\n\n // Get existing field metadata if available\n /** @type {any[]} */\n let existingFields = [];\n if (existingMetadata && existingMetadata.Fields && existingMetadata.Fields.QvdFieldHeader) {\n existingFields = Array.isArray(existingMetadata.Fields.QvdFieldHeader)\n ? existingMetadata.Fields.QvdFieldHeader\n : [existingMetadata.Fields.QvdFieldHeader];\n }\n\n const xmlObject = {\n QvdTableHeader: {\n ...baseMetadata,\n Fields: {\n QvdFieldHeader: this._df.columns.map((/** @type {any} */ column, /** @type {number} */ index) => {\n // Find existing field metadata for this column\n const existingField = existingFields.find((/** @type {any} */ f) => f.FieldName === column);\n\n return {\n FieldName: column,\n BitOffset: this._indexTableMetadata?.[index][0],\n BitWidth: this._indexTableMetadata?.[index][1],\n Bias: this._indexTableMetadata?.[index][2],\n NoOfSymbols: this._symbolTable?.[index].length,\n Offset: this._symbolTableMetadata?.[index][0],\n Length: this._symbolTableMetadata?.[index][1],\n Comment: existingField?.Comment || '',\n NumberFormat: existingField?.NumberFormat || {\n Type: 'UNKNOWN',\n nDec: '0',\n UseThou: '0',\n Fmt: '',\n Dec: '',\n Thou: '',\n },\n Tags: existingField?.Tags || {},\n };\n }),\n },\n NoOfRecords: this._indexTable?.length,\n RecordByteSize: this._recordByteSize,\n Offset:\n this._symbolTableMetadata && this._symbolTableMetadata.length > 0\n ? this._symbolTableMetadata[this._symbolTableMetadata.length - 1][0] +\n this._symbolTableMetadata[this._symbolTableMetadata.length - 1][1]\n : 0,\n Length: this._indexBuffer?.length,\n },\n };\n\n const builder = new xml.Builder({\n renderOpts: {\n pretty: true,\n newline: '\\r\\n',\n indent: ' ',\n },\n });\n this._header = builder.buildObject(xmlObject) + '\\r\\n';\n this._emitProgress('header', 1, 1);\n }\n\n /**\n * Builds the symbol table of the QVD file.\n *\n * PERFORMANCE OPTIMIZATION: This method uses a single-pass algorithm to build\n * symbol tables for all columns simultaneously. This reduces time complexity from\n * O(n×m×s) to O(n×m) where n=rows, m=columns, s=symbols per column.\n *\n * Algorithm:\n * 1. Initialize a Set for each column to collect unique values\n * 2. Single pass through all data rows, adding values to corresponding Sets\n * 3. Convert Sets to arrays and create QvdSymbol instances\n * 4. Serialize symbols to binary format and update metadata\n *\n * This approach provides:\n * - 80-90% performance improvement for large datasets (100K+ rows)\n * - Better cache locality (process all columns in one data traversal)\n * - Lower memory pressure (no intermediate arrays per column)\n *\n * @private\n */\n _buildSymbolTable() {\n this._symbolTable = [];\n this._symbolTableMetadata = [];\n this._symbolBuffer = Buffer.alloc(0);\n\n const numColumns = this._df.columns.length;\n\n this._emitProgress('symbol-table', 0, numColumns);\n\n // Initialize a Set for each column to track unique values\n // Sets provide O(1) add and automatic deduplication\n const uniqueValuesSets = this._df.columns.map(() => new Set());\n\n // Single pass through all data to collect unique values for all columns\n // This is the key optimization: process all columns together instead of\n // iterating through data once per column\n this._df.data.forEach((row) => {\n this._df.columns.forEach((column, columnIndex) => {\n const value = row[columnIndex];\n uniqueValuesSets[columnIndex].add(value);\n });\n });\n\n // Process each column's unique values\n this._df.columns.forEach((column, columnIndex) => {\n const uniqueValuesSet = uniqueValuesSets[columnIndex];\n const uniqueValues = Array.from(uniqueValuesSet);\n const containsNull = uniqueValues.includes(null) || uniqueValues.includes(undefined);\n const symbols = uniqueValues\n .filter((value) => value !== null && value !== undefined)\n .map((value) => QvdFileWriter._convertRawToSymbol(value));\n\n // @ts-ignore:next-line sd\n const currentSymbolBuffer = Buffer.concat(symbols.map((symbol) => symbol.toByteRepresentation()));\n this._symbolBuffer = this._symbolBuffer\n ? Buffer.concat([this._symbolBuffer, currentSymbolBuffer])\n : currentSymbolBuffer;\n\n const symbolsLength = currentSymbolBuffer.length;\n const symbolsOffset = this._symbolBuffer.length - symbolsLength;\n\n this._symbolTableMetadata?.push([symbolsOffset, symbolsLength, containsNull]);\n // @ts-ignore - Symbol array type compatibility\n this._symbolTable?.push(symbols);\n\n this._emitProgress('symbol-table', columnIndex + 1, numColumns);\n });\n }\n\n /**\n * Builds the index table of the QVD file.\n *\n * PERFORMANCE OPTIMIZATION: Uses Map-based lookups for O(1) symbol index retrieval\n * instead of Array.findIndex() which is O(n). For columns with many unique values,\n * this provides significant performance improvements.\n *\n * Algorithm:\n * 1. Build Map<symbol, index> for each column (O(m) where m=unique values)\n * 2. For each data row, lookup indices in maps (O(1) per value)\n * 3. Convert indices to bit-packed binary format\n *\n * Bit Packing:\n * - Calculates minimum bits needed: ceil(log2(numSymbols))\n * - Packs indices into binary string, then converts to bytes\n * - Reduces file size significantly for columns with few unique values\n *\n * Example: Column with 10 unique values needs only 4 bits per value\n * instead of 32 bits (full integer), saving 87.5% space.\n *\n * @private\n */\n _buildIndexTable() {\n this._indexTable = [];\n this._indexTableMetadata = [];\n this._indexBuffer = Buffer.alloc(0);\n\n const numRows = this._df.data.length;\n this._emitProgress('index-table', 0, numRows);\n\n // Build symbol-to-index lookup maps for O(1) lookups\n // This is crucial for performance: findIndex() on large arrays is O(n)\n // while Map.get() is O(1)\n // This converts the O(n×m×s) findIndex operations to O(n×m)\n const symbolIndexMaps = this._symbolTable?.map((symbols) => {\n const map = new Map();\n symbols.forEach((symbol, idx) => {\n // Create a unique key for each symbol based on its values\n const key = `${symbol.intValue}|${symbol.doubleValue}|${symbol.stringValue}`;\n map.set(key, idx);\n });\n return map;\n });\n\n let processedRows = 0;\n const progressInterval = Math.max(1, Math.floor(numRows / 100)); // Report progress every 1%\n\n this._df.data.forEach((/** @type {any} */ row) => {\n // Convert the raw values to indices referring to the symbol table\n const indices = this._df.columns.map((/** @type {any} */ column, columnIndex) => {\n const value = row[columnIndex];\n const symbol = QvdFileWriter._convertRawToSymbol(value);\n const fieldContainsNull = this._symbolTableMetadata?.[columnIndex][2];\n\n // None values are represented by bias shifted negative indices\n if (symbol === null) {\n return 0;\n } else {\n // Use the Map for O(1) lookup instead of findIndex\n const key = `${symbol.intValue}|${symbol.doubleValue}|${symbol.stringValue}`;\n const symbolIndex = symbolIndexMaps?.[columnIndex].get(key);\n // In order to represent None values, the indices are shifted by the bias value of the column\n return fieldContainsNull ? (symbolIndex ?? 0) + 2 : (symbolIndex ?? 0);\n }\n });\n\n // Convert the integer indices to binary representation\n /** @type {string[]} */\n const stringIndices = indices.map((/** @type {number} */ index) => {\n const bits = QvdFileWriter._convertInt32ToBits(index, 32);\n let bitString = bits.join('');\n bitString = bitString.replace(/^0+/, '') || '0';\n return bitString;\n });\n\n // @ts-ignore - Index array type compatibility\n this._indexTable?.push(stringIndices);\n\n // Report progress periodically\n processedRows++;\n if (processedRows % progressInterval === 0 || processedRows === numRows) {\n this._emitProgress('index-table', processedRows, numRows);\n }\n });\n\n // Normalize the bit representation of the indices by padding with zeros\n this._df.columns.forEach((column, columnIndex) => {\n // Bit offset is the sum of the bit widths of all previous columns\n const bitOffset = this._indexTableMetadata?.slice(0, columnIndex).reduce((sum, metadata) => sum + metadata[1], 0);\n\n assert(this._indexTable, 'The QVD file header has not been parsed.');\n\n const fieldContainsNull = this._symbolTableMetadata?.[columnIndex][2];\n const bias = fieldContainsNull ? -2 : 0;\n\n // Bit width is derived from the number of symbols rather than by scanning every row.\n //\n // The largest stored index is (symbolCount - 1), shifted by 2 when the column contains\n // NULLs (index 0 denotes NULL and indices start at 2, which is what Bias=-2 encodes).\n //\n // Deriving it this way is O(1) per column instead of O(rows), and it avoids\n // Math.max(...oneArgumentPerRow), which overflows the call stack somewhere around\n // 120k rows and made toQvd() unusable for realistic table sizes.\n const symbolCount = this._symbolTable?.[columnIndex].length ?? 0;\n const maxStoredIndex = symbolCount === 0 ? 0 : symbolCount - 1 + (fieldContainsNull ? 2 : 0);\n // A single distinct value needs no bits at all, which matches what Qlik emits.\n const bitWidth = maxStoredIndex === 0 ? 0 : 32 - Math.clz32(maxStoredIndex);\n\n this._indexTableMetadata?.push([bitOffset, bitWidth, bias]);\n\n // Pad the bit representation of the indices with zeros to match the bit width.\n //\n // The assertion restores the self-correcting property of the old Math.max() approach,\n // which measured the actual bit strings and so absorbed any mismatch between the symbol\n // table and the indices built from it. Deriving the width instead makes such a mismatch\n // silent: padStart() never truncates, so an over-wide index would make the record wider\n // than BitWidth declares and misalign every field after it in every subsequent row.\n this._indexTable.forEach((/** @type{string[]} */ indices) => {\n const bitString = indices[columnIndex];\n // '0' is the stored index 0, which needs no bits and is written as an empty string\n // when bitWidth is 0; every other value must fit inside the derived width.\n assert(\n bitString === '0' || bitString.length <= bitWidth,\n `Stored index for column '${column}' needs ${bitString.length} bits, ` +\n `but BitWidth was derived as ${bitWidth} from ${symbolCount} symbols. ` +\n `The symbol table and the index table are out of sync.`,\n );\n indices[columnIndex] = bitWidth === 0 ? '' : bitString.padStart(bitWidth, '0');\n });\n });\n\n // Concatenate the bit representation of the indices of each row to a single binary string per row\n // @ts-ignore - Buffer.concat type compatibility\n this._indexBuffer = Buffer.concat(\n // @ts-ignore - Buffer array type compatibility\n this._indexTable.map((/** @type{string[]} */ indices) => {\n indices.reverse();\n const bits = indices.join('');\n\n // Every column may have a bit width of 0 (each holds a single distinct value or only\n // NULLs), leaving no bits at all. Qlik still uses a one-byte record in that situation,\n // and a zero-byte record would be rejected on read, so emit a single zero byte.\n if (bits.length === 0) {\n return Buffer.from(Uint8Array.from([0]));\n }\n\n const paddingWidth = (8 - (bits.length % 8)) % 8;\n const paddedBits = bits.padStart(bits.length + paddingWidth, '0');\n const bytes = paddedBits.match(/.{1,8}/g)?.map((byte) => parseInt(byte, 2));\n bytes?.reverse();\n\n assert(bytes, 'Byte conversion of bit indices failed.');\n\n return Buffer.from(Uint8Array.from(bytes));\n }),\n );\n\n // For empty data, set record byte size to 1 (matching Qlik Sense behavior)\n // instead of 0 or NaN/Infinity\n this._recordByteSize = this._indexTable.length > 0 ? this._indexBuffer.length / this._indexTable.length : 1;\n }\n\n /**\n * Converts a raw value/literal to a QVD symbol.\n *\n * @param {any} raw The raw value/literal to convert.\n * @return {QvdSymbol|null} The converted QVD symbol.\n */\n static _convertRawToSymbol(raw) {\n if (raw === null || raw === undefined) {\n return null;\n }\n\n const INT32_MIN = -2147483648;\n const INT32_MAX = 2147483647;\n\n const isInteger = typeof raw === 'number' && Number.isInteger(raw);\n const isFloat = typeof raw === 'number' && !Number.isInteger(raw);\n const isWithinInt32Range = typeof raw === 'number' && raw >= INT32_MIN && raw <= INT32_MAX;\n\n if (isInteger && isWithinInt32Range) {\n return QvdSymbol.fromDualIntValue(raw, raw.toString());\n } else if (isFloat || (isInteger && !isWithinInt32Range)) {\n return QvdSymbol.fromDualDoubleValue(raw, raw.toString());\n } else {\n return QvdSymbol.fromStringValue(raw);\n }\n }\n\n /**\n * Converts an integer to a list of bits.\n *\n * @param {number} value The integer value to convert.\n * @param {number} width The width of the bit list.\n * @return {Array<number>} The list of bits.\n */\n static _convertInt32ToBits(value, width) {\n return value\n .toString(2)\n .split('')\n .map((bit) => parseInt(bit))\n .reverse()\n .concat(new Array(width).fill(0))\n .slice(0, width)\n .reverse();\n }\n\n /**\n * Persists the data frame to a QVD file.\n */\n async save() {\n this._buildSymbolTable();\n this._buildIndexTable();\n this._buildHeader();\n await this._writeData();\n }\n}\n","// @ts-check\n\n/**\n * Converts a bit array to an integer value.\n *\n * @param {Array<number>} bits The bit array\n * @return {number} The integer value\n */\nexport function convertBitsToInt32(bits) {\n if (bits.length === 0) {\n return 0;\n }\n\n return bits.reduce((value, bit, index) => (value += bit * Math.pow(2, index)), 0);\n}\n","// @ts-check\n\nimport os from 'os';\nimport v8 from 'v8';\nimport {QvdValidationError} from '../QvdErrors.js';\n\n/**\n * Gets the configured V8 heap size limit for the current Node.js process.\n * This respects the --max-old-space-size flag if set.\n *\n * @returns {number} Heap size limit in bytes\n */\nexport function getHeapLimit() {\n return v8.getHeapStatistics().heap_size_limit;\n}\n\n/**\n * Whether v8.getHeapStatistics().heap_size_limit means what it says on this runtime.\n *\n * Bun reports its *current* heap there rather than a ceiling - 229MB on a machine with 128GB of\n * RAM - so treating it as a limit rejects almost everything. It cannot be detected structurally\n * either: Bun spoofs both process.versions.v8 and process.versions.node, so the runtime's own\n * key is the only reliable signal.\n *\n * @return {boolean} True when the heap limit is a real limit.\n */\nfunction heapLimitIsMeaningful() {\n return !process.versions.bun && !process.versions.deno;\n}\n\n/**\n * Works out how much memory this process may actually use, and which limit decided it.\n *\n * Only two things can bind, and the smaller wins:\n *\n * - The V8 heap ceiling, which is what an allocation actually fails against, fatally and\n * uncatchably. V8 sizes it from physical memory by default, so it already scales down on a\n * small machine.\n * - A container memory limit, from process.constrainedMemory(). This is the case os.freemem()\n * gets dangerously wrong: inside a cgroup it reports the *host's* free memory, so a 2GB\n * container on a large host sails past the check and is then killed by the OOM killer with\n * exit 137 and no JavaScript error to catch.\n *\n * What the OS reports as free or available is deliberately *not* one of them. It is recorded for\n * diagnostics and ignored for the decision, because it does not describe a wall the process can\n * hit - a machine with virtual memory gets slower, not fatal - and because the number itself is\n * not trustworthy. os.freemem() counts only free and speculative pages, excluding the inactive\n * and file-cache pages the OS reclaims on demand. process.availableMemory() is meant to fix that\n * and does on Linux, but on macOS it depends on the libuv version underneath: Node 24 reported\n * 63GB on a 128GB machine here while Node 22 on a macOS CI runner reported 74MB, which refused a\n * 45MB load on a machine that had ample room for it. Letting either bind is what made the same\n * file load or fail from one minute, or one Node version, to the next.\n *\n * @return {{bytes: number, limitedBy: string, candidates: Array<{source: string, bytes: number}>,\n * observed: Array<{source: string, bytes: number}>}} The budget, the name of the limit that\n * bound it, what was allowed to bind, and what was recorded but not used.\n */\nexport function getMemoryBudget() {\n /** @type {Array<{source: string, bytes: number}>} */\n const candidates = [];\n\n if (heapLimitIsMeaningful()) {\n candidates.push({source: 'V8 heap limit', bytes: getHeapLimit()});\n }\n\n // Node returns 0 when the process is not constrained. Bun returns os.totalmem() instead, which\n // is not a constraint either, so anything at or above total memory is discarded rather than\n // treated as a container limit.\n const constrained = typeof process.constrainedMemory === 'function' ? process.constrainedMemory() : 0;\n if (constrained > 0 && constrained < os.totalmem()) {\n candidates.push({source: 'container memory limit', bytes: constrained});\n }\n\n // Bun outside a container has neither a usable heap limit nor a container limit, so without\n // this there would be no ceiling at all. Total memory is at least a real upper bound.\n if (candidates.length === 0) {\n candidates.push({source: 'total system memory', bytes: os.totalmem()});\n }\n\n /** @type {Array<{source: string, bytes: number}>} */\n const observed = [{source: 'free memory (os.freemem)', bytes: os.freemem()}];\n if (typeof process.availableMemory === 'function') {\n observed.push({source: 'available memory', bytes: process.availableMemory()});\n }\n\n const binding = candidates.reduce((lowest, candidate) => (candidate.bytes < lowest.bytes ? candidate : lowest));\n\n return {bytes: binding.bytes, limitedBy: binding.source, candidates, observed};\n}\n\n/**\n * Estimates the memory usage for loading a QVD file with given parameters.\n * Takes into account Phase 2.5 optimization which skips parsing unused symbols.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @returns {number} Estimated memory usage in bytes\n */\nexport function estimateMemoryUsage(symbolTableSize, maxRows, totalRows) {\n // Memory overhead multipliers based on empirical testing\n const FULL_PARSE_OVERHEAD = 6.0; // Baseline: JavaScript objects have 6x overhead\n const MINIMAL_OVERHEAD = 0.01; // Skipped symbols: minimal null placeholder overhead\n\n if (maxRows === null || maxRows >= totalRows) {\n // Loading all rows - need all symbols, no filtering benefit\n return symbolTableSize * FULL_PARSE_OVERHEAD;\n }\n\n // Estimate what percentage of symbols we'll need\n // Symbol usage grows slower than linear (diminishing returns as you add rows)\n // Use square root scaling as empirical approximation\n const rowPercentage = maxRows / totalRows;\n const symbolPercentage = Math.sqrt(rowPercentage);\n\n // Calculate memory for kept symbols (full overhead) + skipped symbols (minimal overhead)\n const keptSymbolsMemory = symbolTableSize * symbolPercentage * FULL_PARSE_OVERHEAD;\n const skippedSymbolsMemory = symbolTableSize * (1 - symbolPercentage) * MINIMAL_OVERHEAD;\n\n return keptSymbolsMemory + skippedSymbolsMemory;\n}\n\n/**\n * Validates that there is sufficient memory available to load a QVD file safely.\n * Considers both available system RAM and the configured V8 heap limit.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number} [safetyFactor=0.3] Fraction of the memory budget to use (0.0-1.0). Zero\n * disables the check entirely.\n * @throws {QvdValidationError} If insufficient memory is available\n */\nexport function validateMemoryAvailability(symbolTableSize, maxRows, totalRows, filePath, safetyFactor = 0.3) {\n if (typeof safetyFactor !== 'number' || safetyFactor < 0 || safetyFactor > 1) {\n throw new QvdValidationError('safetyFactor must be a number between 0.0 and 1.0', {safetyFactor});\n }\n\n // Zero disables the check. It used to mean a budget of zero bytes, which refused every file\n // however small - not something any caller can have wanted - so the only reading that makes it\n // useful is \"I will manage memory myself\". This is the documented escape hatch for runtimes\n // whose limits cannot be measured, and for callers who know better than the estimate.\n if (safetyFactor === 0) {\n return;\n }\n\n const budget = getMemoryBudget();\n const heapLimit = getHeapLimit();\n const availableMemory = budget.bytes;\n const estimatedMemory = estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n const maxAllowedMemory = budget.bytes * safetyFactor;\n\n if (estimatedMemory > maxAllowedMemory) {\n // Calculate how many rows would be safe to load\n // Reverse the square root formula: symbolPercentage = sqrt(rowPercentage)\n const safeSymbolPercentage = maxAllowedMemory / (symbolTableSize * 6.0);\n const safeRowPercentage = Math.pow(safeSymbolPercentage, 2);\n const recommendedMaxRows = Math.max(1, Math.floor(totalRows * safeRowPercentage));\n\n const sizeMB = Math.round(symbolTableSize / 1024 / 1024);\n const estimatedMB = Math.round(estimatedMemory / 1024 / 1024);\n const availableMB = Math.round(maxAllowedMemory / 1024 / 1024);\n const heapLimitMB = Math.round(heapLimit / 1024 / 1024);\n const availableRamMB = Math.round(availableMemory / 1024 / 1024);\n\n // Naming the limit that bound the decision is the difference between an actionable error and\n // a puzzling one: raising --max-old-space-size fixes a heap-bound refusal and does nothing\n // for a container-bound one, where it makes the OOM kill more likely rather than less.\n const limitingFactor = budget.limitedBy;\n const budgetBreakdown = budget.candidates\n .map((candidate) => `${candidate.source} ${Math.round(candidate.bytes / 1024 / 1024)}MB`)\n .join(', ');\n const observedBreakdown = budget.observed\n .map((entry) => `${entry.source} ${Math.round(entry.bytes / 1024 / 1024)}MB`)\n .join(', ');\n\n const advice =\n limitingFactor === 'container memory limit'\n ? `The binding limit is the container's, so raising --max-old-space-size would let V8 grow past it and be killed by the OOM killer instead. Set it below the container limit, raise the limit, or load fewer rows with maxRows (recommended: ${recommendedMaxRows.toLocaleString()} rows or less).`\n : `Try loading fewer rows using the maxRows parameter (recommended: ${recommendedMaxRows.toLocaleString()} rows or less), or raise the heap with --max-old-space-size.`;\n\n throw new QvdValidationError(\n `Insufficient memory to load file safely. ` +\n `Symbol table: ${sizeMB}MB, Estimated memory needed: ${estimatedMB}MB, Available: ${availableMB}MB (limited by ${limitingFactor}; considered: ${budgetBreakdown}; observed but not used: ${observedBreakdown}). ` +\n advice,\n {\n file: filePath,\n symbolTableSize,\n symbolTableSizeMB: sizeMB,\n estimatedMemoryMB: estimatedMB,\n availableMemoryMB: availableMB,\n heapLimitMB,\n availableRamMB,\n limitingFactor,\n memoryBudget: budget.candidates,\n memoryObserved: budget.observed,\n totalRows,\n maxRows,\n recommendedMaxRows,\n },\n );\n }\n}\n\n/**\n * Emits a warning for large symbol tables when loading all rows.\n * Warning threshold scales with configured heap size (12.5% of heap).\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n */\nexport function warnLargeSymbolTable(symbolTableSize, maxRows, totalRows) {\n // Dynamic warning threshold: 12.5% of configured heap size\n // Examples: 4GB heap = 512MB, 8GB heap = 1GB, 16GB heap = 2GB\n const heapLimit = getHeapLimit();\n const LARGE_SYMBOL_TABLE_WARNING = heapLimit * 0.125;\n\n if (symbolTableSize > LARGE_SYMBOL_TABLE_WARNING && (maxRows === null || maxRows >= totalRows)) {\n const sizeMB = Math.round(symbolTableSize / 1024 / 1024);\n const estimatedMemory = estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n const estimatedMB = Math.round(estimatedMemory / 1024 / 1024);\n const warnMB = Math.round(LARGE_SYMBOL_TABLE_WARNING / 1024 / 1024);\n\n console.warn(\n `⚠️ Large symbol table detected (${sizeMB}MB > ${warnMB}MB threshold). Loading all ${totalRows.toLocaleString()} rows will use ~${estimatedMB}MB RAM. ` +\n `Consider using the maxRows parameter for better performance and lower memory usage.`,\n );\n }\n}\n","// @ts-check\n\nimport {QvdCorruptedError, QvdValidationError} from '../QvdErrors.js';\nimport {getHeapLimit} from './memoryUtils.js';\n\n/**\n * Validates symbol table size during initial file read (early check).\n * This is the first-pass validation in _readData for lazy loading.\n * Limit scales with configured heap size (12.5% of heap).\n *\n * @param {number} symbolTableLength Size of symbol table in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdValidationError} If symbol table exceeds dynamic limit\n */\nexport function validateSymbolTableSizeEarly(symbolTableLength, filePath) {\n // Dynamic limit: 12.5% of configured heap size\n // Examples: 4GB heap = 512MB, 8GB heap = 1GB, 16GB heap = 2GB\n const heapLimit = getHeapLimit();\n const MAX_SYMBOL_TABLE_SIZE = heapLimit * 0.125;\n\n if (symbolTableLength > MAX_SYMBOL_TABLE_SIZE) {\n const sizeMB = Math.round(symbolTableLength / 1024 / 1024);\n const maxMB = Math.round(MAX_SYMBOL_TABLE_SIZE / 1024 / 1024);\n const heapMB = Math.round(heapLimit / 1024 / 1024);\n\n throw new QvdValidationError(\n `Symbol table too large (${sizeMB}MB exceeds ${maxMB}MB limit for lazy loading). ` +\n `This QVD file contains extremely high-cardinality fields. ` +\n `Limit scales with heap size (current: ${heapMB}MB, limit: 12.5% = ${maxMB}MB). ` +\n `Consider: (1) loading the full file without maxRows, (2) increasing heap size with --max-old-space-size, or (3) aggregating high-cardinality fields.`,\n {\n file: filePath,\n symbolTableSize: symbolTableLength,\n symbolTableSizeMB: sizeMB,\n maxAllowed: MAX_SYMBOL_TABLE_SIZE,\n maxAllowedMB: maxMB,\n heapLimitMB: heapMB,\n limitPercentage: 12.5,\n },\n );\n }\n}\n\n/**\n * Validates symbol table size limits to prevent out-of-memory conditions.\n * This is the comprehensive validation in _parseSymbolTable.\n * Absolute ceiling scales with configured heap size (50% of heap).\n *\n * @param {number} symbolTableLength Size of symbol table in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number} totalRows Total number of rows in the file\n * @throws {QvdValidationError} If symbol table exceeds safety limits\n */\nexport function validateSymbolTableSize(symbolTableLength, filePath, totalRows) {\n // Dynamic absolute ceiling: 50% of configured heap size\n // Examples: 4GB heap = 2GB, 8GB heap = 4GB, 16GB heap = 8GB, 32GB heap = 16GB\n const heapLimit = getHeapLimit();\n const ABSOLUTE_MAX_SYMBOL_TABLE = heapLimit * 0.5;\n\n if (symbolTableLength > ABSOLUTE_MAX_SYMBOL_TABLE) {\n const sizeMB = Math.round(symbolTableLength / 1024 / 1024);\n const maxMB = Math.round(ABSOLUTE_MAX_SYMBOL_TABLE / 1024 / 1024);\n const heapMB = Math.round(heapLimit / 1024 / 1024);\n\n throw new QvdValidationError(\n `Symbol table exceeds absolute maximum size (${sizeMB}MB > ${maxMB}MB). ` +\n `This QVD file has pathological cardinality (likely a data modeling issue). ` +\n `Limit scales with heap size (current: ${heapMB}MB, limit: 50% = ${maxMB}MB). ` +\n `Consider: (1) increasing heap size with --max-old-space-size, (2) aggregating high-cardinality fields, (3) splitting the data, or (4) using a different format.`,\n {\n file: filePath,\n symbolTableSize: symbolTableLength,\n symbolTableSizeMB: sizeMB,\n maxAllowed: ABSOLUTE_MAX_SYMBOL_TABLE,\n maxAllowedMB: maxMB,\n heapLimitMB: heapMB,\n limitPercentage: 50,\n totalRows,\n },\n );\n }\n}\n\n/**\n * Validates field metadata before processing to prevent buffer overflow attacks.\n *\n * @param {any} field Field metadata object\n * @param {number} symbolBufferLength Length of the symbol buffer\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdCorruptedError} If field metadata is invalid\n */\nexport function validateFieldMetadata(field, symbolBufferLength, filePath) {\n const symbolsOffset = parseInt(field['Offset'], 10);\n const symbolsLength = parseInt(field['Length'], 10);\n\n // Validate offset is a valid number and within bounds\n if (isNaN(symbolsOffset) || !Number.isSafeInteger(symbolsOffset) || symbolsOffset < 0) {\n throw new QvdCorruptedError('Invalid symbol offset', {\n field: field['FieldName'],\n offset: symbolsOffset,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n // Validate length is a valid number and non-negative\n if (isNaN(symbolsLength) || !Number.isSafeInteger(symbolsLength) || symbolsLength < 0) {\n throw new QvdCorruptedError('Invalid symbol length', {\n field: field['FieldName'],\n length: symbolsLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n // Validate that offset + length doesn't exceed buffer size\n if (symbolsOffset + symbolsLength > symbolBufferLength) {\n throw new QvdCorruptedError('Symbol data extends beyond buffer', {\n field: field['FieldName'],\n offset: symbolsOffset,\n length: symbolsLength,\n bufferSize: symbolBufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n}\n\n/**\n * Validates index table metadata and bounds.\n *\n * @param {number} recordSize Size of a single record in bytes\n * @param {number} totalRows Total number of rows\n * @param {number} indexTableLength Length of the index table\n * @param {number} indexTableOffset Offset to the index table\n * @param {number} bufferLength Length of the buffer\n * @param {number} rowsToLoad Number of rows to load\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {number|null} [fileSize] Actual size of the file on disk, when known. Used to detect a\n * header that describes more data than the file contains.\n * @throws {QvdCorruptedError} If index table metadata is invalid\n */\nexport function validateIndexTableMetadata(\n recordSize,\n totalRows,\n indexTableLength,\n indexTableOffset,\n bufferLength,\n rowsToLoad,\n filePath,\n fileSize = null,\n) {\n // Validate recordSize\n if (isNaN(recordSize) || !Number.isSafeInteger(recordSize) || recordSize < 0) {\n throw new QvdCorruptedError('Invalid record byte size', {\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate totalRows\n if (isNaN(totalRows) || !Number.isSafeInteger(totalRows) || totalRows < 0) {\n throw new QvdCorruptedError('Invalid number of records', {\n totalRows,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Allow recordSize of 0 or 1 only when there are no records (empty QVD)\n // Qlik Sense uses recordSize=1 for empty QVDs\n if (recordSize === 0 && totalRows > 0) {\n throw new QvdCorruptedError('Record byte size cannot be zero when records exist', {\n recordSize,\n totalRows,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate recordSize is reasonable (max 1MB per record)\n if (recordSize > 1048576) {\n throw new QvdCorruptedError('Record byte size exceeds maximum', {\n recordSize,\n maxSize: 1048576,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate index table length\n if (isNaN(indexTableLength) || !Number.isSafeInteger(indexTableLength) || indexTableLength < 0) {\n throw new QvdCorruptedError('Invalid index table length', {\n length: indexTableLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate index table start offset doesn't extend beyond buffer\n if (indexTableOffset > bufferLength) {\n throw new QvdCorruptedError('Index table offset beyond buffer', {\n indexTableOffset,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // The index table must be exactly as long as the record count implies. Every QVD produced by\n // Qlik or by this library satisfies this, so a mismatch means the header is inconsistent.\n // Checking it catches corrupt headers that would otherwise decode misaligned rows.\n if (indexTableLength !== totalRows * recordSize) {\n throw new QvdCorruptedError('Index table length inconsistent with record count', {\n indexTableLength,\n expectedLength: totalRows * recordSize,\n totalRows,\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate the index table against the actual file when its size is known.\n //\n // Comparing against the in-memory buffer instead is wrong in both directions: during a lazy\n // load the buffer is deliberately truncated, so valid large files were rejected as corrupt,\n // while a truncated file whose header claims more data was accepted and silently returned\n // fewer rows than the header declares.\n if (fileSize !== null) {\n if (indexTableOffset + indexTableLength > fileSize) {\n throw new QvdCorruptedError('Index table extends beyond the end of the file', {\n indexTableOffset,\n indexTableLength,\n fileSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n }\n\n // Ensure the loaded buffer actually holds the rows we were asked to parse.\n const requiredIndexBytes = rowsToLoad * recordSize;\n if (indexTableOffset + requiredIndexBytes > bufferLength) {\n throw new QvdCorruptedError('Index table truncated', {\n indexTableOffset,\n requiredBytes: requiredIndexBytes,\n availableBytes: Math.max(0, bufferLength - indexTableOffset),\n rowsToLoad,\n recordSize,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Ensure the index table length is sufficient for the number of rows to load\n if (indexTableLength < requiredIndexBytes) {\n throw new QvdCorruptedError('Index table length smaller than required', {\n indexTableLength,\n requiredBytes: requiredIndexBytes,\n rowsToLoad,\n recordSize,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n}\n\n/**\n * Validates field bit offset and bit width for index table parsing.\n *\n * @param {any} field Field metadata object\n * @param {number} recordSize Size of a single record in bytes\n * @param {string} filePath Path to the QVD file (for error messages)\n * @throws {QvdCorruptedError} If field bit metadata is invalid\n */\nexport function validateFieldBitMetadata(field, recordSize, filePath) {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n\n // Validate bitOffset\n if (isNaN(bitOffset) || !Number.isSafeInteger(bitOffset) || bitOffset < 0) {\n throw new QvdCorruptedError('Invalid bit offset', {\n field: field['FieldName'],\n bitOffset,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate bitWidth\n if (isNaN(bitWidth) || !Number.isSafeInteger(bitWidth) || bitWidth < 0) {\n throw new QvdCorruptedError('Invalid bit width', {\n field: field['FieldName'],\n bitWidth,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n\n // Validate bitOffset + bitWidth doesn't exceed record size in bits\n const recordSizeInBits = recordSize * 8;\n if (bitOffset + bitWidth > recordSizeInBits) {\n throw new QvdCorruptedError('Bit field extends beyond record size', {\n field: field['FieldName'],\n bitOffset,\n bitWidth,\n recordSizeInBits,\n file: filePath,\n stage: 'parseIndexTable',\n });\n }\n}\n","// @ts-check\n\nimport {QvdSymbol} from '../QvdSymbol.js';\nimport {QvdCorruptedError, QvdParseError} from '../QvdErrors.js';\n\n/**\n * Parses an integer symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for an integer\n if (pointer + 4 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading integer symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const byteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 4));\n const value = Buffer.from(byteData).readIntLE(0, byteData.length);\n return {symbol: QvdSymbol.fromIntValue(value), bytesRead: 4};\n}\n\n/**\n * Parses a double symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for a double\n if (pointer + 8 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading double symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const byteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 8));\n const value = Buffer.from(byteData).readDoubleLE(0);\n return {symbol: QvdSymbol.fromDoubleValue(value), bytesRead: 8};\n}\n\n/**\n * Parses a string symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n const startPointer = pointer;\n const maxStringLength = 1048576; // 1MB max string size to prevent memory exhaustion\n let stringLength = 0;\n\n // Find the null terminator\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('String symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n // Ensure we found the null terminator\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('String symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const value = symbolBuffer.subarray(startPointer, pointer).toString('utf-8');\n return {symbol: QvdSymbol.fromStringValue(value), bytesRead: pointer - startPointer + 1};\n}\n\n/**\n * Skips a string symbol in the buffer without parsing it.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {number} Bytes to skip\n */\nexport function skipStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n const startPointer = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('String symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('String symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n return pointer - startPointer + 1;\n}\n\n/**\n * Parses a dual integer symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDualIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for an integer\n if (pointer + 4 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading dual integer symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const intByteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 4));\n const intValue = Buffer.from(intByteData).readIntLE(0, intByteData.length);\n pointer += 4;\n\n // Parse the string portion\n const stringStart = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const stringValue = symbolBuffer.subarray(stringStart, pointer).toString('utf-8');\n return {symbol: QvdSymbol.fromDualIntValue(intValue, stringValue), bytesRead: pointer - (stringStart - 4) + 1};\n}\n\n/**\n * Parses a dual double symbol from the buffer.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol and bytes read\n */\nexport function parseDualDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath) {\n // Validate we have enough bytes for a double\n if (pointer + 8 > bufferLength) {\n throw new QvdCorruptedError('Buffer overflow reading dual double symbol', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const doubleByteData = new Int32Array(symbolBuffer.subarray(pointer, pointer + 8));\n const doubleValue = Buffer.from(doubleByteData).readDoubleLE(0);\n pointer += 8;\n\n // Parse the string portion\n const stringStart = pointer;\n const maxStringLength = 1048576;\n let stringLength = 0;\n\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const stringValue = symbolBuffer.subarray(stringStart, pointer).toString('utf-8');\n return {\n symbol: QvdSymbol.fromDualDoubleValue(doubleValue, stringValue),\n bytesRead: pointer - (stringStart - 8) + 1,\n };\n}\n\n/**\n * Skips a dual symbol (integer or double) in the buffer without parsing it.\n *\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position\n * @param {number} bufferLength Length of the buffer\n * @param {number} numericBytes Number of bytes for the numeric portion (4 for int, 8 for double)\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @returns {number} Bytes to skip\n */\nexport function skipDualSymbol(symbolBuffer, pointer, bufferLength, numericBytes, fieldName, filePath) {\n if (pointer + numericBytes > bufferLength) {\n throw new QvdCorruptedError(`Buffer overflow reading dual symbol`, {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n const startPointer = pointer;\n pointer += numericBytes;\n\n // Skip the string portion\n const maxStringLength = 1048576;\n let stringLength = 0;\n while (pointer < bufferLength && symbolBuffer[pointer] !== 0) {\n if (stringLength >= maxStringLength) {\n throw new QvdCorruptedError('Dual string symbol exceeds maximum length', {\n field: fieldName,\n maxLength: maxStringLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n pointer++;\n stringLength++;\n }\n\n if (pointer >= bufferLength) {\n throw new QvdCorruptedError('Dual string symbol not null-terminated', {\n field: fieldName,\n pointer,\n bufferSize: bufferLength,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n\n return pointer - startPointer + 1;\n}\n\n/**\n * Parses a symbol based on the type byte.\n *\n * @param {number} typeByte The type byte\n * @param {Buffer} symbolBuffer The symbol buffer\n * @param {number} pointer Current pointer position (after type byte)\n * @param {number} bufferLength Length of the buffer\n * @param {string} fieldName Name of the field being parsed\n * @param {string} filePath Path to the QVD file (for error messages)\n * @param {boolean} shouldParse Whether to parse the symbol (true) or skip it (false)\n * @returns {{symbol: import('../QvdSymbol.js').QvdSymbol | null, bytesRead: number}} Parsed symbol (or null if skipped) and bytes read\n */\nexport function parseSymbol(typeByte, symbolBuffer, pointer, bufferLength, fieldName, filePath, shouldParse) {\n switch (typeByte) {\n case 1: {\n // Integer value (4 Bytes)\n if (shouldParse) {\n return parseIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n return {symbol: null, bytesRead: 4};\n }\n case 2: {\n // Double value (8 Bytes)\n if (shouldParse) {\n return parseDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n return {symbol: null, bytesRead: 8};\n }\n case 4: {\n // String value (0 terminated)\n if (shouldParse) {\n return parseStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipStringSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n case 5: {\n // Dual (Integer format) value (4 bytes), followed by string format\n if (shouldParse) {\n return parseDualIntegerSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipDualSymbol(symbolBuffer, pointer, bufferLength, 4, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n case 6: {\n // Dual (Double format) value (8 bytes), followed by string format\n if (shouldParse) {\n return parseDualDoubleSymbol(symbolBuffer, pointer, bufferLength, fieldName, filePath);\n }\n const bytesRead = skipDualSymbol(symbolBuffer, pointer, bufferLength, 8, fieldName, filePath);\n return {symbol: null, bytesRead};\n }\n default: {\n throw new QvdParseError('Unknown symbol type byte', {\n typeByte: typeByte.toString(16),\n offset: pointer - 1,\n file: filePath,\n stage: 'parseSymbolTable',\n });\n }\n }\n}\n","// @ts-check\n\nimport fs from 'fs';\nimport xml from 'xml2js';\nimport assert from 'assert';\nimport {QvdDataFrame} from './QvdDataFrame.js';\nimport {QvdParseError, QvdValidationError, QvdCorruptedError} from './QvdErrors.js';\nimport {validatePath} from './util/validatePath.js';\nimport {convertBitsToInt32} from './util/bitUtils.js';\nimport {estimateMemoryUsage, validateMemoryAvailability, warnLargeSymbolTable} from './util/memoryUtils.js';\nimport {\n validateSymbolTableSize,\n validateSymbolTableSizeEarly,\n validateFieldMetadata,\n validateIndexTableMetadata,\n validateFieldBitMetadata,\n} from './util/validationUtils.js';\nimport {parseSymbol} from './util/symbolParser.js';\n\n/**\n * Maximum number of bytes searched for the XML header delimiter before giving up.\n * Real QVD headers are a few kilobytes; the largest observed is well under 100KB.\n */\nconst MAX_HEADER_SIZE = 16 * 1024 * 1024;\n\n/**\n * Maximum length of a single fs.read call. Node's fs.read binding requires the length to fit\n * in an Int32: a larger value aborts the process via a C++ assertion instead of throwing.\n */\nconst READ_CHUNK_SIZE = 512 * 1024 * 1024;\n\n/**\n * Parses a QVD file and loads it into memory.\n */\nexport class QvdFileReader {\n /**\n * Constructs a new QVD file parser.\n *\n * @param {string} filePath The path to the QVD file to load.\n * @param {Object} [options={}] Options for the reader.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file\n * path must be within this directory, with symlinks resolved first, so a link inside it that\n * points outside it is rejected. Defaults to the current working directory. To permit\n * an entire volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or\n * empty value falls back to the working directory rather than removing the restriction.\n * @param {number} [options.memorySafetyFactor=0.3] Fraction (0.0-1.0) of the memory budget a\n * load may use. The budget is the smallest of the V8 heap limit, any container memory limit,\n * and the memory the OS reports as available. Default is 0.3. **Zero disables the memory\n * check entirely**, which is the escape hatch for runtimes whose limits cannot be measured -\n * Bun reports its current heap as its heap limit - and for callers who would rather manage\n * memory themselves than trust the estimate.\n * @param {number} [options.symbolFilteringThreshold=52428800] Symbol table size, in bytes,\n * above which a lazy load switches to the two-pass filtering path. The default of 50MB is\n * the point where the extra analysis pass pays for itself; lower it to use filtering on\n * smaller files, raise it to keep the simpler single-pass read for longer.\n */\n constructor(filePath, options = {}) {\n const {allowedDir, memorySafetyFactor = 0.3, symbolFilteringThreshold = 50 * 1024 * 1024} = options;\n this._path = validatePath(filePath, allowedDir);\n this._memorySafetyFactor = memorySafetyFactor;\n this._symbolFilteringThreshold = symbolFilteringThreshold;\n this._buffer = null;\n this._headerOffset = null;\n this._symbolTableOffset = null;\n this._indexTableOffset = null;\n this._header = null;\n /** @type {Array<Array<import('./QvdSymbol.js').QvdSymbol>>|null} */\n this._symbolTable = null;\n /** @type {Array<Array<number>>|null} */\n this._indexTable = null;\n /** @type {number|null} */\n this._fileSize = null;\n }\n\n /**\n * Reads the binary data of the QVD file.\n *\n * LAZY LOADING OPTIMIZATION: When maxRows is specified, this method implements\n * true lazy loading by reading only the necessary portions of the file from disk.\n *\n * For large files (e.g., 5GB), loading only the first 1000 rows can save significant\n * memory and time:\n * - Full load: 5GB in memory, ~30-60s load time\n * - Lazy load (maxRows=1000): ~1.75-2GB in memory, ~2-5s load time\n *\n * Algorithm for Lazy Loading:\n * 1. Stream-read the file until XML header delimiter is found\n * 2. Parse header to determine symbol table and index table locations\n * 3. Calculate bytes needed: header + full symbol table + partial index table\n * 4. Read only those calculated bytes using fs.open/read\n * 5. Rest of parsing proceeds normally with limited data\n *\n * WHY THIS APPROACH:\n * - Symbol table must be fully loaded (contains all unique values)\n * - Index table can be partially loaded (only rows we need)\n * - Streaming for header finding is efficient for unknown header sizes\n * - Direct byte-range reading for remaining data is fastest\n *\n * @param {number|null} maxRows The maximum number of rows to load. If null, all data is loaded.\n * @private\n */\n async _readData(maxRows = null) {\n if (maxRows === null) {\n // Load entire file into memory (original behavior)\n // This is simple and fast for small to medium files\n this._buffer = await fs.promises.readFile(this._path);\n this._fileSize = this._buffer.length;\n return;\n }\n\n const HEADER_DELIMITER = '\\r\\n\\0';\n const CHUNK_SIZE = 64 * 1024; // 64KB chunks - balance between memory and I/O efficiency\n\n // Use streaming to find the header delimiter dynamically\n // We don't know header size in advance, so we must stream-read\n const stream = fs.createReadStream(this._path, {\n highWaterMark: CHUNK_SIZE,\n });\n\n /** @type {Array<Buffer>} */\n const headerChunks = [];\n let headerBytes = 0;\n /** Last (delimiter length - 1) bytes seen so far, carried across chunk boundaries. */\n let tail = Buffer.alloc(0);\n let headerBuffer = Buffer.alloc(0);\n let headerDelimiterIndex = -1;\n\n try {\n // Read chunks until we find the delimiter.\n //\n // Chunks are collected and concatenated once, and each chunk is searched individually\n // (with a small carry-over so a delimiter straddling a chunk boundary is still found).\n // Concatenating the whole accumulated buffer on every chunk and re-scanning it from the\n // start is quadratic: a 200 MB delimiter-less file cost 43 s and 13 GB of memory.\n for await (const chunk of stream) {\n // Search the new chunk prefixed by the bytes already seen, so a delimiter spanning a\n // chunk boundary is not missed.\n //\n // The carry is kept in `tail` across iterations rather than read back off the previous\n // chunk, because a chunk may be shorter than the delimiter. Taking min(bytesSoFar, 2)\n // bytes from a 1-byte previous chunk yields only 1 byte, which both misses a delimiter\n // spread over three chunks and leaves the reported offset short by the difference.\n const chunkStart = headerBytes;\n const searchBuffer = tail.length > 0 ? Buffer.concat([tail, chunk]) : chunk;\n const foundInSearch = searchBuffer.indexOf(HEADER_DELIMITER);\n\n headerChunks.push(chunk);\n headerBytes += chunk.length;\n\n if (foundInSearch !== -1) {\n // searchBuffer starts tail.length bytes before this chunk does.\n headerDelimiterIndex = chunkStart - tail.length + foundInSearch;\n stream.destroy();\n break;\n }\n\n // Copy the carry instead of keeping a subarray view, which would pin the whole chunk.\n tail = Buffer.from(searchBuffer.subarray(-(HEADER_DELIMITER.length - 1)));\n\n // Real QVD headers are a few kilobytes. Without a cap, a non-QVD or corrupt file is\n // read to its end before the error below is raised, which is a denial-of-service\n // vector for any service that accepts uploaded files.\n if (headerBytes > MAX_HEADER_SIZE) {\n stream.destroy();\n throw new QvdCorruptedError(\n `The XML header delimiter was not found within the first ${MAX_HEADER_SIZE / (1024 * 1024)}MB of the file.`,\n {\n file: this._path,\n bytesSearched: headerBytes,\n maxHeaderSize: MAX_HEADER_SIZE,\n stage: 'readData',\n },\n );\n }\n }\n } catch (error) {\n // Destroying the stream once the delimiter is found surfaces as ERR_STREAM_PREMATURE_CLOSE.\n // That one case is expected and ignored; everything else must propagate.\n //\n // The previous condition also required a 'code' property, so any error without one — a\n // TypeError or RangeError raised in the loop body, or a stream error from a source that\n // does not set a code — was swallowed. Execution then fell through to the generic\n // 'header not properly delimited' error below, reporting file corruption for what was\n // actually a bug or an I/O failure.\n const isExpectedEarlyClose =\n headerDelimiterIndex !== -1 &&\n error !== null &&\n typeof error === 'object' &&\n /** @type {{code?: unknown}} */ (error).code === 'ERR_STREAM_PREMATURE_CLOSE';\n\n if (!isExpectedEarlyClose) {\n throw error;\n }\n }\n\n if (headerDelimiterIndex === -1) {\n throw new QvdCorruptedError(\n 'The XML header section does not exist or is not properly delimited from the binary data.',\n {\n file: this._path,\n stage: 'readData',\n },\n );\n }\n\n headerBuffer = Buffer.concat(headerChunks);\n\n const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;\n\n // Parse header to get metadata about symbol and index table locations\n const headerXml = headerBuffer.subarray(0, headerEndIndex).toString();\n const headerObj = await xml.parseStringPromise(headerXml, {explicitArray: false});\n\n if (!headerObj) {\n throw new QvdParseError('The XML header could not be parsed.', {\n file: this._path,\n stage: 'readData',\n });\n }\n\n const symbolTableOffset = headerEndIndex;\n const symbolTableLength = parseInt(headerObj['QvdTableHeader']['Offset'], 10);\n const indexTableOffset = symbolTableOffset + symbolTableLength;\n const recordSize = parseInt(headerObj['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(headerObj['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToLoad = Math.min(maxRows, totalRows);\n\n // SAFETY CHECK: Very large symbol tables (>500MB) are still blocked to prevent OOM\n // Phase 2 filtering can handle up to ~500MB symbol tables efficiently\n validateSymbolTableSizeEarly(symbolTableLength, this._path);\n\n // Validate the header numbers before they are used to size an allocation. Without this,\n // a NaN or negative value reaches Buffer.alloc and surfaces as a raw Node RangeError.\n for (const [name, value] of [\n ['Offset', symbolTableLength],\n ['RecordByteSize', recordSize],\n ['NoOfRecords', totalRows],\n ]) {\n if (!Number.isSafeInteger(value) || Number(value) < 0) {\n throw new QvdCorruptedError(`Invalid header value: ${name}`, {\n name,\n value,\n file: this._path,\n stage: 'readData',\n });\n }\n }\n\n // Calculate how much of the index table we need to read\n const indexTableBytesToRead = rowsToLoad * recordSize;\n\n // Calculate total bytes needed: header + symbol table + partial index table\n const totalBytesToRead = indexTableOffset + indexTableBytesToRead;\n\n // Now read the exact portion we need from the file\n const fd = await fs.promises.open(this._path, 'r');\n try {\n const {size: fileSize} = await fd.stat();\n this._fileSize = fileSize;\n\n // The buffer size is derived entirely from header values, which may not describe the\n // file on disk (truncated download, interrupted copy, file still being written, or a\n // deliberately crafted header). Reading past the end would otherwise leave the tail of\n // the buffer holding whatever memory the allocator handed out, and that memory is then\n // parsed as symbol and index data.\n if (totalBytesToRead > fileSize) {\n throw new QvdCorruptedError('The file is shorter than its header claims.', {\n file: this._path,\n fileSize,\n requiredBytes: totalBytesToRead,\n stage: 'readData',\n });\n }\n\n // Zero-filled rather than allocUnsafe: if any path ever fails to overwrite part of this\n // buffer, the result is zeros instead of leaked process memory.\n this._buffer = Buffer.alloc(totalBytesToRead);\n\n // Read in bounded chunks, checking bytesRead each time. A single fs.read call with a\n // length of 2^31 or more does not throw - it trips a C++ assertion and aborts the whole\n // process, which no try/catch can intercept.\n let position = 0;\n while (position < totalBytesToRead) {\n const length = Math.min(READ_CHUNK_SIZE, totalBytesToRead - position);\n // @ts-ignore - Buffer type compatibility\n const {bytesRead} = await fd.read(this._buffer, position, length, position);\n\n if (bytesRead === 0) {\n throw new QvdCorruptedError('Unexpected end of file while reading QVD data.', {\n file: this._path,\n fileSize,\n bytesRead: position,\n requiredBytes: totalBytesToRead,\n stage: 'readData',\n });\n }\n\n position += bytesRead;\n }\n } finally {\n await fd.close();\n }\n }\n\n /**\n * Parses the XML header of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n */\n async _parseHeader() {\n if (!this._buffer) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseHeader',\n },\n );\n }\n\n const HEADER_DELIMITER = '\\r\\n\\0';\n\n const headerBeginIndex = 0;\n const headerDelimiterIndex = this._buffer.indexOf(HEADER_DELIMITER, headerBeginIndex);\n\n // Check explicitly for -1 (not found) rather than using falsy check (!headerDelimiterIndex)\n // because indexOf() returns 0 when the delimiter is at position 0, which is a valid buffer index.\n // Using !0 would incorrectly treat position 0 as an error.\n if (headerDelimiterIndex === -1) {\n throw new QvdCorruptedError(\n 'The XML header section does not exist or is not properly delimited from the binary data.',\n {\n file: this._path,\n stage: 'parseHeader',\n },\n );\n }\n\n const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;\n const headerBuffer = this._buffer.subarray(headerBeginIndex, headerEndIndex);\n\n /*\n * The following instruction parses the XML header into a JSON object. It is important to\n * note that the object is a plain JavaScript object and not an instance of representative\n * class. Hence, types are not casted, therefore all raw values are strings, and child nodes\n * that contain an array of objects are not represented directly as an array but as an object\n * with a property, named like the array item tag, that is an array of the actual objects. The\n * same applies to child nodes that contain a single object and the root node.\n *\n * The following XML representation of the QVD header for example...\n *\n * <QvdTableHeader>\n * ...\n * <Fields>\n * <QvdFieldHeader>\n * <FieldName>Field1</FieldName>\n * ...\n * </QvdFieldHeader>\n * <QvdFieldHeader>\n * <FieldName>Field1</FieldName>\n * ...\n * </QvdFieldHeader>\n * </Fields>\n * </QvdTableHeader>\n *\n * ...is parsed into the following object:\n *\n * {\n * QvdTableHeader: {\n * ...,\n * Fields: {\n * QvdFieldHeader: [\n * { FieldName: 'Field1', ...},\n * { FieldName: 'Field2', ...}\n * ]\n * }\n * }\n * }\n */\n\n // Note: xml2js (via sax-js) does not support external entity resolution\n // by default, providing inherent protection against XXE attacks.\n this._header = await xml.parseStringPromise(headerBuffer.toString(), {explicitArray: false});\n\n if (!this._header) {\n throw new QvdParseError('The XML header could not be parsed.', {\n file: this._path,\n stage: 'parseHeader',\n });\n }\n\n /*\n * Because the three parts of the QVD file, header, symbol and index table, are seamlessly concatenated,\n * the end of the respective previous part is the beginning of the next part.\n */\n\n this._headerOffset = headerBeginIndex;\n this._symbolTableOffset = headerEndIndex;\n this._indexTableOffset = this._symbolTableOffset + parseInt(this._header['QvdTableHeader']['Offset'], 10);\n }\n\n /**\n * Estimates the memory usage for loading a QVD file with given parameters.\n * Takes into account Phase 2.5 optimization which skips parsing unused symbols.\n *\n * @param {number} symbolTableSize Size of symbol table in bytes\n * @param {number|null} maxRows Maximum number of rows to load (null = all rows)\n * @param {number} totalRows Total number of rows in the file\n * @returns {number} Estimated memory usage in bytes\n * @private\n */\n _estimateMemoryUsage(symbolTableSize, maxRows, totalRows) {\n return estimateMemoryUsage(symbolTableSize, maxRows, totalRows);\n }\n\n /**\n * Analyzes the index table to determine which symbols are actually needed.\n * This is used for two-pass symbol filtering optimization.\n *\n * @param {number} maxRows The maximum number of rows to analyze.\n * @returns {Promise<Map<string, Set<number>>>} Map of field names to Set of needed symbol indices.\n * @private\n */\n async _analyzeIndexTableSymbolUsage(maxRows) {\n if (!this._buffer || !this._header || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'analyzeIndexTableSymbolUsage',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const recordSize = parseInt(this._header['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToAnalyze = Math.min(maxRows, totalRows);\n const indexTableLength = parseInt(this._header['QvdTableHeader']['Length'], 10);\n\n const indexBuffer = this._buffer.subarray(this._indexTableOffset, this._indexTableOffset + indexTableLength + 1);\n\n // Map of field name -> Set of symbol indices needed\n /** @type {Map<string, Set<number>>} */\n const symbolUsage = new Map();\n\n // Initialize sets for each field\n fields.forEach((field) => {\n symbolUsage.set(field['FieldName'], new Set());\n });\n\n // Parse rows to collect symbol indices\n for (\n let pointer = 0, rowCount = 0;\n pointer < indexBuffer.length && rowCount < rowsToAnalyze;\n pointer += recordSize, rowCount++\n ) {\n const bytes = new Int32Array(indexBuffer.subarray(pointer, pointer + recordSize));\n bytes.reverse();\n\n const mask = bytes\n .reduce((bits, byte) => bits + ('00000000' + byte.toString(2)).slice(-8), '')\n .split('')\n .reverse()\n .map((bit) => parseInt(bit));\n\n // Extract symbol index for each field\n fields.forEach((field) => {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n const bias = parseInt(field['Bias'], 10);\n\n let symbolIndex;\n\n if (bitWidth === 0) {\n symbolIndex = 0;\n } else {\n symbolIndex = this._convertBitsToInt32(mask.slice(bitOffset, bitOffset + bitWidth));\n }\n\n // Apply bias. This MUST use the same sign as _parseIndexTable (which adds the bias),\n // otherwise the symbols recorded as \"needed\" here are not the ones the parse pass\n // looks up, and every affected cell silently reads back as undefined. Qlik encodes\n // nullable fields with Bias=-2, so getting this wrong corrupts every nullable column.\n symbolIndex += bias;\n\n // Negative indices denote NULL and reference no symbol, so they never need to be kept.\n if (symbolIndex < 0) {\n return;\n }\n\n // Add to the set of needed symbols for this field\n const fieldName = field['FieldName'];\n symbolUsage.get(fieldName)?.add(symbolIndex);\n });\n }\n\n return symbolUsage;\n }\n\n /**\n * Parses the symbol table of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n *\n * @param {Map<string, Set<number>>|null} symbolsToKeep Optional map of field names to symbol indices to keep.\n * If provided, only these symbols will be parsed (two-pass filtering optimization).\n * @param {number|null} maxRows Optional maximum number of rows being loaded (for memory estimation).\n */\n async _parseSymbolTable(symbolsToKeep = null, maxRows = null) {\n if (!this._buffer || !this._header || !this._symbolTableOffset || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseSymbolTable',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n const symbolBuffer = this._buffer.subarray(this._symbolTableOffset, this._indexTableOffset);\n const symbolTableSize = symbolBuffer.length;\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n\n // SAFETY CHECK 1: Absolute ceiling to prevent pathological cases\n // Phase 2.5 optimization allows much larger symbol tables when using maxRows,\n // but we still need an absolute maximum to prevent truly extreme cases\n validateSymbolTableSize(symbolTableSize, this._path, totalRows);\n\n // SAFETY CHECK 2: Dynamic memory validation\n // Check if we have enough available memory to load this file safely\n validateMemoryAvailability(symbolTableSize, maxRows, totalRows, this._path, this._memorySafetyFactor);\n\n // WARNING ZONE: Large files without maxRows parameter\n // Educate users about best practices but don't block\n warnLargeSymbolTable(symbolTableSize, maxRows, totalRows);\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n /*\n * The symbol table is a contiguous byte array that contains all possible symbols/values of all fields/columns.\n * The symbols/values of one field are stored consecutively in the same order as the fields/columns are defined\n * in the header. The length of the symbol area as well as it's offset, relativ to the begin of the symbol\n * table, are also defined in the header.\n */\n\n // Validate all field metadata before processing to prevent buffer overflow attacks\n for (const field of fields) {\n validateFieldMetadata(field, symbolBuffer.length, this._path);\n }\n\n // Parse all possible symbols of each field/column\n // Phase 2.5 optimization: Skip parsing entirely for symbols we don't need\n this._symbolTable = fields.map((/** @type {any} */ field) => {\n const symbolsOffset = parseInt(field['Offset'], 10); // Offset of the column's symbol area in the symbol table\n const symbolsLength = parseInt(field['Length'], 10); // Length of the column's symbol area in the symbol table\n\n const fieldName = field['FieldName'];\n const neededSymbols = symbolsToKeep ? symbolsToKeep.get(fieldName) : null;\n const filteringEnabled = neededSymbols !== null;\n\n const symbols = [];\n let symbolIndex = 0; // Track current symbol index as we parse\n\n // Parse all possible values of the current field/column\n for (let pointer = symbolsOffset; pointer < symbolsOffset + symbolsLength; pointer++) {\n // Each stored symbol consists of a type byte and the actual value, which length depends on the type\n const typeByte = symbolBuffer[pointer++];\n\n // Check if we should keep this symbol (filtering mode)\n const shouldKeepSymbol = !filteringEnabled || !!(neededSymbols && neededSymbols.has(symbolIndex));\n\n // Use utility function to parse or skip symbol\n const {symbol, bytesRead} = parseSymbol(\n typeByte,\n symbolBuffer,\n pointer,\n symbolBuffer.length,\n fieldName,\n this._path,\n shouldKeepSymbol,\n );\n\n symbols.push(symbol);\n pointer += bytesRead - 1; // -1 because the loop will increment\n symbolIndex++;\n }\n\n return symbols;\n // @ts-ignore - Symbol table type assignment\n });\n }\n\n /**\n * Utility method to convert a bit array to an integer value.\n *\n * @param {Array<number>} bits The bit array\n * @return {Number} The integer value\n */\n _convertBitsToInt32(bits) {\n return convertBitsToInt32(bits);\n }\n\n /**\n * Parses the bit stuffed index table of the QVD file. This method is part of the parsing process\n * and should not be called directly.\n *\n * @param {number|null} maxRows The maximum number of rows to parse. If null, all rows are parsed.\n */\n async _parseIndexTable(maxRows = null) {\n if (!this._buffer || !this._header || !this._indexTableOffset) {\n throw new QvdCorruptedError(\n 'The QVD file has not been loaded in the proper order or has not been loaded at all.',\n {\n file: this._path,\n stage: 'parseIndexTable',\n },\n );\n }\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n // Size of a single row of the index table in bytes\n const recordSize = parseInt(this._header['QvdTableHeader']['RecordByteSize'], 10);\n const totalRows = parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10);\n const rowsToLoad = maxRows !== null ? Math.min(maxRows, totalRows) : totalRows;\n const indexTableLength = parseInt(this._header['QvdTableHeader']['Length'], 10);\n\n // Validate all index table metadata\n validateIndexTableMetadata(\n recordSize,\n totalRows,\n indexTableLength,\n this._indexTableOffset,\n this._buffer.length,\n rowsToLoad,\n this._path,\n this._fileSize,\n );\n\n const indexBuffer = this._buffer.subarray(this._indexTableOffset, this._indexTableOffset + indexTableLength + 1);\n\n // Validate BitOffset and BitWidth for all fields before processing\n for (const field of fields) {\n validateFieldBitMetadata(field, recordSize, this._path);\n }\n\n this._indexTable = [];\n\n // Parse rows of the index table, each row contains the indices of the symbol table for each field/column\n for (\n let pointer = 0, rowCount = 0;\n pointer < indexBuffer.length && rowCount < rowsToLoad;\n pointer += recordSize, rowCount++\n ) {\n // Validate we have enough bytes for this record\n if (pointer + recordSize > indexBuffer.length) {\n throw new QvdCorruptedError('Buffer overflow reading index table record', {\n pointer,\n recordSize,\n bufferSize: indexBuffer.length,\n file: this._path,\n stage: 'parseIndexTable',\n });\n }\n\n const bytes = new Int32Array(indexBuffer.subarray(pointer, pointer + recordSize));\n bytes.reverse();\n\n // The bit mask contains the bit stuffed indices of the symbol table of the current row\n const mask = bytes\n .reduce((bits, byte) => bits + ('00000000' + byte.toString(2)).slice(-8), '')\n .split('')\n .reverse()\n .map((bit) => parseInt(bit));\n\n /** @type {number[]} */\n const symbolIndices = [];\n\n // Extract the index from the current row's bit mask for each field/column\n fields.forEach((/** @type {any} */ field) => {\n const bitOffset = parseInt(field['BitOffset'], 10);\n const bitWidth = parseInt(field['BitWidth'], 10);\n const bias = parseInt(field['Bias'], 10);\n\n let symbolIndex;\n\n if (bitWidth === 0) {\n symbolIndex = 0;\n } else {\n symbolIndex = this._convertBitsToInt32(mask.slice(bitOffset, bitOffset + bitWidth));\n }\n\n symbolIndex += bias;\n symbolIndices.push(symbolIndex);\n });\n\n this._indexTable.push(symbolIndices);\n }\n\n // The loop is bounded by the buffer as well as by rowsToLoad, so a short buffer would\n // otherwise silently yield fewer rows than the header declares.\n if (this._indexTable.length !== rowsToLoad) {\n throw new QvdCorruptedError('Index table contains fewer records than expected', {\n expectedRows: rowsToLoad,\n actualRows: this._indexTable.length,\n totalRows,\n recordSize,\n file: this._path,\n stage: 'parseIndexTable',\n });\n }\n }\n\n /**\n * Loads the QVD file into memory and parses it.\n *\n * @param {number|null} maxRows The maximum number of rows to load. If null, all rows are loaded.\n * Must be a non-negative integer when given.\n * @throws {QvdValidationError} If maxRows is neither null nor a non-negative integer.\n * @return {Promise<QvdDataFrame>} The loaded QVD file.\n */\n async load(maxRows = null) {\n // Validate before any I/O. Every downstream use is Math.min(maxRows, totalRows), which\n // silently accepts nonsense: a negative value yields a negative row count, NaN makes every\n // comparison false, and a fractional value produces a fractional loop bound. Each of those\n // returns a wrong or empty data frame rather than an error, so reject them up front.\n // undefined never reaches here: the default parameter above turns it into null.\n if (maxRows !== null && (typeof maxRows !== 'number' || !Number.isInteger(maxRows) || maxRows < 0)) {\n throw new QvdValidationError('maxRows must be a non-negative integer, or null to load all rows', {\n provided: maxRows,\n type: typeof maxRows,\n file: this._path,\n });\n }\n\n await this._readData(maxRows);\n await this._parseHeader();\n\n // Determine if we should use two-pass symbol filtering\n // This optimization is beneficial for large symbol tables with limited row access\n let symbolsToKeep = null;\n let symbolsKept = null;\n\n if (maxRows !== null && this._header) {\n const symbolTableLength = parseInt(this._header['QvdTableHeader']['Offset'], 10);\n\n // Use two-pass filtering for symbol tables above the threshold when loading limited rows.\n // The threshold is an option rather than a constant so this path can be exercised with a\n // small fixture: it is the most intricate code in the reader, and the only files large\n // enough to reach the 50MB default are ones no repository should be carrying around.\n if (symbolTableLength > this._symbolFilteringThreshold) {\n // Pass 1: Analyze which symbols are actually needed\n symbolsToKeep = await this._analyzeIndexTableSymbolUsage(maxRows);\n\n // Recorded rather than logged. This used to be a console.log, which a library has no\n // business emitting: callers could not silence it, and it was the only way to find out\n // whether filtering had happened. It is now reported through QvdDataFrame.loadStats,\n // which callers can inspect - and tests can assert on deterministically, where the\n // previous test measured a heapUsed delta and failed on GC timing instead.\n symbolsKept = Array.from(symbolsToKeep.values()).reduce((sum, set) => sum + set.size, 0);\n }\n }\n\n // Pass 2: Parse symbol table (with filtering if enabled)\n await this._parseSymbolTable(symbolsToKeep, maxRows);\n await this._parseIndexTable(maxRows);\n\n assert(this._header, 'The QVD file header has not been parsed.');\n assert(this._symbolTable, 'The QVD file symbol table has not been parsed.');\n assert(this._indexTable, 'The QVD file index table has not been parsed.');\n\n /**\n * Retrieves the values of a specific row of the QVD file. Values are in the same order\n * as the field names.\n *\n * @param {number} index The index of the row.\n * @return {Array<any>} The values of the row.\n */\n const getRow = (index) => {\n if (!this._indexTable || index >= this._indexTable.length) {\n throw new QvdValidationError('Row index out of bounds', {\n index,\n max: this._indexTable ? this._indexTable.length - 1 : -1,\n file: this._path,\n });\n }\n\n return this._indexTable?.[index].map((/** @type {number} */ symbolIndex, /** @type {number} */ fieldIndex) => {\n if (symbolIndex < 0) {\n return null;\n }\n\n const symbol = this._symbolTable?.[fieldIndex]?.[symbolIndex];\n const value = symbol?.toPrimaryValue();\n\n if (typeof value === 'string') {\n // Number('') and Number(' ') are 0, which silently turned every blank cell Qlik\n // stored into the number zero - indistinguishable from a real zero, and persisted as\n // one on the next write. Blank strings are never numeric, so exclude them.\n if (value.trim() !== '' && !isNaN(Number(value))) {\n return Number(value);\n }\n }\n\n return value;\n });\n };\n\n let fields = this._header['QvdTableHeader']['Fields']['QvdFieldHeader'];\n\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const columns = fields.map((/** @type {any} */ field) => field['FieldName']);\n const data = this._indexTable.map((_, index) => getRow(index));\n\n // Pass the complete header metadata to the data frame\n const metadata = this._header['QvdTableHeader'];\n\n /** @type {import('./QvdDataFrame.js').QvdLoadStats} */\n const loadStats = {\n symbolTableBytes: parseInt(this._header['QvdTableHeader']['Offset'], 10),\n totalRows: parseInt(this._header['QvdTableHeader']['NoOfRecords'], 10),\n rowsLoaded: data.length,\n symbolFiltering: symbolsToKeep !== null,\n symbolsKept,\n };\n\n return new QvdDataFrame(data, columns, metadata, loadStats);\n }\n}\n","// @ts-check\n\nimport {QvdValidationError} from './QvdErrors.js';\n\n/**\n * @typedef {Object} QvdNumberFormat\n * @property {string} Type - Number format type\n * @property {string} nDec - Number of decimals\n * @property {string} UseThou - Use thousands separator\n * @property {string} Fmt - Format string\n * @property {string} Dec - Decimal separator\n * @property {string} Thou - Thousands separator\n */\n\n/**\n * @typedef {Object} QvdFieldHeader\n * @property {string} FieldName - The name of the field\n * @property {string|number} [BitOffset] - The bit offset\n * @property {string|number} [BitWidth] - The bit width\n * @property {string|number} [Bias] - The bias value\n * @property {string|number} [NoOfSymbols] - Number of symbols\n * @property {string|number} [Offset] - The offset\n * @property {string|number} [Length] - The length\n * @property {string} [Comment] - Field comment\n * @property {QvdNumberFormat|string} [NumberFormat] - Number format\n * @property {Object|string} [Tags] - Field tags\n */\n\n/**\n * @typedef {Object} QvdFields\n * @property {QvdFieldHeader|QvdFieldHeader[]} QvdFieldHeader - Field header(s)\n */\n\n/**\n * @typedef {Object} QvdMetadata\n * @property {string|number} [QvBuildNo] - QlikView build number\n * @property {string} [CreatorDoc] - Creator document\n * @property {string} [CreateUtcTime] - Creation UTC time\n * @property {string} [SourceCreateUtcTime] - Source creation UTC time\n * @property {string} [SourceFileUtcTime] - Source file UTC time\n * @property {string|number} [SourceFileSize] - Source file size\n * @property {string} [StaleUtcTime] - Stale UTC time\n * @property {string} [TableName] - Table name\n * @property {string|number} [NoOfRecords] - Number of records\n * @property {string|number} [RecordByteSize] - Record byte size\n * @property {string|number} [Offset] - Offset\n * @property {string|number} [Length] - Length\n * @property {string} [Compression] - Compression type\n * @property {string} [Comment] - Comment\n * @property {string} [EncryptionInfo] - Encryption info\n * @property {string} [TableTags] - Table tags\n * @property {string} [ProfilingData] - Profiling data\n * @property {Object|string} [Lineage] - Lineage\n * @property {QvdFields} [Fields] - Fields information\n */\n\n/**\n * Statistics describing the read that produced a data frame.\n *\n * @typedef {Object} QvdLoadStats\n * @property {number} symbolTableBytes Size of the file's symbol table, in bytes.\n * @property {number} totalRows Rows the file declares in its header.\n * @property {number} rowsLoaded Rows actually materialised.\n * @property {boolean} symbolFiltering Whether the two-pass symbol-filtering path was used.\n * @property {number|null} symbolsKept Symbols retained by that path, or null when it did not run.\n */\n\n/**\n * Represents a loaded QVD file.\n */\nexport class QvdDataFrame {\n /**\n * Represents the data frame stored inside a QVD file.\n * @param {Array<Array<any>>} data The data of the data frame.\n * @param {Array<string>} columns The columns of the data frame.\n * @param {QvdMetadata|null} metadata The metadata from the QVD file header (optional).\n * @param {QvdLoadStats|null} loadStats Statistics about the read (optional).\n */\n constructor(data, columns, metadata = null, loadStats = null) {\n this._data = data;\n this._columns = columns;\n this._metadata = metadata;\n this._loadStats = loadStats;\n }\n\n /**\n * Returns the data of the data frame.\n */\n get data() {\n return this._data;\n }\n\n /**\n * Returns the columns of the data frame.\n */\n get columns() {\n return this._columns;\n }\n\n /**\n * Returns the shape of the data frame.\n */\n get shape() {\n return [this._data.length, this._columns.length];\n }\n\n /**\n * Returns the complete metadata object from the QVD file header.\n * @return {Object|null} The complete metadata object or null if not available.\n */\n get metadata() {\n return this._metadata;\n }\n\n /**\n * Returns statistics about the read that produced this data frame.\n *\n * Only a frame returned by fromQvd() carries these; fromDict(), head() and tail() produce\n * frames that describe no particular read, and report null rather than a stale figure.\n *\n * The main use is confirming that a lazy load actually filtered the symbol table:\n * `symbolFiltering` says whether the two-pass path ran, and `symbolsKept` how many symbols\n * survived it, which for a small maxRows should be a tiny fraction of the file's total.\n *\n * @return {QvdLoadStats|null} Load statistics, or null if this frame did not come from a file.\n */\n get loadStats() {\n return this._loadStats;\n }\n\n /**\n * Returns file-level metadata from the QVD header.\n * @return {Object} File-level metadata properties.\n */\n get fileMetadata() {\n if (!this._metadata) {\n return {};\n }\n\n const header = this._metadata;\n return {\n qvBuildNo: header.QvBuildNo,\n creatorDoc: header.CreatorDoc,\n createUtcTime: header.CreateUtcTime,\n sourceCreateUtcTime: header.SourceCreateUtcTime,\n sourceFileUtcTime: header.SourceFileUtcTime,\n sourceFileSize: header.SourceFileSize,\n staleUtcTime: header.StaleUtcTime,\n tableName: header.TableName,\n noOfRecords: header.NoOfRecords,\n recordByteSize: header.RecordByteSize,\n offset: header.Offset,\n length: header.Length,\n compression: header.Compression,\n comment: header.Comment,\n encryptionInfo: header.EncryptionInfo,\n tableTags: header.TableTags,\n profilingData: header.ProfilingData,\n lineage: header.Lineage,\n };\n }\n\n /**\n * Returns field-level metadata for a specific field/column.\n * @param {string} fieldName The name of the field.\n * @return {Object|null} Field metadata or null if field not found.\n */\n getFieldMetadata(fieldName) {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return null;\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n const field = fields.find((f) => f.FieldName === fieldName);\n if (!field) {\n return null;\n }\n\n return {\n fieldName: field.FieldName,\n bitOffset: field.BitOffset,\n bitWidth: field.BitWidth,\n bias: field.Bias,\n noOfSymbols: field.NoOfSymbols,\n offset: field.Offset,\n length: field.Length,\n comment: field.Comment,\n numberFormat: field.NumberFormat,\n tags: field.Tags,\n };\n }\n\n /**\n * Returns field-level metadata for all fields.\n * @return {Array<Object>} Array of field metadata objects.\n */\n getAllFieldMetadata() {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return [];\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n }\n\n return fields.map((field) => ({\n fieldName: field.FieldName,\n bitOffset: field.BitOffset,\n bitWidth: field.BitWidth,\n bias: field.Bias,\n noOfSymbols: field.NoOfSymbols,\n offset: field.Offset,\n length: field.Length,\n comment: field.Comment,\n numberFormat: field.NumberFormat,\n tags: field.Tags,\n }));\n }\n\n /**\n * @typedef {Object} FileMetadataUpdate\n * @property {string|number} [qvBuildNo] - QlikView build number\n * @property {string} [creatorDoc] - Creator document\n * @property {string} [createUtcTime] - Creation UTC time\n * @property {string} [sourceCreateUtcTime] - Source creation UTC time\n * @property {string} [sourceFileUtcTime] - Source file UTC time\n * @property {string|number} [sourceFileSize] - Source file size\n * @property {string} [staleUtcTime] - Stale UTC time\n * @property {string} [tableName] - Table name\n * @property {string} [compression] - Compression type\n * @property {string} [comment] - Comment\n * @property {string} [encryptionInfo] - Encryption info\n * @property {string} [tableTags] - Table tags\n * @property {string} [profilingData] - Profiling data\n * @property {Object|string} [lineage] - Lineage\n */\n\n /**\n * Sets modifiable file-level metadata. Immutable properties related to data storage are ignored.\n * @param {FileMetadataUpdate} metadata Object containing metadata properties to update.\n */\n setFileMetadata(metadata) {\n if (!this._metadata) {\n // Initialize metadata structure if it doesn't exist\n this._metadata = {\n QvBuildNo: 50667,\n CreatorDoc: '',\n CreateUtcTime: '',\n SourceCreateUtcTime: '',\n SourceFileUtcTime: '',\n SourceFileSize: -1,\n StaleUtcTime: '',\n TableName: '',\n Fields: {\n QvdFieldHeader: this._columns.map((column) => ({\n FieldName: column,\n BitOffset: 0,\n BitWidth: 0,\n Bias: 0,\n NoOfSymbols: 0,\n Offset: 0,\n Length: 0,\n Comment: '',\n NumberFormat: {\n Type: 'UNKNOWN',\n nDec: '0',\n UseThou: '0',\n Fmt: '',\n Dec: '',\n Thou: '',\n },\n Tags: {},\n })),\n },\n NoOfRecords: 0,\n RecordByteSize: 0,\n Offset: 0,\n Length: 0,\n Compression: '',\n Comment: '',\n EncryptionInfo: '',\n TableTags: '',\n ProfilingData: '',\n Lineage: {},\n };\n }\n\n // Only allow modification of certain fields (not Offset, Length, NoOfRecords, RecordByteSize)\n const modifiableFields = [\n 'qvBuildNo',\n 'creatorDoc',\n 'createUtcTime',\n 'sourceCreateUtcTime',\n 'sourceFileUtcTime',\n 'sourceFileSize',\n 'staleUtcTime',\n 'tableName',\n 'compression',\n 'comment',\n 'encryptionInfo',\n 'tableTags',\n 'profilingData',\n 'lineage',\n ];\n\n // Map camelCase to XML property names\n const fieldMapping = {\n qvBuildNo: 'QvBuildNo',\n creatorDoc: 'CreatorDoc',\n createUtcTime: 'CreateUtcTime',\n sourceCreateUtcTime: 'SourceCreateUtcTime',\n sourceFileUtcTime: 'SourceFileUtcTime',\n sourceFileSize: 'SourceFileSize',\n staleUtcTime: 'StaleUtcTime',\n tableName: 'TableName',\n compression: 'Compression',\n comment: 'Comment',\n encryptionInfo: 'EncryptionInfo',\n tableTags: 'TableTags',\n profilingData: 'ProfilingData',\n lineage: 'Lineage',\n };\n\n modifiableFields.forEach((field) => {\n // @ts-ignore - Dynamic property access for metadata mapping\n if (metadata[field] !== undefined) {\n // @ts-ignore - Dynamic property access for metadata mapping\n this._metadata[fieldMapping[field]] = metadata[field];\n }\n });\n }\n\n /**\n * @typedef {Object} FieldMetadataUpdate\n * @property {string} [comment] - Field comment\n * @property {QvdNumberFormat|string} [numberFormat] - Number format\n * @property {Object|string} [tags] - Field tags\n */\n\n /**\n * Sets modifiable field-level metadata for a specific field.\n * Immutable properties related to data storage (Offset, Length, BitOffset, etc.) are ignored.\n * @param {string} fieldName The name of the field.\n * @param {FieldMetadataUpdate} metadata Object containing field metadata properties to update.\n */\n setFieldMetadata(fieldName, metadata) {\n if (!this._metadata || !this._metadata.Fields || !this._metadata.Fields.QvdFieldHeader) {\n return;\n }\n\n let fields = this._metadata.Fields.QvdFieldHeader;\n if (!Array.isArray(fields)) {\n fields = [fields];\n this._metadata.Fields.QvdFieldHeader = fields;\n }\n\n const fieldIndex = fields.findIndex((f) => f.FieldName === fieldName);\n if (fieldIndex === -1) {\n return;\n }\n\n // Only allow modification of Comment, NumberFormat, and Tags (not Offset, Length, BitOffset, etc.)\n if (metadata.comment !== undefined) {\n fields[fieldIndex].Comment = metadata.comment;\n }\n if (metadata.numberFormat !== undefined) {\n fields[fieldIndex].NumberFormat = metadata.numberFormat;\n }\n if (metadata.tags !== undefined) {\n fields[fieldIndex].Tags = metadata.tags;\n }\n }\n\n /**\n * Returns the first n rows of the data frame.\n *\n * @param {number} n The number of rows to return.\n * @return {QvdDataFrame} The first n rows of the data frame.\n * @throws {QvdValidationError} If n is not a non-negative integer.\n */\n head(n = 5) {\n if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) {\n throw new QvdValidationError('head() requires a non-negative integer', {\n provided: n,\n type: typeof n,\n });\n }\n return new QvdDataFrame(this._data.slice(0, n), this._columns, this._metadata);\n }\n\n /**\n * Returns the last n rows of the data frame.\n *\n * @param {number} n The number of rows to return.\n * @return {QvdDataFrame} The first n rows of the data frame.\n * @throws {QvdValidationError} If n is not a non-negative integer.\n */\n tail(n = 5) {\n if (typeof n !== 'number' || !Number.isInteger(n) || n < 0) {\n throw new QvdValidationError('tail() requires a non-negative integer', {\n provided: n,\n type: typeof n,\n });\n }\n return new QvdDataFrame(n === 0 ? [] : this._data.slice(-n), this._columns, this._metadata);\n }\n\n /**\n * Returns the selected rows of the data frame.\n *\n * @param {...number} args The indices of the rows to return.\n * @return {QvdDataFrame} The selected rows of the data frame.\n * @throws {QvdValidationError} If any index is not an integer or is out of bounds.\n */\n rows(...args) {\n for (const index of args) {\n if (typeof index !== 'number' || !Number.isInteger(index)) {\n throw new QvdValidationError('rows() requires integer indices', {\n provided: index,\n type: typeof index,\n });\n }\n if (index < 0 || index >= this._data.length) {\n throw new QvdValidationError(`Row index ${index} out of bounds`, {\n index,\n validRange: [0, this._data.length - 1],\n dataLength: this._data.length,\n });\n }\n }\n return new QvdDataFrame(\n args.map((index) => this._data[index]),\n this._columns,\n this._metadata,\n );\n }\n\n /**\n * Returns the value at the specified row and column.\n *\n * @param {number} row The index of the row.\n * @param {string} column The name of the column.\n * @return {any} The value at the specified row and column.\n * @throws {QvdValidationError} If row is not an integer, out of bounds, or column does not exist.\n */\n at(row, column) {\n if (typeof row !== 'number' || !Number.isInteger(row)) {\n throw new QvdValidationError('Row index must be an integer', {\n provided: row,\n type: typeof row,\n });\n }\n if (row < 0 || row >= this._data.length) {\n throw new QvdValidationError(`Row index ${row} out of bounds`, {\n index: row,\n validRange: [0, this._data.length - 1],\n dataLength: this._data.length,\n });\n }\n if (!this._columns.includes(column)) {\n throw new QvdValidationError(`Column '${column}' does not exist`, {\n column,\n availableColumns: this._columns,\n });\n }\n return this._data[row][this._columns.indexOf(column)];\n }\n\n /**\n * Selects the specified columns from the data frame.\n *\n * @param {...string} args The names of the columns to select.\n * @return {QvdDataFrame} The selected columns of the data frame.\n * @throws {QvdValidationError} If any column name does not exist.\n */\n select(...args) {\n for (const column of args) {\n if (!this._columns.includes(column)) {\n throw new QvdValidationError(`Column '${column}' does not exist`, {\n column,\n availableColumns: this._columns,\n });\n }\n }\n const indices = args.map((arg) => this._columns.indexOf(arg));\n const data = this._data.map((row) => indices.map((index) => row[index]));\n const columns = indices.map((index) => this._columns[index]);\n return new QvdDataFrame(data, columns, this._metadata);\n }\n\n /**\n * Returns the data frame as a dictionary.\n *\n * @return {Promise<{columns: Array<string>, data: Array<Array<any>>}>} The data frame as a dictionary.\n */\n async toDict() {\n return {columns: this._columns, data: this._data};\n }\n\n /**\n * Persists the data frame to a QVD file.\n *\n * @param {string} path The path to the QVD file.\n * @param {Object} [options] Optional writing options.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file path\n * must be within this directory, with symlinks resolved first, so a link inside it that points\n * outside it is rejected. Defaults to the current working directory. To permit an entire\n * volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or empty value falls\n * back to the working directory rather than removing the restriction.\n * @param {Function} [options.onProgress] Optional progress callback function that receives progress updates during write operations.\n */\n async toQvd(path, options = {}) {\n const {QvdFileWriter} = await import('./QvdFileWriter.js');\n const writerOptions = {\n allowedDir: options.allowedDir,\n onProgress: options.onProgress,\n };\n await new QvdFileWriter(path, this, writerOptions).save();\n }\n\n /**\n * Loads a QVD file and returns its data frame.\n *\n * @param {string} path The path to the QVD file.\n * @param {Object} [options] Optional loading options.\n * @param {number|null} [options.maxRows] The maximum number of rows to load. Must be a non-negative\n * integer; if not specified or null, all rows are loaded. Anything else throws a QvdValidationError.\n * @param {string} [options.allowedDir] Optional allowed directory path. If provided, the file path\n * must be within this directory, with symlinks resolved first, so a link inside it that points\n * outside it is rejected. Defaults to the current working directory. To permit an entire\n * volume, pass its root explicitly ('/' on POSIX, 'C:\\\\' on Windows); a null or empty value falls\n * back to the working directory rather than removing the restriction.\n * @param {number} [options.memorySafetyFactor=0.3] Fraction (0.0-1.0) of the memory budget a load\n * may use. The budget is the smallest of the V8 heap limit, any container memory limit, and the\n * memory the OS reports as available. Default is 0.3; raise it when running with a larger heap via\n * --max-old-space-size. **Zero disables the memory check entirely.**\n * @param {number} [options.symbolFilteringThreshold=52428800] Symbol table size, in bytes, above which\n * a lazy load switches to the two-pass filtering path. Defaults to 50MB.\n * @throws {QvdValidationError} If options.maxRows is neither null/undefined nor a non-negative integer.\n * @return {Promise<QvdDataFrame>} The data frame of the QVD file.\n */\n static async fromQvd(path, options = {}) {\n const {QvdFileReader} = await import('./QvdFileReader.js');\n const readerOptions = {\n allowedDir: options.allowedDir,\n memorySafetyFactor: options.memorySafetyFactor,\n symbolFilteringThreshold: options.symbolFilteringThreshold,\n };\n return await new QvdFileReader(path, readerOptions).load(options.maxRows !== undefined ? options.maxRows : null);\n }\n\n /**\n * Constructs a data frame from a dictionary.\n *\n * @param {{columns: Array<string>, data: Array<Array<any>>}} data The dictionary to construct the data frame from.\n * @return {Promise<QvdDataFrame>} The constructed data frame.\n */\n static async fromDict(data) {\n if (!data.columns) {\n throw new QvdValidationError('The dictionary to construct the data frame from does not contain any columns.', {\n data,\n });\n }\n if (!data.data) {\n throw new QvdValidationError('The dictionary to construct the data frame from does not contain any data.', {\n data,\n });\n }\n\n return new QvdDataFrame(data.data, data.columns);\n }\n}\n","// @ts-check\n\nexport {QvdSymbol} from './QvdSymbol.js';\nexport {QvdDataFrame} from './QvdDataFrame.js';\nexport {QvdFileReader} from './QvdFileReader.js';\nexport {QvdFileWriter} from './QvdFileWriter.js';\nexport {\n QvdError,\n QvdParseError,\n QvdValidationError,\n QvdIOError,\n QvdCorruptedError,\n QvdSecurityError,\n} from './QvdErrors.js';\n"]}
|