UNPKG

netcdf4-wasm

Version:

NetCDF4 library compiled to WebAssembly with TypeScript bindings

78 lines 3.18 kB
"use strict"; // Lazy file reading - Emscripten virtual-filesystem glue // // Mounts a LazyReader as a read-only file in Emscripten's in-memory filesystem by // overriding the node's `stream_ops`. When NetCDF/HDF5 open that path and issue // reads, libc forwards them to `stream_ops.read`, which pulls only the requested // range from the reader instead of materialising the whole file. This is the same // technique Emscripten's own `FS.createLazyFile` and h5wasm's lazy loaders use, // but with ranged reads (not byte-at-a-time) so it stays fast over a block cache. // // Requires the module to be built with the filesystem and `FS` runtime export // available (`-sFORCE_FILESYSTEM=1` plus `FS` in EXPORTED_RUNTIME_METHODS). Object.defineProperty(exports, "__esModule", { value: true }); exports.createLazyStreamOps = createLazyStreamOps; exports.mountLazyFile = mountLazyFile; // whence values from <stdio.h> const SEEK_CUR = 1; const SEEK_END = 2; /** * Build the read-only `stream_ops` that bridge Emscripten reads to a LazyReader. * Pure and self-contained so it can be unit-tested without a real WASM module. */ function createLazyStreamOps(reader) { return { read(_stream, buffer, offset, length, position) { if (position >= reader.size || length <= 0) return 0; const bytes = reader.read(position, length); // Defensively cap at `length`: libc only allotted `length` bytes at // `offset`, so never write past it even if a reader violates its contract // and returns more (that would corrupt adjacent WASM heap memory). const n = Math.min(bytes.length, length); buffer.set(n === bytes.length ? bytes : bytes.subarray(0, n), offset); return n; }, write() { throw new Error("Lazy NetCDF file is read-only"); }, llseek(stream, offset, whence) { let position = offset; if (whence === SEEK_CUR) position += stream.position; else if (whence === SEEK_END) position += reader.size; if (position < 0) throw new Error(`Invalid seek to ${position}`); return position; }, }; } /** * Create a lazily-read file at `path` in the Emscripten filesystem, backed by * `reader`. Returns the created FS node. */ function mountLazyFile(FS, path, reader) { const slash = path.lastIndexOf("/"); const dir = slash > 0 ? path.slice(0, slash) : "/"; const name = path.slice(slash + 1); if (dir && dir !== "/") { try { if (FS.mkdirTree) FS.mkdirTree(dir); else FS.mkdir(dir); } catch { // Directory already exists - ignore. } } const node = FS.createFile(dir, name, {}, /*canRead*/ true, /*canWrite*/ false); // Report the real size so stat/seek-to-end work without loading the file. Object.defineProperty(node, "usedBytes", { get: () => reader.size }); node.stream_ops = createLazyStreamOps(reader); return node; } //# sourceMappingURL=emscripten-fs.js.map