@openmeteo/file-reader
Version:
JavaScript reader for the om file format using WebAssembly
1 lines • 68.2 kB
Source Map (JSON)
{"version":3,"file":"index.browser.cjs","sources":["../../src/lib/types.ts","../../src/lib/wasm.ts","../../src/lib/OmFileReader.ts","../../src/lib/backends/FileBackend.ts","../../src/lib/backends/MemoryHttpBackend.ts"],"sourcesContent":["export interface Range {\n start: number;\n end: number;\n}\n\nexport interface OffsetSize {\n offset: number;\n size: number;\n}\n\nexport enum CompressionType {\n /// Lossy compression using 2D delta coding and scale-factor.\n /// Only supports float and scales to 16-bit signed integer.\n PforDelta2dInt16 = 0,\n /// Lossless float/double compression using 2D xor coding.\n FpxXor2d = 1,\n /// PFor integer compression.\n /// f32 values are scaled to u32, f64 are scaled to u64.\n PforDelta2d = 2,\n /// Similar to `PforDelta2dInt16` but applies `log10(1+x)` before.\n PforDelta2dInt16Logarithmic = 3,\n None = 4,\n}\n\nexport enum OmDataType {\n None = 0,\n Int8 = 1,\n Uint8 = 2,\n Int16 = 3,\n Uint16 = 4,\n Int32 = 5,\n Uint32 = 6,\n Int64 = 7,\n Uint64 = 8,\n Float = 9,\n Double = 10,\n String = 11,\n Int8Array = 12,\n Uint8Array = 13,\n Int16Array = 14,\n Uint16Array = 15,\n Int32Array = 16,\n Uint32Array = 17,\n Int64Array = 18,\n Uint64Array = 19,\n FloatArray = 20,\n DoubleArray = 21,\n StringArray = 22,\n}\n\nexport type TypedArray =\n | Int8Array\n | Uint8Array\n | Int16Array\n | Uint16Array\n | Int32Array\n | Uint32Array\n | Float32Array\n | Float64Array;\n// | BigInt64Array\n// | BigUint64Array;\n","export interface WasmModule {\n _malloc(size: number): number;\n _free(ptr: number): void;\n setValue(ptr: number, value: any, type: string): void;\n getValue(ptr: number, type: string): any;\n HEAPU8: Uint8Array;\n\n // C-API functions\n om_header_size(): number;\n om_header_type(ptr: number): number;\n om_trailer_size(): number;\n om_trailer_read(trailerPtr: number, offsetPtr: number, sizePtr: number): boolean;\n om_variable_init(dataPtr: number): number;\n om_variable_get_type(variable: number): number;\n om_variable_get_compression(variable: number): number;\n om_variable_get_scale_factor(variable: number): number;\n om_variable_get_add_offset(variable: number): number;\n om_variable_get_dimension_count(variable: number): number;\n om_variable_get_dimension_value(variable: number, index: bigint): number;\n om_variable_get_chunk_count(variable: number): number;\n om_variable_get_chunk_value(variable: number, index: bigint): number;\n om_variable_get_name_count(variable: number): number;\n om_variable_get_name_ptr(variable: number): number;\n om_variable_get_children_count(variable: number): number;\n om_variable_get_children(variable: number, index: number, count: number, offsetPtr: number, sizePtr: number): boolean;\n om_variable_get_scalar(variable: number, ptrPtr: number, sizePtr: number): number;\n om_decoder_init(\n decoderPtr: number,\n variable: number,\n nDims: BigInt,\n readOffsetPtr: number,\n readCountPtr: number,\n intoCubeOffsetPtr: number,\n intoCubeDimensionPtr: number,\n ioSizeMerge: bigint,\n ioSizeMax: bigint\n ): number;\n om_decoder_init_index_read(decoder: number, indexReadPtr: number): void;\n om_decoder_init_data_read(dataReadPtr: number, indexReadPtr: number): void;\n om_decoder_read_buffer_size(decoderPtr: number): number;\n om_decoder_next_index_read(decoder: number, indexRead: number): boolean;\n om_decoder_next_data_read(\n decoder: number,\n dataRead: number,\n indexData: number,\n indexCount: bigint,\n error: number\n ): boolean;\n om_decoder_decode_chunks(\n decoder: number,\n chunkIndex: number,\n data: number,\n count: bigint,\n output: number,\n chunkBuffer: number,\n error: number\n ): boolean;\n\n // Constants\n OM_HEADER_INVALID: number;\n OM_HEADER_LEGACY: number;\n OM_HEADER_READ_TRAILER: number;\n ERROR_OK: number;\n DATA_TYPE_INT8_ARRAY: number;\n DATA_TYPE_UINT8_ARRAY: number;\n DATA_TYPE_INT16_ARRAY: number;\n DATA_TYPE_UINT16_ARRAY: number;\n DATA_TYPE_INT32_ARRAY: number;\n DATA_TYPE_UINT32_ARRAY: number;\n DATA_TYPE_INT64_ARRAY: number;\n DATA_TYPE_UINT64_ARRAY: number;\n DATA_TYPE_FLOAT_ARRAY: number;\n DATA_TYPE_DOUBLE_ARRAY: number;\n\n // Additional info\n sizeof_decoder: number;\n}\n\n// Constants mapping\nconst DATA_TYPES = {\n DATA_TYPE_NONE: 0,\n DATA_TYPE_INT8: 1,\n DATA_TYPE_UINT8: 2,\n DATA_TYPE_INT16: 3,\n DATA_TYPE_UINT16: 4,\n DATA_TYPE_INT32: 5,\n DATA_TYPE_UINT32: 6,\n DATA_TYPE_INT64: 7,\n DATA_TYPE_UINT64: 8,\n DATA_TYPE_FLOAT: 9,\n DATA_TYPE_DOUBLE: 10,\n DATA_TYPE_STRING: 11,\n DATA_TYPE_INT8_ARRAY: 12,\n DATA_TYPE_UINT8_ARRAY: 13,\n DATA_TYPE_INT16_ARRAY: 14,\n DATA_TYPE_UINT16_ARRAY: 15,\n DATA_TYPE_INT32_ARRAY: 16,\n DATA_TYPE_UINT32_ARRAY: 17,\n DATA_TYPE_INT64_ARRAY: 18,\n DATA_TYPE_UINT64_ARRAY: 19,\n DATA_TYPE_FLOAT_ARRAY: 20,\n DATA_TYPE_DOUBLE_ARRAY: 21,\n DATA_TYPE_STRING_ARRAY: 22,\n};\n\nconst HEADER_TYPES = {\n OM_HEADER_INVALID: 0,\n OM_HEADER_LEGACY: 1,\n OM_HEADER_READ_TRAILER: 2,\n};\n\nconst ERROR_CODES = {\n ERROR_OK: 0,\n};\n\n// Size of the decoder structure (estimate, will be updated during init)\nconst SIZEOF_DECODER = 256;\n\nlet wasmModuleRaw: any = null;\nlet wasmModuleWrapped: WasmModule | null = null;\n\nexport async function initWasm(): Promise<WasmModule> {\n if (wasmModuleWrapped) return wasmModuleWrapped;\n\n try {\n // Import the factory function that creates the module\n // @ts-ignore\n const OmFileFormat = await import(\"@openmeteo/file-format-wasm\");\n // Initialize the module by calling the factory function\n const wasmModuleRaw = await OmFileFormat.default();\n\n // Create our wrapped module with the expected interface\n wasmModuleWrapped = createWrappedModule(wasmModuleRaw);\n\n return wasmModuleWrapped;\n } catch (error) {\n throw new Error(`Failed to initialize WASM module: ${error}`);\n }\n}\n\nfunction createWrappedModule(rawModule: any): WasmModule {\n // Create a wrapper that maps the prefixed function names to our interface\n return {\n // Memory management functions\n _malloc: rawModule._malloc,\n _free: rawModule._free,\n setValue: rawModule.setValue,\n getValue: rawModule.getValue,\n HEAPU8: rawModule.HEAPU8,\n\n // Map all the C functions to their prefixed versions\n om_header_size: rawModule._om_header_size,\n om_header_type: rawModule._om_header_type,\n om_trailer_size: rawModule._om_trailer_size,\n om_trailer_read: rawModule._om_trailer_read,\n om_variable_init: rawModule._om_variable_init,\n om_variable_get_type: rawModule._om_variable_get_type,\n om_variable_get_compression: rawModule._om_variable_get_compression,\n om_variable_get_scale_factor: rawModule._om_variable_get_scale_factor,\n om_variable_get_add_offset: rawModule._om_variable_get_add_offset,\n om_variable_get_dimension_count: rawModule._om_variable_get_dimension_count,\n om_variable_get_dimension_value: rawModule._om_variable_get_dimension_value,\n om_variable_get_chunk_count: rawModule._om_variable_get_chunk_count,\n om_variable_get_chunk_value: rawModule._om_variable_get_chunk_value,\n om_variable_get_name_count: rawModule._om_variable_get_name_count,\n om_variable_get_name_ptr: rawModule._om_variable_get_name_ptr,\n om_variable_get_children_count: rawModule._om_variable_get_children_count,\n om_variable_get_children: rawModule._om_variable_get_children,\n om_variable_get_scalar: rawModule._om_variable_get_scalar,\n om_decoder_init: rawModule._om_decoder_init,\n om_decoder_init_index_read: rawModule._om_decoder_init_index_read,\n om_decoder_init_data_read: rawModule._om_decoder_init_data_read,\n om_decoder_read_buffer_size: rawModule._om_decoder_read_buffer_size,\n om_decoder_next_index_read: rawModule._om_decoder_next_index_read,\n om_decoder_next_data_read: rawModule._om_decoder_next_data_read,\n om_decoder_decode_chunks: rawModule._om_decoder_decode_chunks,\n\n // Constants\n ...HEADER_TYPES,\n ...ERROR_CODES,\n ...DATA_TYPES,\n\n // Additional info\n sizeof_decoder: SIZEOF_DECODER, // We could try to determine this dynamically if there's a C API for it\n };\n}\n\nexport function getWasmModule() {\n if (!wasmModuleWrapped) {\n throw new Error(\"WASM module not initialized. Call initWasm() first.\");\n }\n return wasmModuleWrapped;\n}\n","import { OmFileReaderBackend } from \"./backends/OmFileReaderBackend\";\nimport { OffsetSize, OmDataType, TypedArray, Range } from \"./types\";\nimport { WasmModule, initWasm, getWasmModule } from \"./wasm\";\n\nexport class OmFileReader {\n private backend: OmFileReaderBackend;\n private wasm: WasmModule;\n private variable: number | null;\n private variableDataPtr: number | null;\n private verbose: boolean;\n\n constructor(backend: OmFileReaderBackend, wasm?: WasmModule) {\n this.backend = backend;\n this.wasm = wasm || getWasmModule();\n this.variable = null;\n this.variableDataPtr = null;\n this.verbose = false;\n }\n\n /**\n * Static factory method to create and initialize an OmFileReader\n */\n static async create(backend: OmFileReaderBackend): Promise<OmFileReader> {\n // Make sure WASM is initialized\n const wasm = await initWasm();\n const reader = new OmFileReader(backend, wasm);\n await reader.initialize();\n return reader;\n }\n\n async initialize(): Promise<OmFileReader> {\n // Similar to the 'new' method in Rust\n const headerSize = this.wasm.om_header_size();\n\n const headerData = await this.backend.getBytes(0, headerSize);\n const headerPtr = this.wasm._malloc(headerData.length);\n this.wasm.HEAPU8.set(headerData, headerPtr);\n\n const headerType = this.wasm.om_header_type(headerPtr);\n\n if (headerType === this.wasm.OM_HEADER_INVALID) {\n this.wasm._free(headerPtr);\n throw new Error(\"Not a valid OM file\");\n }\n\n let variableData: Uint8Array;\n\n if (headerType === this.wasm.OM_HEADER_LEGACY) {\n variableData = headerData;\n } else if (headerType === this.wasm.OM_HEADER_READ_TRAILER) {\n const fileSize = await this.backend.count();\n const trailerSize = this.wasm.om_trailer_size();\n const trailerOffset = fileSize - trailerSize;\n\n const trailerPtr = await this.readDataBlock(trailerOffset, trailerSize);\n\n // Create pointers for offset and size (out parameters)\n const offsetPtr = this.wasm._malloc(8); // 64-bit value = 8 bytes\n const sizePtr = this.wasm._malloc(8);\n\n const success = this.wasm.om_trailer_read(trailerPtr, offsetPtr, sizePtr);\n\n if (!success) {\n this.wasm._free(headerPtr);\n this.wasm._free(trailerPtr);\n this.wasm._free(offsetPtr);\n this.wasm._free(sizePtr);\n throw new Error(\"Failed to read trailer\");\n }\n\n // Read values from memory\n const offset = Number(this.wasm.getValue(offsetPtr, \"i64\"));\n const size = Number(this.wasm.getValue(sizePtr, \"i64\"));\n\n // Free memory\n this.wasm._free(trailerPtr);\n this.wasm._free(offsetPtr);\n this.wasm._free(sizePtr);\n\n // Get variable data\n variableData = await this.backend.getBytes(offset, size);\n } else {\n this.wasm._free(headerPtr);\n throw new Error(\"Unknown header type\");\n }\n\n // Initialize variable\n const variableDataPtr = this.wasm._malloc(variableData.length);\n this.wasm.HEAPU8.set(variableData, variableDataPtr);\n this.variable = this.wasm.om_variable_init(variableDataPtr);\n this.variableDataPtr = variableDataPtr;\n\n this.wasm._free(headerPtr);\n\n return this;\n }\n\n // Helper method to convert C strings to JS strings\n private _getString(strPtr: number, strLen: number): string {\n const bytes = this.wasm.HEAPU8.subarray(strPtr, strPtr + strLen);\n return new TextDecoder(\"utf8\").decode(bytes);\n }\n\n dataType(): number {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n return this.wasm.om_variable_get_type(this.variable);\n }\n\n compression(): number {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n return this.wasm.om_variable_get_compression(this.variable);\n }\n\n scaleFactor(): number {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n return this.wasm.om_variable_get_scale_factor(this.variable);\n }\n\n addOffset(): number {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n return this.wasm.om_variable_get_add_offset(this.variable);\n }\n\n getDimensions(): number[] {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n // Get count using the wrapper function\n const count = Number(this.wasm.om_variable_get_dimension_count(this.variable));\n\n // Get each dimension individually\n const dimensions: number[] = [];\n for (let i = 0; i < count; i++) {\n dimensions.push(Number(this.wasm.om_variable_get_dimension_value(this.variable, BigInt(i))));\n }\n\n return dimensions;\n }\n\n getChunkDimensions(): number[] {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n // Get count using the wrapper function\n const count = Number(this.wasm.om_variable_get_chunk_count(this.variable));\n\n // Get each chunk dimension individually\n const chunks: number[] = [];\n for (let i = 0; i < count; i++) {\n chunks.push(Number(this.wasm.om_variable_get_chunk_value(this.variable, BigInt(i))));\n }\n\n return chunks;\n }\n\n getName(): string | null {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n const size = this.wasm.om_variable_get_name_count(this.variable);\n if (size === 0) {\n return null;\n }\n\n const valuePtr = this.wasm.om_variable_get_name_ptr(this.variable);\n if (valuePtr === 0) {\n return null;\n }\n return this._getString(valuePtr, size);\n }\n\n numberOfChildren(): number {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n return this.wasm.om_variable_get_children_count(this.variable);\n }\n\n async getChild(index: number): Promise<OmFileReader | null> {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n // Allocate memory for the output parameters\n const offsetPtr = this.wasm._malloc(8);\n const sizePtr = this.wasm._malloc(8);\n\n const success = this.wasm.om_variable_get_children(this.variable, index, 1, offsetPtr, sizePtr);\n\n if (!success) {\n this.wasm._free(offsetPtr);\n this.wasm._free(sizePtr);\n return null;\n }\n\n const offset = Number(this.wasm.getValue(offsetPtr, \"i64\"));\n const size = Number(this.wasm.getValue(sizePtr, \"i64\"));\n\n this.wasm._free(offsetPtr);\n this.wasm._free(sizePtr);\n\n return this.initChildFromOffsetSize({ offset, size });\n }\n\n async initChildFromOffsetSize(offsetSize: OffsetSize): Promise<OmFileReader> {\n const childDataPtr = await this.readDataBlock(offsetSize.offset, offsetSize.size);\n\n const childReader = new OmFileReader(this.backend, this.wasm);\n\n childReader.variable = this.wasm.om_variable_init(childDataPtr);\n childReader.variableDataPtr = childDataPtr;\n\n return childReader;\n }\n\n // Method to read scalar values\n readScalar<T>(dataType: OmDataType): T | null {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n if (this.dataType() !== dataType) {\n return null;\n }\n\n // Allocate memory for output parameters\n const ptrPtr = this.wasm._malloc(4); // pointer to pointer\n const sizePtr = this.wasm._malloc(8); // u64\n\n try {\n const error = this.wasm.om_variable_get_scalar(this.variable, ptrPtr, sizePtr);\n\n if (error !== this.wasm.ERROR_OK) {\n return null;\n }\n\n const dataPtr = this.wasm.getValue(ptrPtr, \"*\");\n const size = Number(this.wasm.getValue(sizePtr, \"i64\"));\n\n if (dataPtr === 0) {\n return null;\n }\n\n // Read data based on type\n let result: any;\n\n switch (dataType) {\n case OmDataType.Int8:\n result = this.wasm.getValue(dataPtr, \"i8\");\n break;\n case OmDataType.Uint8:\n result = this.wasm.getValue(dataPtr, \"i8\") & 0xff;\n break;\n case OmDataType.Int16:\n result = this.wasm.getValue(dataPtr, \"i16\");\n break;\n case OmDataType.Uint16:\n result = this.wasm.getValue(dataPtr, \"i16\") & 0xffff;\n break;\n case OmDataType.Int32:\n result = this.wasm.getValue(dataPtr, \"i32\");\n break;\n case OmDataType.Uint32:\n result = this.wasm.getValue(dataPtr, \"i32\") >>> 0;\n break;\n case OmDataType.Float:\n result = this.wasm.getValue(dataPtr, \"float\");\n break;\n case OmDataType.Double:\n result = this.wasm.getValue(dataPtr, \"double\");\n break;\n default:\n result = null;\n }\n\n return result as T;\n } finally {\n this.wasm._free(ptrPtr);\n this.wasm._free(sizePtr);\n }\n }\n\n private newIndexRead(decoderPtr: number): number {\n // Calculate proper size for OmDecoder_indexRead_t\n const sizeOfRange = 16; // 8 bytes for lowerBound + 8 bytes for upperBound\n const sizeOfIndexRead = 8 + 8 + sizeOfRange * 3; // offset + count + 3 range structs\n\n // Allocate and zero the memory\n const indexReadPtr = this.wasm._malloc(sizeOfIndexRead);\n\n // Zero out the memory (equivalent to std::mem::zeroed())\n const zeroBuffer = new Uint8Array(sizeOfIndexRead);\n this.wasm.HEAPU8.set(zeroBuffer, indexReadPtr);\n\n // Initialize the structure using C function\n this.wasm.om_decoder_init_index_read(decoderPtr, indexReadPtr);\n\n return indexReadPtr;\n }\n\n private newDataRead(indexReadPtr: number): number {\n // Size of OmDecoder_dataRead_t\n const sizeOfRange = 16; // 8 bytes for lowerBound + 8 bytes for upperBound\n const sizeOfDataRead = 8 + 8 + sizeOfRange * 3; // offset + count + 3 range structs\n\n // Allocate and zero the memory\n const dataReadPtr = this.wasm._malloc(sizeOfDataRead);\n\n // Zero out the memory (equivalent to std::mem::zeroed())\n const zeroBuffer = new Uint8Array(sizeOfDataRead);\n this.wasm.HEAPU8.set(zeroBuffer, dataReadPtr);\n\n // Initialize the structure using C function\n this.wasm.om_decoder_init_data_read(dataReadPtr, indexReadPtr);\n\n return dataReadPtr;\n }\n\n async read(\n dataType: OmDataType,\n dimRanges: Range[],\n ioSizeMax: bigint = BigInt(65536),\n ioSizeMerge: bigint = BigInt(512)\n ): Promise<TypedArray> {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n if (this.dataType() !== dataType) {\n throw new Error(`Invalid data type: expected ${this.dataType()}, got ${dataType}`);\n }\n\n // Calculate output dimensions\n const outDims = dimRanges.map((range) => Number(range.end - range.start));\n const totalSize = outDims.reduce((a, b) => a * b, 1);\n\n // Create output TypedArray based on data type\n let output: TypedArray;\n switch (dataType) {\n case this.wasm.DATA_TYPE_INT8_ARRAY:\n output = new Int8Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_UINT8_ARRAY:\n output = new Uint8Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_INT16_ARRAY:\n output = new Int16Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_UINT16_ARRAY:\n output = new Uint16Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_INT32_ARRAY:\n output = new Int32Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_UINT32_ARRAY:\n output = new Uint32Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_FLOAT_ARRAY:\n output = new Float32Array(totalSize);\n break;\n case this.wasm.DATA_TYPE_DOUBLE_ARRAY:\n output = new Float64Array(totalSize);\n break;\n default:\n throw new Error(\"Unsupported data type\");\n }\n\n await this.readInto(dataType, output, dimRanges, ioSizeMax, ioSizeMerge);\n return output;\n }\n\n /**\n * Read data into an existing TypedArray with specified dimension ranges\n * @param dataType The data type to read\n * @param output The TypedArray to read data into\n * @param dimRanges Ranges for each dimension to read\n * @param ioSizeMax Maximum I/O size (default: 65536)\n * @param ioSizeMerge Merge threshold for I/O operations (default: 512)\n */\n async readInto(\n dataType: OmDataType,\n output: TypedArray,\n dimRanges: Range[],\n ioSizeMax: bigint = BigInt(65536),\n ioSizeMerge: bigint = BigInt(512)\n ): Promise<void> {\n if (this.variable === null) throw new Error(\"Reader not initialized\");\n\n if (this.dataType() !== dataType) {\n throw new Error(`Invalid data type: expected ${this.dataType()}, got ${dataType}`);\n }\n\n const nDims = dimRanges.length;\n const fileDims = this.getDimensions();\n\n // Validate dimension counts\n if (fileDims.length !== nDims) {\n throw new Error(`Mismatched dimensions: file has ${fileDims.length}, request has ${nDims}`);\n }\n\n // Calculate output dimensions and prepare arrays for WASM\n const outDims = dimRanges.map((range) => range.end - range.start);\n const intoCubeOffset = new Array(nDims).fill(0);\n\n // Calculate total elements to ensure output array has correct size\n const totalElements = outDims.reduce((a, b) => a * Number(b), 1);\n if (output.length < totalElements) {\n throw new Error(`Output array is too small: needs ${totalElements} elements, has ${output.length}`);\n }\n\n // Allocate memory for arrays\n const readOffsetPtr = this.wasm._malloc(nDims * 8); // u64 array\n const readCountPtr = this.wasm._malloc(nDims * 8);\n const intoCubeOffsetPtr = this.wasm._malloc(nDims * 8);\n const intoCubeDimensionPtr = this.wasm._malloc(nDims * 8);\n\n try {\n // Fill arrays\n for (let i = 0; i < nDims; i++) {\n // Validate ranges\n if (dimRanges[i].start < 0 || dimRanges[i].end > fileDims[i] || dimRanges[i].start >= dimRanges[i].end) {\n throw new Error(`Invalid range for dimension ${i}: ${JSON.stringify(dimRanges[i])}`);\n }\n\n this.wasm.setValue(readOffsetPtr + i * 8, BigInt(dimRanges[i].start), \"i64\");\n this.wasm.setValue(readCountPtr + i * 8, BigInt(outDims[i]), \"i64\");\n this.wasm.setValue(intoCubeOffsetPtr + i * 8, BigInt(intoCubeOffset[i]), \"i64\");\n this.wasm.setValue(intoCubeDimensionPtr + i * 8, BigInt(outDims[i]), \"i64\");\n }\n\n // Create decoder\n const decoderPtr = this.wasm._malloc(this.wasm.sizeof_decoder);\n\n try {\n // Initialize decoder\n const error = this.wasm.om_decoder_init(\n decoderPtr,\n this.variable,\n BigInt(nDims),\n readOffsetPtr,\n readCountPtr,\n intoCubeOffsetPtr,\n intoCubeDimensionPtr,\n ioSizeMerge,\n ioSizeMax\n );\n\n if (error !== this.wasm.ERROR_OK) {\n throw new Error(`Decoder initialization failed: error code ${error}`);\n }\n await this.decode(decoderPtr, output);\n } finally {\n this.wasm._free(decoderPtr);\n }\n } finally {\n // Clean up input arrays\n this.wasm._free(readOffsetPtr);\n this.wasm._free(readCountPtr);\n this.wasm._free(intoCubeOffsetPtr);\n this.wasm._free(intoCubeDimensionPtr);\n }\n }\n\n private async decode(decoderPtr: number, outputArray: TypedArray): Promise<void> {\n if (this.verbose){\n \tconsole.log(`Starting decode with ${outputArray.constructor.name}, length=${outputArray.length}`);\n }\n\n const outputPtr = this.wasm._malloc(outputArray.byteLength);\n const chunkBufferSize = Number(this.wasm.om_decoder_read_buffer_size(decoderPtr));\n const chunkBufferPtr = this.wasm._malloc(chunkBufferSize);\n // Create index_read struct\n const indexReadPtr = this.newIndexRead(decoderPtr);\n const errorPtr = this.wasm._malloc(4);\n // Initialize error to OK\n this.wasm.setValue(errorPtr, this.wasm.ERROR_OK, \"i32\");\n\n try {\n // Loop over index blocks\n let indexBlockCount = 0;\n while (this.wasm.om_decoder_next_index_read(decoderPtr, indexReadPtr)) {\n indexBlockCount++;\n\n // Get index_read parameters\n const indexOffset = Number(this.wasm.getValue(indexReadPtr, \"i64\"));\n const indexCount = Number(this.wasm.getValue(indexReadPtr + 8, \"i64\"));\n\n if (this.verbose){\n console.log(`Index block #${indexBlockCount}: offset=${indexOffset}, count=${indexCount}`);\n }\n\n // Get bytes for index-read\n const indexDataPtr = await this.readDataBlock(indexOffset, indexCount);\n\n // Create data_read struct\n let dataReadPtr = this.newDataRead(indexReadPtr);\n\n try {\n // Loop over data blocks and read compressed data chunks\n // Loop over data blocks\n let dataBlockCount = 0;\n while (\n this.wasm.om_decoder_next_data_read(decoderPtr, dataReadPtr, indexDataPtr, BigInt(indexCount), errorPtr)\n ) {\n dataBlockCount++;\n\n // Get data_read parameters\n const dataOffset = Number(this.wasm.getValue(dataReadPtr, \"i64\"));\n const dataCount = Number(this.wasm.getValue(dataReadPtr + 8, \"i64\"));\n const chunkIndexPtr = dataReadPtr + 32; // offset(8), count(8), indexRange(16)\n if (this.verbose) {\n console.log(\n ` Data block #${dataBlockCount}: offset=${dataOffset}, count=${dataCount}, chunkIndexPtr=${chunkIndexPtr}`\n );\n }\n\n // Get bytes for data-read\n const dataBlockPtr = await this.readDataBlock(dataOffset, dataCount);\n\n try {\n // Decode chunks\n const success = this.wasm.om_decoder_decode_chunks(\n decoderPtr,\n chunkIndexPtr,\n dataBlockPtr,\n BigInt(dataCount),\n outputPtr,\n chunkBufferPtr,\n errorPtr\n );\n\n // Check for error\n if (!success) {\n const error = this.wasm.getValue(errorPtr, \"i32\");\n throw new Error(`Decoder failed to decode chunks: error ${error}`);\n }\n } finally {\n this.wasm._free(dataBlockPtr);\n }\n }\n\n // Check for errors after data_read loop\n const error = this.wasm.getValue(errorPtr, \"i32\");\n if (error !== this.wasm.ERROR_OK) {\n throw new Error(`Data read error: ${error}`);\n }\n } finally {\n this.wasm._free(dataReadPtr);\n this.wasm._free(indexDataPtr);\n }\n }\n\n // Copy the data back to the output array with the correct type\n this.copyToTypedArray(outputPtr, outputArray);\n } finally {\n this.wasm._free(errorPtr);\n this.wasm._free(indexReadPtr);\n this.wasm._free(chunkBufferPtr);\n this.wasm._free(outputPtr);\n }\n }\n\n private async readDataBlock(offset: number, size: number): Promise<number> {\n const data = await this.backend.getBytes(offset, size);\n const ptr = this.wasm._malloc(data.length);\n this.wasm.HEAPU8.set(data, ptr);\n return ptr;\n }\n\n /**\n * Helper method to copy data from WASM memory to a TypedArray with the correct type\n */\n private copyToTypedArray(sourcePtr: number, targetArray: TypedArray): void {\n switch (targetArray.constructor) {\n case Float32Array:\n const f32Array = new Float32Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Float32Array).set(f32Array);\n break;\n case Float64Array:\n const f64Array = new Float64Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Float64Array).set(f64Array);\n break;\n case Int8Array:\n const i8Array = new Int8Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Int8Array).set(i8Array);\n break;\n case Uint8Array:\n const u8Array = new Uint8Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Uint8Array).set(u8Array);\n break;\n case Int16Array:\n const i16Array = new Int16Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Int16Array).set(i16Array);\n break;\n case Uint16Array:\n const u16Array = new Uint16Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Uint16Array).set(u16Array);\n break;\n case Int32Array:\n const i32Array = new Int32Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Int32Array).set(i32Array);\n break;\n case Uint32Array:\n const u32Array = new Uint32Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.length);\n (targetArray as Uint32Array).set(u32Array);\n break;\n default:\n // Fallback to byte-by-byte copy\n const byteArray = new Uint8Array(this.wasm.HEAPU8.buffer, sourcePtr, targetArray.byteLength);\n new Uint8Array(targetArray.buffer).set(byteArray);\n }\n }\n\n // Clean up resources when done\n dispose(): void {\n if (this.variableDataPtr !== null) {\n this.wasm._free(this.variableDataPtr);\n this.variableDataPtr = null;\n }\n this.variable = null;\n }\n}\n","import { OmFileReaderBackend } from \"./OmFileReaderBackend\";\n\nexport class FileBackend implements OmFileReaderBackend {\n private fileObj: File | Blob | null = null;\n private memory: Uint8Array | null = null;\n private fileSize: number = 0;\n\n constructor(source: File | Blob | Uint8Array | ArrayBuffer) {\n if (typeof File !== \"undefined\" && source instanceof File) {\n this.fileObj = source;\n this.fileSize = source.size;\n } else if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n this.fileObj = source;\n this.fileSize = source.size;\n } else if (source instanceof ArrayBuffer) {\n this.memory = new Uint8Array(source);\n this.fileSize = this.memory.length;\n } else if (source instanceof Uint8Array) {\n this.memory = source;\n this.fileSize = source.length;\n } else {\n throw new Error(\"Unsupported file source type for browser FileBackend\");\n }\n }\n\n async count(): Promise<number> {\n return this.fileSize;\n }\n\n async getBytes(offset: number, size: number): Promise<Uint8Array> {\n if (this.memory) {\n return this.memory.slice(offset, offset + size);\n }\n if (this.fileObj) {\n const blob = this.fileObj.slice(offset, offset + size);\n const buffer = await blob.arrayBuffer();\n return new Uint8Array(buffer);\n }\n throw new Error(\"No file or memory buffer available\");\n }\n\n async close(): Promise<void> {\n // Nothing to clean up in browser\n }\n}\n","import { OmFileReaderBackend } from \"./OmFileReaderBackend\";\n\nexport class MemoryHttpBackend implements OmFileReaderBackend {\n private url: string;\n private fileSize: number | null = null;\n private fileData: Uint8Array | null = null;\n private loadPromise: Promise<void> | null = null;\n private countPromise: Promise<number> | null = null;\n private maxFileSize: number;\n private onProgress?: (loaded: number, total: number) => void;\n private debug: boolean;\n\n /**\n * Create a new MemoryHttpBackend\n * @param options Configuration options\n */\n constructor(options: {\n url: string;\n maxFileSize?: number;\n onProgress?: (loaded: number, total: number) => void;\n debug?: boolean;\n }) {\n this.url = options.url;\n this.maxFileSize = options.maxFileSize ?? 200 * 1024 * 1024; // 200 MB default\n this.onProgress = options.onProgress;\n this.debug = options.debug ?? false;\n\n // Start loading the file in the background\n this.loadFile().catch((err) => {\n if (this.debug) console.error(\"Background file load failed:\", err);\n });\n }\n\n /**\n * Get the total size of the file\n */\n async count(): Promise<number> {\n if (this.fileSize !== null) {\n return this.fileSize;\n }\n\n if (!this.countPromise) {\n if (this.debug) console.log(`Making HEAD request to ${this.url}`);\n\n this.countPromise = (async () => {\n try {\n const response = await fetch(this.url, {\n method: \"HEAD\",\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (!contentLength) {\n throw new Error(\"Content-Length header not available\");\n }\n\n this.fileSize = parseInt(contentLength, 10);\n\n if (this.fileSize > this.maxFileSize) {\n throw new Error(\n `File size (${this.fileSize} bytes) exceeds maximum allowed size (${this.maxFileSize} bytes)`\n );\n }\n\n if (this.debug) console.log(`File size: ${this.fileSize} bytes`);\n return this.fileSize;\n } catch (error) {\n this.countPromise = null;\n throw new Error(`Failed to get file size: ${error instanceof Error ? error.message : String(error)}`);\n }\n })();\n }\n\n return this.countPromise;\n }\n\n /**\n * Load the entire file into memory\n */\n async loadFile(): Promise<void> {\n // If already loaded or loading, return that promise\n if (this.fileData) {\n return Promise.resolve();\n }\n\n if (this.loadPromise) {\n return this.loadPromise;\n }\n\n this.loadPromise = (async () => {\n try {\n // First get the file size\n const size = await this.count();\n\n if (this.debug) console.log(`Fetching entire file (${size} bytes) from ${this.url}`);\n\n // Use fetch with streaming and progress tracking\n const response = await fetch(this.url);\n\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`);\n }\n\n // Check if ReadableStream is supported and if progress tracking is needed\n if (this.onProgress && response.body && \"getReader\" in response.body) {\n // Stream the response with progress tracking\n const contentLength = Number(response.headers.get(\"content-length\") || size);\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n\n let receivedLength = 0;\n let lastProgressUpdate = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n chunks.push(value);\n receivedLength += value.length;\n\n // Don't update progress too frequently (throttle updates)\n const now = Date.now();\n if (now - lastProgressUpdate > 100) {\n // update every 100ms\n this.onProgress(receivedLength, contentLength);\n lastProgressUpdate = now;\n }\n }\n\n // Concatenate chunks into a single Uint8Array\n this.fileData = new Uint8Array(receivedLength);\n let position = 0;\n for (const chunk of chunks) {\n this.fileData.set(chunk, position);\n position += chunk.length;\n }\n\n // Final progress update\n this.onProgress(receivedLength, contentLength);\n } else {\n // Simple approach without streaming\n const buffer = await response.arrayBuffer();\n this.fileData = new Uint8Array(buffer);\n\n if (this.onProgress) {\n this.onProgress(this.fileData.length, size);\n }\n }\n\n if (this.debug) console.log(`File loaded successfully (${this.fileData.length} bytes)`);\n return;\n } catch (error) {\n this.loadPromise = null;\n throw new Error(`Failed to load file: ${error instanceof Error ? error.message : String(error)}`);\n }\n })();\n\n return this.loadPromise;\n }\n\n /**\n * Get bytes from the file\n * @param offset The starting position in the file\n * @param size The number of bytes to read\n */\n async getBytes(offset: number, size: number): Promise<Uint8Array> {\n try {\n // Make sure the file is loaded\n if (!this.fileData) {\n if (this.debug) console.log(`getBytes(${offset}, ${size}): Waiting for file to load...`);\n await this.loadFile();\n if (this.debug) console.log(`getBytes(${offset}, ${size}): File loaded`);\n }\n\n // At this point, fileData should be available\n if (!this.fileData) {\n throw new Error(\"File data is not available after load\");\n }\n\n // Bounds check\n if (offset < 0 || offset + size > this.fileData.length) {\n throw new Error(`Requested range (${offset}:${offset + size}) is out of bounds (0:${this.fileData.length})`);\n }\n\n if (this.debug) console.log(`Serving ${size} bytes from offset ${offset} from memory`);\n\n // Return the requested slice of data\n return this.fileData.slice(offset, offset + size);\n } catch (error) {\n throw new Error(`Error in getBytes: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Check if the file is fully loaded\n */\n isLoaded(): boolean {\n return !!this.fileData;\n }\n\n /**\n * Get the current loaded data or null if not loaded\n */\n getFileData(): Uint8Array | null {\n return this.fileData;\n }\n\n /**\n * Force a reload of the file\n */\n async reload(): Promise<void> {\n this.fileData = null;\n this.loadPromise = null;\n return this.loadFile();\n }\n\n /**\n * Close the backend and release any resources\n */\n async close(): Promise<void> {\n this.fileData = null;\n this.loadPromise = null;\n }\n}\n"],"names":["CompressionType","OmDataType"],"mappings":"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