UNPKG

igir

Version:

🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.

108 lines (107 loc) • 3.87 kB
import APSPatch from "../models/patches/apsPatch.js"; import BPSPatch from "../models/patches/bpsPatch.js"; import DPSPatch from "../models/patches/dpsPatch.js"; import IPSPatch from "../models/patches/ipsPatch.js"; import NinjaPatch from "../models/patches/ninjaPatch.js"; import PPFPatch from "../models/patches/ppfPatch.js"; import UPSPatch from "../models/patches/upsPatch.js"; import VcdiffPatch from "../models/patches/vcdiffPatch.js"; import ArrayUtil from "../utils/arrayUtil.js"; class PatchFactory { static PATCH_PARSERS = [ { extensions: APSPatch.SUPPORTED_EXTENSIONS, fileSignatures: [APSPatch.FILE_SIGNATURE], factory: APSPatch.patchFrom.bind(APSPatch) }, { extensions: BPSPatch.SUPPORTED_EXTENSIONS, fileSignatures: [BPSPatch.FILE_SIGNATURE], factory: BPSPatch.patchFrom.bind(BPSPatch) }, { extensions: DPSPatch.SUPPORTED_EXTENSIONS, fileSignatures: [], factory: DPSPatch.patchFrom.bind(DPSPatch) }, { extensions: IPSPatch.SUPPORTED_EXTENSIONS, fileSignatures: IPSPatch.FILE_SIGNATURES, factory: IPSPatch.patchFrom.bind(IPSPatch) }, { extensions: NinjaPatch.SUPPORTED_EXTENSIONS, fileSignatures: [NinjaPatch.FILE_SIGNATURE], factory: NinjaPatch.patchFrom.bind(NinjaPatch) }, { extensions: PPFPatch.SUPPORTED_EXTENSIONS, fileSignatures: [PPFPatch.FILE_SIGNATURE], factory: PPFPatch.patchFrom.bind(PPFPatch) }, { extensions: UPSPatch.SUPPORTED_EXTENSIONS, fileSignatures: [UPSPatch.FILE_SIGNATURE], factory: UPSPatch.patchFrom.bind(UPSPatch) }, { extensions: VcdiffPatch.SUPPORTED_EXTENSIONS, fileSignatures: [VcdiffPatch.FILE_SIGNATURE], factory: VcdiffPatch.patchFrom.bind(VcdiffPatch) } ]; static MAX_HEADER_LENGTH_BYTES = Object.values(PatchFactory.PATCH_PARSERS).flatMap((parser) => parser.fileSignatures).reduce((max, fileSignature) => Math.max(max, fileSignature.length), 0); static getSupportedExtensions() { return Object.values(this.PATCH_PARSERS).flatMap((parser) => parser.extensions).reduce(ArrayUtil.reduceUnique(), []).toSorted((a, b) => a.localeCompare(b)); } /** * Return a {@link Patch} for a file by matching its filename extension against the supported * patch formats, or undefined if no extension matches. */ static async patchFromFilename(file) { const filePath = file.getExtractedFilePath(); const parsers = Object.values(this.PATCH_PARSERS); for (const parser of parsers) { if (parser.extensions.some((ext) => filePath.toLowerCase().endsWith(ext))) { return await parser.factory(file); } } return void 0; } static async readHeaderHex(readable, length) { const chunks = []; let readBytes = 0; for await (const chunk of readable) { if (chunk.length > 0) { chunks.push(chunk); readBytes += chunk.length; } if (readBytes >= length) { break; } } return Buffer.concat(chunks).subarray(0, length).toString("hex").toLowerCase(); } /** * Return a {@link Patch} for a file by reading its leading bytes and matching them against * the known patch-format file signatures, or undefined if no signature matches. */ static async patchFromFileContents(file) { const fileHeader = await file.createReadStream( async (readable) => await this.readHeaderHex(readable, this.MAX_HEADER_LENGTH_BYTES) ); const parsers = Object.values(this.PATCH_PARSERS); for (const parser of parsers) { if (parser.fileSignatures.some( (fileSignature) => fileHeader.startsWith(fileSignature.toString("hex")) )) { return await parser.factory(file); } } return void 0; } } export { PatchFactory as default }; //# sourceMappingURL=patchFactory.js.map