UNPKG

geotiff

Version:

GeoTIFF image decoding in JavaScript

236 lines (207 loc) 5.94 kB
export function assign< T extends Record<string, unknown>, S extends Record<string, unknown>, >(target: T, source: S): T & S { for (const key in source) { if (source.hasOwnProperty(key)) { (target as Record<string, unknown>)[key] = source[key]; } } return target as T & S; } export function chunk<T>(iterable: ArrayLike<T>, length: number): T[][] { const results: T[][] = []; const lengthOfIterable = iterable.length; for (let i = 0; i < lengthOfIterable; i += length) { const chunked: T[] = []; for (let ci = i; ci < i + length; ci++) { chunked.push(iterable[ci]); } results.push(chunked); } return results; } export function endsWith(string: string, expectedEnding: string): boolean { if (string.length < expectedEnding.length) { return false; } const actualEnding = string.substr(string.length - expectedEnding.length); return actualEnding === expectedEnding; } export function forEach<T>( iterable: ArrayLike<T>, func: (item: T, index: number) => void, ): void { const { length } = iterable; for (let i = 0; i < length; i++) { func(iterable[i], i); } } export function invert<K extends string | number, V extends string | number>( oldObj: Record<K, V>, ): Record<V, K> { const newObj = {} as Record<V, K>; for (const key in oldObj) { if (oldObj.hasOwnProperty(key)) { const value = oldObj[key]; newObj[value] = key; } } return newObj; } export function range(n: number): number[] { const results: number[] = []; for (let i = 0; i < n; i++) { results.push(i); } return results; } export function times<T>(numTimes: number, func: (index: number) => T): T[] { const results: T[] = []; for (let i = 0; i < numTimes; i++) { results.push(func(i)); } return results; } export function toArray<T>(iterable: ArrayLike<T>): T[] { const results: T[] = []; const { length } = iterable; for (let i = 0; i < length; i++) { results.push(iterable[i]); } return results; } export function toArrayRecursively(input: unknown): unknown { if (isArrayLike(input)) { return toArray(input).map(toArrayRecursively); } return input; } function isArrayLike(v: unknown): v is ArrayLike<unknown> { return Boolean( typeof v === 'object' && v !== null && 'length' in v, // v && typeof v === 'object' && 'length' in v && typeof (v as { length: unknown }).length === 'number', ); } /** Copied from https://github.com/academia-de-codigo/parse-content-range-header/blob/master/index.js */ export function parseContentRange(headerValue: string): null | { unit: string | null; first: number | null; last: number | null; length: number | null; } { if (!headerValue) { return null; } if (typeof headerValue !== 'string') { throw new Error('invalid argument'); } const parseInt: (number: string) => number = (number) => Number.parseInt(number, 10); // Check for presence of unit let matches = headerValue.match(/^(\w*) /); const unit = matches && matches[1]; // check for start-end/size header format matches = headerValue.match(/(\d+)-(\d+)\/(\d+|\*)/); if (matches) { return { unit, first: parseInt(matches[1]), last: parseInt(matches[2]), length: matches[3] === '*' ? null : parseInt(matches[3]), }; } // check for size header format matches = headerValue.match(/(\d+|\*)/); if (matches) { return { unit, first: null, last: null, length: matches[1] === '*' ? null : parseInt(matches[1]), }; } return null; } /** * Promisified wrapper around 'setTimeout' to allow 'await' * @param {number} [milliseconds] * @returns {Promise<void>} */ export async function wait(milliseconds?: number): Promise<void> { return new Promise((resolve) => setTimeout(resolve, milliseconds)); } export function zip<T, U>(a: Iterable<T>, b: Iterable<U>): [T, U][] { const A = Array.isArray(a) ? a : Array.from(a); const B = Array.isArray(b) ? b : Array.from(b); return A.map((k, i) => [k, B[i]]); } // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error export class AbortError extends Error { signal?: AbortSignal; constructor(...args: any[]) { // Pass remaining arguments (including vendor specific ones) to parent constructor super(...args); // Maintains proper stack trace for where our error was thrown (only available on V8) if (Error.captureStackTrace) { Error.captureStackTrace(this, AbortError); } this.name = 'AbortError'; this.signal = undefined; } } export class CustomAggregateError extends Error { errors: Error[]; constructor(errors: Error[], message: string) { super(message); this.errors = errors; this.message = message; this.name = 'AggregateError'; } } export const AggregateError = CustomAggregateError; export function isTypedFloatArray( input: unknown, ): input is Float32Array | Float64Array { if (ArrayBuffer.isView(input)) { const ctr = input.constructor; if (ctr === Float32Array || ctr === Float64Array) { return true; } } return false; } export function isTypedIntArray( input: unknown, ): input is Int8Array | Int16Array | Int32Array { if (ArrayBuffer.isView(input)) { const ctr = input.constructor; if (ctr === Int8Array || ctr === Int16Array || ctr === Int32Array) { return true; } } return false; } export function isTypedUintArray( input: unknown, ): input is Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray { if (ArrayBuffer.isView(input)) { const ctr = input.constructor; if ( ctr === Uint8Array || ctr === Uint16Array || ctr === Uint32Array || ctr === Uint8ClampedArray ) { return true; } } return false; } export const typeMap = { Float64Array, Float32Array, Uint32Array, Uint16Array, Uint8Array, };