Introduction
Type System
Definitions are for OpenAPI v3.1.0:
JSON Schema Type | OpenAPI Format Modifier | WIT Type |
---|---|---|
null | - | option<T> |
boolean | - | bool |
object | - | record |
array | - | list<T> |
number | - | float64 |
number | float | float32 |
number | double | float64 |
string | - | string |
string | password | string |
integer | int32 | s32 |
integer | int64 | s64 |
Discussion
number
The base number
type without any qualifier here is mapped to float64
. The
JSON Schema specification mentions it should actually be:
An arbitrary-precision, base-10 decimal number value, from the JSON "number" value.
But we want to be able to use serde-json
for this, which defines number
as
an
f64
.
WIT does not (yet?) support arbitrary-precision floating point numbers, so in
the absence of any constraining information we should just pick the biggest
number we can support.
null
WIT also has no notion of null
in the type system; instead it uses the
option
type to indicate a value may or may not be present. A field which can
only ever be null
should be rejected in any encoding - in Rust terms we'd want
to translate that to a type of Option<!>
(only None
can be constructed) - or
Option<Unreachable>
(an empty enum akin to !
). But in WIT we can't do either of these things, so a field that's hard-coded to only ever be none
should be rejected to prevent any ambiguities in the encoding.
password
Regarding password strings: for the sake of simplicity we should treat this as a
regular string for the time being. However in the future we may want to define a
generic type sensitive<T>
which can hold strings whose contents are sensitive
and should never be printed or displayed. This will require a non-trivial type
system addition though, as we'll also want to consider secret encoding /
decoding schemes, if only to ensure we're making the right tradeoffs. So to not
have that conversation right now, we're just treating password strings as
regular strings.
See Also
Examples
These are example mappings from WIT
<-> OpenAPI
, showing how we intend
codegen to work between the two.
Pet Store
OpenAPI definition
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}
WIT definition
Routes
interface pets {
record list-pets-input {
limit: option<s32>
}
record list-pets-response {
pet-array: list<pet>,
x-next: string,
}
func list-pets(input: list-pets-input) -> result<list-pets-response, error>;
func create-pets() -> result<_, error> {}
record show-pet-by-id-input {
pet-id: string,
}
func show-pet-by-id(show-pet-by-id-input) -> result<pet, error> {}
}
Schemas
record pet {
id: s64,
name: string,
tag: string,
}
type pets = list<pet>;
record error {
code: s32,
message: string,
}