import { o as __toESM } from "./chunk-D_gEzPfs.js";
import { i as fromWebStream, n as fromBuffer, o as EndOfStreamError, t as fromBlob } from "./core-B0gbHtnb.js";
import { a as INT32_BE, d as UINT16_BE, f as UINT16_LE, g as UINT32_LE, h as UINT32_BE, u as StringType, v as UINT64_LE, y as UINT8 } from "./lib-Dpcb6PNT.js";
import { t as require_src } from "./src-DMKTTTD5.js";
import { t as getUintBE } from "./uint8array-extras-E7vicUr0.js";

//#region node_modules/.pnpm/@tokenizer+inflate@0.4.1/node_modules/@tokenizer/inflate/lib/ZipToken.js
/**
* Ref https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
*/
const Signature = {
	LocalFileHeader: 67324752,
	DataDescriptor: 134695760,
	CentralFileHeader: 33639248,
	EndOfCentralDirectory: 101010256
};
const DataDescriptor = {
	get(array) {
		return {
			signature: UINT32_LE.get(array, 0),
			compressedSize: UINT32_LE.get(array, 8),
			uncompressedSize: UINT32_LE.get(array, 12)
		};
	},
	len: 16
};
/**
* First part of the ZIP Local File Header
* Offset | Bytes| Description
* -------|------+-------------------------------------------------------------------
*      0 |    4 | Signature (0x04034b50)
*      4 |    2 | Minimum version needed to extract
*      6 |    2 | Bit flag
*      8 |    2 | Compression method
*     10 |    2 | File last modification time (MS-DOS format)
*     12 |    2 | File last modification date (MS-DOS format)
*     14 |    4 | CRC-32 of uncompressed data
*     18 |    4 | Compressed size
*     22 |    4 | Uncompressed size
*     26 |    2 | File name length (n)
*     28 |    2 | Extra field length (m)
*     30 |    n | File name
* 30 + n |    m | Extra field
*/
const LocalFileHeaderToken = {
	get(array) {
		const flags = UINT16_LE.get(array, 6);
		return {
			signature: UINT32_LE.get(array, 0),
			minVersion: UINT16_LE.get(array, 4),
			dataDescriptor: !!(flags & 8),
			compressedMethod: UINT16_LE.get(array, 8),
			compressedSize: UINT32_LE.get(array, 18),
			uncompressedSize: UINT32_LE.get(array, 22),
			filenameLength: UINT16_LE.get(array, 26),
			extraFieldLength: UINT16_LE.get(array, 28),
			filename: null
		};
	},
	len: 30
};
/**
* 4.3.16  End of central directory record:
*  end of central dir signature (0x06064b50)                                      4 bytes
*  number of this disk                                                            2 bytes
*  number of the disk with the start of the central directory                     2 bytes
*  total number of entries in the central directory on this disk                  2 bytes
*  total number of entries in the size of the central directory                   2 bytes
*  sizeOfTheCentralDirectory                                                      4 bytes
*  offset of start of central directory with respect to the starting disk number  4 bytes
*  .ZIP file comment length                                                       2 bytes
*  .ZIP file comment       (variable size)
*/
const EndOfCentralDirectoryRecordToken = {
	get(array) {
		return {
			signature: UINT32_LE.get(array, 0),
			nrOfThisDisk: UINT16_LE.get(array, 4),
			nrOfThisDiskWithTheStart: UINT16_LE.get(array, 6),
			nrOfEntriesOnThisDisk: UINT16_LE.get(array, 8),
			nrOfEntriesOfSize: UINT16_LE.get(array, 10),
			sizeOfCd: UINT32_LE.get(array, 12),
			offsetOfStartOfCd: UINT32_LE.get(array, 16),
			zipFileCommentLength: UINT16_LE.get(array, 20)
		};
	},
	len: 22
};
/**
* File header:
*    central file header signature   4 bytes   0 (0x02014b50)
*    version made by                 2 bytes   4
*    version needed to extract       2 bytes   6
*    general purpose bit flag        2 bytes   8
*    compression method              2 bytes  10
*    last mod file time              2 bytes  12
*    last mod file date              2 bytes  14
*    crc-32                          4 bytes  16
*    compressed size                 4 bytes  20
*    uncompressed size               4 bytes  24
*    file name length                2 bytes  28
*    extra field length              2 bytes  30
*    file comment length             2 bytes  32
*    disk number start               2 bytes  34
*    internal file attributes        2 bytes  36
*    external file attributes        4 bytes  38
*    relative offset of local header 4 bytes  42
*/
const FileHeader = {
	get(array) {
		const flags = UINT16_LE.get(array, 8);
		return {
			signature: UINT32_LE.get(array, 0),
			minVersion: UINT16_LE.get(array, 6),
			dataDescriptor: !!(flags & 8),
			compressedMethod: UINT16_LE.get(array, 10),
			compressedSize: UINT32_LE.get(array, 20),
			uncompressedSize: UINT32_LE.get(array, 24),
			filenameLength: UINT16_LE.get(array, 28),
			extraFieldLength: UINT16_LE.get(array, 30),
			fileCommentLength: UINT16_LE.get(array, 32),
			relativeOffsetOfLocalHeader: UINT32_LE.get(array, 42),
			filename: null
		};
	},
	len: 46
};

