Skip to content

Commit 1ebce2f

Browse files
committed
Better behavior for zip -> brarchive.
1 parent c45baee commit 1ebce2f

File tree

1 file changed

+58
-50
lines changed

1 file changed

+58
-50
lines changed

src/handlers/brarchive.ts

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -129,90 +129,98 @@ class BRARCHIVEHandler implements FormatHandler {
129129
}
130130
}
131131
else if ((inputFormat.internal === "json" || inputFormat.internal === "zip") && outputFormat.internal === "brarchive") {
132-
const working_files : FileData[] = [];
132+
const working_files: { [key: string]: FileData[] } = {};
133133

134134
// Special handling for zip input.
135135
if (inputFormat.internal === "zip") {
136136
for (const file of inputFiles) {
137137
const zip = new JSZip();
138138
await zip.loadAsync(file.bytes);
139139

140+
let done_something_flag = false;
141+
140142
// Extract all files from ZIP
143+
working_files[file.name] = [];
141144
for (const [filename, zipEntry] of Object.entries(zip.files)) {
142145
if (!zipEntry.dir) {
143146
if (filename.endsWith(".json") === false) {
144147
throw new Error("Archive contains more than just .json files; abort.");
145148
}
146149
else {
150+
done_something_flag = true;
147151
const data = await zipEntry.async("uint8array");
148-
working_files.push({
152+
working_files[file.name].push({
149153
name: filename,
150154
bytes: data
151155
});
152156
}
153157
}
154158
}
155-
}
156-
157-
// Throw error if empty
158-
if (working_files.length === 0) {
159-
throw new Error("No applicable files to unzip found.");
159+
160+
// Throw error if empty
161+
if (!done_something_flag) {
162+
throw new Error("No applicable files to unzip found in "+file.name);
163+
}
160164
}
161165
}
162166
else {
163-
working_files.push(...inputFiles);
167+
working_files["Unnamed.brarchive"] = [];
168+
working_files["Unnamed.brarchive"].push(...inputFiles);
164169
}
165170

166-
// Unlikely, but handle it.
167-
if (working_files.length > 0xFFFFFFFF) {
168-
throw new Error("Too many input files to encode in 4 bytes.");
169-
}
170-
171-
// Zip all the inputs into one archive.
172-
const working_bytes : number[] = [];
173-
174-
// Write headers and magic numbers.
175-
working_bytes.push(0x7D, 0x27, 0x25, 0xB1);
176-
working_bytes.push(0xA0, 0x52, 0x70, 0x26);
177-
working_bytes.push(...write_lendian_4(working_files.length));
178-
working_bytes.push(0x01, 0x00, 0x00, 0x00);
179-
180-
// Start writing FileEntry's
181-
const encoder = new TextEncoder();
182-
for (let i = 0; i < working_files.length; i++) {
183-
// Shorten name if need be
184-
let name = working_files[i].name
185-
while ((encoder.encode(name)).length > 247) {
186-
name = name.substring(0,name.length-1);
171+
// Iterate through each collection of files.
172+
for (const key in working_files) {
173+
// Unlikely, but handle it.
174+
if (working_files[key].length > 0xFFFFFFFF) {
175+
throw new Error("Too many input files to encode in 4 bytes.");
187176
}
177+
178+
// Zip all the inputs into one archive.
179+
const working_bytes : number[] = [];
188180

189-
const name_bytes : Uint8Array = encoder.encode(name);
190-
working_bytes.push(name_bytes.length);
181+
// Write headers and magic numbers.
182+
working_bytes.push(0x7D, 0x27, 0x25, 0xB1);
183+
working_bytes.push(0xA0, 0x52, 0x70, 0x26);
184+
working_bytes.push(...write_lendian_4(working_files[key].length));
185+
working_bytes.push(0x01, 0x00, 0x00, 0x00);
191186

192-
// Push name and padding
193-
working_bytes.push(...name_bytes);
194-
for (let pushed = name_bytes.length; pushed < 247; pushed++) {
195-
working_bytes.push(0x00);
187+
// Start writing FileEntry's
188+
const encoder = new TextEncoder();
189+
for (let i = 0; i < working_files[key].length; i++) {
190+
// Shorten name if need be
191+
let name = working_files[key][i].name
192+
while ((encoder.encode(name)).length > 247) {
193+
name = name.substring(0,name.length-1);
194+
}
195+
196+
const name_bytes : Uint8Array = encoder.encode(name);
197+
working_bytes.push(name_bytes.length);
198+
199+
// Push name and padding
200+
working_bytes.push(...name_bytes);
201+
for (let pushed = name_bytes.length; pushed < 247; pushed++) {
202+
working_bytes.push(0x00);
203+
}
204+
205+
// Relative offset is the sum of the file sizes of every file that comes before it.
206+
let relative_offset = 0;
207+
for (let i2 = i-1; i2 >= 0; i2--) {
208+
relative_offset += working_files[key][i2].bytes.length;
209+
}
210+
working_bytes.push(...write_lendian_4(relative_offset));
211+
212+
// Then, the file size of *this* file.
213+
working_bytes.push(...write_lendian_4(working_files[key][i].bytes.length));
196214
}
197215

198-
// Relative offset is the sum of the file sizes of every file that comes before it.
199-
let relative_offset = 0;
200-
for (let i2 = i-1; i2 >= 0; i2--) {
201-
relative_offset += working_files[i2].bytes.length;
216+
// FileEntry's are done. Write raw data.
217+
for (let i = 0; i < working_files[key].length; i++) {
218+
working_bytes.push(...working_files[key][i].bytes);
202219
}
203-
working_bytes.push(...write_lendian_4(relative_offset));
204220

205-
// Then, the file size of *this* file.
206-
working_bytes.push(...write_lendian_4(working_files[i].bytes.length));
221+
// Finally, push our file.
222+
outputFiles.push({bytes: new Uint8Array(working_bytes), name: key.split(".").slice(0, -1).join(".") + "." + outputFormat.extension});
207223
}
208-
209-
// FileEntry's are done. Write raw data.
210-
for (let i = 0; i < working_files.length; i++) {
211-
working_bytes.push(...working_files[i].bytes);
212-
}
213-
214-
// Finally, push our file.
215-
outputFiles.push({bytes: new Uint8Array(working_bytes), name: "Unnamed.brarchive"});
216224
}
217225
else {
218226
throw new Error("Invalid input-output");

0 commit comments

Comments
 (0)