@thi.ng/wasm-api 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/README.md +146 -120
- package/api.d.ts +76 -11
- package/bridge.d.ts +11 -1
- package/bridge.js +13 -8
- package/cli.js +27 -6
- package/codegen/c.d.ts +33 -0
- package/codegen/c.js +100 -0
- package/codegen/c11.d.ts +22 -0
- package/codegen/c11.js +125 -0
- package/codegen/typescript.d.ts +2 -12
- package/codegen/typescript.js +120 -84
- package/codegen/utils.d.ts +48 -1
- package/codegen/utils.js +55 -0
- package/codegen/zig.d.ts +2 -9
- package/codegen/zig.js +54 -28
- package/codegen.d.ts +1 -23
- package/codegen.js +31 -8
- package/doc/assets/main.js +52 -0
- package/doc/assets/search.js +1 -0
- package/include/wasmapi.h +34 -20
- package/include/wasmapi.zig +53 -46
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +31 -19
- package/pointer.d.ts +23 -0
- package/pointer.js +27 -0
- package/string.d.ts +97 -0
- package/string.js +145 -0
package/bridge.js
CHANGED
|
@@ -2,10 +2,10 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { INotifyMixin } from "@thi.ng/api/mixins/inotify";
|
|
3
3
|
import { defError } from "@thi.ng/errors/deferror";
|
|
4
4
|
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
5
|
-
import { U16, U32,
|
|
5
|
+
import { U16, U32, U64BIG, U8 } from "@thi.ng/hex";
|
|
6
6
|
import { ConsoleLogger } from "@thi.ng/logger/console";
|
|
7
7
|
import { EVENT_MEMORY_CHANGED, } from "./api.js";
|
|
8
|
-
const
|
|
8
|
+
export const Panic = defError(() => "Panic");
|
|
9
9
|
export const OutOfMemoryError = defError(() => "Out of memory");
|
|
10
10
|
/**
|
|
11
11
|
* The main interop API bridge between the JS host environment and a WebAssembly
|
|
@@ -34,18 +34,18 @@ let WasmBridge = class WasmBridge {
|
|
|
34
34
|
this.api = {
|
|
35
35
|
printI8: logN,
|
|
36
36
|
printU8: logN,
|
|
37
|
-
printU8Hex: (x) => this.logger.debug(`0x${U8(x)}`),
|
|
38
37
|
printI16: logN,
|
|
39
38
|
printU16: logN,
|
|
40
|
-
printU16Hex: (x) => this.logger.debug(`0x${U16(x)}`),
|
|
41
39
|
printI32: logN,
|
|
42
40
|
printU32: (x) => this.logger.debug(x >>> 0),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
_printU64: (hi, lo) => this.logger.debug((BigInt(hi >>> 0) << B32) | BigInt(lo >>> 0)),
|
|
46
|
-
_printU64Hex: (hi, lo) => this.logger.debug(`0x${U64HL(hi, lo)}`),
|
|
41
|
+
printI64: (x) => this.logger.debug(x),
|
|
42
|
+
printU64: (x) => this.logger.debug(x),
|
|
47
43
|
printF32: logN,
|
|
48
44
|
printF64: logN,
|
|
45
|
+
printU8Hex: (x) => this.logger.debug(`0x${U8(x)}`),
|
|
46
|
+
printU16Hex: (x) => this.logger.debug(`0x${U16(x)}`),
|
|
47
|
+
printU32Hex: (x) => this.logger.debug(`0x${U32(x)}`),
|
|
48
|
+
printU64Hex: (x) => this.logger.debug(`0x${U64BIG(x)}`),
|
|
49
49
|
_printI8Array: logA(this.getI8Array.bind(this)),
|
|
50
50
|
_printU8Array: logA(this.getU8Array.bind(this)),
|
|
51
51
|
_printI16Array: logA(this.getI16Array.bind(this)),
|
|
@@ -61,6 +61,11 @@ let WasmBridge = class WasmBridge {
|
|
|
61
61
|
debug: () => {
|
|
62
62
|
debugger;
|
|
63
63
|
},
|
|
64
|
+
_panic: (addr, len) => {
|
|
65
|
+
throw new Panic(this.getString(addr, len));
|
|
66
|
+
},
|
|
67
|
+
timer: () => performance.now(),
|
|
68
|
+
epoch: () => BigInt(Date.now()),
|
|
64
69
|
};
|
|
65
70
|
}
|
|
66
71
|
/**
|
package/cli.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { flag, oneOfMulti, parse, ParseError, string, strings, usage, } from "@thi.ng/args";
|
|
1
|
+
import { flag, oneOf, oneOfMulti, parse, ParseError, string, strings, usage, } from "@thi.ng/args";
|
|
2
2
|
import { isArray, isPlainObject } from "@thi.ng/checks";
|
|
3
3
|
import { illegalArgs } from "@thi.ng/errors";
|
|
4
|
-
import {
|
|
4
|
+
import { mutIn } from "@thi.ng/paths/mut-in";
|
|
5
|
+
import { readJSON, readText, writeText } from "@thi.ng/file-io";
|
|
5
6
|
import { ConsoleLogger } from "@thi.ng/logger";
|
|
6
7
|
import { resolve } from "path";
|
|
7
8
|
import { generateTypes } from "./codegen.js";
|
|
9
|
+
import { C11 } from "./codegen/c11.js";
|
|
8
10
|
import { TYPESCRIPT } from "./codegen/typescript.js";
|
|
9
|
-
import { isWasmPrim, isWasmString } from "./codegen/utils.js";
|
|
11
|
+
import { isPadding, isWasmPrim, isWasmString } from "./codegen/utils.js";
|
|
10
12
|
import { ZIG } from "./codegen/zig.js";
|
|
11
|
-
const GENERATORS = { ts: TYPESCRIPT, zig: ZIG };
|
|
13
|
+
const GENERATORS = { c11: C11, ts: TYPESCRIPT, zig: ZIG };
|
|
12
14
|
const argOpts = {
|
|
13
15
|
config: string({
|
|
14
16
|
alias: "c",
|
|
@@ -27,6 +29,11 @@ const argOpts = {
|
|
|
27
29
|
delim: ",",
|
|
28
30
|
}),
|
|
29
31
|
out: strings({ alias: "o", hint: "FILE", desc: "output file path" }),
|
|
32
|
+
string: oneOf(["slice", "ptr"], {
|
|
33
|
+
alias: "s",
|
|
34
|
+
hint: "TYPE",
|
|
35
|
+
desc: "Force string type implementation",
|
|
36
|
+
}),
|
|
30
37
|
};
|
|
31
38
|
export const INSTALL_DIR = resolve(`${process.argv[2]}/..`);
|
|
32
39
|
export const PKG = readJSON(`${INSTALL_DIR}/package.json`);
|
|
@@ -72,7 +79,10 @@ const validateTypeRefs = (coll) => {
|
|
|
72
79
|
if (spec.type !== "struct")
|
|
73
80
|
continue;
|
|
74
81
|
for (let f of spec.fields) {
|
|
75
|
-
if (!(
|
|
82
|
+
if (!(isPadding(f) ||
|
|
83
|
+
isWasmPrim(f.type) ||
|
|
84
|
+
isWasmString(f.type) ||
|
|
85
|
+
coll[f.type])) {
|
|
76
86
|
invalidSpec(spec.__path, `structfield ${spec.name}.${f.name} of unknown type: ${f.type}`);
|
|
77
87
|
}
|
|
78
88
|
}
|
|
@@ -127,12 +137,23 @@ try {
|
|
|
127
137
|
}
|
|
128
138
|
const ctx = {
|
|
129
139
|
logger: new ConsoleLogger("wasm-api", opts.debug ? "DEBUG" : "INFO"),
|
|
130
|
-
config: {},
|
|
140
|
+
config: { global: {} },
|
|
131
141
|
opts,
|
|
132
142
|
};
|
|
133
143
|
if (opts.config) {
|
|
134
144
|
ctx.config = readJSON(resolve(opts.config), ctx.logger);
|
|
145
|
+
for (let id in ctx.config) {
|
|
146
|
+
const conf = ctx.config[id];
|
|
147
|
+
if (conf.pre && conf.pre[0] === "@") {
|
|
148
|
+
conf.pre = readText(conf.pre.substring(1), ctx.logger);
|
|
149
|
+
}
|
|
150
|
+
if (conf.post && conf.post[0] === "@") {
|
|
151
|
+
conf.post = readText(conf.post.substring(1), ctx.logger);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
135
154
|
}
|
|
155
|
+
opts.debug && mutIn(ctx, ["config", "global", "debug"], true);
|
|
156
|
+
opts.string && mutIn(ctx, ["config", "global", "stringType"], opts.string);
|
|
136
157
|
generateOutputs(ctx, parseTypeSpecs(ctx, rest));
|
|
137
158
|
}
|
|
138
159
|
catch (e) {
|
package/codegen/c.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ICodeGen } from "../api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Zig code generator options.
|
|
4
|
+
*/
|
|
5
|
+
export interface COpts {
|
|
6
|
+
/**
|
|
7
|
+
* If true, generates various struct & struct field analysis functions
|
|
8
|
+
* (sizes, alignment, offsets etc.).
|
|
9
|
+
*
|
|
10
|
+
* @defaultValue false
|
|
11
|
+
*/
|
|
12
|
+
debug: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Optional prelude
|
|
15
|
+
*/
|
|
16
|
+
pre: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional postfix (inserted after the generated code)
|
|
19
|
+
*/
|
|
20
|
+
post: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Zig code generator. Call with options and then pass to {@link generateTypes}
|
|
24
|
+
* (see its docs for further usage).
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* This codegen generates struct and enum definitions for a {@link TypeColl}
|
|
28
|
+
* given to {@link generateTypes}.
|
|
29
|
+
*
|
|
30
|
+
* @param opts
|
|
31
|
+
*/
|
|
32
|
+
export declare const C11: (opts?: Partial<COpts>) => ICodeGen;
|
|
33
|
+
//# sourceMappingURL=c.d.ts.map
|
package/codegen/c.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { isString } from "@thi.ng/checks/is-string";
|
|
2
|
+
import { isPadding, isStringSlice, prefixLines, withIndentation, } from "./utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Zig code generator. Call with options and then pass to {@link generateTypes}
|
|
5
|
+
* (see its docs for further usage).
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* This codegen generates struct and enum definitions for a {@link TypeColl}
|
|
9
|
+
* given to {@link generateTypes}.
|
|
10
|
+
*
|
|
11
|
+
* @param opts
|
|
12
|
+
*/
|
|
13
|
+
export const C11 = (opts = {}) => {
|
|
14
|
+
const { debug } = { debug: false, ...opts };
|
|
15
|
+
const INDENT = " ";
|
|
16
|
+
const SCOPES = [/\{$/, /\}\)?[;,]?$/];
|
|
17
|
+
const gen = {
|
|
18
|
+
pre: (opts) => `#pragma once
|
|
19
|
+
#include <stddef.h>
|
|
20
|
+
#include <stdint.h>${opts.pre ? `\n${opts.pre}` : ""}`,
|
|
21
|
+
post: () => opts.post || "",
|
|
22
|
+
doc: (doc, acc) => {
|
|
23
|
+
acc.push(prefixLines("// ", doc));
|
|
24
|
+
},
|
|
25
|
+
enum: (e, _, acc) => {
|
|
26
|
+
const lines = [];
|
|
27
|
+
lines.push(`enum {`);
|
|
28
|
+
for (let v of e.values) {
|
|
29
|
+
let line;
|
|
30
|
+
if (!isString(v)) {
|
|
31
|
+
v.doc && gen.doc(v.doc, lines);
|
|
32
|
+
line = `${e.name}_${v.name}`;
|
|
33
|
+
if (v.value != null)
|
|
34
|
+
line += ` = ${v.value}`;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
line = v;
|
|
38
|
+
}
|
|
39
|
+
lines.push(line + ",");
|
|
40
|
+
}
|
|
41
|
+
lines.push("};", "");
|
|
42
|
+
acc.push(...withIndentation(lines, INDENT, ...SCOPES));
|
|
43
|
+
},
|
|
44
|
+
struct: (struct, _, acc, opts) => {
|
|
45
|
+
const name = struct.name;
|
|
46
|
+
const res = [];
|
|
47
|
+
res.push(`typedef struct ${name} ${name};`, `struct ${name} {`);
|
|
48
|
+
const ftypes = {};
|
|
49
|
+
let padID = 0;
|
|
50
|
+
for (let f of struct.fields) {
|
|
51
|
+
// autolabel explicit padding fields
|
|
52
|
+
if (isPadding(f)) {
|
|
53
|
+
res.push(`__pad${padID++}: [${f.pad}]u8,`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
f.doc && gen.doc(f.doc, res);
|
|
57
|
+
let ftype = f.type === "string"
|
|
58
|
+
? isStringSlice(opts.stringType)
|
|
59
|
+
? f.const !== false
|
|
60
|
+
? "[]const u8"
|
|
61
|
+
: "[]u8"
|
|
62
|
+
: f.const !== false
|
|
63
|
+
? "[*:0]const u8"
|
|
64
|
+
: "[*:0]u8"
|
|
65
|
+
: f.type;
|
|
66
|
+
switch (f.tag) {
|
|
67
|
+
case "array":
|
|
68
|
+
case "vec":
|
|
69
|
+
ftype = `[${f.len}]${ftype}`;
|
|
70
|
+
break;
|
|
71
|
+
case "slice":
|
|
72
|
+
ftype = `[]${f.const ? "const " : ""}${ftype}`;
|
|
73
|
+
break;
|
|
74
|
+
case "ptr":
|
|
75
|
+
ftype = `*${f.const ? "const " : ""}${f.len ? `[${f.len}]` : ""}${ftype}`;
|
|
76
|
+
break;
|
|
77
|
+
case "scalar":
|
|
78
|
+
default:
|
|
79
|
+
}
|
|
80
|
+
ftypes[f.name] = ftype;
|
|
81
|
+
res.push(`${f.name}: ${ftype},`);
|
|
82
|
+
}
|
|
83
|
+
res.push("};");
|
|
84
|
+
if (debug) {
|
|
85
|
+
res.push("");
|
|
86
|
+
const fn = (fname, body) => res.push(`size_t __attribute__((used)) ${name}_${fname}() {`, `return ${body};`, `}`);
|
|
87
|
+
fn("align", `alignof(${name})`);
|
|
88
|
+
fn("size", `sizeof(${name})`);
|
|
89
|
+
for (let f of struct.fields) {
|
|
90
|
+
fn(f.name + "_align", `alignof(${ftypes[f.name]})`);
|
|
91
|
+
fn(f.name + "_offset", `offsetOf(${name}, "${f.name}")`);
|
|
92
|
+
fn(f.name + "_size", `sizeof(${ftypes[f.name]})`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
res.push("");
|
|
96
|
+
acc.push(...withIndentation(res, INDENT, ...SCOPES));
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
return gen;
|
|
100
|
+
};
|
package/codegen/c11.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CodeGenOptsBase, ICodeGen } from "../api.js";
|
|
2
|
+
/**
|
|
3
|
+
* Zig code generator options.
|
|
4
|
+
*/
|
|
5
|
+
export interface C11Opts extends CodeGenOptsBase {
|
|
6
|
+
/**
|
|
7
|
+
* Optional name prefix for generated types, e.g. `WASM_`.
|
|
8
|
+
*/
|
|
9
|
+
typePrefix: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Zig code generator. Call with options and then pass to {@link generateTypes}
|
|
13
|
+
* (see its docs for further usage).
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This codegen generates struct and enum definitions for a {@link TypeColl}
|
|
17
|
+
* given to {@link generateTypes}.
|
|
18
|
+
*
|
|
19
|
+
* @param opts
|
|
20
|
+
*/
|
|
21
|
+
export declare const C11: (opts?: Partial<C11Opts>) => ICodeGen;
|
|
22
|
+
//# sourceMappingURL=c11.d.ts.map
|
package/codegen/c11.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { isString } from "@thi.ng/checks/is-string";
|
|
2
|
+
import { unsupported } from "@thi.ng/errors/unsupported";
|
|
3
|
+
import { enumName, isPadding, isStringSlice, prefixLines, withIndentation, } from "./utils.js";
|
|
4
|
+
const PRIM_ALIASES = {
|
|
5
|
+
i8: "int8_t",
|
|
6
|
+
u8: "uint8_t",
|
|
7
|
+
i16: "int16_t",
|
|
8
|
+
u16: "uint16_t",
|
|
9
|
+
i32: "int32_t",
|
|
10
|
+
u32: "uint32_t",
|
|
11
|
+
i64: "int64_t",
|
|
12
|
+
u64: "uint64_t",
|
|
13
|
+
f32: "float",
|
|
14
|
+
f64: "double",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Zig code generator. Call with options and then pass to {@link generateTypes}
|
|
18
|
+
* (see its docs for further usage).
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* This codegen generates struct and enum definitions for a {@link TypeColl}
|
|
22
|
+
* given to {@link generateTypes}.
|
|
23
|
+
*
|
|
24
|
+
* @param opts
|
|
25
|
+
*/
|
|
26
|
+
export const C11 = (opts = {}) => {
|
|
27
|
+
const { typePrefix } = {
|
|
28
|
+
typePrefix: "",
|
|
29
|
+
...opts,
|
|
30
|
+
};
|
|
31
|
+
const INDENT = " ";
|
|
32
|
+
const SCOPES = [/\{$/, /^\}[ A-Za-z0-9_]*[;,]?$/];
|
|
33
|
+
const gen = {
|
|
34
|
+
pre: (opts) => `#pragma once
|
|
35
|
+
${opts.debug ? "\n#include <stdalign.h>" : ""}
|
|
36
|
+
#include <stddef.h>
|
|
37
|
+
#include <stdint.h>${opts.pre ? `\n${opts.pre}` : ""}`,
|
|
38
|
+
post: () => opts.post || "",
|
|
39
|
+
doc: (doc, acc) => {
|
|
40
|
+
acc.push(prefixLines("// ", doc));
|
|
41
|
+
},
|
|
42
|
+
enum: (e, _, acc, opts) => {
|
|
43
|
+
if (!(e.tag === "i32" || e.tag === "u32")) {
|
|
44
|
+
unsupported(`enum ${e.name} must be a i32/u32 in C, but got '${e.tag}'`);
|
|
45
|
+
}
|
|
46
|
+
const name = typePrefix + e.name;
|
|
47
|
+
const lines = [];
|
|
48
|
+
lines.push(`typedef enum {`);
|
|
49
|
+
for (let v of e.values) {
|
|
50
|
+
let line;
|
|
51
|
+
if (!isString(v)) {
|
|
52
|
+
v.doc && gen.doc(v.doc, lines);
|
|
53
|
+
line = enumName(opts, v.name);
|
|
54
|
+
if (v.value != null)
|
|
55
|
+
line += ` = ${v.value}`;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
line = enumName(opts, v);
|
|
59
|
+
}
|
|
60
|
+
lines.push(line + ",");
|
|
61
|
+
}
|
|
62
|
+
lines.push(`} ${name};`, "");
|
|
63
|
+
acc.push(...withIndentation(lines, INDENT, ...SCOPES));
|
|
64
|
+
},
|
|
65
|
+
struct: (struct, coll, acc, opts) => {
|
|
66
|
+
const name = typePrefix + struct.name;
|
|
67
|
+
const res = [];
|
|
68
|
+
res.push(`typedef struct ${name} ${name};`, `struct ${name} {`);
|
|
69
|
+
const ftypes = {};
|
|
70
|
+
let padID = 0;
|
|
71
|
+
for (let f of struct.fields) {
|
|
72
|
+
// autolabel explicit padding fields
|
|
73
|
+
if (isPadding(f)) {
|
|
74
|
+
res.push(`uint8_t __pad${padID++}[${f.pad}];`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
f.doc && gen.doc(f.doc, res);
|
|
78
|
+
const fconst = f.const ? "const " : "";
|
|
79
|
+
let ftype = f.type === "string"
|
|
80
|
+
? isStringSlice(opts.stringType)
|
|
81
|
+
? __slice("char", fconst)
|
|
82
|
+
: `${f.const !== false ? "const " : ""}char*`
|
|
83
|
+
: PRIM_ALIASES[f.type] || f.type;
|
|
84
|
+
if (coll[ftype])
|
|
85
|
+
ftype = typePrefix + ftype;
|
|
86
|
+
switch (f.tag) {
|
|
87
|
+
case "array":
|
|
88
|
+
case "vec":
|
|
89
|
+
res.push(`${fconst}${ftype} ${f.name}[${f.len}];`);
|
|
90
|
+
ftype = `${ftype}[${f.len}]`;
|
|
91
|
+
break;
|
|
92
|
+
case "slice":
|
|
93
|
+
ftype = __slice(ftype, fconst);
|
|
94
|
+
res.push(`${ftype} ${f.name};`);
|
|
95
|
+
break;
|
|
96
|
+
case "ptr":
|
|
97
|
+
ftype = `${fconst}${ftype}*`;
|
|
98
|
+
res.push(`${ftype} ${f.name};`);
|
|
99
|
+
break;
|
|
100
|
+
case "scalar":
|
|
101
|
+
default:
|
|
102
|
+
res.push(`${ftype} ${f.name};`);
|
|
103
|
+
}
|
|
104
|
+
ftypes[f.name] = ftype;
|
|
105
|
+
}
|
|
106
|
+
res.push("};");
|
|
107
|
+
if (opts.debug) {
|
|
108
|
+
const fn = (fname, body) => res.push("", `size_t __attribute__((used)) ${name}_${fname}() {`, `return ${body};`, `}`);
|
|
109
|
+
fn("align", `alignof(${name})`);
|
|
110
|
+
fn("size", `sizeof(${name})`);
|
|
111
|
+
for (let f of struct.fields) {
|
|
112
|
+
if (isPadding(f))
|
|
113
|
+
continue;
|
|
114
|
+
fn(f.name + "_align", `alignof(${ftypes[f.name]})`);
|
|
115
|
+
fn(f.name + "_offset", `offsetof(${name}, ${f.name})`);
|
|
116
|
+
fn(f.name + "_size", `sizeof(${ftypes[f.name]})`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
res.push("");
|
|
120
|
+
acc.push(...withIndentation(res, INDENT, ...SCOPES));
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
return gen;
|
|
124
|
+
};
|
|
125
|
+
const __slice = (type, $const) => `struct { ${$const}${type} *ptr; size_t len; }`;
|
package/codegen/typescript.d.ts
CHANGED
|
@@ -1,24 +1,14 @@
|
|
|
1
|
-
import { ICodeGen } from "../api.js";
|
|
1
|
+
import { CodeGenOptsBase, ICodeGen } from "../api.js";
|
|
2
2
|
/**
|
|
3
3
|
* TypeScript code generator options.
|
|
4
4
|
*/
|
|
5
|
-
export interface TSOpts {
|
|
5
|
+
export interface TSOpts extends CodeGenOptsBase {
|
|
6
6
|
/**
|
|
7
7
|
* Indentation string
|
|
8
8
|
*
|
|
9
9
|
* @defaultValue "\t"
|
|
10
10
|
*/
|
|
11
11
|
indent: string;
|
|
12
|
-
/**
|
|
13
|
-
* If true (default), forces uppercase enums
|
|
14
|
-
*
|
|
15
|
-
* @defaultValue true
|
|
16
|
-
*/
|
|
17
|
-
uppercaseEnums: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* Same as {@link CodeGenOpts.stringType}.
|
|
20
|
-
*/
|
|
21
|
-
stringType: "slice" | "ptr";
|
|
22
12
|
}
|
|
23
13
|
/**
|
|
24
14
|
* TypeScript code generator. Call with options and then pass to
|