Introduction

Type System

Definitions are for OpenAPI v3.1.0:

JSON Schema TypeOpenAPI Format ModifierWIT Type
null-option<T>
boolean-bool
object-record
array-list<T>
number-float64
numberfloatfloat32
numberdoublefloat64
string-string
stringpasswordstring
integerint32s32
integerint64s64

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,
}