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
JavaScript
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