@thi.ng/wasm-api-bindgen
Version:
Polyglot bindings code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects
77 lines (76 loc) • 3.23 kB
JavaScript
import { isArray } from "@thi.ng/checks/is-array";
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
import { isString } from "@thi.ng/checks/is-string";
import { split } from "@thi.ng/strings/split";
import { wordWrapLine, wordWrapLines } from "@thi.ng/strings/word-wrap";
const isNumeric = (x) => /^(([iu](8|16|32))|(f(32|64)))$/.test(x);
const isBigNumeric = (x) => /^[iu]64$/.test(x);
const isSizeT = (x) => /^[iu]size$/.test(x);
const isWasmPrim = (x) => isNumeric(x) || isBigNumeric(x);
const isWasmString = (x) => x === "string";
const isPadding = (f) => f.pad != null && f.pad > 0;
const isPointer = (x) => x === "ptr";
const isFuncPointer = (type, coll) => coll[type]?.type === "funcptr";
const isEnum = (type, coll) => coll[type]?.type === "enum";
const isExternal = (type, coll) => coll[type]?.type === "ext";
const isSlice = (x) => x === "slice";
const isOpaque = (x) => x === "opaque";
const isPointerLike = (f, coll) => isPointer(f.tag) || isSlice(f.tag) || isWasmString(f.type) || isOpaque(f.type) || isFuncPointer(f.type, coll);
const isStringSlice = (type) => type === "slice";
const isStruct = (x) => x.type === "struct";
const isUnion = (x) => x.type === "union";
const hasStringFields = (x) => {
if (!isStruct(x) || isUnion(x)) return false;
return x.fields.some((f) => f.type === "string");
};
const usesStrings = (coll) => Object.values(coll).some(hasStringFields);
const pointerFields = (fields) => fields.filter((f) => isPointer(f.tag));
const stringFields = (fields) => fields.filter((f) => isWasmString(f.type) && f.tag !== "ptr");
const sliceTypes = (coll) => new Set(
Object.values(coll).flatMap((x) => isStruct(x) || isUnion(x) ? x.fields : []).map((x) => x.tag === "slice" ? x.type : null).filter((x) => !!x)
);
const enumName = (opts, name) => opts.uppercaseEnums ? name.toUpperCase() : name;
const defaultValue = (f, lang) => f.default !== void 0 ? isPlainObject(f.default) ? f.default[lang] : f.default : void 0;
const prefixLines = (prefix, str, width) => (isString(str) ? wordWrapLines(str, { width: width - prefix.length }) : str.flatMap((x) => wordWrapLine(x, { width: width - prefix.length }))).map((line) => prefix + line);
const ensureLines = (src, key) => isString(src) ? split(src) : isArray(src) ? src : key ? src[key] ? ensureLines(src[key], key) : [] : [];
const ensureStringArray = (src) => isString(src) ? [src] : src;
function* withIndentation(lines, indent, scopeStart, scopeEnd, level = 0) {
const stack = new Array(level).fill(indent);
for (let l of lines) {
scopeEnd.test(l) && stack.pop();
const curr = stack.length ? stack[stack.length - 1] : "";
yield curr + l;
scopeStart.test(l) && stack.push(curr + indent);
}
}
const injectBody = (acc, body, key = "impl") => body && acc.push("", ...ensureLines(body, key), "");
export {
defaultValue,
ensureLines,
ensureStringArray,
enumName,
hasStringFields,
injectBody,
isBigNumeric,
isEnum,
isExternal,
isFuncPointer,
isNumeric,
isOpaque,
isPadding,
isPointer,
isPointerLike,
isSizeT,
isSlice,
isStringSlice,
isStruct,
isUnion,
isWasmPrim,
isWasmString,
pointerFields,
prefixLines,
sliceTypes,
stringFields,
usesStrings,
withIndentation
};