//#endregion
//#region node_modules/.pnpm/@tokenizer+inflate@0.4.1/node_modules/@tokenizer/inflate/lib/ZipHandler.js
var import_src = /* @__PURE__ */ __toESM(require_src(), 1);
function signatureToArray(signature) {
	const signatureBytes = new Uint8Array(UINT32_LE.len);
	UINT32_LE.put(signatureBytes, 0, signature);
	return signatureBytes;
}
const debug = (0, import_src.default)("tokenizer:inflate");
const syncBufferSize = 256 * 1024;
const ddSignatureArray = signatureToArray(Signature.DataDescriptor);
const eocdSignatureBytes = signatureToArray(Signature.EndOfCentralDirectory);
var ZipHandler = class ZipHandler {
	constructor(tokenizer) {
		this.tokenizer = tokenizer;
		this.syncBuffer = new Uint8Array(syncBufferSize);
	}
	async isZip() {
		return await this.peekSignature() === Signature.LocalFileHeader;
	}
	peekSignature() {
		return this.tokenizer.peekToken(UINT32_LE);
	}
	async findEndOfCentralDirectoryLocator() {
		const randomReadTokenizer = this.tokenizer;
		const chunkLength = Math.min(16 * 1024, randomReadTokenizer.fileInfo.size);
		const buffer = this.syncBuffer.subarray(0, chunkLength);
		await this.tokenizer.readBuffer(buffer, { position: randomReadTokenizer.fileInfo.size - chunkLength });
		for (let i = buffer.length - 4; i >= 0; i--) if (buffer[i] === eocdSignatureBytes[0] && buffer[i + 1] === eocdSignatureBytes[1] && buffer[i + 2] === eocdSignatureBytes[2] && buffer[i + 3] === eocdSignatureBytes[3]) return randomReadTokenizer.fileInfo.size - chunkLength + i;
		return -1;
	}
	async readCentralDirectory() {
		if (!this.tokenizer.supportsRandomAccess()) {
			debug("Cannot reading central-directory without random-read support");
			return;
		}
		debug("Reading central-directory...");
		const pos = this.tokenizer.position;
		const offset = await this.findEndOfCentralDirectoryLocator();
		if (offset > 0) {
			debug("Central-directory 32-bit signature found");
			const eocdHeader = await this.tokenizer.readToken(EndOfCentralDirectoryRecordToken, offset);
			const files = [];
			this.tokenizer.setPosition(eocdHeader.offsetOfStartOfCd);
			for (let n = 0; n < eocdHeader.nrOfEntriesOfSize; ++n) {
				const entry = await this.tokenizer.readToken(FileHeader);
				if (entry.signature !== Signature.CentralFileHeader) throw new Error("Expected Central-File-Header signature");
				entry.filename = await this.tokenizer.readToken(new StringType(entry.filenameLength, "utf-8"));
				await this.tokenizer.ignore(entry.extraFieldLength);
				await this.tokenizer.ignore(entry.fileCommentLength);
				files.push(entry);
				debug(`Add central-directory file-entry: n=${n + 1}/${files.length}: filename=${files[n].filename}`);
			}
			this.tokenizer.setPosition(pos);
			return files;
		}
		this.tokenizer.setPosition(pos);
	}
	async unzip(fileCb) {
		const entries = await this.readCentralDirectory();
		if (entries) return this.iterateOverCentralDirectory(entries, fileCb);
		let stop = false;
		do {
			const zipHeader = await this.readLocalFileHeader();
			if (!zipHeader) break;
			const next = fileCb(zipHeader);
			stop = !!next.stop;
			let fileData;
			await this.tokenizer.ignore(zipHeader.extraFieldLength);
			if (zipHeader.dataDescriptor && zipHeader.compressedSize === 0) {
				const chunks = [];
				let len = syncBufferSize;
				debug("Compressed-file-size unknown, scanning for next data-descriptor-signature....");
				let nextHeaderIndex = -1;
				while (nextHeaderIndex < 0 && len === syncBufferSize) {
					len = await this.tokenizer.peekBuffer(this.syncBuffer, { mayBeLess: true });
					nextHeaderIndex = indexOf(this.syncBuffer.subarray(0, len), ddSignatureArray);
					const size = nextHeaderIndex >= 0 ? nextHeaderIndex : len;
					if (next.handler) {
						const data = new Uint8Array(size);
						await this.tokenizer.readBuffer(data);
						chunks.push(data);
					} else await this.tokenizer.ignore(size);
				}
				debug(`Found data-descriptor-signature at pos=${this.tokenizer.position}`);
				if (next.handler) await this.inflate(zipHeader, mergeArrays(chunks), next.handler);
			} else if (next.handler) {
				debug(`Reading compressed-file-data: ${zipHeader.compressedSize} bytes`);
				fileData = new Uint8Array(zipHeader.compressedSize);
				await this.tokenizer.readBuffer(fileData);
				await this.inflate(zipHeader, fileData, next.handler);
			} else {
				debug(`Ignoring compressed-file-data: ${zipHeader.compressedSize} bytes`);
				await this.tokenizer.ignore(zipHeader.compressedSize);
			}
			debug(`Reading data-descriptor at pos=${this.tokenizer.position}`);
			if (zipHeader.dataDescriptor) {
				if ((await this.tokenizer.readToken(DataDescriptor)).signature !== 134695760) throw new Error(`Expected data-descriptor-signature at position ${this.tokenizer.position - DataDescriptor.len}`);
			}
		} while (!stop);
	}
	async iterateOverCentralDirectory(entries, fileCb) {
		for (const fileHeader of entries) {
			const next = fileCb(fileHeader);
			if (next.handler) {
				this.tokenizer.setPosition(fileHeader.relativeOffsetOfLocalHeader);
				const zipHeader = await this.readLocalFileHeader();
				if (zipHeader) {
					await this.tokenizer.ignore(zipHeader.extraFieldLength);
					const fileData = new Uint8Array(fileHeader.compressedSize);
					await this.tokenizer.readBuffer(fileData);
					await this.inflate(zipHeader, fileData, next.handler);
				}
			}
			if (next.stop) break;
		}
	}
	async inflate(zipHeader, fileData, cb) {
		if (zipHeader.compressedMethod === 0) return cb(fileData);
		if (zipHeader.compressedMethod !== 8) throw new Error(`Unsupported ZIP compression method: ${zipHeader.compressedMethod}`);
		debug(`Decompress filename=${zipHeader.filename}, compressed-size=${fileData.length}`);
		return cb(await ZipHandler.decompressDeflateRaw(fileData));
	}
	static async decompressDeflateRaw(data) {
		const input = new ReadableStream({ start(controller) {
			controller.enqueue(data);
			controller.close();
		} });
		const ds = new DecompressionStream("deflate-raw");
		const output = input.pipeThrough(ds);
		try {
			const buffer = await new Response(output).arrayBuffer();
			return new Uint8Array(buffer);
		} catch (err) {
			const message = err instanceof Error ? `Failed to deflate ZIP entry: ${err.message}` : "Unknown decompression error in ZIP entry";
			throw new TypeError(message);
		}
	}
	async readLocalFileHeader() {
		const signature = await this.tokenizer.peekToken(UINT32_LE);
		if (signature === Signature.LocalFileHeader) {
			const header = await this.tokenizer.readToken(LocalFileHeaderToken);
			header.filename = await this.tokenizer.readToken(new StringType(header.filenameLength, "utf-8"));
			return header;
		}
		if (signature === Signature.CentralFileHeader) return false;
		if (signature === 3759263696) throw new Error("Encrypted ZIP");
		throw new Error("Unexpected signature");
	}
};
function indexOf(buffer, portion) {
	const bufferLength = buffer.length;
	const portionLength = portion.length;
	if (portionLength > bufferLength) return -1;
	for (let i = 0; i <= bufferLength - portionLength; i++) {
		let found = true;
		for (let j = 0; j < portionLength; j++) if (buffer[i + j] !== portion[j]) {
			found = false;
			break;
		}
		if (found) return i;
	}
	return -1;
}
function mergeArrays(chunks) {
	const totalLength = chunks.reduce((acc, curr) => acc + curr.length, 0);
	const mergedArray = new Uint8Array(totalLength);
	let offset = 0;
	for (const chunk of chunks) {
		mergedArray.set(chunk, offset);
		offset += chunk.length;
	}
	return mergedArray;
}

//#endregion
//#region node_modules/.pnpm/@tokenizer+inflate@0.4.1/node_modules/@tokenizer/inflate/lib/GzipHandler.js
var GzipHandler = class {
	constructor(tokenizer) {
		this.tokenizer = tokenizer;
	}
	inflate() {
		const tokenizer = this.tokenizer;
		return new ReadableStream({ async pull(controller) {
			const buffer = new Uint8Array(1024);
			const size = await tokenizer.readBuffer(buffer, { mayBeLess: true });
			if (size === 0) {
				controller.close();
				return;
			}
			controller.enqueue(buffer.subarray(0, size));
		} }).pipeThrough(new DecompressionStream("gzip"));
	}
};

//#endregion
//#region node_modules/.pnpm/file-type@21.3.0/node_modules/file-type/util.js
function stringToBytes(string, encoding) {
	if (encoding === "utf-16le") {
		const bytes = [];
		for (let index = 0; index < string.length; index++) {
			const code = string.charCodeAt(index);
			bytes.push(code & 255, code >> 8 & 255);
		}
		return bytes;
	}
	if (encoding === "utf-16be") {
		const bytes = [];
		for (let index = 0; index < string.length; index++) {
			const code = string.charCodeAt(index);
			bytes.push(code >> 8 & 255, code & 255);
		}
		return bytes;
	}
	return [...string].map((character) => character.charCodeAt(0));
}
/**
Checks whether the TAR checksum is valid.

@param {Uint8Array} arrayBuffer - The TAR header `[offset ... offset + 512]`.
@param {number} offset - TAR header offset.
@returns {boolean} `true` if the TAR checksum is valid, otherwise `false`.
*/
function tarHeaderChecksumMatches(arrayBuffer, offset = 0) {
	const readSum = Number.parseInt(new StringType(6).get(arrayBuffer, 148).replace(/\0.*$/, "").trim(), 8);
	if (Number.isNaN(readSum)) return false;
	let sum = 256;
	for (let index = offset; index < offset + 148; index++) sum += arrayBuffer[index];
	for (let index = offset + 156; index < offset + 512; index++) sum += arrayBuffer[index];
	return readSum === sum;
}
/**
ID3 UINT32 sync-safe tokenizer token.
28 bits (representing up to 256MB) integer, the msb is 0 to avoid "false syncsignals".
*/
const uint32SyncSafeToken = {
	get: (buffer, offset) => buffer[offset + 3] & 127 | buffer[offset + 2] << 7 | buffer[offset + 1] << 14 | buffer[offset] << 21,
	len: 4
};

