UNPKG

@thi.ng/wasm-api-bindgen

Version:

Polyglot bindings code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects

435 lines 13.3 kB
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