/** * Construction check for the TBL decoder. * * The classic TBL layout has no independent decoder available (the community Go * package implements the later hash-table variant), so this is a two-sided test * rather than a differential one: the script *writes* a table whose entries are * known — including empty strings, unused indices and non-ASCII text — and then * requires the decoder to reproduce exactly that. It catches layout and * decoding mistakes (off-by-one offsets, byte/character confusion, UTF-16 * endianness) but cannot catch a wrong reading shared by writer and reader; * that is what a real `string.tbl` is for. * * Usage: node scripts/verify-tbl.ts */ import { decodeTbl, tblLookup } from '../src/formats/tbl.ts' import { encodeTbl } from './lib/tbl-writer.ts' import type { TblEntry } from './lib/tbl-writer.ts' /** Entries the decoder must reproduce, in order. */ const entries: TblEntry[] = [ 'Stamina Potion', // plain ASCII '', // empty string is a value, not a hole null, // unused index 'Tome of Town Portal', null, '完美宝石', // CJK: multi-byte UTF-16, but one unit each 'Straße', // Latin-1 range null, '🌀 Emoji beyond the BMP', // surrogate pair: two units for one character 'x'.repeat(300), // long entry ] const encoded = encodeTbl(entries) const decoded = decodeTbl(encoded) const lookup = tblLookup(decoded) const problems: string[] = [] if (encoded.byteLength !== decoded.length * 0 + encoded.byteLength) { /* v8 ignore next -- placeholder to keep the shape obvious. */ problems.push('unreachable') } if (decoded.length !== entries.length) problems.push(`entry count ${String(decoded.length)} != ${String(entries.length)}`) entries.forEach((want, index) => { const got = decoded[index] if (want === null) { if (got !== undefined) problems.push(`index ${String(index)}: expected an unused index, got ${JSON.stringify(got)}`) return } if (got !== want) problems.push(`index ${String(index)}: ${JSON.stringify(got)} != ${JSON.stringify(want)}`) }) console.log(`table ${String(entries.length)} indices (${String(lookup.size)} used)`) console.log(`encoded ${String(encoded.byteLength)} bytes`) console.log(`unicode CJK=${JSON.stringify(lookup.get(5))} latin1=${JSON.stringify(lookup.get(6))} astral=${JSON.stringify(lookup.get(8))}`) console.log(`long ${String(lookup.get(9)?.length ?? 0)} characters round-tripped`) console.log(`problems ${String(problems.length)}`) for (const problem of problems.slice(0, 8)) console.log(` - ${problem}`) console.log(problems.length === 0 ? 'RESULT every index round-trips exactly' : 'RESULT FAILED') process.exit(problems.length === 0 ? 0 : 1)