//#endregion
//#region node_modules/.pnpm/file-type@21.3.0/node_modules/file-type/supported.js
const extensions = [
	"jpg",
	"png",
	"apng",
	"gif",
	"webp",
	"flif",
	"xcf",
	"cr2",
	"cr3",
	"orf",
	"arw",
	"dng",
	"nef",
	"rw2",
	"raf",
	"tif",
	"bmp",
	"icns",
	"jxr",
	"psd",
	"indd",
	"zip",
	"tar",
	"rar",
	"gz",
	"bz2",
	"7z",
	"dmg",
	"mp4",
	"mid",
	"mkv",
	"webm",
	"mov",
	"avi",
	"mpg",
	"mp2",
	"mp3",
	"m4a",
	"oga",
	"ogg",
	"ogv",
	"opus",
	"flac",
	"wav",
	"spx",
	"amr",
	"pdf",
	"epub",
	"elf",
	"macho",
	"exe",
	"swf",
	"rtf",
	"wasm",
	"woff",
	"woff2",
	"eot",
	"ttf",
	"otf",
	"ttc",
	"ico",
	"flv",
	"ps",
	"xz",
	"sqlite",
	"nes",
	"crx",
	"xpi",
	"cab",
	"deb",
	"ar",
	"rpm",
	"Z",
	"lz",
	"cfb",
	"mxf",
	"mts",
	"blend",
	"bpg",
	"docx",
	"pptx",
	"xlsx",
	"3gp",
	"3g2",
	"j2c",
	"jp2",
	"jpm",
	"jpx",
	"mj2",
	"aif",
	"qcp",
	"odt",
	"ods",
	"odp",
	"xml",
	"mobi",
	"heic",
	"cur",
	"ktx",
	"ape",
	"wv",
	"dcm",
	"ics",
	"glb",
	"pcap",
	"dsf",
	"lnk",
	"alias",
	"voc",
	"ac3",
	"m4v",
	"m4p",
	"m4b",
	"f4v",
	"f4p",
	"f4b",
	"f4a",
	"mie",
	"asf",
	"ogm",
	"ogx",
	"mpc",
	"arrow",
	"shp",
	"aac",
	"mp1",
	"it",
	"s3m",
	"xm",
	"skp",
	"avif",
	"eps",
	"lzh",
	"pgp",
	"asar",
	"stl",
	"chm",
	"3mf",
	"zst",
	"jxl",
	"vcf",
	"jls",
	"pst",
	"dwg",
	"parquet",
	"class",
	"arj",
	"cpio",
	"ace",
	"avro",
	"icc",
	"fbx",
	"vsdx",
	"vtt",
	"apk",
	"drc",
	"lz4",
	"potx",
	"xltx",
	"dotx",
	"xltm",
	"ott",
	"ots",
	"otp",
	"odg",
	"otg",
	"xlsm",
	"docm",
	"dotm",
	"potm",
	"pptm",
	"jar",
	"jmp",
	"rm",
	"sav",
	"ppsm",
	"ppsx",
	"tar.gz",
	"reg",
	"dat"
];
const mimeTypes = [
	"image/jpeg",
	"image/png",
	"image/gif",
	"image/webp",
	"image/flif",
	"image/x-xcf",
	"image/x-canon-cr2",
	"image/x-canon-cr3",
	"image/tiff",
	"image/bmp",
	"image/vnd.ms-photo",
	"image/vnd.adobe.photoshop",
	"application/x-indesign",
	"application/epub+zip",
	"application/x-xpinstall",
	"application/vnd.ms-powerpoint.slideshow.macroenabled.12",
	"application/vnd.oasis.opendocument.text",
	"application/vnd.oasis.opendocument.spreadsheet",
	"application/vnd.oasis.opendocument.presentation",
	"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
	"application/vnd.openxmlformats-officedocument.presentationml.presentation",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
	"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
	"application/zip",
	"application/x-tar",
	"application/x-rar-compressed",
	"application/gzip",
	"application/x-bzip2",
	"application/x-7z-compressed",
	"application/x-apple-diskimage",
	"application/vnd.apache.arrow.file",
	"video/mp4",
	"audio/midi",
	"video/matroska",
	"video/webm",
	"video/quicktime",
	"video/vnd.avi",
	"audio/wav",
	"audio/qcelp",
	"audio/x-ms-asf",
	"video/x-ms-asf",
	"application/vnd.ms-asf",
	"video/mpeg",
	"video/3gpp",
	"audio/mpeg",
	"audio/mp4",
	"video/ogg",
	"audio/ogg",
	"audio/ogg; codecs=opus",
	"application/ogg",
	"audio/flac",
	"audio/ape",
	"audio/wavpack",
	"audio/amr",
	"application/pdf",
	"application/x-elf",
	"application/x-mach-binary",
	"application/x-msdownload",
	"application/x-shockwave-flash",
	"application/rtf",
	"application/wasm",
	"font/woff",
	"font/woff2",
	"application/vnd.ms-fontobject",
	"font/ttf",
	"font/otf",
	"font/collection",
	"image/x-icon",
	"video/x-flv",
	"application/postscript",
	"application/eps",
	"application/x-xz",
	"application/x-sqlite3",
	"application/x-nintendo-nes-rom",
	"application/x-google-chrome-extension",
	"application/vnd.ms-cab-compressed",
	"application/x-deb",
	"application/x-unix-archive",
	"application/x-rpm",
	"application/x-compress",
	"application/x-lzip",
	"application/x-cfb",
	"application/x-mie",
	"application/mxf",
	"video/mp2t",
	"application/x-blender",
	"image/bpg",
	"image/j2c",
	"image/jp2",
	"image/jpx",
	"image/jpm",
	"image/mj2",
	"audio/aiff",
	"application/xml",
	"application/x-mobipocket-ebook",
	"image/heif",
	"image/heif-sequence",
	"image/heic",
	"image/heic-sequence",
	"image/icns",
	"image/ktx",
	"application/dicom",
	"audio/x-musepack",
	"text/calendar",
	"text/vcard",
	"text/vtt",
	"model/gltf-binary",
	"application/vnd.tcpdump.pcap",
	"audio/x-dsf",
	"application/x.ms.shortcut",
	"application/x.apple.alias",
	"audio/x-voc",
	"audio/vnd.dolby.dd-raw",
	"audio/x-m4a",
	"image/apng",
	"image/x-olympus-orf",
	"image/x-sony-arw",
	"image/x-adobe-dng",
	"image/x-nikon-nef",
	"image/x-panasonic-rw2",
	"image/x-fujifilm-raf",
	"video/x-m4v",
	"video/3gpp2",
	"application/x-esri-shape",
	"audio/aac",
	"audio/x-it",
	"audio/x-s3m",
	"audio/x-xm",
	"video/MP1S",
	"video/MP2P",
	"application/vnd.sketchup.skp",
	"image/avif",
	"application/x-lzh-compressed",
	"application/pgp-encrypted",
	"application/x-asar",
	"model/stl",
	"application/vnd.ms-htmlhelp",
	"model/3mf",
	"image/jxl",
	"application/zstd",
	"image/jls",
	"application/vnd.ms-outlook",
	"image/vnd.dwg",
	"application/vnd.apache.parquet",
	"application/java-vm",
	"application/x-arj",
	"application/x-cpio",
	"application/x-ace-compressed",
	"application/avro",
	"application/vnd.iccprofile",
	"application/x.autodesk.fbx",
	"application/vnd.visio",
	"application/vnd.android.package-archive",
	"application/vnd.google.draco",
	"application/x-lz4",
	"application/vnd.openxmlformats-officedocument.presentationml.template",
	"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
	"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
	"application/vnd.ms-excel.template.macroenabled.12",
	"application/vnd.oasis.opendocument.text-template",
	"application/vnd.oasis.opendocument.spreadsheet-template",
	"application/vnd.oasis.opendocument.presentation-template",
	"application/vnd.oasis.opendocument.graphics",
	"application/vnd.oasis.opendocument.graphics-template",
	"application/vnd.ms-excel.sheet.macroenabled.12",
	"application/vnd.ms-word.document.macroenabled.12",
	"application/vnd.ms-word.template.macroenabled.12",
	"application/vnd.ms-powerpoint.template.macroenabled.12",
	"application/vnd.ms-powerpoint.presentation.macroenabled.12",
	"application/java-archive",
	"application/vnd.rn-realmedia",
	"application/x-spss-sav",
	"application/x-ms-regedit",
	"application/x-ft-windows-registry-hive",
	"application/x-jmp-data"
];

