@thi.ng/wasm-api-bindgen
Version:
Polyglot bindings code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects
435 lines • 13.3 kB
TypeScript
import type { BigType, FloatType, Fn, Fn2, IObjectOf, NumOrString } from "@thi.ng/api";
import type { Pow2 } from "@thi.ng/binary";
export declare const PKG_NAME = "@thi.ng/wasm-api-bindgen";
export type WasmInt = "i8" | "i16" | "i32" | "i64";
export type WasmUint = "u8" | "u16" | "u32" | "u64";
export type WasmFloat = FloatType;
export type WasmPrim = WasmInt | WasmUint | WasmFloat;
export type WasmPrim32 = Exclude<WasmPrim, BigType>;
export type TypeColl = IObjectOf<TopLevelType>;
export interface TypeInfo {
/**
* Auto-computed size (in bytes)
*
* @internal
*/
__size?: number;
/**
* Auto-computed offset (in bytes) in parent struct.
*
* @internal
*/
__offset?: number;
/**
* Auto-computed alignment (in bytes) actually used.
*
* @internal
*/
__align?: Pow2;
}
export interface TopLevelType extends TypeInfo {
/**
* Type name
*/
name: string;
/**
* Optional (multi-line) docstring for this type
*/
doc?: string | string[];
/**
* Type / kind.
*
* @remarks
* The {@link TYPESCRIPT} codegen doesn't emit function pointer types
* themselves and only supports them indirectly, e.g. as struct fields.
*/
type: "enum" | "ext" | "funcptr" | "struct" | "union";
/**
* Optional object of user provided source codes to be injected into the
* generated type (language dependent, only structs or unions, after
* generated fields). Keys of this object are language IDs (`ts` for
* {@link TYPESCRIPT}, `zig` for {@link ZIG}).
*
* @remarks
* Currently only supported by the code gens mentioned, ignored otherwise.
*/
body?: IObjectOf<string | string[] | InjectedBody>;
/**
* Optional array of language IDs for which code generation of this type
* will be skipped.
*/
skip?: string[];
}
export interface InjectedBody {
decl?: string | string[];
impl?: string | string[];
}
export interface External extends TopLevelType {
type: "ext";
/**
* Type alignment (in bytes)
*/
align: number;
/**
* Type's byte size
*/
size: number;
}
export interface Struct extends TopLevelType {
type: "struct";
/**
* Array of struct fields (might be re-ordered if {@link Struct.auto} is
* enabled).
*/
fields: Field[];
/**
* If true, struct fields will be re-ordered in descending order based on
* their {@link TypeInfo.__align} size. This might result in overall smaller
* structs due to minimizing implicit inter-field padding caused by
* alignment requirements. **If this option is enabled, then the struct MUST
* NOT contain any padding fields!**
*
* @defaultValue false
*/
auto?: boolean;
/**
* Optional user supplied {@link AlignStrategy}. By default uses
* {@link ALIGN_C}.
*/
align?: AlignStrategy;
}
export interface Union extends TopLevelType {
type: "union";
/**
* Array of union fields.
*/
fields: Field[];
/**
* Optional user supplied {@link AlignStrategy}. By default uses
* {@link ALIGN_C}.
*/
align?: AlignStrategy;
}
export type FieldTag = "single" | "array" | "ptr" | "slice" | "vec";
export interface Field extends TypeInfo {
/**
* Field name (prefix: "__" is reserved)
*/
name: string;
/**
* Field docstring (can be multiline, will be formatted)
*/
doc?: string | string[];
/**
* Field type tag/qualifier. `vec` is only supported by Zig & TS. `slice`
* fields will be polyfilled using auto-generated wrappers.
*
* @remarks
* - Array & vector fields are statically sized (using {@link Field.len})
* - If `pointer` and no `len` is given, pointers are emitted as
* single-value pointers (where this distinction exist)
* - If `pointer` and `len` is > 0, pointers are emitted as pointing to N
* values (for languages supporting this distinction, e.g. Zig)
* - If `pointer` and `len = 0`, pointers are emitted as pointing to an
* unspecified number of items (where this distinction is supported). In
* TypeScript only the target address of these pointers can be accessed.
* - `slice` will result in a struct consisting of a pointer, followed by
* length field. In Zig this struct also provides coercion functions
* to/from "normal" Zig slices.
* - Zig vectors will be processed using SIMD (if enabled in WASM target)
* and therefore will have stricter (larger) alignment requirements.
*
* @defaultValue `"single"`
*/
tag?: FieldTag;
/**
* Field base type. If not a {@link WasmPrim}, `string` or `opaque`, the
* value is interpreted as another type name in the {@link TypeColl}.
*
* @remarks
* Please see {@link CodeGenOpts.stringType} and consult package readme for
* further details re: string handling.
*
* Since `opaque` types have unknown size, they'll be **always** defined &
* interpreted as pointers. In TypeScript these fields can only be accessed
* as numbers (aka the pointers' target addresses).
*/
type: WasmPrim | "isize" | "usize" | "string" | "opaque" | string;
/**
* **Only used for pointers or slices.** Const qualifier (default is true
* for `string`, false for all other types).
*
* @remarks
* In our context, constness **always** refers to the target data, never to
* the pointer or slice itself (i.e. the pointer itself will always be
* mutable).
*/
const?: boolean;
/**
* Optional type qualifier. Currently only supported (as type) in
* {@link ZIG} for pointers (incl. `opaque`). In C/TypeScript the equivalent
* semantics are that the value will be zero if there's no value, otherwise
* the value is the pointer's target address.
*
* @defaultValue false
*/
optional?: boolean;
/**
* Currently only supported for {@link ZIG} arrays & slices, otherwise
* ignored!
*/
sentinel?: number;
/**
* Array or vector length (see {@link Field.tag})
*/
len?: number;
/**
* Currently only supported for {@link ZIG}, otherwise ignored!
*
* @remarks
* The object form allows for different default values per language (in
* theory). So if given as object, the keys refer to the lang ID and the
* values as the defaults for those languages.
*/
default?: NumOrString | IObjectOf<NumOrString>;
/**
* If defined and > 0, the field will be considered for padding purposes
* only and the value provided is the number of bytes used. All other config
* for this field will be ignored!
*/
pad?: number;
/**
* If true (default: false), code generation of this field will be skipped
* for WASM host environment languages (i.e. TypeScript).
*
* @remarks
* This is useful if some fields of a struct/union aren't actually used for
* WASM<>JS interop and thus can reduce the API surface & file size of the
* generated wrappers.
*
* @defaultValue false
*/
skip?: boolean;
/**
* If false, omits getter for languages which would usually define one (e.g.
* for TypeScript). Useful to avoid obsolete code and reduce file size.
*
* @defaultValue true
*/
getter?: boolean;
/**
* If false, omits setter for languages which would usually define one (e.g.
* for TypeScript). Useful to avoid obsolete code and reduce file size.
*
* @remarks
* If a field has its setter disabled, the generated TypeScript interface
* will declare this field as `readonly`.
*
* @defaultValue true
*/
setter?: boolean;
}
export interface Enum extends TopLevelType {
type: "enum";
/**
* No i64/u64 support, due to Typescript not supporting bigint enum values.
* For C compatibility only i32 or u32 is allowed.
*
* @defaultValue "i32"
*/
tag: Exclude<WasmPrim32, FloatType>;
/**
* List of possible values/IDs. Use {@link EnumValue}s for more detailed
* config.
*/
values: (string | EnumValue)[];
}
export interface EnumValue {
/**
* Enum value name/ID
*/
name: string;
/**
* Optional associated numeric value
*/
value?: number;
/**
* Optional docstring for this value
*/
doc?: string;
}
/**
* @remarks
* For Zig v0.12.0 compatibility, the Zig codegen emits all function pointers
* with the `callconv(.C)` attribute. Any function assigned to such a pointer
* will also have to specify the same calling convention.
*/
export interface FuncPointer extends TopLevelType {
type: "funcptr";
/**
* Return type spec (subset of {@link Field}).
*/
rtype: "void" | Pick<Field, "const" | "len" | "sentinel" | "tag" | "type">;
/**
* Function arg specs (subset of {@link Field}).
*/
args: Pick<Field, "const" | "len" | "name" | "sentinel" | "tag" | "type">[];
}
export interface AlignStrategy {
/**
* Returns implementation specific alignment for given struct field.
*/
align: Fn<Field, Pow2>;
/**
* Returns possibly rounded value for given base size & alignment.
*/
size: Fn2<number, Pow2, number>;
/**
* Returns possibly rounded value for given base offset & alignment.
*/
offset: Fn2<number, Pow2, number>;
}
export interface CodeGenOptsBase {
/**
* Optional string to be injected before generated type defs (but after
* codegen's own prelude, if any)
*/
pre?: string | string[];
/**
* Optional string to be injected after generated type defs (but before
* codegen's own epilogue, if any)
*/
post?: string | string[];
}
/**
* Global/shared code generator options.
*/
export interface CodeGenOpts extends CodeGenOptsBase {
/**
* WASM target specification.
*
* @defaultValue {@link WASM32}
*/
target: WasmTarget;
/**
* Identifier how strings are stored on WASM side, e.g. in Zig string
* literals are slices (8 bytes), in C just plain pointers (4 bytes) to
* zero-terminated char sequences.
*
* @defaultValue "ptr"
*/
stringType: "slice" | "ptr";
/**
* If true (default), forces uppercase enum identifiers.
*
* @remarks
* This option is ignored in {@link ZIG} since it's idiomatic for that
* language to only use lowercase/camelCase enum IDs.
*
* @defaultValue true
*/
uppercaseEnums: boolean;
/**
* Unless set to false, the generated output will be prefixed with a header
* line comment of generator meta data
*/
header: boolean;
/**
* If true, codegens MAY generate various additional struct & struct field
* analysis functions (sizes, alignment, offsets etc.).
*
* @defaultValue false
*/
debug: boolean;
/**
* Target line width for word wrapping doc strings
*
* @defaultValue 80
*/
lineWidth: number;
}
export interface ICodeGen {
/**
* Unique language ID. E.g. used to suppress generation for types utilizing
* {@link TopLevelType.skip}.
*/
id: string;
/**
* Optional prelude source, to be prepended before any generated type defs.
*/
pre?: Fn2<TypeColl, CodeGenOpts, string>;
/**
* Optional source code to be appended after any generated type defs.
*/
post?: Fn2<TypeColl, CodeGenOpts, string>;
/**
* Codegen for docstrings.
*
* @param doc
* @param acc
* @param opts
* @param topLevel
*/
doc(doc: string | string[], acc: string[], opts: CodeGenOpts, topLevel?: boolean): void;
/**
* Codegen for enum types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
enum(type: Enum, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Codegen for external types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
ext(type: External, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Code gen for function pointers.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
funcptr(type: FuncPointer, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Codegen for struct types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
struct(type: Struct, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Codegen for union types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
union(type: Union, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
}
export interface WasmTarget {
isize: "i32" | "i64";
usize: "u32" | "u64";
bits: number;
sizeBytes: number;
shift: number;
}
/**
* WASM32 target spec
*/
export declare const WASM32: WasmTarget;
/**
* WASM64 target spec
*/
export declare const WASM64: WasmTarget;
//# sourceMappingURL=api.d.ts.map