import { ungzip } from 'pako-esm2' import { decompressAll, decompressChunkSlice, } from './wasm/bgzf-wasm-inlined.js' interface VirtualOffset { blockPosition: number dataPosition: number } interface Chunk { minv: VirtualOffset maxv: VirtualOffset } function hasGzipHeader(data: Uint8Array) { return data[0] === 0x1f && data[1] === 0x8b } function errorMessage(error: unknown) { return error instanceof Error ? error.message : `${error}` } async function decompressGzip(inputData: Uint8Array) { if (typeof DecompressionStream !== 'undefined') { const stream = new Blob([inputData as Uint8Array]) .stream() .pipeThrough(new DecompressionStream('gzip')) return new Uint8Array(await new Response(stream).arrayBuffer()) } else { return ungzip(inputData, undefined) } } function wrapGzipHeaderError(error: unknown) { if (errorMessage(error).includes('invalid gzip header')) { return new Error( 'problem decompressing block: incorrect gzip header check', { cause: error }, ) } return error } export async function unzip(inputData: Uint8Array) { try { return await decompressAll(inputData) } catch (error) { const message = errorMessage(error) if (message.includes('invalid bgzf header')) { if (hasGzipHeader(inputData)) { return decompressGzip(inputData) } throw new Error( 'problem decompressing block: not a valid bgzf or gzip block', { cause: error }, ) } throw wrapGzipHeaderError(error) } } export async function unzipChunkSlice(inputData: Uint8Array, chunk: Chunk) { const { minv, maxv } = chunk try { const result = await decompressChunkSlice( inputData, minv.blockPosition, minv.dataPosition, maxv.blockPosition, maxv.dataPosition, ) return { buffer: result.buffer, cpositions: result.cpositions, dpositions: result.dpositions, } } catch (error) { throw wrapGzipHeaderError(error) } }