//#endregion
//#region node_modules/.pnpm/file-type@21.3.0/node_modules/file-type/core.js
/**
Primary entry point, Node.js specific entry point is index.js
*/
const reasonableDetectionSizeInBytes = 4100;
async function fileTypeFromBuffer(input, options) {
	return new FileTypeParser(options).fromBuffer(input);
}
function getFileTypeFromMimeType(mimeType) {
	mimeType = mimeType.toLowerCase();
	switch (mimeType) {
		case "application/epub+zip": return {
			ext: "epub",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.text": return {
			ext: "odt",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.text-template": return {
			ext: "ott",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.spreadsheet": return {
			ext: "ods",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.spreadsheet-template": return {
			ext: "ots",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.presentation": return {
			ext: "odp",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.presentation-template": return {
			ext: "otp",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.graphics": return {
			ext: "odg",
			mime: mimeType
		};
		case "application/vnd.oasis.opendocument.graphics-template": return {
			ext: "otg",
			mime: mimeType
		};
		case "application/vnd.openxmlformats-officedocument.presentationml.slideshow": return {
			ext: "ppsx",
			mime: mimeType
		};
		case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": return {
			ext: "xlsx",
			mime: mimeType
		};
		case "application/vnd.ms-excel.sheet.macroenabled": return {
			ext: "xlsm",
			mime: "application/vnd.ms-excel.sheet.macroenabled.12"
		};
		case "application/vnd.openxmlformats-officedocument.spreadsheetml.template": return {
			ext: "xltx",
			mime: mimeType
		};
		case "application/vnd.ms-excel.template.macroenabled": return {
			ext: "xltm",
			mime: "application/vnd.ms-excel.template.macroenabled.12"
		};
		case "application/vnd.ms-powerpoint.slideshow.macroenabled": return {
			ext: "ppsm",
			mime: "application/vnd.ms-powerpoint.slideshow.macroenabled.12"
		};
		case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": return {
			ext: "docx",
			mime: mimeType
		};
		case "application/vnd.ms-word.document.macroenabled": return {
			ext: "docm",
			mime: "application/vnd.ms-word.document.macroenabled.12"
		};
		case "application/vnd.openxmlformats-officedocument.wordprocessingml.template": return {
			ext: "dotx",
			mime: mimeType
		};
		case "application/vnd.ms-word.template.macroenabledtemplate": return {
			ext: "dotm",
			mime: "application/vnd.ms-word.template.macroenabled.12"
		};
		case "application/vnd.openxmlformats-officedocument.presentationml.template": return {
			ext: "potx",
			mime: mimeType
		};
		case "application/vnd.ms-powerpoint.template.macroenabled": return {
			ext: "potm",
			mime: "application/vnd.ms-powerpoint.template.macroenabled.12"
		};
		case "application/vnd.openxmlformats-officedocument.presentationml.presentation": return {
			ext: "pptx",
			mime: mimeType
		};
		case "application/vnd.ms-powerpoint.presentation.macroenabled": return {
			ext: "pptm",
			mime: "application/vnd.ms-powerpoint.presentation.macroenabled.12"
		};
		case "application/vnd.ms-visio.drawing": return {
			ext: "vsdx",
			mime: "application/vnd.visio"
		};
		case "application/vnd.ms-package.3dmanufacturing-3dmodel+xml": return {
			ext: "3mf",
			mime: "model/3mf"
		};
		default:
	}
}
function _check(buffer, headers, options) {
	options = {
		offset: 0,
		...options
	};
	for (const [index, header] of headers.entries()) if (options.mask) {
		if (header !== (options.mask[index] & buffer[index + options.offset])) return false;
	} else if (header !== buffer[index + options.offset]) return false;
	return true;
}
var FileTypeParser = class {
	constructor(options) {
		this.options = {
			mpegOffsetTolerance: 0,
			...options
		};
		this.detectors = [
			...options?.customDetectors ?? [],
			{
				id: "core",
				detect: this.detectConfident
			},
			{
				id: "core.imprecise",
				detect: this.detectImprecise
			}
		];
		this.tokenizerOptions = { abortSignal: options?.signal };
	}
	async fromTokenizer(tokenizer) {
		const initialPosition = tokenizer.position;
		for (const detector of this.detectors) {
			const fileType = await detector.detect(tokenizer);
			if (fileType) return fileType;
			if (initialPosition !== tokenizer.position) return;
		}
	}
	async fromBuffer(input) {
		if (!(input instanceof Uint8Array || input instanceof ArrayBuffer)) throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`ArrayBuffer\`, got \`${typeof input}\``);
		const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
		if (!(buffer?.length > 1)) return;
		return this.fromTokenizer(fromBuffer(buffer, this.tokenizerOptions));
	}
	async fromBlob(blob) {
		const tokenizer = fromBlob(blob, this.tokenizerOptions);
		try {
			return await this.fromTokenizer(tokenizer);
		} finally {
			await tokenizer.close();
		}
	}
	async fromStream(stream) {
		const tokenizer = fromWebStream(stream, this.tokenizerOptions);
		try {
			return await this.fromTokenizer(tokenizer);
		} finally {
			await tokenizer.close();
		}
	}
	async toDetectionStream(stream, options) {
		const { sampleSize = reasonableDetectionSizeInBytes } = options;
		let detectedFileType;
		let firstChunk;
		const reader = stream.getReader({ mode: "byob" });
		try {
			const { value: chunk, done } = await reader.read(new Uint8Array(sampleSize));
			firstChunk = chunk;
			if (!done && chunk) try {
				detectedFileType = await this.fromBuffer(chunk.subarray(0, sampleSize));
			} catch (error) {
				if (!(error instanceof EndOfStreamError)) throw error;
				detectedFileType = void 0;
			}
			firstChunk = chunk;
		} finally {
			reader.releaseLock();
		}
		const transformStream = new TransformStream({
			async start(controller) {
				controller.enqueue(firstChunk);
			},
			transform(chunk, controller) {
				controller.enqueue(chunk);
			}
		});
		const newStream = stream.pipeThrough(transformStream);
		newStream.fileType = detectedFileType;
		return newStream;
	}
	check(header, options) {
		return _check(this.buffer, header, options);
	}
	checkString(header, options) {
		return this.check(stringToBytes(header, options?.encoding), options);
	}
	detectConfident = async (tokenizer) => {
		this.buffer = new Uint8Array(reasonableDetectionSizeInBytes);
		if (tokenizer.fileInfo.size === void 0) tokenizer.fileInfo.size = Number.MAX_SAFE_INTEGER;
		this.tokenizer = tokenizer;
		await tokenizer.peekBuffer(this.buffer, {
			length: 32,
			mayBeLess: true
		});
		if (this.check([66, 77])) return {
			ext: "bmp",
			mime: "image/bmp"
		};
		if (this.check([11, 119])) return {
			ext: "ac3",
			mime: "audio/vnd.dolby.dd-raw"
		};
		if (this.check([120, 1])) return {
			ext: "dmg",
			mime: "application/x-apple-diskimage"
		};
		if (this.check([77, 90])) return {
			ext: "exe",
			mime: "application/x-msdownload"
		};
		if (this.check([37, 33])) {
			await tokenizer.peekBuffer(this.buffer, {
				length: 24,
				mayBeLess: true
			});
			if (this.checkString("PS-Adobe-", { offset: 2 }) && this.checkString(" EPSF-", { offset: 14 })) return {
				ext: "eps",
				mime: "application/eps"
			};
			return {
				ext: "ps",
				mime: "application/postscript"
			};
		}
		if (this.check([31, 160]) || this.check([31, 157])) return {
			ext: "Z",
			mime: "application/x-compress"
		};
		if (this.check([199, 113])) return {
			ext: "cpio",
			mime: "application/x-cpio"
		};
		if (this.check([96, 234])) return {
			ext: "arj",
			mime: "application/x-arj"
		};
		if (this.check([
			239,
			187,
			191
		])) {
			this.tokenizer.ignore(3);
			return this.detectConfident(tokenizer);
		}
		if (this.check([
			71,
			73,
			70
		])) return {
			ext: "gif",
			mime: "image/gif"
		};
		if (this.check([
			73,
			73,
			188
		])) return {
			ext: "jxr",
			mime: "image/vnd.ms-photo"
		};
		if (this.check([
			31,
			139,
			8
		])) {
			const stream = new GzipHandler(tokenizer).inflate();
			let shouldCancelStream = true;
			try {
				let compressedFileType;
				try {
					compressedFileType = await this.fromStream(stream);
				} catch {
					shouldCancelStream = false;
				}
				if (compressedFileType && compressedFileType.ext === "tar") return {
					ext: "tar.gz",
					mime: "application/gzip"
				};
			} finally {
				if (shouldCancelStream) await stream.cancel();
			}
			return {
				ext: "gz",
				mime: "application/gzip"
			};
		}
		if (this.check([
			66,
			90,
			104
		])) return {
			ext: "bz2",
			mime: "application/x-bzip2"
		};
		if (this.checkString("ID3")) {
			await tokenizer.ignore(6);
			const id3HeaderLength = await tokenizer.readToken(uint32SyncSafeToken);
			if (tokenizer.position + id3HeaderLength > tokenizer.fileInfo.size) return {
				ext: "mp3",
				mime: "audio/mpeg"
			};
			await tokenizer.ignore(id3HeaderLength);
			return this.fromTokenizer(tokenizer);
		}
		if (this.checkString("MP+")) return {
			ext: "mpc",
			mime: "audio/x-musepack"
		};
		if ((this.buffer[0] === 67 || this.buffer[0] === 70) && this.check([87, 83], { offset: 1 })) return {
			ext: "swf",
			mime: "application/x-shockwave-flash"
		};
		if (this.check([
			255,
			216,
			255
		])) {
			if (this.check([247], { offset: 3 })) return {
				ext: "jls",
				mime: "image/jls"
			};
			return {
				ext: "jpg",
				mime: "image/jpeg"
			};
		}
		if (this.check([
			79,
			98,
			106,
			1
		])) return {
			ext: "avro",
			mime: "application/avro"
		};
		if (this.checkString("FLIF")) return {
			ext: "flif",
			mime: "image/flif"
		};
		if (this.checkString("8BPS")) return {
			ext: "psd",
			mime: "image/vnd.adobe.photoshop"
		};
		if (this.checkString("MPCK")) return {
			ext: "mpc",
			mime: "audio/x-musepack"
		};
		if (this.checkString("FORM")) return {
			ext: "aif",
			mime: "audio/aiff"
		};
		if (this.checkString("icns", { offset: 0 })) return {
			ext: "icns",
			mime: "image/icns"
		};
		if (this.check([
			80,
			75,
			3,
			4
		])) {
			let fileType;
			await new ZipHandler(tokenizer).unzip((zipHeader) => {
				switch (zipHeader.filename) {
					case "META-INF/mozilla.rsa":
						fileType = {
							ext: "xpi",
							mime: "application/x-xpinstall"
						};
						return { stop: true };
					case "META-INF/MANIFEST.MF":
						fileType = {
							ext: "jar",
							mime: "application/java-archive"
						};
						return { stop: true };
					case "mimetype": return {
						async handler(fileData) {
							fileType = getFileTypeFromMimeType(new TextDecoder("utf-8").decode(fileData).trim());
						},
						stop: true
					};
					case "[Content_Types].xml": return {
						async handler(fileData) {
							let xmlContent = new TextDecoder("utf-8").decode(fileData);
							const endPos = xmlContent.indexOf(".main+xml\"");
							if (endPos === -1) {
								const mimeType = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml";
								if (xmlContent.includes(`ContentType="${mimeType}"`)) fileType = getFileTypeFromMimeType(mimeType);
							} else {
								xmlContent = xmlContent.slice(0, Math.max(0, endPos));
								const firstPos = xmlContent.lastIndexOf("\"");
								fileType = getFileTypeFromMimeType(xmlContent.slice(Math.max(0, firstPos + 1)));
							}
						},
						stop: true
					};
					default:
						if (/classes\d*\.dex/.test(zipHeader.filename)) {
							fileType = {
								ext: "apk",
								mime: "application/vnd.android.package-archive"
							};
							return { stop: true };
						}
						return {};
				}
			}).catch((error) => {
				if (!(error instanceof EndOfStreamError)) throw error;
			});
			return fileType ?? {
				ext: "zip",
				mime: "application/zip"
			};
		}
		if (this.checkString("OggS")) {
			await tokenizer.ignore(28);
			const type = new Uint8Array(8);
			await tokenizer.readBuffer(type);
			if (_check(type, [
				79,
				112,
				117,
				115,
				72,
				101,
				97,
				100
			])) return {
				ext: "opus",
				mime: "audio/ogg; codecs=opus"
			};
			if (_check(type, [
				128,
				116,
				104,
				101,
				111,
				114,
				97
			])) return {
				ext: "ogv",
				mime: "video/ogg"
			};
			if (_check(type, [
				1,
				118,
				105,
				100,
				101,
				111,
				0
			])) return {
				ext: "ogm",
				mime: "video/ogg"
			};
			if (_check(type, [
				127,
				70,
				76,
				65,
				67
			])) return {
				ext: "oga",
				mime: "audio/ogg"
			};
			if (_check(type, [
				83,
				112,
				101,
				101,
				120,
				32,
				32
			])) return {
				ext: "spx",
				mime: "audio/ogg"
			};
			if (_check(type, [
				1,
				118,
				111,
				114,
				98,
				105,
				115
			])) return {
				ext: "ogg",
				mime: "audio/ogg"
			};
			return {
				ext: "ogx",
				mime: "application/ogg"
			};
		}
		if (this.check([80, 75]) && (this.buffer[2] === 3 || this.buffer[2] === 5 || this.buffer[2] === 7) && (this.buffer[3] === 4 || this.buffer[3] === 6 || this.buffer[3] === 8)) return {
			ext: "zip",
			mime: "application/zip"
		};
		if (this.checkString("MThd")) return {
			ext: "mid",
			mime: "audio/midi"
		};
		if (this.checkString("wOFF") && (this.check([
			0,
			1,
			0,
			0
		], { offset: 4 }) || this.checkString("OTTO", { offset: 4 }))) return {
			ext: "woff",
			mime: "font/woff"
		};
		if (this.checkString("wOF2") && (this.check([
			0,
			1,
			0,
			0
		], { offset: 4 }) || this.checkString("OTTO", { offset: 4 }))) return {
			ext: "woff2",
			mime: "font/woff2"
		};
		if (this.check([
			212,
			195,
			178,
			161
		]) || this.check([
			161,
			178,
			195,
			212
		])) return {
			ext: "pcap",
			mime: "application/vnd.tcpdump.pcap"
		};
		if (this.checkString("DSD ")) return {
			ext: "dsf",
			mime: "audio/x-dsf"
		};
		if (this.checkString("LZIP")) return {
			ext: "lz",
			mime: "application/x-lzip"
		};
		if (this.checkString("fLaC")) return {
			ext: "flac",
			mime: "audio/flac"
		};
		if (this.check([
			66,
			80,
			71,
			251
		])) return {
			ext: "bpg",
			mime: "image/bpg"
		};
		if (this.checkString("wvpk")) return {
			ext: "wv",
			mime: "audio/wavpack"
		};
		if (this.checkString("%PDF")) return {
			ext: "pdf",
			mime: "application/pdf"
		};
		if (this.check([
			0,
			97,
			115,
			109
		])) return {
			ext: "wasm",
			mime: "application/wasm"
		};
		if (this.check([73, 73])) {
			const fileType = await this.readTiffHeader(false);
			if (fileType) return fileType;
		}
		if (this.check([77, 77])) {
			const fileType = await this.readTiffHeader(true);
			if (fileType) return fileType;
		}
		if (this.checkString("MAC ")) return {
			ext: "ape",
			mime: "audio/ape"
		};
		if (this.check([
			26,
			69,
			223,
			163
		])) {
			async function readField() {
				const msb = await tokenizer.peekNumber(UINT8);
				let mask = 128;
				let ic = 0;
				while ((msb & mask) === 0 && mask !== 0) {
					++ic;
					mask >>= 1;
				}
				const id = new Uint8Array(ic + 1);
				await tokenizer.readBuffer(id);
				return id;
			}
			async function readElement() {
				const idField = await readField();
				const lengthField = await readField();
				lengthField[0] ^= 128 >> lengthField.length - 1;
				const nrLength = Math.min(6, lengthField.length);
				const idView = new DataView(idField.buffer);
				const lengthView = new DataView(lengthField.buffer, lengthField.length - nrLength, nrLength);
				return {
					id: getUintBE(idView),
					len: getUintBE(lengthView)
				};
			}
			async function readChildren(children) {
				while (children > 0) {
					const element = await readElement();
					if (element.id === 17026) return (await tokenizer.readToken(new StringType(element.len))).replaceAll(/\00.*$/g, "");
					await tokenizer.ignore(element.len);
					--children;
				}
			}
			switch (await readChildren((await readElement()).len)) {
				case "webm": return {
					ext: "webm",
					mime: "video/webm"
				};
				case "matroska": return {
					ext: "mkv",
					mime: "video/matroska"
				};
				default: return;
			}
		}
		if (this.checkString("SQLi")) return {
			ext: "sqlite",
			mime: "application/x-sqlite3"
		};
		if (this.check([
			78,
			69,
			83,
			26
		])) return {
			ext: "nes",
			mime: "application/x-nintendo-nes-rom"
		};
		if (this.checkString("Cr24")) return {
			ext: "crx",
			mime: "application/x-google-chrome-extension"
		};
		if (this.checkString("MSCF") || this.checkString("ISc(")) return {
			ext: "cab",
			mime: "application/vnd.ms-cab-compressed"
		};
		if (this.check([
			237,
			171,
			238,
			219
		])) return {
			ext: "rpm",
			mime: "application/x-rpm"
		};
		if (this.check([
			197,
			208,
			211,
			198
		])) return {
			ext: "eps",
			mime: "application/eps"
		};
		if (this.check([
			40,
			181,
			47,
			253
		])) return {
			ext: "zst",
			mime: "application/zstd"
		};
		if (this.check([
			127,
			69,
			76,
			70
		])) return {
			ext: "elf",
			mime: "application/x-elf"
		};
		if (this.check([
			33,
			66,
			68,
			78
		])) return {
			ext: "pst",
			mime: "application/vnd.ms-outlook"
		};
		if (this.checkString("PAR1") || this.checkString("PARE")) return {
			ext: "parquet",
			mime: "application/vnd.apache.parquet"
		};
		if (this.checkString("ttcf")) return {
			ext: "ttc",
			mime: "font/collection"
		};
		if (this.check([
			254,
			237,
			250,
			206
		]) || this.check([
			254,
			237,
			250,
			207
		]) || this.check([
			206,
			250,
			237,
			254
		]) || this.check([
			207,
			250,
			237,
			254
		])) return {
			ext: "macho",
			mime: "application/x-mach-binary"
		};
		if (this.check([
			4,
			34,
			77,
			24
		])) return {
			ext: "lz4",
			mime: "application/x-lz4"
		};
		if (this.checkString("regf")) return {
			ext: "dat",
			mime: "application/x-ft-windows-registry-hive"
		};
		if (this.checkString("$FL2") || this.checkString("$FL3")) return {
			ext: "sav",
			mime: "application/x-spss-sav"
		};
		if (this.check([
			79,
			84,
			84,
			79,
			0
		])) return {
			ext: "otf",
			mime: "font/otf"
		};
		if (this.checkString("#!AMR")) return {
			ext: "amr",
			mime: "audio/amr"
		};
		if (this.checkString("{\\rtf")) return {
			ext: "rtf",
			mime: "application/rtf"
		};
		if (this.check([
			70,
			76,
			86,
			1
		])) return {
			ext: "flv",
			mime: "video/x-flv"
		};
		if (this.checkString("IMPM")) return {
			ext: "it",
			mime: "audio/x-it"
		};
		if (this.checkString("-lh0-", { offset: 2 }) || this.checkString("-lh1-", { offset: 2 }) || this.checkString("-lh2-", { offset: 2 }) || this.checkString("-lh3-", { offset: 2 }) || this.checkString("-lh4-", { offset: 2 }) || this.checkString("-lh5-", { offset: 2 }) || this.checkString("-lh6-", { offset: 2 }) || this.checkString("-lh7-", { offset: 2 }) || this.checkString("-lzs-", { offset: 2 }) || this.checkString("-lz4-", { offset: 2 }) || this.checkString("-lz5-", { offset: 2 }) || this.checkString("-lhd-", { offset: 2 })) return {
			ext: "lzh",
			mime: "application/x-lzh-compressed"
		};
		if (this.check([
			0,
			0,
			1,
			186
		])) {
			if (this.check([33], {
				offset: 4,
				mask: [241]
			})) return {
				ext: "mpg",
				mime: "video/MP1S"
			};
			if (this.check([68], {
				offset: 4,
				mask: [196]
			})) return {
				ext: "mpg",
				mime: "video/MP2P"
			};
		}
		if (this.checkString("ITSF")) return {
			ext: "chm",
			mime: "application/vnd.ms-htmlhelp"
		};
		if (this.check([
			202,
			254,
			186,
			190
		])) {
			const machOArchitectureCount = UINT32_BE.get(this.buffer, 4);
			const javaClassFileMajorVersion = UINT16_BE.get(this.buffer, 6);
			if (machOArchitectureCount > 0 && machOArchitectureCount <= 30) return {
				ext: "macho",
				mime: "application/x-mach-binary"
			};
			if (javaClassFileMajorVersion > 30) return {
				ext: "class",
				mime: "application/java-vm"
			};
		}
		if (this.checkString(".RMF")) return {
			ext: "rm",
			mime: "application/vnd.rn-realmedia"
		};
		if (this.checkString("DRACO")) return {
			ext: "drc",
			mime: "application/vnd.google.draco"
		};
		if (this.check([
			253,
			55,
			122,
			88,
			90,
			0
		])) return {
			ext: "xz",
			mime: "application/x-xz"
		};
		if (this.checkString("<?xml ")) return {
			ext: "xml",
			mime: "application/xml"
		};
		if (this.check([
			55,
			122,
			188,
			175,
			39,
			28
		])) return {
			ext: "7z",
			mime: "application/x-7z-compressed"
		};
		if (this.check([
			82,
			97,
			114,
			33,
			26,
			7
		]) && (this.buffer[6] === 0 || this.buffer[6] === 1)) return {
			ext: "rar",
			mime: "application/x-rar-compressed"
		};
		if (this.checkString("solid ")) return {
			ext: "stl",
			mime: "model/stl"
		};
		if (this.checkString("AC")) {
			const version = new StringType(4, "latin1").get(this.buffer, 2);
			if (version.match("^d*") && version >= 1e3 && version <= 1050) return {
				ext: "dwg",
				mime: "image/vnd.dwg"
			};
		}
		if (this.checkString("070707")) return {
			ext: "cpio",
			mime: "application/x-cpio"
		};
		if (this.checkString("BLENDER")) return {
			ext: "blend",
			mime: "application/x-blender"
		};
		if (this.checkString("!<arch>")) {
			await tokenizer.ignore(8);
			if (await tokenizer.readToken(new StringType(13, "ascii")) === "debian-binary") return {
				ext: "deb",
				mime: "application/x-deb"
			};
			return {
				ext: "ar",
				mime: "application/x-unix-archive"
			};
		}
		if (this.checkString("WEBVTT") && [
			"\n",
			"\r",
			"	",
			" ",
			"\0"
		].some((char7) => this.checkString(char7, { offset: 6 }))) return {
			ext: "vtt",
			mime: "text/vtt"
		};
		if (this.check([
			137,
			80,
			78,
			71,
			13,
			10,
			26,
			10
		])) {
			await tokenizer.ignore(8);
			async function readChunkHeader() {
				return {
					length: await tokenizer.readToken(INT32_BE),
					type: await tokenizer.readToken(new StringType(4, "latin1"))
				};
			}
			do {
				const chunk = await readChunkHeader();
				if (chunk.length < 0) return;
				switch (chunk.type) {
					case "IDAT": return {
						ext: "png",
						mime: "image/png"
					};
					case "acTL": return {
						ext: "apng",
						mime: "image/apng"
					};
					default: await tokenizer.ignore(chunk.length + 4);
				}
			} while (tokenizer.position + 8 < tokenizer.fileInfo.size);
			return {
				ext: "png",
				mime: "image/png"
			};
		}
		if (this.check([
			65,
			82,
			82,
			79,
			87,
			49,
			0,
			0
		])) return {
			ext: "arrow",
			mime: "application/vnd.apache.arrow.file"
		};
		if (this.check([
			103,
			108,
			84,
			70,
			2,
			0,
			0,
			0
		])) return {
			ext: "glb",
			mime: "model/gltf-binary"
		};
		if (this.check([
			102,
			114,
			101,
			101
		], { offset: 4 }) || this.check([
			109,
			100,
			97,
			116
		], { offset: 4 }) || this.check([
			109,
			111,
			111,
			118
		], { offset: 4 }) || this.check([
			119,
			105,
			100,
			101
		], { offset: 4 })) return {
			ext: "mov",
			mime: "video/quicktime"
		};
		if (this.check([
			73,
			73,
			82,
			79,
			8,
			0,
			0,
			0,
			24
		])) return {
			ext: "orf",
			mime: "image/x-olympus-orf"
		};
		if (this.checkString("gimp xcf ")) return {
			ext: "xcf",
			mime: "image/x-xcf"
		};
		if (this.checkString("ftyp", { offset: 4 }) && (this.buffer[8] & 96) !== 0) {
			const brandMajor = new StringType(4, "latin1").get(this.buffer, 8).replace("\0", " ").trim();
			switch (brandMajor) {
				case "avif":
				case "avis": return {
					ext: "avif",
					mime: "image/avif"
				};
				case "mif1": return {
					ext: "heic",
					mime: "image/heif"
				};
				case "msf1": return {
					ext: "heic",
					mime: "image/heif-sequence"
				};
				case "heic":
				case "heix": return {
					ext: "heic",
					mime: "image/heic"
				};
				case "hevc":
				case "hevx": return {
					ext: "heic",
					mime: "image/heic-sequence"
				};
				case "qt": return {
					ext: "mov",
					mime: "video/quicktime"
				};
				case "M4V":
				case "M4VH":
				case "M4VP": return {
					ext: "m4v",
					mime: "video/x-m4v"
				};
				case "M4P": return {
					ext: "m4p",
					mime: "video/mp4"
				};
				case "M4B": return {
					ext: "m4b",
					mime: "audio/mp4"
				};
				case "M4A": return {
					ext: "m4a",
					mime: "audio/x-m4a"
				};
				case "F4V": return {
					ext: "f4v",
					mime: "video/mp4"
				};
				case "F4P": return {
					ext: "f4p",
					mime: "video/mp4"
				};
				case "F4A": return {
					ext: "f4a",
					mime: "audio/mp4"
				};
				case "F4B": return {
					ext: "f4b",
					mime: "audio/mp4"
				};
				case "crx": return {
					ext: "cr3",
					mime: "image/x-canon-cr3"
				};
				default:
					if (brandMajor.startsWith("3g")) {
						if (brandMajor.startsWith("3g2")) return {
							ext: "3g2",
							mime: "video/3gpp2"
						};
						return {
							ext: "3gp",
							mime: "video/3gpp"
						};
					}
					return {
						ext: "mp4",
						mime: "video/mp4"
					};
			}
		}
		if (this.checkString("REGEDIT4\r\n")) return {
			ext: "reg",
			mime: "application/x-ms-regedit"
		};
		if (this.check([
			82,
			73,
			70,
			70
		])) {
			if (this.checkString("WEBP", { offset: 8 })) return {
				ext: "webp",
				mime: "image/webp"
			};
			if (this.check([
				65,
				86,
				73
			], { offset: 8 })) return {
				ext: "avi",
				mime: "video/vnd.avi"
			};
			if (this.check([
				87,
				65,
				86,
				69
			], { offset: 8 })) return {
				ext: "wav",
				mime: "audio/wav"
			};
			if (this.check([
				81,
				76,
				67,
				77
			], { offset: 8 })) return {
				ext: "qcp",
				mime: "audio/qcelp"
			};
		}
		if (this.check([
			73,
			73,
			85,
			0,
			24,
			0,
			0,
			0,
			136,
			231,
			116,
			216
		])) return {
			ext: "rw2",
			mime: "image/x-panasonic-rw2"
		};
		if (this.check([
			48,
			38,
			178,
			117,
			142,
			102,
			207,
			17,
			166,
			217
		])) {
			async function readHeader() {
				const guid = new Uint8Array(16);
				await tokenizer.readBuffer(guid);
				return {
					id: guid,
					size: Number(await tokenizer.readToken(UINT64_LE))
				};
			}
			await tokenizer.ignore(30);
			while (tokenizer.position + 24 < tokenizer.fileInfo.size) {
				const header = await readHeader();
				let payload = header.size - 24;
				if (_check(header.id, [
					145,
					7,
					220,
					183,
					183,
					169,
					207,
					17,
					142,
					230,
					0,
					192,
					12,
					32,
					83,
					101
				])) {
					const typeId = new Uint8Array(16);
					payload -= await tokenizer.readBuffer(typeId);
					if (_check(typeId, [
						64,
						158,
						105,
						248,
						77,
						91,
						207,
						17,
						168,
						253,
						0,
						128,
						95,
						92,
						68,
						43
					])) return {
						ext: "asf",
						mime: "audio/x-ms-asf"
					};
					if (_check(typeId, [
						192,
						239,
						25,
						188,
						77,
						91,
						207,
						17,
						168,
						253,
						0,
						128,
						95,
						92,
						68,
						43
					])) return {
						ext: "asf",
						mime: "video/x-ms-asf"
					};
					break;
				}
				await tokenizer.ignore(payload);
			}
			return {
				ext: "asf",
				mime: "application/vnd.ms-asf"
			};
		}
		if (this.check([
			171,
			75,
			84,
			88,
			32,
			49,
			49,
			187,
			13,
			10,
			26,
			10
		])) return {
			ext: "ktx",
			mime: "image/ktx"
		};
		if ((this.check([
			126,
			16,
			4
		]) || this.check([
			126,
			24,
			4
		])) && this.check([
			48,
			77,
			73,
			69
		], { offset: 4 })) return {
			ext: "mie",
			mime: "application/x-mie"
		};
		if (this.check([
			39,
			10,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0
		], { offset: 2 })) return {
			ext: "shp",
			mime: "application/x-esri-shape"
		};
		if (this.check([
			255,
			79,
			255,
			81
		])) return {
			ext: "j2c",
			mime: "image/j2c"
		};
		if (this.check([
			0,
			0,
			0,
			12,
			106,
			80,
			32,
			32,
			13,
			10,
			135,
			10
		])) {
			await tokenizer.ignore(20);
			switch (await tokenizer.readToken(new StringType(4, "ascii"))) {
				case "jp2 ": return {
					ext: "jp2",
					mime: "image/jp2"
				};
				case "jpx ": return {
					ext: "jpx",
					mime: "image/jpx"
				};
				case "jpm ": return {
					ext: "jpm",
					mime: "image/jpm"
				};
				case "mjp2": return {
					ext: "mj2",
					mime: "image/mj2"
				};
				default: return;
			}
		}
		if (this.check([255, 10]) || this.check([
			0,
			0,
			0,
			12,
			74,
			88,
			76,
			32,
			13,
			10,
			135,
			10
		])) return {
			ext: "jxl",
			mime: "image/jxl"
		};
		if (this.check([254, 255])) {
			if (this.checkString("<?xml ", {
				offset: 2,
				encoding: "utf-16be"
			})) return {
				ext: "xml",
				mime: "application/xml"
			};
			return;
		}
		if (this.check([
			208,
			207,
			17,
			224,
			161,
			177,
			26,
			225
		])) return {
			ext: "cfb",
			mime: "application/x-cfb"
		};
		await tokenizer.peekBuffer(this.buffer, {
			length: Math.min(256, tokenizer.fileInfo.size),
			mayBeLess: true
		});
		if (this.check([
			97,
			99,
			115,
			112
		], { offset: 36 })) return {
			ext: "icc",
			mime: "application/vnd.iccprofile"
		};
		if (this.checkString("**ACE", { offset: 7 }) && this.checkString("**", { offset: 12 })) return {
			ext: "ace",
			mime: "application/x-ace-compressed"
		};
		if (this.checkString("BEGIN:")) {
			if (this.checkString("VCARD", { offset: 6 })) return {
				ext: "vcf",
				mime: "text/vcard"
			};
			if (this.checkString("VCALENDAR", { offset: 6 })) return {
				ext: "ics",
				mime: "text/calendar"
			};
		}
		if (this.checkString("FUJIFILMCCD-RAW")) return {
			ext: "raf",
			mime: "image/x-fujifilm-raf"
		};
		if (this.checkString("Extended Module:")) return {
			ext: "xm",
			mime: "audio/x-xm"
		};
		if (this.checkString("Creative Voice File")) return {
			ext: "voc",
			mime: "audio/x-voc"
		};
		if (this.check([
			4,
			0,
			0,
			0
		]) && this.buffer.length >= 16) {
			const jsonSize = new DataView(this.buffer.buffer).getUint32(12, true);
			if (jsonSize > 12 && this.buffer.length >= jsonSize + 16) try {
				const header = new TextDecoder().decode(this.buffer.subarray(16, jsonSize + 16));
				if (JSON.parse(header).files) return {
					ext: "asar",
					mime: "application/x-asar"
				};
			} catch {}
		}
		if (this.check([
			6,
			14,
			43,
			52,
			2,
			5,
			1,
			1,
			13,
			1,
			2,
			1,
			1,
			2
		])) return {
			ext: "mxf",
			mime: "application/mxf"
		};
		if (this.checkString("SCRM", { offset: 44 })) return {
			ext: "s3m",
			mime: "audio/x-s3m"
		};
		if (this.check([71]) && this.check([71], { offset: 188 })) return {
			ext: "mts",
			mime: "video/mp2t"
		};
		if (this.check([71], { offset: 4 }) && this.check([71], { offset: 196 })) return {
			ext: "mts",
			mime: "video/mp2t"
		};
		if (this.check([
			66,
			79,
			79,
			75,
			77,
			79,
			66,
			73
		], { offset: 60 })) return {
			ext: "mobi",
			mime: "application/x-mobipocket-ebook"
		};
		if (this.check([
			68,
			73,
			67,
			77
		], { offset: 128 })) return {
			ext: "dcm",
			mime: "application/dicom"
		};
		if (this.check([
			76,
			0,
			0,
			0,
			1,
			20,
			2,
			0,
			0,
			0,
			0,
			0,
			192,
			0,
			0,
			0,
			0,
			0,
			0,
			70
		])) return {
			ext: "lnk",
			mime: "application/x.ms.shortcut"
		};
		if (this.check([
			98,
			111,
			111,
			107,
			0,
			0,
			0,
			0,
			109,
			97,
			114,
			107,
			0,
			0,
			0,
			0
		])) return {
			ext: "alias",
			mime: "application/x.apple.alias"
		};
		if (this.checkString("Kaydara FBX Binary  \0")) return {
			ext: "fbx",
			mime: "application/x.autodesk.fbx"
		};
		if (this.check([76, 80], { offset: 34 }) && (this.check([
			0,
			0,
			1
		], { offset: 8 }) || this.check([
			1,
			0,
			2
		], { offset: 8 }) || this.check([
			2,
			0,
			2
		], { offset: 8 }))) return {
			ext: "eot",
			mime: "application/vnd.ms-fontobject"
		};
		if (this.check([
			6,
			6,
			237,
			245,
			216,
			29,
			70,
			229,
			189,
			49,
			239,
			231,
			254,
			116,
			183,
			29
		])) return {
			ext: "indd",
			mime: "application/x-indesign"
		};
		if (this.check([
			255,
			255,
			0,
			0,
			7,
			0,
			0,
			0,
			4,
			0,
			0,
			0,
			1,
			0,
			1,
			0
		]) || this.check([
			0,
			0,
			255,
			255,
			0,
			0,
			0,
			7,
			0,
			0,
			0,
			4,
			0,
			1,
			0,
			1
		])) return {
			ext: "jmp",
			mime: "application/x-jmp-data"
		};
		await tokenizer.peekBuffer(this.buffer, {
			length: Math.min(512, tokenizer.fileInfo.size),
			mayBeLess: true
		});
		if (this.checkString("ustar", { offset: 257 }) && (this.checkString("\0", { offset: 262 }) || this.checkString(" ", { offset: 262 })) || this.check([
			0,
			0,
			0,
			0,
			0,
			0
		], { offset: 257 }) && tarHeaderChecksumMatches(this.buffer)) return {
			ext: "tar",
			mime: "application/x-tar"
		};
		if (this.check([255, 254])) {
			const encoding = "utf-16le";
			if (this.checkString("<?xml ", {
				offset: 2,
				encoding
			})) return {
				ext: "xml",
				mime: "application/xml"
			};
			if (this.check([255, 14], { offset: 2 }) && this.checkString("SketchUp Model", {
				offset: 4,
				encoding
			})) return {
				ext: "skp",
				mime: "application/vnd.sketchup.skp"
			};
			if (this.checkString("Windows Registry Editor Version 5.00\r\n", {
				offset: 2,
				encoding
			})) return {
				ext: "reg",
				mime: "application/x-ms-regedit"
			};
			return;
		}
		if (this.checkString("-----BEGIN PGP MESSAGE-----")) return {
			ext: "pgp",
			mime: "application/pgp-encrypted"
		};
	};
	detectImprecise = async (tokenizer) => {
		this.buffer = new Uint8Array(reasonableDetectionSizeInBytes);
		await tokenizer.peekBuffer(this.buffer, {
			length: Math.min(8, tokenizer.fileInfo.size),
			mayBeLess: true
		});
		if (this.check([
			0,
			0,
			1,
			186
		]) || this.check([
			0,
			0,
			1,
			179
		])) return {
			ext: "mpg",
			mime: "video/mpeg"
		};
		if (this.check([
			0,
			1,
			0,
			0,
			0
		])) return {
			ext: "ttf",
			mime: "font/ttf"
		};
		if (this.check([
			0,
			0,
			1,
			0
		])) return {
			ext: "ico",
			mime: "image/x-icon"
		};
		if (this.check([
			0,
			0,
			2,
			0
		])) return {
			ext: "cur",
			mime: "image/x-icon"
		};
		await tokenizer.peekBuffer(this.buffer, {
			length: Math.min(2 + this.options.mpegOffsetTolerance, tokenizer.fileInfo.size),
			mayBeLess: true
		});
		if (this.buffer.length >= 2 + this.options.mpegOffsetTolerance) for (let depth = 0; depth <= this.options.mpegOffsetTolerance; ++depth) {
			const type = this.scanMpeg(depth);
			if (type) return type;
		}
	};
	async readTiffTag(bigEndian) {
		const tagId = await this.tokenizer.readToken(bigEndian ? UINT16_BE : UINT16_LE);
		this.tokenizer.ignore(10);
		switch (tagId) {
			case 50341: return {
				ext: "arw",
				mime: "image/x-sony-arw"
			};
			case 50706: return {
				ext: "dng",
				mime: "image/x-adobe-dng"
			};
			default:
		}
	}
	async readTiffIFD(bigEndian) {
		const numberOfTags = await this.tokenizer.readToken(bigEndian ? UINT16_BE : UINT16_LE);
		for (let n = 0; n < numberOfTags; ++n) {
			const fileType = await this.readTiffTag(bigEndian);
			if (fileType) return fileType;
		}
	}
	async readTiffHeader(bigEndian) {
		const version = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 2);
		const ifdOffset = (bigEndian ? UINT32_BE : UINT32_LE).get(this.buffer, 4);
		if (version === 42) {
			if (ifdOffset >= 6) {
				if (this.checkString("CR", { offset: 8 })) return {
					ext: "cr2",
					mime: "image/x-canon-cr2"
				};
				if (ifdOffset >= 8) {
					const someId1 = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 8);
					const someId2 = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 10);
					if (someId1 === 28 && someId2 === 254 || someId1 === 31 && someId2 === 11) return {
						ext: "nef",
						mime: "image/x-nikon-nef"
					};
				}
			}
			await this.tokenizer.ignore(ifdOffset);
			return await this.readTiffIFD(bigEndian) ?? {
				ext: "tif",
				mime: "image/tiff"
			};
		}
		if (version === 43) return {
			ext: "tif",
			mime: "image/tiff"
		};
	}
	/**
	Scan check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE).
	
	@param offset - Offset to scan for sync-preamble.
	@returns {{ext: string, mime: string}}
	*/
	scanMpeg(offset) {
		if (this.check([255, 224], {
			offset,
			mask: [255, 224]
		})) {
			if (this.check([16], {
				offset: offset + 1,
				mask: [22]
			})) {
				if (this.check([8], {
					offset: offset + 1,
					mask: [8]
				})) return {
					ext: "aac",
					mime: "audio/aac"
				};
				return {
					ext: "aac",
					mime: "audio/aac"
				};
			}
			if (this.check([2], {
				offset: offset + 1,
				mask: [6]
			})) return {
				ext: "mp3",
				mime: "audio/mpeg"
			};
			if (this.check([4], {
				offset: offset + 1,
				mask: [6]
			})) return {
				ext: "mp2",
				mime: "audio/mpeg"
			};
			if (this.check([6], {
				offset: offset + 1,
				mask: [6]
			})) return {
				ext: "mp1",
				mime: "audio/mpeg"
			};
		}
	}
};
const supportedExtensions = new Set(extensions);
const supportedMimeTypes = new Set(mimeTypes);

//#endregion
export { fileTypeFromBuffer as t };