272 lines
10 KiB
JavaScript
272 lines
10 KiB
JavaScript
// @generated by `cargo run -p satteri-layout-codegen`. Do not edit by hand.
|
|
import { ru16, ru32, rstr } from "../../wire-read.js";
|
|
import { restorePhantomSpaces } from "../../phantom.js";
|
|
import { lazyGroup } from "../../lazy-props.js";
|
|
import { decodeMdxJsxAttr } from "../../mdx-attr.js";
|
|
import { decodeColumnAlign } from "../column-align.js";
|
|
/** Walk-wire fields per node-type tag (see Rust `write_mdast_type_data_inline`). */
|
|
const MDAST_LAYOUTS = {
|
|
2: [{ js: "depth", offset: 0, kind: "u8", default: 1 }],
|
|
7: [{ js: "value", offset: 0, kind: "str32" }],
|
|
10: [{ js: "value", offset: 0, kind: "str32" }],
|
|
13: [{ js: "value", offset: 0, kind: "str32" }],
|
|
25: [{ js: "value", offset: 0, kind: "str32" }],
|
|
26: [{ js: "value", offset: 0, kind: "str32" }],
|
|
8: [
|
|
{ js: "lang", offset: 0, kind: "str16", nullable: true },
|
|
{ js: "meta", offset: 8, kind: "str16", nullable: true },
|
|
{ js: "value", offset: 16, kind: "str32" },
|
|
],
|
|
9: [
|
|
{ js: "url", offset: 0, kind: "str16" },
|
|
{ js: "title", offset: 8, kind: "str16", nullable: true },
|
|
{ js: "identifier", offset: 16, kind: "str16" },
|
|
{ js: "label", offset: 24, kind: "str16" },
|
|
],
|
|
15: [
|
|
{ js: "url", offset: 0, kind: "str16" },
|
|
{ js: "title", offset: 8, kind: "str16", nullable: true },
|
|
],
|
|
16: [
|
|
{ js: "url", offset: 0, kind: "str16" },
|
|
{ js: "alt", offset: 8, kind: "str16" },
|
|
{ js: "title", offset: 16, kind: "str16", nullable: true },
|
|
],
|
|
17: [
|
|
{ js: "identifier", offset: 0, kind: "str16" },
|
|
{ js: "label", offset: 8, kind: "str16" },
|
|
{ js: "referenceType", offset: 16, kind: "u8", values: ["shortcut", "collapsed", "full"] },
|
|
],
|
|
18: [
|
|
{ js: "identifier", offset: 0, kind: "str16" },
|
|
{ js: "label", offset: 8, kind: "str16" },
|
|
{ js: "referenceType", offset: 16, kind: "u8", values: ["shortcut", "collapsed", "full"] },
|
|
{ js: "alt", offset: 20, kind: "str16" },
|
|
],
|
|
19: [
|
|
{ js: "identifier", offset: 0, kind: "str16" },
|
|
{ js: "label", offset: 8, kind: "str16" },
|
|
],
|
|
20: [
|
|
{ js: "identifier", offset: 0, kind: "str16" },
|
|
{ js: "label", offset: 8, kind: "str16" },
|
|
{ js: "", offset: 16, kind: "u8", skip: true },
|
|
],
|
|
27: [
|
|
{ js: "meta", offset: 0, kind: "str16", nullable: true },
|
|
{ js: "value", offset: 8, kind: "str32" },
|
|
],
|
|
28: [{ js: "value", offset: 8, kind: "str32" }],
|
|
102: [{ js: "value", offset: 0, kind: "str32", phantom: true }],
|
|
103: [{ js: "value", offset: 0, kind: "str32", phantom: true }],
|
|
104: [{ js: "value", offset: 0, kind: "str32", phantom: true }],
|
|
};
|
|
/** Materialized property names per tag (the non-skip `js` names above),
|
|
* precomputed so `materializeMdastFields` doesn't rebuild them per node.
|
|
* Exported for the child-stub field tables. */
|
|
export const MDAST_LAYOUT_KEYS = {
|
|
2: ["depth"],
|
|
7: ["value"],
|
|
10: ["value"],
|
|
13: ["value"],
|
|
25: ["value"],
|
|
26: ["value"],
|
|
8: ["lang", "meta", "value"],
|
|
9: ["url", "title", "identifier", "label"],
|
|
15: ["url", "title"],
|
|
16: ["url", "alt", "title"],
|
|
17: ["identifier", "label", "referenceType"],
|
|
18: ["identifier", "label", "referenceType", "alt"],
|
|
19: ["identifier", "label"],
|
|
20: ["identifier", "label"],
|
|
27: ["meta", "value"],
|
|
28: ["value"],
|
|
102: ["value"],
|
|
103: ["value"],
|
|
104: ["value"],
|
|
};
|
|
/** Walk-wire tail descriptors (a name head, then a counted item list) for
|
|
* the variable-length attribute types the generic decoder below handles
|
|
* without a hand-written case: `map` is a string key/value object
|
|
* (directives), `jsx` a typed MDX-JSX attribute array. */
|
|
const MDAST_TAILS = {
|
|
21: { head: [], item: [{ js: "align", kind: "u8" }], bytes: { attrsKey: "align" } },
|
|
30: {
|
|
head: [{ js: "name", kind: "str16" }],
|
|
item: [
|
|
{ js: "key", kind: "str16" },
|
|
{ js: "value", kind: "str16" },
|
|
],
|
|
map: { attrsKey: "attributes", key: "key", value: "value" },
|
|
},
|
|
31: {
|
|
head: [{ js: "name", kind: "str16" }],
|
|
item: [
|
|
{ js: "key", kind: "str16" },
|
|
{ js: "value", kind: "str16" },
|
|
],
|
|
map: { attrsKey: "attributes", key: "key", value: "value" },
|
|
},
|
|
32: {
|
|
head: [{ js: "name", kind: "str16" }],
|
|
item: [
|
|
{ js: "key", kind: "str16" },
|
|
{ js: "value", kind: "str16" },
|
|
],
|
|
map: { attrsKey: "attributes", key: "key", value: "value" },
|
|
},
|
|
100: {
|
|
head: [{ js: "name", kind: "str16" }],
|
|
item: [
|
|
{ js: "kind", kind: "u8" },
|
|
{ js: "name", kind: "str16" },
|
|
{ js: "value", kind: "str32" },
|
|
],
|
|
jsx: { attrsKey: "attributes" },
|
|
},
|
|
101: {
|
|
head: [{ js: "name", kind: "str16" }],
|
|
item: [
|
|
{ js: "kind", kind: "u8" },
|
|
{ js: "name", kind: "str16" },
|
|
{ js: "value", kind: "str32" },
|
|
],
|
|
jsx: { attrsKey: "attributes" },
|
|
},
|
|
};
|
|
/**
|
|
* Decode a node's type-specific `type_data` from the walk buffer onto `node`,
|
|
* driven by `MDAST_LAYOUTS` (fixed-field types) and `MDAST_TAILS` (counted
|
|
* attribute lists). Returns `false` for tags in neither, so the caller falls
|
|
* through to the remaining hand-written cases (list, listItem).
|
|
*/
|
|
export function decodeMdastTypeData(view, buf, start, nodeType, node) {
|
|
const fields = MDAST_LAYOUTS[nodeType];
|
|
if (fields !== undefined) {
|
|
let pos = start;
|
|
for (const f of fields) {
|
|
if (f.kind === "u8") {
|
|
const b = buf[pos];
|
|
pos += 1;
|
|
if (f.skip)
|
|
continue;
|
|
node[f.js] = f.values ? (f.values[b] ?? f.values[0]) : b;
|
|
}
|
|
else {
|
|
const len = f.kind === "str32" ? ru32(view, pos) : ru16(view, pos);
|
|
pos += f.kind === "str32" ? 4 : 2;
|
|
const raw = rstr(buf, pos, len);
|
|
pos += len;
|
|
if (f.skip)
|
|
continue;
|
|
node[f.js] = f.nullable && len === 0 ? null : f.phantom ? restorePhantomSpaces(raw) : raw;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
const tail = MDAST_TAILS[nodeType];
|
|
if (tail !== undefined) {
|
|
let pos = start;
|
|
// Reads are inlined and advance `pos` in place (no per-field tuple): this
|
|
// runs per attribute item in the matched-node decode path, and the
|
|
// unoptimized tiers CodSpeed measures won't elide the allocation.
|
|
for (const f of tail.head) {
|
|
let value;
|
|
if (f.kind === "u8") {
|
|
value = buf[pos];
|
|
pos += 1;
|
|
}
|
|
else {
|
|
const len = f.kind === "str32" ? ru32(view, pos) : ru16(view, pos);
|
|
pos += f.kind === "str32" ? 4 : 2;
|
|
const raw = rstr(buf, pos, len);
|
|
pos += len;
|
|
value = f.phantom ? restorePhantomSpaces(raw) : raw;
|
|
}
|
|
// MDX JSX elements carry a nullable name (empty → null); map heads keep it.
|
|
node[f.js] = tail.jsx !== undefined && value === "" ? null : value;
|
|
}
|
|
const count = ru16(view, pos);
|
|
pos += 2;
|
|
const readItem = () => {
|
|
const item = {};
|
|
for (const f of tail.item) {
|
|
if (f.kind === "u8") {
|
|
item[f.js] = buf[pos];
|
|
pos += 1;
|
|
}
|
|
else {
|
|
const len = f.kind === "str32" ? ru32(view, pos) : ru16(view, pos);
|
|
pos += f.kind === "str32" ? 4 : 2;
|
|
const raw = rstr(buf, pos, len);
|
|
pos += len;
|
|
item[f.js] = f.phantom ? restorePhantomSpaces(raw) : raw;
|
|
}
|
|
}
|
|
return item;
|
|
};
|
|
if (tail.map !== undefined) {
|
|
const attrs = {};
|
|
for (let i = 0; i < count; i++) {
|
|
const item = readItem();
|
|
attrs[item[tail.map.key]] = item[tail.map.value];
|
|
}
|
|
node[tail.map.attrsKey] = attrs;
|
|
}
|
|
else if (tail.jsx !== undefined) {
|
|
const attrs = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const item = readItem();
|
|
attrs.push(decodeMdxJsxAttr(item.kind, item.name, item.value));
|
|
}
|
|
node[tail.jsx.attrsKey] = attrs;
|
|
}
|
|
else {
|
|
const align = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const item = readItem();
|
|
align.push(decodeColumnAlign(item.align));
|
|
}
|
|
node[tail.bytes.attrsKey] = align;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Attach a node's fixed `type_data` fields, materialized from the arena
|
|
* snapshot, driven by `MDAST_LAYOUTS`. Returns `false` for tags with no entry,
|
|
* so the materializer falls through to its hand-written cases (list, table,
|
|
* directives, MDX JSX). Fields resolve lazily on first access.
|
|
*/
|
|
export function materializeMdastFields(reader, node, nodeId, nodeType) {
|
|
const fields = MDAST_LAYOUTS[nodeType];
|
|
if (fields === undefined)
|
|
return false;
|
|
lazyGroup(node, MDAST_LAYOUT_KEYS[nodeType], () => {
|
|
const data = reader.getTypeData(nodeId);
|
|
const out = {};
|
|
for (const f of fields) {
|
|
if (f.kind === "u8") {
|
|
// Short type_data falls back to the layout's declared default,
|
|
// matching the Rust walk serializer.
|
|
const b = data[f.offset] ?? f.default ?? 0;
|
|
if (!f.skip)
|
|
out[f.js] = f.values ? (f.values[b] ?? f.values[0]) : b;
|
|
}
|
|
else {
|
|
// Short type_data (e.g. a 20-byte ReferenceData-only imageReference)
|
|
// yields an empty ref, mirroring the Rust decoders' bounds checks.
|
|
const ref = f.offset + 8 <= data.length
|
|
? reader.readStringRef(data, f.offset)
|
|
: { offset: 0, len: 0 };
|
|
if (f.skip)
|
|
continue;
|
|
const s = f.nullable && ref.len === 0 ? null : reader.getString(ref.offset, ref.len);
|
|
out[f.js] = f.phantom && typeof s === "string" ? restorePhantomSpaces(s) : s;
|
|
}
|
|
}
|
|
return out;
|
|
});
|
|
return true;
|
|
}
|