feat: updated parser

pull/1/head
flop 4 weeks ago
parent 1cc948a85c
commit ec21555d3a
  1. 17
      ts/src/parser.ts

@ -20,7 +20,7 @@ export class MonoDisplayParser {
// File header (12 bytes) // File header (12 bytes)
const magic = r.readUint32(); const magic = r.readUint32();
if (magic !== MONOFORMAT_MAGIC_HEADER) throw new Error(`Bad magic 0x${magic.toString(16)} expected 0x632B7EAF`); if (magic !== MONOFORMAT_MAGIC_HEADER) throw new Error(`Bad magic 0x${magic.toString(16)} - expected 0x632B7EAF`);
const version = r.readUint32(); const version = r.readUint32();
if (version === 0 || version > 1) throw new Error(`Unsupported version ${version}`); if (version === 0 || version > 1) throw new Error(`Unsupported version ${version}`);
@ -36,18 +36,19 @@ export class MonoDisplayParser {
const sectionStart = r.offset; // start of section DATA const sectionStart = r.offset; // start of section DATA
const dataSize = sectionSize - 4; const dataSize = sectionSize - 4;
const sectionEnd = sectionStart + dataSize;
switch (sectionType) { switch (sectionType) {
case SectionType.ElementsAlways: case SectionType.ElementsAlways:
sections.push(this.#parseElementsSection(r, SectionType.ElementsAlways, false)); sections.push(this.#parseElementsSection(r, SectionType.ElementsAlways, false, sectionEnd));
break; break;
case SectionType.ElementsTimespan: case SectionType.ElementsTimespan:
sections.push(this.#parseElementsSection(r, SectionType.ElementsTimespan, true)); sections.push(this.#parseElementsSection(r, SectionType.ElementsTimespan, true, sectionEnd));
break; break;
case SectionType.CustomFont: case SectionType.CustomFont:
sections.push(this.#parseCustomFont(r, dataSize)); sections.push(this.#parseCustomFont(r, dataSize));
break; break;
default: default:
// Unknown skip // Unknown - skip
break; break;
} }
@ -70,6 +71,7 @@ export class MonoDisplayParser {
r: BinaryReader, r: BinaryReader,
type: SectionType.ElementsAlways | SectionType.ElementsTimespan, type: SectionType.ElementsAlways | SectionType.ElementsTimespan,
hasTimestamp: boolean, hasTimestamp: boolean,
sectionEnd: number,
): MonoFormatElementsAlways | MonoFormatElementsTimespan { ): MonoFormatElementsAlways | MonoFormatElementsTimespan {
const flags = this.#parseFlags(r.readUint16()); const flags = this.#parseFlags(r.readUint16());
const numElements = r.readUint16(); const numElements = r.readUint16();
@ -82,8 +84,11 @@ export class MonoDisplayParser {
const elements: MonoFormatElement[] = []; const elements: MonoFormatElement[] = [];
for (let i = 0; i < numElements; i++) { for (let i = 0; i < numElements; i++) {
// Stop if fewer than 2 bytes remain in section (can't read element type)
if (r.offset + 2 > sectionEnd) break;
const el = this.#parseElement(r); const el = this.#parseElement(r);
if (el) elements.push(el); if (el === null) break; // unknown type - can't determine size, stop
elements.push(el);
} }
if (hasTimestamp) { if (hasTimestamp) {
@ -112,7 +117,7 @@ export class MonoDisplayParser {
case ElementType.ClippedText: return this.#parseClippedText(r, elementStart); case ElementType.ClippedText: return this.#parseClippedText(r, elementStart);
case ElementType.HScrollText: return this.#parseHScrollText(r, elementStart); case ElementType.HScrollText: return this.#parseHScrollText(r, elementStart);
default: default:
// Unknown element type cannot safely skip without knowing size; stop parsing section elements // Unknown element type - cannot safely skip without knowing size; stop parsing section elements
return null; return null;
} }
} }

Loading…
Cancel
Save