@thi.ng/wasm-api-bindgen
Version:
Polyglot bindings code generators (TS/JS, Zig, C11) for hybrid WebAssembly projects
313 lines (312 loc) • 9.55 kB
JSON
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schema.thi.ng/wasm-api/20221111.json",
"title": "WASM API code generator type specs",
"description": "Polyglot type definition for hybrid WASM/TypeScript applications",
"type": "array",
"items": {
"type": "object",
"oneOf": [
{ "$ref": "#/$defs/enum" },
{ "$ref": "#/$defs/ext" },
{ "$ref": "#/$defs/funcptr" },
{ "$ref": "#/$defs/struct" },
{ "$ref": "#/$defs/union" }
]
},
"$defs": {
"enum": {
"type": "object",
"properties": {
"body": { "$ref": "#/$defs/body" },
"doc": { "$ref": "#/$defs/doc" },
"name": { "$ref": "#/$defs/name" },
"skip": { "$ref": "#/$defs/skip" },
"type": {
"const": "enum",
"description": "This spec describes an `enum`-style type."
},
"tag": {
"$ref": "#/$defs/int",
"description": "Optional integer type to use. Defaults to `i32` Note: If C ABI compatibility is required, then `i32` MUST be used."
},
"values": {
"type": "array",
"items": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"name": { "type": "string" },
"value": {
"type": "integer",
"description": "Integer value associated with this name"
},
"doc": { "$ref": "#/$defs/doc" }
},
"required": ["name"]
}
],
"description": "Names should be given in lowercase. Some code generators can be configured to auto-capitalize these names."
},
"title": "Possible enum names",
"description": "Nonconsecutive or specific values are described via objects of `name`/`value` pairs."
}
},
"required": ["name", "type", "values"]
},
"ext": {
"type": "object",
"properties": {
"doc": { "$ref": "#/$defs/doc" },
"name": { "$ref": "#/$defs/name" },
"type": {
"const": "ext",
"description": "This spec describes an external type."
},
"align": {
"type": "integer",
"description": "Type alignment (in bytes)"
},
"size": {
"type": "integer",
"description": "Type size (in bytes)"
}
},
"required": ["name", "type", "align", "size"]
},
"funcptr": {
"type": "object",
"properties": {
"body": { "$ref": "#/$defs/body" },
"doc": { "$ref": "#/$defs/doc" },
"name": { "$ref": "#/$defs/name" },
"skip": { "$ref": "#/$defs/skip" },
"type": {
"const": "funcptr",
"description": "This spec describes a function pointer type."
},
"rtype": {
"anyOf": [
{ "const": "void" },
{ "$ref": "#/$defs/prim" },
{ "type": "string" }
],
"title": "Function return type",
"$ref": "#/$defs/docArgs"
},
"args": {
"type": "array",
"items": { "$ref": "#/$defs/field" },
"title": "Function arguments",
"$ref": "#/$defs/docArgs"
}
},
"required": ["name", "type", "rtype", "args"]
},
"struct": {
"type": "object",
"properties": {
"body": { "$ref": "#/$defs/body" },
"doc": { "$ref": "#/$defs/doc" },
"fields": { "$ref": "#/$defs/fields" },
"name": { "$ref": "#/$defs/name" },
"skip": { "$ref": "#/$defs/skip" },
"type": {
"const": "struct",
"description": "This spec describes a struct-style type."
}
}
},
"union": {
"type": "object",
"properties": {
"body": { "$ref": "#/$defs/body" },
"doc": { "$ref": "#/$defs/doc" },
"fields": { "$ref": "#/$defs/fields" },
"name": { "$ref": "#/$defs/name" },
"skip": { "$ref": "#/$defs/skip" },
"type": {
"const": "union",
"description": "This spec describes a union type."
}
}
},
"int": {
"enum": [
"i8",
"u8",
"i16",
"u16",
"i32",
"u32",
"i64",
"u64",
"isize",
"usize"
]
},
"prim": {
"oneOf": [
{ "$ref": "#/$defs/int" },
{
"enum": ["f32", "f64"]
}
]
},
"stringOrArray": {
"oneOf": [
{ "type": "string" },
{
"type": "array",
"items": { "type": "string" }
}
],
"description": "Each line will be automatically word-wrapped and prefixed with the appropriate comment syntax of the target language."
},
"name": {
"type": "string",
"title": "Type or field name",
"description": "This name will be used as-is by all code generators and therefore should ensure to not violate naming rules of any of the intended target languages."
},
"doc": {
"$ref": "#/$defs/stringOrArray",
"title": "Docstring for this type or field."
},
"docArgs": {
"description": "With a few exceptions & language specific limitations, the range of possibilities is similar to field types."
},
"field": {
"type": "object",
"description": "Type spec for a single field within a struct or union. If `pad` is given, all other keys are ignored and the field is only considered for padding/alignment/sizing purposes. Names for padding fields will be autogenerated.",
"properties": {
"name": { "$ref": "#/$defs/name" },
"doc": { "$ref": "#/$defs/doc" },
"type": { "$ref": "#/$defs/fieldType" },
"tag": { "$ref": "#/$defs/fieldTag" },
"const": {
"type": "boolean",
"description": "Marks type as constant / readonly data. Note: For pointers this refers to the target data, not to the pointer itself."
},
"optional": {
"type": "boolean",
"description": "Marks type as optional. Language specific and currently only supported for pointer types."
},
"sentinel": {
"type": "integer",
"description": "Optional value for sentinel-terminated arrays/pointers"
},
"pad": {
"type": "integer",
"minimum": 1,
"description": "Number of padding bytes. If given, all other keys are ignored."
},
"default": {
"description": "Optional default value (or verbatim source code). If given as object, language specific defaults can be provided.",
"oneOf": [
{ "type": "number" },
{ "type": "string" },
{
"type": "object",
"additionalProperties": {
"oneOf": [
{ "type": "number" },
{ "type": "string" }
]
}
}
]
},
"skip": {
"type": "boolean",
"default": false,
"description": "If true, code generation of this field will be skipped for WASM host environment languages (e.g. TypeScript)"
},
"getter": {
"type": "boolean",
"default": true,
"description": "If false, omits getter for languages which would usually define one (e.g. TypeScript)"
},
"setter": {
"type": "boolean",
"default": true,
"description": "If false, omits setter for languages which would usually define one (e.g. TypeScript)"
}
},
"required": ["name", "type"],
"if": {
"properties": {
"tag": {
"oneOf": [{ "const": "array" }, { "const": "vec" }]
}
},
"required": ["tag"]
},
"then": {
"properties": {
"len": {
"type": "integer",
"minimum": 1,
"default": 1,
"description": "Array or vector length"
}
},
"required": ["len"]
}
},
"fieldType": {
"anyOf": [
{ "$ref": "#/$defs/prim" },
{
"enum": ["opaque", "string"]
},
{
"type": "string"
}
],
"title": "Field type",
"description": "Either a WASM primitive type, a preset name (i.e. `opaque` or `string`) or the name of another type in this document.\n\n- `isize` / `usize` types will be sized depending on chosen WASM target (wasm32/wasm64).\n- `opaque` types are always considered pointers only.\n- `string` types are language specific and the result type can be configured via codegen options (i.e. slice vs. raw pointer)."
},
"fieldTag": {
"enum": ["array", "ptr", "single", "slice", "vec"],
"default": "single",
"title": "Optional array type modifier",
"description": "If `array` or `vec` is selected, the `len` MUST be given too. Note: Not all tags are natively supported by all languages and might result in generation of \"polyfills\". E.g. vectors are similar to arrays, but have stricter alignment & potentially different codegeneration (language specific)."
},
"fields": {
"type": "array",
"items": { "$ref": "#/$defs/field" },
"description": "Array of fields specs for a struct or union type"
},
"body": {
"type": "object",
"title": "Optional custom per-language user code injections",
"description": "Keys of this object are target language IDs and values are source code (will be automatically indented). Use object values (with `decl` and `impl` keys) for languages requiring multiple injection points for declaration vs. implementation (e.g. TypeScript).",
"additionalProperties": {
"oneOf": [
{ "$ref": "#/$defs/stringOrArray" },
{
"type": "object",
"properties": {
"decl": {
"$ref": "#/$defs/stringOrArray",
"title": "User code for additional declarations"
},
"impl": {
"$ref": "#/$defs/stringOrArray",
"title": "User code for additional implementations"
}
},
"description": "The `decl` and `impl` keys can be used for languages requiring multiple injection points for declarations (e.g. interface additions) vs. implementation methods (e.g. within a struct)"
}
]
}
},
"skip": {
"type": "array",
"items": { "type": "string" },
"description": "List of language IDs for which code generation of this type should be skipped."
}
}
}