"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // dist/index.js var dist_exports = {}; __export(dist_exports, { NetCDFLoader: () => NetCDFLoader, NetCDFReader: () => NetCDFReader }); module.exports = __toCommonJS(dist_exports); // dist/iobuffer/iobuffer.js var DEFAULT_BYTE_LENGTH = 1024 * 8; var IOBuffer = class { /** * Reference to the internal ArrayBuffer object. */ buffer; /** * Byte length of the internal ArrayBuffer. */ byteLength; /** * Byte offset of the internal ArrayBuffer. */ byteOffset; /** * Byte length of the internal ArrayBuffer. */ length; /** * The current offset of the buffer's pointer. */ offset; lastWrittenByte; littleEndian; _data; _mark; _marks; textDecoder = new TextDecoder(); textEncoder = new TextEncoder(); /** * @param data - The data to construct the IOBuffer with. * If data is a number, it will be the new buffer's length
* If data is `undefined`, the buffer will be initialized with a default length of 8Kb
* If data is an ArrayBuffer, SharedArrayBuffer, an ArrayBufferView (Typed Array), an IOBuffer instance, * or a Node.js Buffer, a view will be created over the underlying ArrayBuffer. * @param options */ constructor(data = DEFAULT_BYTE_LENGTH, options = {}) { let dataIsGiven = false; if (typeof data === "number") { data = new ArrayBuffer(data); } else { dataIsGiven = true; this.lastWrittenByte = data.byteLength; } const offset = options.offset ? options.offset >>> 0 : 0; const byteLength = data.byteLength - offset; let dvOffset = offset; if (ArrayBuffer.isView(data) || data instanceof IOBuffer) { if (data.byteLength !== data.buffer.byteLength) { dvOffset = data.byteOffset + offset; } data = data.buffer; } if (dataIsGiven) { this.lastWrittenByte = byteLength; } else { this.lastWrittenByte = 0; } this.buffer = data; this.length = byteLength; this.byteLength = byteLength; this.byteOffset = dvOffset; this.offset = 0; this.littleEndian = true; this._data = new DataView(this.buffer, dvOffset, byteLength); this._mark = 0; this._marks = []; } /** * Checks if the memory allocated to the buffer is sufficient to store more * bytes after the offset. * @param byteLength - The needed memory in bytes. * @returns `true` if there is sufficient space and `false` otherwise. */ available(byteLength = 1) { return this.offset + byteLength <= this.length; } /** * Check if little-endian mode is used for reading and writing multi-byte * values. * @returns `true` if little-endian mode is used, `false` otherwise. */ isLittleEndian() { return this.littleEndian; } /** * Set little-endian mode for reading and writing multi-byte values. */ setLittleEndian() { this.littleEndian = true; return this; } /** * Check if big-endian mode is used for reading and writing multi-byte values. * @returns `true` if big-endian mode is used, `false` otherwise. */ isBigEndian() { return !this.littleEndian; } /** * Switches to big-endian mode for reading and writing multi-byte values. */ setBigEndian() { this.littleEndian = false; return this; } /** * Move the pointer n bytes forward. * @param n - Number of bytes to skip. */ skip(n = 1) { this.offset += n; return this; } /** * Move the pointer to the given offset. * @param offset */ seek(offset) { this.offset = offset; return this; } /** * Store the current pointer offset. * @see {@link IOBuffer#reset} */ mark() { this._mark = this.offset; return this; } /** * Move the pointer back to the last pointer offset set by mark. * @see {@link IOBuffer#mark} */ reset() { this.offset = this._mark; return this; } /** * Push the current pointer offset to the mark stack. * @see {@link IOBuffer#popMark} */ pushMark() { this._marks.push(this.offset); return this; } /** * Pop the last pointer offset from the mark stack, and set the current * pointer offset to the popped value. * @see {@link IOBuffer#pushMark} */ popMark() { const offset = this._marks.pop(); if (offset === void 0) { throw new Error("Mark stack empty"); } this.seek(offset); return this; } /** * Move the pointer offset back to 0. */ rewind() { this.offset = 0; return this; } /** * Make sure the buffer has sufficient memory to write a given byteLength at * the current pointer offset. * If the buffer's memory is insufficient, this method will create a new * buffer (a copy) with a length that is twice (byteLength + current offset). * @param byteLength */ ensureAvailable(byteLength = 1) { if (!this.available(byteLength)) { const lengthNeeded = this.offset + byteLength; const newLength = lengthNeeded * 2; const newArray = new Uint8Array(newLength); newArray.set(new Uint8Array(this.buffer)); this.buffer = newArray.buffer; this.length = this.byteLength = newLength; this._data = new DataView(this.buffer); } return this; } /** * Read a byte and return false if the byte's value is 0, or true otherwise. * Moves pointer forward by one byte. */ readBoolean() { return this.readUint8() !== 0; } /** * Read a signed 8-bit integer and move pointer forward by 1 byte. */ readInt8() { return this._data.getInt8(this.offset++); } /** * Read an unsigned 8-bit integer and move pointer forward by 1 byte. */ readUint8() { return this._data.getUint8(this.offset++); } /** * Alias for {@link IOBuffer#readUint8}. */ readByte() { return this.readUint8(); } /** * Read `n` bytes and move pointer forward by `n` bytes. */ readBytes(n = 1) { const bytes = new Uint8Array(n); for (let i = 0; i < n; i++) { bytes[i] = this.readByte(); } return bytes; } /** * Read a 16-bit signed integer and move pointer forward by 2 bytes. */ readInt16() { const value = this._data.getInt16(this.offset, this.littleEndian); this.offset += 2; return value; } /** * Read a 16-bit unsigned integer and move pointer forward by 2 bytes. */ readUint16() { const value = this._data.getUint16(this.offset, this.littleEndian); this.offset += 2; return value; } /** * Read a 32-bit signed integer and move pointer forward by 4 bytes. */ readInt32() { const value = this._data.getInt32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 32-bit unsigned integer and move pointer forward by 4 bytes. */ readUint32() { const value = this._data.getUint32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 32-bit floating number and move pointer forward by 4 bytes. */ readFloat32() { const value = this._data.getFloat32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 64-bit floating number and move pointer forward by 8 bytes. */ readFloat64() { const value = this._data.getFloat64(this.offset, this.littleEndian); this.offset += 8; return value; } /** * Read a 1-byte ASCII character and move pointer forward by 1 byte. */ readChar() { return String.fromCharCode(this.readInt8()); } /** * Read `n` 1-byte ASCII characters and move pointer forward by `n` bytes. */ readChars(n = 1) { let result = ""; for (let i = 0; i < n; i++) { result += this.readChar(); } return result; } /** * Read the next `n` bytes, return a UTF-8 decoded string and move pointer * forward by `n` bytes. */ readUtf8(n = 1) { return this.textDecoder.decode(this.readBytes(n)); } /** * Write 0xff if the passed value is truthy, 0x00 otherwise and move pointer * forward by 1 byte. */ writeBoolean(value) { this.writeUint8(value ? 255 : 0); return this; } /** * Write `value` as an 8-bit signed integer and move pointer forward by 1 byte. */ writeInt8(value) { this.ensureAvailable(1); this._data.setInt8(this.offset++, value); this._updateLastWrittenByte(); return this; } /** * Write `value` as an 8-bit unsigned integer and move pointer forward by 1 * byte. */ writeUint8(value) { this.ensureAvailable(1); this._data.setUint8(this.offset++, value); this._updateLastWrittenByte(); return this; } /** * An alias for {@link IOBuffer#writeUint8}. */ writeByte(value) { return this.writeUint8(value); } /** * Write all elements of `bytes` as uint8 values and move pointer forward by * `bytes.length` bytes. */ writeBytes(bytes) { this.ensureAvailable(bytes.length); for (let i = 0; i < bytes.length; i++) { this._data.setUint8(this.offset++, bytes[i]); } this._updateLastWrittenByte(); return this; } /** * Write `value` as a 16-bit signed integer and move pointer forward by 2 * bytes. */ writeInt16(value) { this.ensureAvailable(2); this._data.setInt16(this.offset, value, this.littleEndian); this.offset += 2; this._updateLastWrittenByte(); return this; } /** * Write `value` as a 16-bit unsigned integer and move pointer forward by 2 * bytes. */ writeUint16(value) { this.ensureAvailable(2); this._data.setUint16(this.offset, value, this.littleEndian); this.offset += 2; this._updateLastWrittenByte(); return this; } /** * Write `value` as a 32-bit signed integer and move pointer forward by 4 * bytes. */ writeInt32(value) { this.ensureAvailable(4); this._data.setInt32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write `value` as a 32-bit unsigned integer and move pointer forward by 4 * bytes. */ writeUint32(value) { this.ensureAvailable(4); this._data.setUint32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write `value` as a 32-bit floating number and move pointer forward by 4 * bytes. */ writeFloat32(value) { this.ensureAvailable(4); this._data.setFloat32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write `value` as a 64-bit floating number and move pointer forward by 8 * bytes. */ writeFloat64(value) { this.ensureAvailable(8); this._data.setFloat64(this.offset, value, this.littleEndian); this.offset += 8; this._updateLastWrittenByte(); return this; } /** * Write the charCode of `str`'s first character as an 8-bit unsigned integer * and move pointer forward by 1 byte. */ writeChar(str) { return this.writeUint8(str.charCodeAt(0)); } /** * Write the charCodes of all `str`'s characters as 8-bit unsigned integers * and move pointer forward by `str.length` bytes. */ writeChars(str) { for (let i = 0; i < str.length; i++) { this.writeUint8(str.charCodeAt(i)); } return this; } /** * UTF-8 encode and write `str` to the current pointer offset and move pointer * forward according to the encoded length. */ writeUtf8(str) { const bytes = this.textEncoder.encode(str); return this.writeBytes(bytes); } /** * Export a Uint8Array view of the internal buffer. * The view starts at the byte offset and its length * is calculated to stop at the last written byte or the original length. */ toArray() { return new Uint8Array(this.buffer, this.byteOffset, this.lastWrittenByte); } /** * Update the last written byte offset * @private */ _updateLastWrittenByte() { if (this.offset > this.lastWrittenByte) { this.lastWrittenByte = this.offset; } } }; // dist/netcdfjs/read-type.js var TYPES = { BYTE: 1, CHAR: 2, SHORT: 3, INT: 4, FLOAT: 5, DOUBLE: 6 }; function readType(buffer, type, size) { switch (type) { case TYPES.BYTE: return buffer.readBytes(size); case TYPES.CHAR: return trimNull(buffer.readChars(size)); case TYPES.SHORT: return readNumber(size, buffer.readInt16.bind(buffer)); case TYPES.INT: return readNumber(size, buffer.readInt32.bind(buffer)); case TYPES.FLOAT: return readNumber(size, buffer.readFloat32.bind(buffer)); case TYPES.DOUBLE: return readNumber(size, buffer.readFloat64.bind(buffer)); default: throw new Error(`NetCDF: non valid type ${type}`); } } function num2str(type) { switch (Number(type)) { case TYPES.BYTE: return "byte"; case TYPES.CHAR: return "char"; case TYPES.SHORT: return "short"; case TYPES.INT: return "int"; case TYPES.FLOAT: return "float"; case TYPES.DOUBLE: return "double"; default: return "undefined"; } } function num2bytes(type) { switch (Number(type)) { case TYPES.BYTE: return 1; case TYPES.CHAR: return 1; case TYPES.SHORT: return 2; case TYPES.INT: return 4; case TYPES.FLOAT: return 4; case TYPES.DOUBLE: return 8; default: return -1; } } function str2num(type) { switch (String(type)) { case "byte": return TYPES.BYTE; case "char": return TYPES.CHAR; case "short": return TYPES.SHORT; case "int": return TYPES.INT; case "float": return TYPES.FLOAT; case "double": return TYPES.DOUBLE; default: return -1; } } function readNumber(size, bufferReader) { if (size !== 1) { const numbers = new Array(size); for (let i = 0; i < size; i++) { numbers[i] = bufferReader(); } return numbers; } return bufferReader(); } function trimNull(value) { if (value.charCodeAt(value.length - 1) === 0) { return value.substring(0, value.length - 1); } return value; } // dist/netcdfjs/read-header.js var ZERO = 0; var NC_DIMENSION = 10; var NC_VARIABLE = 11; var NC_ATTRIBUTE = 12; var NC_UNLIMITED = 0; function readNetCDFHeader(buffer, version) { const recordDimensionLength = buffer.readUint32(); const dimList = readDimensionsList(buffer); const attributes = readAttributesList(buffer); const variableList = readVariablesList(buffer, dimList.recordId, version); const header = { version, recordDimension: { length: recordDimensionLength, id: dimList.recordId, // id of the unlimited dimension name: dimList.recordName, // name of the unlimited dimension recordStep: variableList.recordStep }, dimensions: dimList.dimensions, variables: variableList.variables, attributes }; return header; } function readDimensionsList(buffer) { const dimList = buffer.readUint32(); if (dimList === ZERO) { if (buffer.readUint32() !== ZERO) { throw new Error("NetCDF: wrong empty tag for list of dimensions"); } return { recordId: 0, recordName: "", dimensions: [] }; } if (dimList !== NC_DIMENSION) { throw new Error("NetCDF: wrong tag for list of dimensions"); } const dimensionSize = buffer.readUint32(); const dimensions = new Array(dimensionSize); let recordId; let recordName; for (let dim = 0; dim < dimensionSize; dim++) { const name = readName(buffer); const size = buffer.readUint32(); if (size === NC_UNLIMITED) { recordId = dim; recordName = name; } dimensions[dim] = { name, size }; } return { dimensions, recordId, recordName }; } function readAttributesList(buffer) { const gAttList = buffer.readUint32(); if (gAttList === ZERO) { if (buffer.readUint32() !== ZERO) { throw new Error("NetCDF: wrong empty tag for list of attributes"); } return []; } if (gAttList !== NC_ATTRIBUTE) { throw new Error("NetCDF: wrong tag for list of attributes"); } const attributeSize = buffer.readUint32(); const attributes = new Array(attributeSize); for (let gAtt = 0; gAtt < attributeSize; gAtt++) { const name = readName(buffer); const type = buffer.readUint32(); if (type < 1 || type > 6) { throw new Error(`NetCDF: non valid type ${type}`); } const size = buffer.readUint32(); const value = readType(buffer, type, size); padding(buffer); attributes[gAtt] = { name, type: num2str(type), value }; } return attributes; } function readVariablesList(buffer, recordId, version) { const varList = buffer.readUint32(); let recordStep = 0; if (varList === ZERO) { if (buffer.readUint32() !== ZERO) { throw new Error("NetCDF: wrong empty tag for list of variables"); } return { recordStep, variables: [] }; } if (varList !== NC_VARIABLE) { throw new Error("NetCDF: wrong tag for list of variables"); } const variableSize = buffer.readUint32(); const variables = new Array(variableSize); for (let v = 0; v < variableSize; v++) { const name = readName(buffer); const dimensionality = buffer.readUint32(); const dimensionsIds = new Array(dimensionality); for (let dim = 0; dim < dimensionality; dim++) { dimensionsIds[dim] = buffer.readUint32(); } const attributes = readAttributesList(buffer); const type = buffer.readUint32(); if (type < 1 && type > 6) { throw new Error(`NetCDF: non valid type ${type}`); } const varSize = buffer.readUint32(); let offset = buffer.readUint32(); if (version === 2) { if (offset > 0) { throw new Error("NetCDF: offsets larger than 4GB not supported"); } offset = buffer.readUint32(); } let record = false; if (typeof recordId !== "undefined" && dimensionsIds[0] === recordId) { recordStep += varSize; record = true; } variables[v] = { name, dimensions: dimensionsIds, attributes, type: num2str(type), size: varSize, offset, record }; } return { variables, recordStep }; } function readName(buffer) { const nameLength = buffer.readUint32(); const name = buffer.readChars(nameLength); padding(buffer); return name; } function padding(buffer) { if (buffer.offset % 4 !== 0) { buffer.skip(4 - buffer.offset % 4); } } // dist/netcdfjs/read-data.js function readNonRecord(buffer, variable) { const type = str2num(variable.type); const size = variable.size / num2bytes(type); const data = new Array(size); for (let i = 0; i < size; i++) { data[i] = readType(buffer, type, 1); } return data; } function readRecord(buffer, variable, recordDimension) { const type = str2num(variable.type); const width = variable.size ? variable.size / num2bytes(type) : 1; const size = recordDimension.length; const data = new Array(size); const step = recordDimension.recordStep; for (let i = 0; i < size; i++) { const currentOffset = buffer.offset; data[i] = readType(buffer, type, width); buffer.seek(currentOffset + step); } return data; } // dist/netcdfjs/netcdf-reader.js var NetCDFReader = class { header; buffer; constructor(data) { const buffer = new IOBuffer(data); buffer.setBigEndian(); const magic = buffer.readChars(3); if (magic !== "CDF") { throw new Error(`NetCDF: file should start with 'CDF', found ${magic}`); } const version = buffer.readByte(); if (version > 2) { throw new Error(`NetCDF: unsupported version ${version}`); } this.header = readNetCDFHeader(buffer, version); this.buffer = buffer; } /** * @return {string} - Version for the NetCDF format */ get version() { if (this.header.version === 1) { return "classic format"; } return "64-bit offset format"; } /** * Get metadata for the record dimension */ get recordDimension() { return this.header.recordDimension; } /** * Get list of dimensions (each with `name` and `size`) */ get dimensions() { return this.header.dimensions; } /** * Get list of global attributes with: * * `name`: String with the name of the attribute * * `type`: String with the type of the attribute * * `value`: A number or string with the value of the attribute */ get attributes() { return this.header.attributes; } /** * Get list of variables */ get variables() { return this.header.variables; } /** * Check if an attribute exists * @param attributeName - Name of the attribute to find * @return */ attributeExists(attributeName) { const attribute = this.attributes.find((val) => val.name === attributeName); return attribute !== void 0; } /** * Returns the value of an attribute * @param attributeName * @return Value of the attributeName or null */ getAttribute(attributeName) { const attribute = this.attributes.find((val) => val.name === attributeName); if (attribute) return attribute.value; return null; } /** * Check if a dataVariable exists * @param variableName - Name of the variable to find * @return */ dataVariableExists(variableName) { const variable = this.header.variables.find(function(val) { return val.name === variableName; }); return variable !== void 0; } /** * Returns the value of a variable as a string * @param variableName * @return Value of the variable as a string or null */ getDataVariableAsString(variableName) { const variable = this.getDataVariable(variableName); if (variable) return variable.join(""); return null; } /** * Retrieves the data for a given variable * @param variableName - Name of the variable to search or variable object * @return List with the variable values */ getDataVariable(variableName) { let variable; if (typeof variableName === "string") { variable = this.header.variables.find(function(val) { return val.name === variableName; }); } else { variable = variableName; } if (variable === void 0) { let errorOutput; if (typeof variableName === "string") { errorOutput = variableName; } else if (typeof variableName === "object") { errorOutput = JSON.stringify(variableName); } throw new Error(`NetCDF: variable not found: ${errorOutput}`); } this.buffer.seek(variable.offset); if (variable.record) { return readRecord(this.buffer, variable, this.header.recordDimension); } return readNonRecord(this.buffer, variable); } toString() { const result = []; result.push("DIMENSIONS"); for (const dimension of this.dimensions) { result.push(` ${dimension.name.padEnd(30)} = size: ${dimension.size}`); } result.push(""); result.push("GLOBAL ATTRIBUTES"); for (const attribute of this.attributes) { result.push(` ${attribute.name.padEnd(30)} = ${attribute.value}`); } const variables = JSON.parse(JSON.stringify(this.variables)); result.push(""); result.push("VARIABLES:"); for (const variable of variables) { variable.value = this.getDataVariable(variable); let stringify = JSON.stringify(variable.value); if (stringify.length > 50) stringify = stringify.substring(0, 50); if (!isNaN(variable.value.length)) { stringify += ` (length: ${variable.value.length})`; } result.push(` ${variable.name.padEnd(30)} = ${stringify}`); } return result.join("\n"); } }; // dist/netcdf-loader.js var VERSION = true ? "4.3.1" : "latest"; var NetCDFWorkerLoader = { dataType: null, batchType: null, name: "NetCDF", id: "mvt", module: "mvt", version: VERSION, extensions: ["cdf", "nc"], mimeTypes: [ "application/netcdf", "application/x-netcdf" // 'application/octet-stream' ], category: "image", options: { netcdf: { loadVariables: false } } }; var NetCDFLoader = { ...NetCDFWorkerLoader, parse: async (arrayBuffer, options) => parseNetCDF(arrayBuffer, options), binary: true }; function parseNetCDF(arrayBuffer, options) { var _a; const reader = new NetCDFReader(arrayBuffer); const variables = {}; if ((_a = options == null ? void 0 : options.netcdf) == null ? void 0 : _a.loadData) { for (const variable of reader.variables) { variables[variable.name] = reader.getDataVariable(variable); } } return { loaderData: reader.header, data: variables }; } //# sourceMappingURL=index.cjs.map