An Overview of WIT
The WIT (Wasm Interface Type) language is used to define Component Model interfaces and worlds. WIT isn't a general-purpose coding language and doesn't define behaviour; it defines only contracts between components. This topic provides an overview of key elements of the WIT language. The official WIT specification and history can be found in the WebAssembly/component-model repository.
- An Overview of WIT
Structure of a WIT file
A WIT file contains one or more interfaces or worlds. An interface or world can define types and/or functions.
Types and functions can't be defined outside of interfaces or worlds.
A file may optionally start with a package declaration.
Comments
WIT comment syntax is similar to the one used by the C++ family of languages:
- Everything from
//to end of line is a comment. - Any text enclosed in
/*...*/is a comment.- Unlike the C++ family, block comments can be nested, e.g.
/* blah /* rabbit */ rhubarb */.
- Unlike the C++ family, block comments can be nested, e.g.
Documentation
WIT defines special comment formats for documentation:
- Everything from
///to end of line is documentation for the following item. - Any text enclosed in
/**...*/is documentation for the following item.
For example:
<span class='hljs-comment'>/// Prints "hello".</span>
print-hello<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>/**
Prints "hello".
*/</span>
print-hello<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
Identifiers
WIT identifiers have a slightly different set of rules from what you might be familiar with from, say, C, Rust, or Java. These rules apply to all names - types, functions, interfaces, and worlds. (Package identifiers are a little more complex and will be covered in the Packages section.)
- Identifiers are restricted to ASCII
kebab-case- sequences of words, separated by single hyphens.- Double hyphens (
--) are not allowed. - Hyphens aren't allowed at the beginning or end of the sequence, only between words.
- Double hyphens (
- An identifier may be preceded by a single
%sign.- This is required if the identifier would otherwise be a WIT keyword. For example,
interfaceis not a legal identifier, but%interfaceis legal.
- This is required if the identifier would otherwise be a WIT keyword. For example,
- Each word in the sequence must begin with an ASCII letter, and may contain only ASCII letters and digits.
- A word cannot begin with a digit.
- A word cannot contain a non-ASCII Unicode character.
- A word cannot contain punctuation, underscores, etc.
- Each word must be either all
lowercaseor allUPPERCASE.- Different words in the identifier may have different cases. For example,
WIT-demois allowed.
- Different words in the identifier may have different cases. For example,
- An identifier cannot be a WIT keyword such as
interface(unless preceded by a%sign).
Built-in types
The types in this section are defined by the WIT language itself.
Primitive types
WIT defines the following primitive types:
| Identifier | Description |
|---|---|
bool | Boolean value true or false. |
s8, s16, s32, s64 | Signed integers of the appropriate width. For example, s32 is a signed 32-bit integer. |
u8, u16, u32, u64 | Unsigned integers of the appropriate width. For example, u32 is an unsigned 32-bit integer. |
f32, f64 | Floating-point numbers of the appropriate width. For example, f64 is a 64-bit (double precision) floating-point number. See the note on NaNs below. |
char | Unicode character. (Specifically, a Unicode scalar value.) |
string | A Unicode string - that is, a finite sequence of characters. |
The
f32andf64types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a singlenanvalue. The exact bit-level representation of an IEEE 754NaNis not guaranteed to be preserved when values pass through WIT interfaces as the singular WITnanvalue.
Lists
list<T> for any type T denotes an ordered sequence of values of type T. T can be any type, built-in or user-defined:
<span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span> <span class='hljs-comment'>// byte buffer</span>
<span class='hljs-type'>list</span><span class='hljs-punctuation'><</span>customer<span class='hljs-punctuation'>></span> <span class='hljs-comment'>// a list of customers</span>
This is similar to Rust Vec, or Java List.
Options
option<T> for any type T may contain a value of type T, or may contain no value. T can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found:
<span class='hljs-type'>option</span><span class='hljs-punctuation'><</span>customer<span class='hljs-punctuation'>></span>
This is similar to Rust Option, C++ std::optional, or Haskell Maybe.
This is a special case of a variant type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types.
Results
result<T, E> for any types T and E may contain a value of type T or a value of type E (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the T type) representing a HTTP response, and the error case (the E type) representing the various kinds of error that might occur:
<span class='hljs-type'>result</span><span class='hljs-punctuation'><</span>http-response<span class='hljs-punctuation'>,</span> http-error<span class='hljs-punctuation'>></span>
This is similar to Rust Result, or Haskell Either.
This is a special case of a variant type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types.
Sometimes there is no data associated with one or both of the cases. For example, a print function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows:
<span class='hljs-type'>result</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u32</span><span class='hljs-punctuation'>></span> <span class='hljs-comment'>// no data associated with the error case</span>
<span class='hljs-type'>result</span><span class='hljs-punctuation'><</span><span class='hljs-punctuation'>_</span><span class='hljs-punctuation'>,</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>></span> <span class='hljs-comment'>// no data associated with the success case</span>
<span class='hljs-type'>result</span> <span class='hljs-comment'>// no data associated with either case</span>
Tuples
A tuple type is an ordered fixed length sequence of values of specified types. It is similar to a record, except that the fields are identified by their order instead of by names.
<span class='hljs-type'>tuple</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u64</span><span class='hljs-punctuation'>,</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>></span> <span class='hljs-comment'>// An integer and a string</span>
<span class='hljs-type'>tuple</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u64</span><span class='hljs-punctuation'>,</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>,</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>></span> <span class='hljs-comment'>// An integer, then a string, then an integer</span>
This is similar to tuples in Rust or OCaml.
User-defined types
You can define your own types within an interface or world. WIT offers several ways of defining new types.
Records
A record type declares a set of named fields, each of the form name: type, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows:
<span class='hljs-keyword'>record</span> customer <span class='hljs-punctuation'>{</span>
id<span class='hljs-punctuation'>:</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>,</span>
name<span class='hljs-punctuation'>:</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>,</span>
picture<span class='hljs-punctuation'>:</span> <span class='hljs-type'>option</span><span class='hljs-punctuation'><</span><span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>,</span>
account-manager<span class='hljs-punctuation'>:</span> employee<span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
Records are similar to C or Rust structs.
User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic.
Variants
A variant type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows:
<span class='hljs-keyword'>variant</span> allowed-destinations <span class='hljs-punctuation'>{</span>
none<span class='hljs-punctuation'>,</span>
any<span class='hljs-punctuation'>,</span>
restricted<span class='hljs-punctuation'>(</span><span class='hljs-type'>list</span><span class='hljs-punctuation'><</span>address<span class='hljs-punctuation'>></span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
Variants are similar to Rust enums or OCaml discriminated unions. The closest C equivalent is a tagged union, but WIT both takes care of the "tag" (the case) and enforces the correct data shape for each tag.
User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic.
Enums
An enum type is a variant type where none of the cases have associated data:
<span class='hljs-keyword'>enum</span> color <span class='hljs-punctuation'>{</span>
hot-pink<span class='hljs-punctuation'>,</span>
lime-green<span class='hljs-punctuation'>,</span>
navy-blue<span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
This can provide a simpler representation in languages without discriminated unions. For example, a WIT enum can translate directly to a C++ enum.
Resources
Resources are handles to some entity that lives outside of the component. They describe things that can't or shouldn't be copied by value; instead, their ownership or reference can be passed between two components via a handle. Unlike other WIT types which are simply plain data, resources only expose behavior through methods. Resources can be thought of as objects that implement an interface.
For example, we could model a blob (binary large object) as a resource. The
following WIT defines the blob resource type, which contains a constructor,
two methods, and a static function:
<span class='hljs-keyword'>resource</span> blob <span class='hljs-punctuation'>{</span>
constructor<span class='hljs-punctuation'>(</span>init<span class='hljs-punctuation'>:</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
write<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>bytes<span class='hljs-punctuation'>:</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
read<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>n<span class='hljs-punctuation'>:</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
merge<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>static</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>lhs<span class='hljs-punctuation'>:</span> blob<span class='hljs-punctuation'>,</span> rhs<span class='hljs-punctuation'>:</span> blob<span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> blob<span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
As shown in the blob example, a resource can contain:
- methods: functions that implicitly take a
self(often calledthisin many languages) parameter that is a handle - static functions: functions which do not have an implicit
selfparameter but are meant to be nested in the scope of the resource type - at most one constructor: a function that is syntactic sugar for a function returning a handle of the containing resource type
Methods always desugar to a borrowed self parameter whereas constructors
always desugar to an owned return value. For example, the blob resource
above could be approximated as:
<span class='hljs-keyword'>resource</span> blob<span class='hljs-punctuation'>;</span>
blob-constructor<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>bytes<span class='hljs-punctuation'>:</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> blob<span class='hljs-punctuation'>;</span>
blob-write<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>self<span class='hljs-punctuation'>:</span> <span class='hljs-type'>borrow</span><span class='hljs-punctuation'><</span>blob<span class='hljs-punctuation'>></span><span class='hljs-punctuation'>,</span> bytes<span class='hljs-punctuation'>:</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
blob-read<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>self<span class='hljs-punctuation'>:</span> <span class='hljs-type'>borrow</span><span class='hljs-punctuation'><</span>blob<span class='hljs-punctuation'>></span><span class='hljs-punctuation'>,</span> n<span class='hljs-punctuation'>:</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
blob-merge<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>static</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>lhs<span class='hljs-punctuation'>:</span> blob<span class='hljs-punctuation'>,</span> rhs<span class='hljs-punctuation'>:</span> blob<span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> blob<span class='hljs-punctuation'>;</span>
When a resource type name is wrapped with borrow<...>, it stands for a
"borrowed" resource. A borrowed resource represents a temporary loan of a resource from the
caller to the callee for the duration of the call. In contrast, when the owner
of an owned resource drops that resource, the resource is destroyed.
More precisely, these are borrowed or owned
handlesof the resource. Learn more abouthandlesin the upstream component model specification.
Flags
A flags type is a set of named booleans. In an instance of the type, each flag will be either true or false.
<span class='hljs-keyword'>flags</span> allowed-methods <span class='hljs-punctuation'>{</span>
get<span class='hljs-punctuation'>,</span>
post<span class='hljs-punctuation'>,</span>
put<span class='hljs-punctuation'>,</span>
delete<span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
A
flagstype is logically equivalent to a record type where each field is of typebool, but it is represented more efficiently (as a bitfield) at the binary level.
Type aliases
You can define a new named type using type ... = .... This can be useful for giving shorter or more meaningful names to types:
<span class='hljs-keyword'>type</span> buffer <span class='hljs-operator'>=</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>type</span> http-<span class='hljs-type'>result</span> <span class='hljs-operator'>=</span> <span class='hljs-type'>result</span><span class='hljs-punctuation'><</span>http-response<span class='hljs-punctuation'>,</span> http-error<span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
Functions
A function is defined by a name and a function type. Like in record fields, the name is separated from the type by a colon:
do-nothing<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
The function type is the word func, followed by a parenthesised, comma-separated list of parameters (names and types). If the function returns a value, this is expressed as an arrow symbol (->) followed by the return type:
<span class='hljs-comment'>// This function does not return a value</span>
print<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>message<span class='hljs-punctuation'>:</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// These functions return values</span>
add<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>a<span class='hljs-punctuation'>:</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>,</span> b<span class='hljs-punctuation'>:</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>;</span>
lookup<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>store<span class='hljs-punctuation'>:</span> kv-store<span class='hljs-punctuation'>,</span> key<span class='hljs-punctuation'>:</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-type'>option</span><span class='hljs-punctuation'><</span><span class='hljs-type'>string</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
A function can have multiple return values. In this case the return values must be named, similar to the parameter list. All return values must be populated (in the same way as tuple or record fields).
get-customers-paged<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span>cont<span class='hljs-punctuation'>:</span> continuation-token<span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-punctuation'>(</span>customers<span class='hljs-punctuation'>:</span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span>customer<span class='hljs-punctuation'>></span><span class='hljs-punctuation'>,</span> cont<span class='hljs-punctuation'>:</span> continuation-token<span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
A function can be declared as part of an interface, or can be declared as an import or export in a world.
Interfaces
An interface is a named set of types and functions, enclosed in braces and introduced with the interface keyword:
<span class='hljs-keyword'>interface</span> canvas <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>type</span> <span class='hljs-type'>canvas-id</span> <span class='hljs-operator'>=</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>record</span> <span class='hljs-type'>point</span> <span class='hljs-punctuation'>{</span>
<span class='hljs-variable'>x</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>,</span>
<span class='hljs-variable'>y</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-title function_'>draw-line</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-variable'>canvas</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>canvas-id</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable'>from</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>point</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable'>to</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>point</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
Notice that items in an interface are not comma-separated.
Using definitions from elsewhere
An interface can reuse types declared in another interface via a use directive. The use directive must give the interface where the types are declared, then a dot, then a braced list of the types to be reused. The interface can then refer to the types named in the use.
<span class='hljs-keyword'>interface</span> types <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>type</span> <span class='hljs-type'>dimension</span> <span class='hljs-operator'>=</span> <span class='hljs-type'>u32</span><span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>record</span> <span class='hljs-type'>point</span> <span class='hljs-punctuation'>{</span>
<span class='hljs-variable'>x</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>dimension</span><span class='hljs-punctuation'>,</span>
<span class='hljs-variable'>y</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>dimension</span><span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-keyword'>interface</span> canvas <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>use</span> types<span class='hljs-punctuation'>.</span><span class='hljs-punctuation'>{</span>dimension<span class='hljs-punctuation'>,</span> point<span class='hljs-punctuation'>}</span><span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>type</span> <span class='hljs-type'>canvas-id</span> <span class='hljs-operator'>=</span> <span class='hljs-type'>u64</span><span class='hljs-punctuation'>;</span>
<span class='hljs-title function_'>draw-line</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-variable'>canvas</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>canvas-id</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable'>from</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>point</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable'>to</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>point</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable'>thickness</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>dimension</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
Even if you are only using one type, it must still be enclosed in braces. For example,
use types.{dimension}is legal butuse types.dimensionis not.
This works across files as long as the files are in the same package (effectively, in the same directory). For information about using definitions from other packages, see the specification.
Worlds
A world describes a set of imports and exports, enclosed in braces and introduced with the world keyword. Roughly, a world describes the contract of a component. Exports are provided by the component, and define what consumers of the component may call; imports are things the component may call. The imports and exports may be interfaces or individual functions.
<span class='hljs-keyword'>interface</span> printer <span class='hljs-punctuation'>{</span>
<span class='hljs-title function_'>print</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-variable'>text</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-keyword'>interface</span> error-reporter <span class='hljs-punctuation'>{</span>
<span class='hljs-title function_'>report-error</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-variable'>error-message</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>string</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-keyword'>world</span> multi-function-device <span class='hljs-punctuation'>{</span>
<span class='hljs-comment'>// The component implements the `printer` interface</span>
<span class='hljs-keyword'>export</span> printer<span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// The component implements the `scan` function</span>
<span class='hljs-keyword'>export</span> <span class='hljs-title function_'>scan</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>-></span> <span class='hljs-type'>list</span><span class='hljs-punctuation'><</span><span class='hljs-type'>u8</span><span class='hljs-punctuation'>></span><span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// The component needs to be supplied with an `error-reporter`</span>
<span class='hljs-keyword'>import</span> error-reporter<span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
Interfaces from other packages
You can import and export interfaces defined in other packages. This can be done using package/name syntax:
<span class='hljs-keyword'>world</span> http-proxy <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>export</span> wasi<span class='hljs-punctuation'>:</span>http<span class='hljs-punctuation'>/</span>incoming-handler<span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>import</span> wasi<span class='hljs-punctuation'>:</span>http<span class='hljs-punctuation'>/</span>outgoing-handler<span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour.
WIT does not define how packages are resolved - different tools may resolve them in different ways.
Inline interfaces
Interfaces can be declared inline in a world:
<span class='hljs-keyword'>world</span> toy <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>export</span> example<span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>interface</span> <span class='hljs-punctuation'>{</span>
<span class='hljs-title function_'>do-nothing</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-punctuation'>}</span>
Including other worlds
You can include another world. This causes your world to export all that world's exports, and import all that world's imports.
<span class='hljs-keyword'>world</span> glow-in-the-dark-multi-function-device <span class='hljs-punctuation'>{</span>
<span class='hljs-comment'>// The component provides all the same exports, and depends on</span>
<span class='hljs-comment'>// all the same imports, as a `multi-function-device`...</span>
<span class='hljs-keyword'>include</span> multi-function-device<span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// ...but also exports a function to make it glow in the dark</span>
<span class='hljs-keyword'>export</span> <span class='hljs-title function_'>glow</span><span class='hljs-punctuation'>:</span> <span class='hljs-keyword'>func</span><span class='hljs-punctuation'>(</span><span class='hljs-variable'>brightness</span><span class='hljs-punctuation'>:</span> <span class='hljs-type'>u8</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
As with use directives, you can include worlds from other packages.
Packages
A package is a set of interfaces and worlds, potentially defined across multiple files. To declare a package, use the package directive to specify the package ID. This must include a namespace and name, separated by a colon, and may optionally include a semver-compliant version:
<span class='hljs-keyword'>package</span> documentation<span class='hljs-punctuation'>:</span>example<span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>package</span> documentation<span class='hljs-punctuation'>:</span>example<span class='hljs-punctuation'>@</span><span class='hljs-string'>1.0.1</span><span class='hljs-punctuation'>;</span>
If a package spans multiple files, only one file needs to contain a package declaration (but if multiple files contain declarations then they must all be the same). All files must have the .wit extension and must be in the same directory. For example, the following documentation:http package is spread across four files:
<span class='hljs-comment'>// types.wit</span>
<span class='hljs-keyword'>interface</span> types <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>record</span> <span class='hljs-type'>request</span> <span class='hljs-punctuation'>{</span> <span class='hljs-comment'>/* ... */</span> <span class='hljs-punctuation'>}</span>
<span class='hljs-keyword'>record</span> <span class='hljs-type'>response</span> <span class='hljs-punctuation'>{</span> <span class='hljs-comment'>/* ... */</span> <span class='hljs-punctuation'>}</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-comment'>// incoming.wit</span>
<span class='hljs-keyword'>interface</span> incoming-handler <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>use</span> types<span class='hljs-punctuation'>.</span><span class='hljs-punctuation'>{</span>request<span class='hljs-punctuation'>,</span> response<span class='hljs-punctuation'>}</span><span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// ...</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-comment'>// outgoing.wit</span>
<span class='hljs-keyword'>interface</span> outgoing-handler <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>use</span> types<span class='hljs-punctuation'>.</span><span class='hljs-punctuation'>{</span>request<span class='hljs-punctuation'>,</span> response<span class='hljs-punctuation'>}</span><span class='hljs-punctuation'>;</span>
<span class='hljs-comment'>// ...</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-comment'>// http.wit</span>
<span class='hljs-keyword'>package</span> documentation<span class='hljs-punctuation'>:</span>http<span class='hljs-punctuation'>@</span><span class='hljs-string'>1.0.0</span><span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>world</span> proxy <span class='hljs-punctuation'>{</span>
<span class='hljs-keyword'>export</span> incoming-handler<span class='hljs-punctuation'>;</span>
<span class='hljs-keyword'>import</span> outgoing-handler<span class='hljs-punctuation'>;</span>
<span class='hljs-punctuation'>}</span>
For a more formal definition of the WIT language, take a look at the WIT specification.