Files
rea/src/wasm/WabtString.ts
T

55 lines
1.8 KiB
TypeScript

/** Locate a WAT string's exclusive end without decoding or copying its payload. */
export const watStringEnd = (form: string, start: number): number => {
for (
let end = form.indexOf('"', start);
end !== -1;
end = form.indexOf('"', end + 1)
) {
let escapes = end;
while (escapes > start && form[escapes - 1] === "\\") escapes--;
if ((end - escapes) % 2 === 0) return end + 1;
}
throw new Error("Incomplete WABT string.");
};
/** Decode a producer WAT string only where its bytes are interpreted. */
export const watString = (form: string, start: number) => {
const end = watStringEnd(form, start);
const name = form.slice(start, end - 1);
// Escapes shrink; literal UTF-8 has the same byte extent as its source.
const bytes = Buffer.alloc(Buffer.byteLength(name, "utf8"));
let length = 0;
for (let index = 0; index < name.length;) {
if (name[index] !== "\\") {
const next = name.indexOf("\\", index);
const end = next < 0 ? name.length : next;
length += bytes.write(name.slice(index, end), length, "utf8");
index = end;
continue;
}
const hex = name.slice(index + 1, index + 3);
if (/^[\da-f]{2}$/iu.test(hex)) {
bytes[length++] = Number.parseInt(hex, 16);
index += 3;
} else {
const escape = name[index + 1];
const value =
escape === "t"
? 9
: escape === "n"
? 10
: escape === "r"
? 13
: escape === '"'
? 34
: escape === "\\"
? 92
: undefined;
if (value === undefined) throw new Error("Unsupported WABT name escape.");
bytes[length++] = value;
index += 2;
}
}
return { bytes: bytes.subarray(0, length), end };
};