├── .gitattributes ├── .github └── workflows │ └── main.yml ├── README.md ├── http-service.md ├── imports.md ├── messaging-service.md ├── service.md ├── test └── README.md └── wit ├── deps.lock ├── deps.toml ├── deps ├── blobstore │ ├── blobstore.wit │ ├── container.wit │ ├── types.wit │ └── world.wit ├── cli │ ├── command.wit │ ├── environment.wit │ ├── exit.wit │ ├── imports.wit │ ├── run.wit │ ├── stdio.wit │ └── terminal.wit ├── clocks │ ├── monotonic-clock.wit │ ├── timezone.wit │ ├── wall-clock.wit │ └── world.wit ├── filesystem │ ├── preopens.wit │ ├── types.wit │ └── world.wit ├── http │ ├── handler.wit │ ├── proxy.wit │ └── types.wit ├── io │ ├── error.wit │ ├── poll.wit │ ├── streams.wit │ └── world.wit ├── keyvalue │ ├── atomic.wit │ ├── batch.wit │ ├── store.wit │ ├── watch.wit │ └── world.wit ├── messaging │ ├── consumer.wit │ ├── guest.wit │ ├── messaging.wit │ ├── producer.wit │ └── types.wit ├── random │ ├── insecure-seed.wit │ ├── insecure.wit │ ├── random.wit │ └── world.wit ├── runtime-config │ ├── store.wit │ └── world.wit ├── sockets │ ├── instance-network.wit │ ├── ip-name-lookup.wit │ ├── network.wit │ ├── tcp-create-socket.wit │ ├── tcp.wit │ ├── udp-create-socket.wit │ ├── udp.wit │ └── world.wit └── sql │ ├── readwrite.wit │ ├── sql.wit │ └── types.wit └── world.wit /.gitattributes: -------------------------------------------------------------------------------- 1 | # A hack to enable some degree of syntax highlighting on GitHub. Should be removed if GitHub ever receives native support for Wit files. 2 | *.wit linguist-language=Rust -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [main] 5 | pull_request: 6 | branches: [main] 7 | 8 | jobs: 9 | abi-up-to-date: 10 | name: Check ABI files are up-to-date 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: ensure `./wit/deps` are in sync 15 | run: | 16 | curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.2/wit-deps-x86_64-unknown-linux-musl 17 | chmod +x ./wit-deps 18 | ./wit-deps lock --check 19 | - uses: WebAssembly/wit-abi-up-to-date@v17 20 | with: 21 | wit-bindgen: '0.30.0' 22 | worlds: 'imports messaging-service http-service service' 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `wasi-cloud-core` 2 | 3 | A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) API. 4 | 5 | ### Current Phase 6 | 7 | `wasi-cloud-core` is currently in [Phase 1](https://github.com/WebAssembly/WASI/blob/main/Proposals.md#phase-1---feature-proposal-cg). 8 | 9 | ### Champions 10 | 11 | - [Dan Chiarlone](https://github.com/danbugs) 12 | - [David Justice](https://github.com/devigned) 13 | - [Jiaxiao Zhou](https://github.com/Mossaka) 14 | - [Taylor Thomas](https://github.com/thomastaylor312) 15 | 16 | ### Phase 4 Advancement Criteria 17 | 18 | `wasi-cloud-core` should have at least two implementations (i.e., from service providers, and or cloud providers), and, at the very minimum, pass the testsuite for Windows, Linux, and MacOS. 19 | 20 | ## Table of Contents [if the explainer is longer than one printed page] 21 | 22 | - [Introduction](#introduction) 23 | - [Out-of-Scope Capabilities (for now)](#out-of-scope-capabilities-for-now) 24 | 25 | ### Introduction 26 | 27 | > Note: This proposal currently only contains the proposed WIT interfaces; more work is necessary to fully document the proposal. 28 | 29 | `wasi-cloud-core` World aims to provide a generic way for WASI applications to interact with services. This world is created by including many other WASI worlds being proposed in the WASI community. The following is a list of the worlds that are currently being included in `wasi-cloud-core`. 30 | 31 | - [wasi-keyvalue](https://github.com/WebAssembly/wasi-keyvalue) 32 | - [wasi-messaging](https://github.com/WebAssembly/wasi-messaging) 33 | - [wasi-http](https://github.com/WebAssembly/wasi-http) 34 | - [wasi-runtime-config](https://github.com/WebAssembly/wasi-runtime-config) 35 | - [wasi-blob-store](https://github.com/WebAssembly/wasi-blob-store) 36 | 37 | This list of services provide a set of capabilities that are common to many applications. Examples: handling an HTTP request, responding to a pub/sub message, storing a key/value pair, etc. It targets a wide range of applications, from long-running services to "bursty workloads" like Edge functions, serverless functions or Cloud events. 38 | 39 | This set of capabilities are derived from the best practices of building distributed applications. It is not intended to be a complete set of capabilities, but rather are needed by 80% of applications. 40 | 41 | ### Out-of-Scope Capabilities (for now) 42 | 43 | - [wasi-sql](https://github.com/WebAssembly/wasi-sql): the scope of the `wasi:sql` is not clear yet, and it is decided to be dropped from the wasi-cloud-core proposal. 44 | - [wasi-distributed-lock-service](https://github.com/WebAssembly/wasi-distributed-lock-service): the distributed lock service is a very specific service that is not needed by 80% of applications. It is decided to be dropped from the wasi-cloud-core proposal. 45 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Testing guidelines 2 | 3 | TK fill in testing guidelines 4 | 5 | ## Installing the tools 6 | 7 | TK fill in instructions 8 | 9 | ## Running the tests 10 | 11 | TK fill in instructions 12 | -------------------------------------------------------------------------------- /wit/deps.lock: -------------------------------------------------------------------------------- 1 | [blobstore] 2 | url = "https://github.com/WebAssembly/wasi-blobstore/archive/main.tar.gz" 3 | sha256 = "20cef78d42a6b933a6fd46b06275119219e22197dc33c4426df3b2a4c5562dbc" 4 | sha512 = "f0ae942f356f6ec5ff23451dddf638042ab120cf8aea858b45dae5f467b3f60f5442802912963e6cd9ede84a216aabaee930917f062c0906fe2124e52d5d118b" 5 | 6 | [cli] 7 | sha256 = "1de50b8e6940e73110cda10b7f90ca87a8fea886f0fa36c748f96dc70671ee38" 8 | sha512 = "bbb6cd3e7b4d3237b6af9bfbb2633ccd2c4ea2a4f37b8c033255c7e0c1cb037be7f22ec1f8ca792cc8ec1942199582943979e646b4b272b85dcff7654eac51d0" 9 | 10 | [clocks] 11 | sha256 = "ea9d69ee803bc176e23e5268f5e24a2ac485dd1f62a0ab4c748e9d3f901f576f" 12 | sha512 = "5efc22927c46cd56c41e5549ec775561c7fac2ea0d365abc0b55396d9475a7c9f984077a81f84a44a726f1c008fd2fadbffffa4fa53ecd5fbfd05afd379ab428" 13 | 14 | [filesystem] 15 | sha256 = "cfe8c420e8b857de612ae2a3336680dae16b95c93c8ba3a6ff05b21210966740" 16 | sha512 = "3c00c5544a58658e3e8025677091685286027fd49f37abf198c30b4e83b9e68f19723975aaa98794fba9f425ae9ef4f3dc0f5b9cf59203b5ecfaadf62b296f9a" 17 | 18 | [http] 19 | url = "https://github.com/WebAssembly/wasi-http/archive/main.tar.gz" 20 | sha256 = "4c29be1bbe660c3d995b1eadf5dd702484c0b417fd273331bafaf6a002188ddd" 21 | sha512 = "3b76ea7263f8d71b264c9f6ae7cdcba09d52be04427dfcb8f785a447ceba09519a6f46807fe82444df796feb2d58129acd108028839ca881777ddcabb3c863a7" 22 | deps = ["cli", "clocks", "filesystem", "random", "sockets"] 23 | 24 | [io] 25 | url = "https://github.com/WebAssembly/wasi-io/archive/main.tar.gz" 26 | sha256 = "47d2cfaacb3648de9b0b3458e87363d21e28440506036e8f32896129b7512f9b" 27 | sha512 = "594ce1a78fda400de47a45044308472e7ea5f37a8e6a5d2fa28b067a8e2d0954dd84d4b1d764b1c343935bb2b24e89364e82deaa17e97bbb5cbf1667bad1202c" 28 | 29 | [keyvalue] 30 | url = "https://github.com/WebAssembly/wasi-keyvalue/archive/main.tar.gz" 31 | sha256 = "7eaf2e10af6e2de6d5a168893e2656c6685de2009bd37fdc944859f5a6753e55" 32 | sha512 = "ecf0dd2e0b6e5f62c2e10673cc8c2aab86c532f8b19c984fe2ecd9306e9a5c2783183143274477cc4fb3b037b2db2817f248a6bf84b3279180ca4dba832bf5dc" 33 | 34 | [messaging] 35 | url = "https://github.com/WebAssembly/wasi-messaging/archive/main.tar.gz" 36 | sha256 = "78a631ca15186602187fc5b4e5686e08ed4b412253d5112d37d7641aca4f4149" 37 | sha512 = "62d5df0f892b41ce704f7b989e85cad4743599b275f6e11fdb13a63be9079f5dfbf19d3198ef1824e2571381fe1061e699dad91b950c1c219d685d70a55e955a" 38 | 39 | [random] 40 | sha256 = "9e2d5056186f81b2e7f96bc97d2babd0341840f6abb4f170449b70992f1b598f" 41 | sha512 = "67bf41d8d5d4b7af084124ee85196585225785969059f59e2f9ddb77ac1a8095cfe811ae29d076aac817418fa01064d7b9fbc0233930bace680758eeb21e36f8" 42 | 43 | [runtime-config] 44 | url = "https://github.com/WebAssembly/wasi-runtime-config/archive/main.tar.gz" 45 | sha256 = "31fe247a242af7abe32dfadcb4edbc7720f9c47c2bff34b7e5c75df915ab5eb9" 46 | sha512 = "ce5367f3a104843852236799a3386a44da12ee5e287eb94075fd5252c1400b6ef84438f3b3e19f75fb3d842d82fe3a1bc999385fe59fc8e1696fed69bad69eac" 47 | 48 | [sockets] 49 | sha256 = "4c361137a7e61e8b9a73da2a0899dd9ad1a0c2dfee7d310cf168704c57b7a07c" 50 | sha512 = "348b4ef381f57aec23d48537df8b69ab8963587dcb056e94c4cd5657e217677a4ee2a545868a5c829d2334cc6b8b0a61d3e72797999f44d78553fbd3a73c5b8d" 51 | 52 | [sql] 53 | url = "https://github.com/WebAssembly/wasi-sql/archive/main.tar.gz" 54 | sha256 = "b059c4b9951f656e24af3eff9f3dfedd2e45ffa3462bf5ddc17d8c51f757c315" 55 | sha512 = "cda940f0c995286ed6286ca40706e1811db1fc451f223b63db55edbf47deadff80e5be9fdef3fb3d307161df1671cbca399c6af2006a3498030b0d61bb5a0de1" 56 | -------------------------------------------------------------------------------- /wit/deps.toml: -------------------------------------------------------------------------------- 1 | keyvalue = "https://github.com/WebAssembly/wasi-keyvalue/archive/main.tar.gz" 2 | blobstore = "https://github.com/WebAssembly/wasi-blobstore/archive/main.tar.gz" 3 | http = "https://github.com/WebAssembly/wasi-http/archive/main.tar.gz" 4 | messaging = "https://github.com/WebAssembly/wasi-messaging/archive/main.tar.gz" 5 | sql = "https://github.com/WebAssembly/wasi-sql/archive/main.tar.gz" 6 | runtime-config = "https://github.com/WebAssembly/wasi-runtime-config/archive/main.tar.gz" 7 | 8 | # transitive dependencies 9 | io = "https://github.com/WebAssembly/wasi-io/archive/main.tar.gz" -------------------------------------------------------------------------------- /wit/deps/blobstore/blobstore.wit: -------------------------------------------------------------------------------- 1 | // wasi-cloud Blobstore service definition 2 | interface blobstore { 3 | use container.{container}; 4 | use types.{error, container-name, object-id}; 5 | 6 | // creates a new empty container 7 | create-container: func(name: container-name) -> result; 8 | 9 | // retrieves a container by name 10 | get-container: func(name: container-name) -> result; 11 | 12 | // deletes a container and all objects within it 13 | delete-container: func(name: container-name) -> result<_, error>; 14 | 15 | // returns true if the container exists 16 | container-exists: func(name: container-name) -> result; 17 | 18 | // copies (duplicates) an object, to the same or a different container. 19 | // returns an error if the target container does not exist. 20 | // overwrites destination object if it already existed. 21 | copy-object: func(src: object-id, dest: object-id) -> result<_, error>; 22 | 23 | // moves or renames an object, to the same or a different container 24 | // returns an error if the destination container does not exist. 25 | // overwrites destination object if it already existed. 26 | move-object: func(src:object-id, dest: object-id) -> result<_, error>; 27 | } -------------------------------------------------------------------------------- /wit/deps/blobstore/container.wit: -------------------------------------------------------------------------------- 1 | // a Container is a collection of objects 2 | interface container { 3 | use wasi:io/streams@0.2.1.{ 4 | input-stream, 5 | output-stream, 6 | }; 7 | 8 | use types.{ 9 | container-metadata, 10 | error, 11 | incoming-value, 12 | object-metadata, 13 | object-name, 14 | outgoing-value, 15 | }; 16 | 17 | // this defines the `container` resource 18 | resource container { 19 | // returns container name 20 | name: func() -> result; 21 | 22 | // returns container metadata 23 | info: func() -> result; 24 | 25 | // retrieves an object or portion of an object, as a resource. 26 | // Start and end offsets are inclusive. 27 | // Once a data-blob resource has been created, the underlying bytes are held by the blobstore service for the lifetime 28 | // of the data-blob resource, even if the object they came from is later deleted. 29 | get-data: func(name: object-name, start: u64, end: u64) -> result; 30 | 31 | // creates or replaces an object with the data blob. 32 | write-data: func(name: object-name, data: borrow) -> result<_, error>; 33 | 34 | // returns list of objects in the container. Order is undefined. 35 | list-objects: func() -> result; 36 | 37 | // deletes object. 38 | // does not return error if object did not exist. 39 | delete-object: func(name: object-name) -> result<_, error>; 40 | 41 | // deletes multiple objects in the container 42 | delete-objects: func(names: list) -> result<_, error>; 43 | 44 | // returns true if the object exists in this container 45 | has-object: func(name: object-name) -> result; 46 | 47 | // returns metadata for the object 48 | object-info: func(name: object-name) -> result; 49 | 50 | // removes all objects within the container, leaving the container empty. 51 | clear: func() -> result<_, error>; 52 | } 53 | 54 | // this defines the `stream-object-names` resource which is a representation of stream 55 | resource stream-object-names { 56 | // reads the next number of objects from the stream 57 | // 58 | // This function returns the list of objects read, and a boolean indicating if the end of the stream was reached. 59 | read-stream-object-names: func(len: u64) -> result, bool>, error>; 60 | 61 | // skip the next number of objects in the stream 62 | // 63 | // This function returns the number of objects skipped, and a boolean indicating if the end of the stream was reached. 64 | skip-stream-object-names: func(num: u64) -> result, error>; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /wit/deps/blobstore/types.wit: -------------------------------------------------------------------------------- 1 | // Types used by blobstore 2 | interface types { 3 | use wasi:io/streams@0.2.1.{input-stream, output-stream}; 4 | 5 | // name of a container, a collection of objects. 6 | // The container name may be any valid UTF-8 string. 7 | type container-name = string; 8 | 9 | // name of an object within a container 10 | // The object name may be any valid UTF-8 string. 11 | type object-name = string; 12 | 13 | // TODO: define timestamp to include seconds since 14 | // Unix epoch and nanoseconds 15 | // https://github.com/WebAssembly/wasi-blob-store/issues/7 16 | type timestamp = u64; 17 | 18 | // size of an object, in bytes 19 | type object-size = u64; 20 | 21 | type error = string; 22 | 23 | // information about a container 24 | record container-metadata { 25 | // the container's name 26 | name: container-name, 27 | // date and time container was created 28 | created-at: timestamp, 29 | } 30 | 31 | // information about an object 32 | record object-metadata { 33 | // the object's name 34 | name: object-name, 35 | // the object's parent container 36 | container: container-name, 37 | // date and time the object was created 38 | created-at: timestamp, 39 | // size of the object, in bytes 40 | size: object-size, 41 | } 42 | 43 | // identifier for an object that includes its container name 44 | record object-id { 45 | container: container-name, 46 | object: object-name 47 | } 48 | 49 | /// A data is the data stored in a data blob. The value can be of any type 50 | /// that can be represented in a byte array. It provides a way to write the value 51 | /// to the output-stream defined in the `wasi-io` interface. 52 | // Soon: switch to `resource value { ... }` 53 | resource outgoing-value { 54 | new-outgoing-value: static func() -> outgoing-value; 55 | 56 | /// Returns a stream for writing the value contents. 57 | /// 58 | /// The returned `output-stream` is a child resource: it must be dropped 59 | /// before the parent `outgoing-value` resource is dropped (or finished), 60 | /// otherwise the `outgoing-value` drop or `finish` will trap. 61 | /// 62 | /// Returns success on the first call: the `output-stream` resource for 63 | /// this `outgoing-value` may be retrieved at most once. Subsequent calls 64 | /// will return error. 65 | outgoing-value-write-body: func() -> result; 66 | 67 | /// Finalize an outgoing value. This must be 68 | /// called to signal that the outgoing value is complete. If the `outgoing-value` 69 | /// is dropped without calling `outgoing-value.finalize`, the implementation 70 | /// should treat the value as corrupted. 71 | finish: static func(this: outgoing-value) -> result<_, error>; 72 | } 73 | 74 | /// A incoming-value is a wrapper around a value. It provides a way to read the value 75 | /// from the input-stream defined in the `wasi-io` interface. 76 | /// 77 | /// The incoming-value provides two ways to consume the value: 78 | /// 1. `incoming-value-consume-sync` consumes the value synchronously and returns the 79 | /// value as a list of bytes. 80 | /// 2. `incoming-value-consume-async` consumes the value asynchronously and returns the 81 | /// value as an input-stream. 82 | // Soon: switch to `resource incoming-value { ... }` 83 | resource incoming-value { 84 | incoming-value-consume-sync: static func(this: incoming-value) -> result; 85 | incoming-value-consume-async: static func(this: incoming-value) -> result; 86 | size: func() -> u64; 87 | } 88 | 89 | type incoming-value-async-body = input-stream; 90 | type incoming-value-sync-body = list; 91 | } 92 | -------------------------------------------------------------------------------- /wit/deps/blobstore/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:blobstore@0.2.0-draft; 2 | 3 | world imports { 4 | import blobstore; 5 | } 6 | -------------------------------------------------------------------------------- /wit/deps/cli/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world command { 5 | @since(version = 0.2.0) 6 | include imports; 7 | 8 | @since(version = 0.2.0) 9 | export run; 10 | } 11 | -------------------------------------------------------------------------------- /wit/deps/cli/environment.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface environment { 3 | /// Get the POSIX-style environment variables. 4 | /// 5 | /// Each environment variable is provided as a pair of string variable names 6 | /// and string value. 7 | /// 8 | /// Morally, these are a value import, but until value imports are available 9 | /// in the component model, this import function should return the same 10 | /// values each time it is called. 11 | @since(version = 0.2.0) 12 | get-environment: func() -> list>; 13 | 14 | /// Get the POSIX-style arguments to the program. 15 | @since(version = 0.2.0) 16 | get-arguments: func() -> list; 17 | 18 | /// Return a path that programs should use as their initial current working 19 | /// directory, interpreting `.` as shorthand for this. 20 | @since(version = 0.2.0) 21 | initial-cwd: func() -> option; 22 | } 23 | -------------------------------------------------------------------------------- /wit/deps/cli/exit.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface exit { 3 | /// Exit the current instance and any linked instances. 4 | @since(version = 0.2.0) 5 | exit: func(status: result); 6 | 7 | /// Exit the current instance and any linked instances, reporting the 8 | /// specified status code to the host. 9 | /// 10 | /// The meaning of the code depends on the context, with 0 usually meaning 11 | /// "success", and other values indicating various types of failure. 12 | /// 13 | /// This function does not return; the effect is analogous to a trap, but 14 | /// without the connotation that something bad has happened. 15 | @unstable(feature = cli-exit-with-code) 16 | exit-with-code: func(status-code: u8); 17 | } 18 | -------------------------------------------------------------------------------- /wit/deps/cli/imports.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | include wasi:clocks/imports@0.2.1; 7 | @since(version = 0.2.0) 8 | include wasi:filesystem/imports@0.2.1; 9 | @since(version = 0.2.0) 10 | include wasi:sockets/imports@0.2.1; 11 | @since(version = 0.2.0) 12 | include wasi:random/imports@0.2.1; 13 | @since(version = 0.2.0) 14 | include wasi:io/imports@0.2.1; 15 | 16 | @since(version = 0.2.0) 17 | import environment; 18 | @since(version = 0.2.0) 19 | import exit; 20 | @since(version = 0.2.0) 21 | import stdin; 22 | @since(version = 0.2.0) 23 | import stdout; 24 | @since(version = 0.2.0) 25 | import stderr; 26 | @since(version = 0.2.0) 27 | import terminal-input; 28 | @since(version = 0.2.0) 29 | import terminal-output; 30 | @since(version = 0.2.0) 31 | import terminal-stdin; 32 | @since(version = 0.2.0) 33 | import terminal-stdout; 34 | @since(version = 0.2.0) 35 | import terminal-stderr; 36 | } 37 | -------------------------------------------------------------------------------- /wit/deps/cli/run.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface run { 3 | /// Run the program. 4 | @since(version = 0.2.0) 5 | run: func() -> result; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/cli/stdio.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface stdin { 3 | @since(version = 0.2.0) 4 | use wasi:io/streams@0.2.1.{input-stream}; 5 | 6 | @since(version = 0.2.0) 7 | get-stdin: func() -> input-stream; 8 | } 9 | 10 | @since(version = 0.2.0) 11 | interface stdout { 12 | @since(version = 0.2.0) 13 | use wasi:io/streams@0.2.1.{output-stream}; 14 | 15 | @since(version = 0.2.0) 16 | get-stdout: func() -> output-stream; 17 | } 18 | 19 | @since(version = 0.2.0) 20 | interface stderr { 21 | @since(version = 0.2.0) 22 | use wasi:io/streams@0.2.1.{output-stream}; 23 | 24 | @since(version = 0.2.0) 25 | get-stderr: func() -> output-stream; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/cli/terminal.wit: -------------------------------------------------------------------------------- 1 | /// Terminal input. 2 | /// 3 | /// In the future, this may include functions for disabling echoing, 4 | /// disabling input buffering so that keyboard events are sent through 5 | /// immediately, querying supported features, and so on. 6 | @since(version = 0.2.0) 7 | interface terminal-input { 8 | /// The input side of a terminal. 9 | @since(version = 0.2.0) 10 | resource terminal-input; 11 | } 12 | 13 | /// Terminal output. 14 | /// 15 | /// In the future, this may include functions for querying the terminal 16 | /// size, being notified of terminal size changes, querying supported 17 | /// features, and so on. 18 | @since(version = 0.2.0) 19 | interface terminal-output { 20 | /// The output side of a terminal. 21 | @since(version = 0.2.0) 22 | resource terminal-output; 23 | } 24 | 25 | /// An interface providing an optional `terminal-input` for stdin as a 26 | /// link-time authority. 27 | @since(version = 0.2.0) 28 | interface terminal-stdin { 29 | @since(version = 0.2.0) 30 | use terminal-input.{terminal-input}; 31 | 32 | /// If stdin is connected to a terminal, return a `terminal-input` handle 33 | /// allowing further interaction with it. 34 | @since(version = 0.2.0) 35 | get-terminal-stdin: func() -> option; 36 | } 37 | 38 | /// An interface providing an optional `terminal-output` for stdout as a 39 | /// link-time authority. 40 | @since(version = 0.2.0) 41 | interface terminal-stdout { 42 | @since(version = 0.2.0) 43 | use terminal-output.{terminal-output}; 44 | 45 | /// If stdout is connected to a terminal, return a `terminal-output` handle 46 | /// allowing further interaction with it. 47 | @since(version = 0.2.0) 48 | get-terminal-stdout: func() -> option; 49 | } 50 | 51 | /// An interface providing an optional `terminal-output` for stderr as a 52 | /// link-time authority. 53 | @since(version = 0.2.0) 54 | interface terminal-stderr { 55 | @since(version = 0.2.0) 56 | use terminal-output.{terminal-output}; 57 | 58 | /// If stderr is connected to a terminal, return a `terminal-output` handle 59 | /// allowing further interaction with it. 60 | @since(version = 0.2.0) 61 | get-terminal-stderr: func() -> option; 62 | } 63 | -------------------------------------------------------------------------------- /wit/deps/clocks/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 3 | /// time. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A monotonic clock is a clock which has an unspecified initial value, and 9 | /// successive reads of the clock will produce non-decreasing values. 10 | @since(version = 0.2.0) 11 | interface monotonic-clock { 12 | @since(version = 0.2.0) 13 | use wasi:io/poll@0.2.1.{pollable}; 14 | 15 | /// An instant in time, in nanoseconds. An instant is relative to an 16 | /// unspecified initial value, and can only be compared to instances from 17 | /// the same monotonic-clock. 18 | @since(version = 0.2.0) 19 | type instant = u64; 20 | 21 | /// A duration of time, in nanoseconds. 22 | @since(version = 0.2.0) 23 | type duration = u64; 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// The clock is monotonic, therefore calling this function repeatedly will 28 | /// produce a sequence of non-decreasing values. 29 | @since(version = 0.2.0) 30 | now: func() -> instant; 31 | 32 | /// Query the resolution of the clock. Returns the duration of time 33 | /// corresponding to a clock tick. 34 | @since(version = 0.2.0) 35 | resolution: func() -> duration; 36 | 37 | /// Create a `pollable` which will resolve once the specified instant 38 | /// has occurred. 39 | @since(version = 0.2.0) 40 | subscribe-instant: func( 41 | when: instant, 42 | ) -> pollable; 43 | 44 | /// Create a `pollable` that will resolve after the specified duration has 45 | /// elapsed from the time this function is invoked. 46 | @since(version = 0.2.0) 47 | subscribe-duration: func( 48 | when: duration, 49 | ) -> pollable; 50 | } 51 | -------------------------------------------------------------------------------- /wit/deps/clocks/timezone.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | 3 | @unstable(feature = clocks-timezone) 4 | interface timezone { 5 | @unstable(feature = clocks-timezone) 6 | use wall-clock.{datetime}; 7 | 8 | /// Return information needed to display the given `datetime`. This includes 9 | /// the UTC offset, the time zone name, and a flag indicating whether 10 | /// daylight saving time is active. 11 | /// 12 | /// If the timezone cannot be determined for the given `datetime`, return a 13 | /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight 14 | /// saving time. 15 | @unstable(feature = clocks-timezone) 16 | display: func(when: datetime) -> timezone-display; 17 | 18 | /// The same as `display`, but only return the UTC offset. 19 | @unstable(feature = clocks-timezone) 20 | utc-offset: func(when: datetime) -> s32; 21 | 22 | /// Information useful for displaying the timezone of a specific `datetime`. 23 | /// 24 | /// This information may vary within a single `timezone` to reflect daylight 25 | /// saving time adjustments. 26 | @unstable(feature = clocks-timezone) 27 | record timezone-display { 28 | /// The number of seconds difference between UTC time and the local 29 | /// time of the timezone. 30 | /// 31 | /// The returned value will always be less than 86400 which is the 32 | /// number of seconds in a day (24*60*60). 33 | /// 34 | /// In implementations that do not expose an actual time zone, this 35 | /// should return 0. 36 | utc-offset: s32, 37 | 38 | /// The abbreviated name of the timezone to display to a user. The name 39 | /// `UTC` indicates Coordinated Universal Time. Otherwise, this should 40 | /// reference local standards for the name of the time zone. 41 | /// 42 | /// In implementations that do not expose an actual time zone, this 43 | /// should be the string `UTC`. 44 | /// 45 | /// In time zones that do not have an applicable name, a formatted 46 | /// representation of the UTC offset may be returned, such as `-04:00`. 47 | name: string, 48 | 49 | /// Whether daylight saving time is active. 50 | /// 51 | /// In implementations that do not expose an actual time zone, this 52 | /// should return false. 53 | in-daylight-saving-time: bool, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wit/deps/clocks/wall-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | /// WASI Wall Clock is a clock API intended to let users query the current 3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 4 | /// is not necessarily monotonic as it may be reset. 5 | /// 6 | /// It is intended to be portable at least between Unix-family platforms and 7 | /// Windows. 8 | /// 9 | /// A wall clock is a clock which measures the date and time according to 10 | /// some external reference. 11 | /// 12 | /// External references may be reset, so this clock is not necessarily 13 | /// monotonic, making it unsuitable for measuring elapsed time. 14 | /// 15 | /// It is intended for reporting the current date and time for humans. 16 | @since(version = 0.2.0) 17 | interface wall-clock { 18 | /// A time and date in seconds plus nanoseconds. 19 | @since(version = 0.2.0) 20 | record datetime { 21 | seconds: u64, 22 | nanoseconds: u32, 23 | } 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// This clock is not monotonic, therefore calling this function repeatedly 28 | /// will not necessarily produce a sequence of non-decreasing values. 29 | /// 30 | /// The returned timestamps represent the number of seconds since 31 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 32 | /// also known as [Unix Time]. 33 | /// 34 | /// The nanoseconds field of the output is always less than 1000000000. 35 | /// 36 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 37 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 38 | @since(version = 0.2.0) 39 | now: func() -> datetime; 40 | 41 | /// Query the resolution of the clock. 42 | /// 43 | /// The nanoseconds field of the output is always less than 1000000000. 44 | @since(version = 0.2.0) 45 | resolution: func() -> datetime; 46 | } 47 | -------------------------------------------------------------------------------- /wit/deps/clocks/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import monotonic-clock; 7 | @since(version = 0.2.0) 8 | import wall-clock; 9 | @unstable(feature = clocks-timezone) 10 | import timezone; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/filesystem/preopens.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | interface preopens { 5 | @since(version = 0.2.0) 6 | use types.{descriptor}; 7 | 8 | /// Return the set of preopened directories, and their path. 9 | @since(version = 0.2.0) 10 | get-directories: func() -> list>; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/filesystem/types.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.1; 2 | /// WASI filesystem is a filesystem API primarily intended to let users run WASI 3 | /// programs that access their files on their existing filesystems, without 4 | /// significant overhead. 5 | /// 6 | /// It is intended to be roughly portable between Unix-family platforms and 7 | /// Windows, though it does not hide many of the major differences. 8 | /// 9 | /// Paths are passed as interface-type `string`s, meaning they must consist of 10 | /// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain 11 | /// paths which are not accessible by this API. 12 | /// 13 | /// The directory separator in WASI is always the forward-slash (`/`). 14 | /// 15 | /// All paths in WASI are relative paths, and are interpreted relative to a 16 | /// `descriptor` referring to a base directory. If a `path` argument to any WASI 17 | /// function starts with `/`, or if any step of resolving a `path`, including 18 | /// `..` and symbolic link steps, reaches a directory outside of the base 19 | /// directory, or reaches a symlink to an absolute or rooted path in the 20 | /// underlying filesystem, the function fails with `error-code::not-permitted`. 21 | /// 22 | /// For more information about WASI path resolution and sandboxing, see 23 | /// [WASI filesystem path resolution]. 24 | /// 25 | /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md 26 | @since(version = 0.2.0) 27 | interface types { 28 | @since(version = 0.2.0) 29 | use wasi:io/streams@0.2.1.{input-stream, output-stream, error}; 30 | @since(version = 0.2.0) 31 | use wasi:clocks/wall-clock@0.2.1.{datetime}; 32 | 33 | /// File size or length of a region within a file. 34 | @since(version = 0.2.0) 35 | type filesize = u64; 36 | 37 | /// The type of a filesystem object referenced by a descriptor. 38 | /// 39 | /// Note: This was called `filetype` in earlier versions of WASI. 40 | @since(version = 0.2.0) 41 | enum descriptor-type { 42 | /// The type of the descriptor or file is unknown or is different from 43 | /// any of the other types specified. 44 | unknown, 45 | /// The descriptor refers to a block device inode. 46 | block-device, 47 | /// The descriptor refers to a character device inode. 48 | character-device, 49 | /// The descriptor refers to a directory inode. 50 | directory, 51 | /// The descriptor refers to a named pipe. 52 | fifo, 53 | /// The file refers to a symbolic link inode. 54 | symbolic-link, 55 | /// The descriptor refers to a regular file inode. 56 | regular-file, 57 | /// The descriptor refers to a socket. 58 | socket, 59 | } 60 | 61 | /// Descriptor flags. 62 | /// 63 | /// Note: This was called `fdflags` in earlier versions of WASI. 64 | @since(version = 0.2.0) 65 | flags descriptor-flags { 66 | /// Read mode: Data can be read. 67 | read, 68 | /// Write mode: Data can be written to. 69 | write, 70 | /// Request that writes be performed according to synchronized I/O file 71 | /// integrity completion. The data stored in the file and the file's 72 | /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. 73 | /// 74 | /// The precise semantics of this operation have not yet been defined for 75 | /// WASI. At this time, it should be interpreted as a request, and not a 76 | /// requirement. 77 | file-integrity-sync, 78 | /// Request that writes be performed according to synchronized I/O data 79 | /// integrity completion. Only the data stored in the file is 80 | /// synchronized. This is similar to `O_DSYNC` in POSIX. 81 | /// 82 | /// The precise semantics of this operation have not yet been defined for 83 | /// WASI. At this time, it should be interpreted as a request, and not a 84 | /// requirement. 85 | data-integrity-sync, 86 | /// Requests that reads be performed at the same level of integrity 87 | /// requested for writes. This is similar to `O_RSYNC` in POSIX. 88 | /// 89 | /// The precise semantics of this operation have not yet been defined for 90 | /// WASI. At this time, it should be interpreted as a request, and not a 91 | /// requirement. 92 | requested-write-sync, 93 | /// Mutating directories mode: Directory contents may be mutated. 94 | /// 95 | /// When this flag is unset on a descriptor, operations using the 96 | /// descriptor which would create, rename, delete, modify the data or 97 | /// metadata of filesystem objects, or obtain another handle which 98 | /// would permit any of those, shall fail with `error-code::read-only` if 99 | /// they would otherwise succeed. 100 | /// 101 | /// This may only be set on directories. 102 | mutate-directory, 103 | } 104 | 105 | /// File attributes. 106 | /// 107 | /// Note: This was called `filestat` in earlier versions of WASI. 108 | @since(version = 0.2.0) 109 | record descriptor-stat { 110 | /// File type. 111 | %type: descriptor-type, 112 | /// Number of hard links to the file. 113 | link-count: link-count, 114 | /// For regular files, the file size in bytes. For symbolic links, the 115 | /// length in bytes of the pathname contained in the symbolic link. 116 | size: filesize, 117 | /// Last data access timestamp. 118 | /// 119 | /// If the `option` is none, the platform doesn't maintain an access 120 | /// timestamp for this file. 121 | data-access-timestamp: option, 122 | /// Last data modification timestamp. 123 | /// 124 | /// If the `option` is none, the platform doesn't maintain a 125 | /// modification timestamp for this file. 126 | data-modification-timestamp: option, 127 | /// Last file status-change timestamp. 128 | /// 129 | /// If the `option` is none, the platform doesn't maintain a 130 | /// status-change timestamp for this file. 131 | status-change-timestamp: option, 132 | } 133 | 134 | /// Flags determining the method of how paths are resolved. 135 | @since(version = 0.2.0) 136 | flags path-flags { 137 | /// As long as the resolved path corresponds to a symbolic link, it is 138 | /// expanded. 139 | symlink-follow, 140 | } 141 | 142 | /// Open flags used by `open-at`. 143 | @since(version = 0.2.0) 144 | flags open-flags { 145 | /// Create file if it does not exist, similar to `O_CREAT` in POSIX. 146 | create, 147 | /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. 148 | directory, 149 | /// Fail if file already exists, similar to `O_EXCL` in POSIX. 150 | exclusive, 151 | /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. 152 | truncate, 153 | } 154 | 155 | /// Number of hard links to an inode. 156 | @since(version = 0.2.0) 157 | type link-count = u64; 158 | 159 | /// When setting a timestamp, this gives the value to set it to. 160 | @since(version = 0.2.0) 161 | variant new-timestamp { 162 | /// Leave the timestamp set to its previous value. 163 | no-change, 164 | /// Set the timestamp to the current time of the system clock associated 165 | /// with the filesystem. 166 | now, 167 | /// Set the timestamp to the given value. 168 | timestamp(datetime), 169 | } 170 | 171 | /// A directory entry. 172 | record directory-entry { 173 | /// The type of the file referred to by this directory entry. 174 | %type: descriptor-type, 175 | 176 | /// The name of the object. 177 | name: string, 178 | } 179 | 180 | /// Error codes returned by functions, similar to `errno` in POSIX. 181 | /// Not all of these error codes are returned by the functions provided by this 182 | /// API; some are used in higher-level library layers, and others are provided 183 | /// merely for alignment with POSIX. 184 | enum error-code { 185 | /// Permission denied, similar to `EACCES` in POSIX. 186 | access, 187 | /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. 188 | would-block, 189 | /// Connection already in progress, similar to `EALREADY` in POSIX. 190 | already, 191 | /// Bad descriptor, similar to `EBADF` in POSIX. 192 | bad-descriptor, 193 | /// Device or resource busy, similar to `EBUSY` in POSIX. 194 | busy, 195 | /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. 196 | deadlock, 197 | /// Storage quota exceeded, similar to `EDQUOT` in POSIX. 198 | quota, 199 | /// File exists, similar to `EEXIST` in POSIX. 200 | exist, 201 | /// File too large, similar to `EFBIG` in POSIX. 202 | file-too-large, 203 | /// Illegal byte sequence, similar to `EILSEQ` in POSIX. 204 | illegal-byte-sequence, 205 | /// Operation in progress, similar to `EINPROGRESS` in POSIX. 206 | in-progress, 207 | /// Interrupted function, similar to `EINTR` in POSIX. 208 | interrupted, 209 | /// Invalid argument, similar to `EINVAL` in POSIX. 210 | invalid, 211 | /// I/O error, similar to `EIO` in POSIX. 212 | io, 213 | /// Is a directory, similar to `EISDIR` in POSIX. 214 | is-directory, 215 | /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. 216 | loop, 217 | /// Too many links, similar to `EMLINK` in POSIX. 218 | too-many-links, 219 | /// Message too large, similar to `EMSGSIZE` in POSIX. 220 | message-size, 221 | /// Filename too long, similar to `ENAMETOOLONG` in POSIX. 222 | name-too-long, 223 | /// No such device, similar to `ENODEV` in POSIX. 224 | no-device, 225 | /// No such file or directory, similar to `ENOENT` in POSIX. 226 | no-entry, 227 | /// No locks available, similar to `ENOLCK` in POSIX. 228 | no-lock, 229 | /// Not enough space, similar to `ENOMEM` in POSIX. 230 | insufficient-memory, 231 | /// No space left on device, similar to `ENOSPC` in POSIX. 232 | insufficient-space, 233 | /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. 234 | not-directory, 235 | /// Directory not empty, similar to `ENOTEMPTY` in POSIX. 236 | not-empty, 237 | /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. 238 | not-recoverable, 239 | /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. 240 | unsupported, 241 | /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. 242 | no-tty, 243 | /// No such device or address, similar to `ENXIO` in POSIX. 244 | no-such-device, 245 | /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. 246 | overflow, 247 | /// Operation not permitted, similar to `EPERM` in POSIX. 248 | not-permitted, 249 | /// Broken pipe, similar to `EPIPE` in POSIX. 250 | pipe, 251 | /// Read-only file system, similar to `EROFS` in POSIX. 252 | read-only, 253 | /// Invalid seek, similar to `ESPIPE` in POSIX. 254 | invalid-seek, 255 | /// Text file busy, similar to `ETXTBSY` in POSIX. 256 | text-file-busy, 257 | /// Cross-device link, similar to `EXDEV` in POSIX. 258 | cross-device, 259 | } 260 | 261 | /// File or memory access pattern advisory information. 262 | @since(version = 0.2.0) 263 | enum advice { 264 | /// The application has no advice to give on its behavior with respect 265 | /// to the specified data. 266 | normal, 267 | /// The application expects to access the specified data sequentially 268 | /// from lower offsets to higher offsets. 269 | sequential, 270 | /// The application expects to access the specified data in a random 271 | /// order. 272 | random, 273 | /// The application expects to access the specified data in the near 274 | /// future. 275 | will-need, 276 | /// The application expects that it will not access the specified data 277 | /// in the near future. 278 | dont-need, 279 | /// The application expects to access the specified data once and then 280 | /// not reuse it thereafter. 281 | no-reuse, 282 | } 283 | 284 | /// A 128-bit hash value, split into parts because wasm doesn't have a 285 | /// 128-bit integer type. 286 | @since(version = 0.2.0) 287 | record metadata-hash-value { 288 | /// 64 bits of a 128-bit hash value. 289 | lower: u64, 290 | /// Another 64 bits of a 128-bit hash value. 291 | upper: u64, 292 | } 293 | 294 | /// A descriptor is a reference to a filesystem object, which may be a file, 295 | /// directory, named pipe, special file, or other object on which filesystem 296 | /// calls may be made. 297 | @since(version = 0.2.0) 298 | resource descriptor { 299 | /// Return a stream for reading from a file, if available. 300 | /// 301 | /// May fail with an error-code describing why the file cannot be read. 302 | /// 303 | /// Multiple read, write, and append streams may be active on the same open 304 | /// file and they do not interfere with each other. 305 | /// 306 | /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. 307 | @since(version = 0.2.0) 308 | read-via-stream: func( 309 | /// The offset within the file at which to start reading. 310 | offset: filesize, 311 | ) -> result; 312 | 313 | /// Return a stream for writing to a file, if available. 314 | /// 315 | /// May fail with an error-code describing why the file cannot be written. 316 | /// 317 | /// Note: This allows using `write-stream`, which is similar to `write` in 318 | /// POSIX. 319 | @since(version = 0.2.0) 320 | write-via-stream: func( 321 | /// The offset within the file at which to start writing. 322 | offset: filesize, 323 | ) -> result; 324 | 325 | /// Return a stream for appending to a file, if available. 326 | /// 327 | /// May fail with an error-code describing why the file cannot be appended. 328 | /// 329 | /// Note: This allows using `write-stream`, which is similar to `write` with 330 | /// `O_APPEND` in in POSIX. 331 | @since(version = 0.2.0) 332 | append-via-stream: func() -> result; 333 | 334 | /// Provide file advisory information on a descriptor. 335 | /// 336 | /// This is similar to `posix_fadvise` in POSIX. 337 | @since(version = 0.2.0) 338 | advise: func( 339 | /// The offset within the file to which the advisory applies. 340 | offset: filesize, 341 | /// The length of the region to which the advisory applies. 342 | length: filesize, 343 | /// The advice. 344 | advice: advice 345 | ) -> result<_, error-code>; 346 | 347 | /// Synchronize the data of a file to disk. 348 | /// 349 | /// This function succeeds with no effect if the file descriptor is not 350 | /// opened for writing. 351 | /// 352 | /// Note: This is similar to `fdatasync` in POSIX. 353 | @since(version = 0.2.0) 354 | sync-data: func() -> result<_, error-code>; 355 | 356 | /// Get flags associated with a descriptor. 357 | /// 358 | /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. 359 | /// 360 | /// Note: This returns the value that was the `fs_flags` value returned 361 | /// from `fdstat_get` in earlier versions of WASI. 362 | @since(version = 0.2.0) 363 | get-flags: func() -> result; 364 | 365 | /// Get the dynamic type of a descriptor. 366 | /// 367 | /// Note: This returns the same value as the `type` field of the `fd-stat` 368 | /// returned by `stat`, `stat-at` and similar. 369 | /// 370 | /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided 371 | /// by `fstat` in POSIX. 372 | /// 373 | /// Note: This returns the value that was the `fs_filetype` value returned 374 | /// from `fdstat_get` in earlier versions of WASI. 375 | @since(version = 0.2.0) 376 | get-type: func() -> result; 377 | 378 | /// Adjust the size of an open file. If this increases the file's size, the 379 | /// extra bytes are filled with zeros. 380 | /// 381 | /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. 382 | @since(version = 0.2.0) 383 | set-size: func(size: filesize) -> result<_, error-code>; 384 | 385 | /// Adjust the timestamps of an open file or directory. 386 | /// 387 | /// Note: This is similar to `futimens` in POSIX. 388 | /// 389 | /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. 390 | @since(version = 0.2.0) 391 | set-times: func( 392 | /// The desired values of the data access timestamp. 393 | data-access-timestamp: new-timestamp, 394 | /// The desired values of the data modification timestamp. 395 | data-modification-timestamp: new-timestamp, 396 | ) -> result<_, error-code>; 397 | 398 | /// Read from a descriptor, without using and updating the descriptor's offset. 399 | /// 400 | /// This function returns a list of bytes containing the data that was 401 | /// read, along with a bool which, when true, indicates that the end of the 402 | /// file was reached. The returned list will contain up to `length` bytes; it 403 | /// may return fewer than requested, if the end of the file is reached or 404 | /// if the I/O operation is interrupted. 405 | /// 406 | /// In the future, this may change to return a `stream`. 407 | /// 408 | /// Note: This is similar to `pread` in POSIX. 409 | @since(version = 0.2.0) 410 | read: func( 411 | /// The maximum number of bytes to read. 412 | length: filesize, 413 | /// The offset within the file at which to read. 414 | offset: filesize, 415 | ) -> result, bool>, error-code>; 416 | 417 | /// Write to a descriptor, without using and updating the descriptor's offset. 418 | /// 419 | /// It is valid to write past the end of a file; the file is extended to the 420 | /// extent of the write, with bytes between the previous end and the start of 421 | /// the write set to zero. 422 | /// 423 | /// In the future, this may change to take a `stream`. 424 | /// 425 | /// Note: This is similar to `pwrite` in POSIX. 426 | @since(version = 0.2.0) 427 | write: func( 428 | /// Data to write 429 | buffer: list, 430 | /// The offset within the file at which to write. 431 | offset: filesize, 432 | ) -> result; 433 | 434 | /// Read directory entries from a directory. 435 | /// 436 | /// On filesystems where directories contain entries referring to themselves 437 | /// and their parents, often named `.` and `..` respectively, these entries 438 | /// are omitted. 439 | /// 440 | /// This always returns a new stream which starts at the beginning of the 441 | /// directory. Multiple streams may be active on the same directory, and they 442 | /// do not interfere with each other. 443 | @since(version = 0.2.0) 444 | read-directory: func() -> result; 445 | 446 | /// Synchronize the data and metadata of a file to disk. 447 | /// 448 | /// This function succeeds with no effect if the file descriptor is not 449 | /// opened for writing. 450 | /// 451 | /// Note: This is similar to `fsync` in POSIX. 452 | @since(version = 0.2.0) 453 | sync: func() -> result<_, error-code>; 454 | 455 | /// Create a directory. 456 | /// 457 | /// Note: This is similar to `mkdirat` in POSIX. 458 | @since(version = 0.2.0) 459 | create-directory-at: func( 460 | /// The relative path at which to create the directory. 461 | path: string, 462 | ) -> result<_, error-code>; 463 | 464 | /// Return the attributes of an open file or directory. 465 | /// 466 | /// Note: This is similar to `fstat` in POSIX, except that it does not return 467 | /// device and inode information. For testing whether two descriptors refer to 468 | /// the same underlying filesystem object, use `is-same-object`. To obtain 469 | /// additional data that can be used do determine whether a file has been 470 | /// modified, use `metadata-hash`. 471 | /// 472 | /// Note: This was called `fd_filestat_get` in earlier versions of WASI. 473 | @since(version = 0.2.0) 474 | stat: func() -> result; 475 | 476 | /// Return the attributes of a file or directory. 477 | /// 478 | /// Note: This is similar to `fstatat` in POSIX, except that it does not 479 | /// return device and inode information. See the `stat` description for a 480 | /// discussion of alternatives. 481 | /// 482 | /// Note: This was called `path_filestat_get` in earlier versions of WASI. 483 | @since(version = 0.2.0) 484 | stat-at: func( 485 | /// Flags determining the method of how the path is resolved. 486 | path-flags: path-flags, 487 | /// The relative path of the file or directory to inspect. 488 | path: string, 489 | ) -> result; 490 | 491 | /// Adjust the timestamps of a file or directory. 492 | /// 493 | /// Note: This is similar to `utimensat` in POSIX. 494 | /// 495 | /// Note: This was called `path_filestat_set_times` in earlier versions of 496 | /// WASI. 497 | @since(version = 0.2.0) 498 | set-times-at: func( 499 | /// Flags determining the method of how the path is resolved. 500 | path-flags: path-flags, 501 | /// The relative path of the file or directory to operate on. 502 | path: string, 503 | /// The desired values of the data access timestamp. 504 | data-access-timestamp: new-timestamp, 505 | /// The desired values of the data modification timestamp. 506 | data-modification-timestamp: new-timestamp, 507 | ) -> result<_, error-code>; 508 | 509 | /// Create a hard link. 510 | /// 511 | /// Note: This is similar to `linkat` in POSIX. 512 | @since(version = 0.2.0) 513 | link-at: func( 514 | /// Flags determining the method of how the path is resolved. 515 | old-path-flags: path-flags, 516 | /// The relative source path from which to link. 517 | old-path: string, 518 | /// The base directory for `new-path`. 519 | new-descriptor: borrow, 520 | /// The relative destination path at which to create the hard link. 521 | new-path: string, 522 | ) -> result<_, error-code>; 523 | 524 | /// Open a file or directory. 525 | /// 526 | /// The returned descriptor is not guaranteed to be the lowest-numbered 527 | /// descriptor not currently open/ it is randomized to prevent applications 528 | /// from depending on making assumptions about indexes, since this is 529 | /// error-prone in multi-threaded contexts. The returned descriptor is 530 | /// guaranteed to be less than 2**31. 531 | /// 532 | /// If `flags` contains `descriptor-flags::mutate-directory`, and the base 533 | /// descriptor doesn't have `descriptor-flags::mutate-directory` set, 534 | /// `open-at` fails with `error-code::read-only`. 535 | /// 536 | /// If `flags` contains `write` or `mutate-directory`, or `open-flags` 537 | /// contains `truncate` or `create`, and the base descriptor doesn't have 538 | /// `descriptor-flags::mutate-directory` set, `open-at` fails with 539 | /// `error-code::read-only`. 540 | /// 541 | /// Note: This is similar to `openat` in POSIX. 542 | @since(version = 0.2.0) 543 | open-at: func( 544 | /// Flags determining the method of how the path is resolved. 545 | path-flags: path-flags, 546 | /// The relative path of the object to open. 547 | path: string, 548 | /// The method by which to open the file. 549 | open-flags: open-flags, 550 | /// Flags to use for the resulting descriptor. 551 | %flags: descriptor-flags, 552 | ) -> result; 553 | 554 | /// Read the contents of a symbolic link. 555 | /// 556 | /// If the contents contain an absolute or rooted path in the underlying 557 | /// filesystem, this function fails with `error-code::not-permitted`. 558 | /// 559 | /// Note: This is similar to `readlinkat` in POSIX. 560 | @since(version = 0.2.0) 561 | readlink-at: func( 562 | /// The relative path of the symbolic link from which to read. 563 | path: string, 564 | ) -> result; 565 | 566 | /// Remove a directory. 567 | /// 568 | /// Return `error-code::not-empty` if the directory is not empty. 569 | /// 570 | /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. 571 | @since(version = 0.2.0) 572 | remove-directory-at: func( 573 | /// The relative path to a directory to remove. 574 | path: string, 575 | ) -> result<_, error-code>; 576 | 577 | /// Rename a filesystem object. 578 | /// 579 | /// Note: This is similar to `renameat` in POSIX. 580 | @since(version = 0.2.0) 581 | rename-at: func( 582 | /// The relative source path of the file or directory to rename. 583 | old-path: string, 584 | /// The base directory for `new-path`. 585 | new-descriptor: borrow, 586 | /// The relative destination path to which to rename the file or directory. 587 | new-path: string, 588 | ) -> result<_, error-code>; 589 | 590 | /// Create a symbolic link (also known as a "symlink"). 591 | /// 592 | /// If `old-path` starts with `/`, the function fails with 593 | /// `error-code::not-permitted`. 594 | /// 595 | /// Note: This is similar to `symlinkat` in POSIX. 596 | @since(version = 0.2.0) 597 | symlink-at: func( 598 | /// The contents of the symbolic link. 599 | old-path: string, 600 | /// The relative destination path at which to create the symbolic link. 601 | new-path: string, 602 | ) -> result<_, error-code>; 603 | 604 | /// Unlink a filesystem object that is not a directory. 605 | /// 606 | /// Return `error-code::is-directory` if the path refers to a directory. 607 | /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. 608 | @since(version = 0.2.0) 609 | unlink-file-at: func( 610 | /// The relative path to a file to unlink. 611 | path: string, 612 | ) -> result<_, error-code>; 613 | 614 | /// Test whether two descriptors refer to the same filesystem object. 615 | /// 616 | /// In POSIX, this corresponds to testing whether the two descriptors have the 617 | /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. 618 | /// wasi-filesystem does not expose device and inode numbers, so this function 619 | /// may be used instead. 620 | @since(version = 0.2.0) 621 | is-same-object: func(other: borrow) -> bool; 622 | 623 | /// Return a hash of the metadata associated with a filesystem object referred 624 | /// to by a descriptor. 625 | /// 626 | /// This returns a hash of the last-modification timestamp and file size, and 627 | /// may also include the inode number, device number, birth timestamp, and 628 | /// other metadata fields that may change when the file is modified or 629 | /// replaced. It may also include a secret value chosen by the 630 | /// implementation and not otherwise exposed. 631 | /// 632 | /// Implementations are encourated to provide the following properties: 633 | /// 634 | /// - If the file is not modified or replaced, the computed hash value should 635 | /// usually not change. 636 | /// - If the object is modified or replaced, the computed hash value should 637 | /// usually change. 638 | /// - The inputs to the hash should not be easily computable from the 639 | /// computed hash. 640 | /// 641 | /// However, none of these is required. 642 | @since(version = 0.2.0) 643 | metadata-hash: func() -> result; 644 | 645 | /// Return a hash of the metadata associated with a filesystem object referred 646 | /// to by a directory descriptor and a relative path. 647 | /// 648 | /// This performs the same hash computation as `metadata-hash`. 649 | @since(version = 0.2.0) 650 | metadata-hash-at: func( 651 | /// Flags determining the method of how the path is resolved. 652 | path-flags: path-flags, 653 | /// The relative path of the file or directory to inspect. 654 | path: string, 655 | ) -> result; 656 | } 657 | 658 | /// A stream of directory entries. 659 | @since(version = 0.2.0) 660 | resource directory-entry-stream { 661 | /// Read a single directory entry from a `directory-entry-stream`. 662 | @since(version = 0.2.0) 663 | read-directory-entry: func() -> result, error-code>; 664 | } 665 | 666 | /// Attempts to extract a filesystem-related `error-code` from the stream 667 | /// `error` provided. 668 | /// 669 | /// Stream operations which return `stream-error::last-operation-failed` 670 | /// have a payload with more information about the operation that failed. 671 | /// This payload can be passed through to this function to see if there's 672 | /// filesystem-related information about the error to return. 673 | /// 674 | /// Note that this function is fallible because not all stream-related 675 | /// errors are filesystem-related errors. 676 | @since(version = 0.2.0) 677 | filesystem-error-code: func(err: borrow) -> option; 678 | } 679 | -------------------------------------------------------------------------------- /wit/deps/filesystem/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import types; 7 | @since(version = 0.2.0) 8 | import preopens; 9 | } 10 | -------------------------------------------------------------------------------- /wit/deps/http/handler.wit: -------------------------------------------------------------------------------- 1 | /// This interface defines a handler of incoming HTTP Requests. It should 2 | /// be exported by components which can respond to HTTP Requests. 3 | @since(version = 0.2.0) 4 | interface incoming-handler { 5 | @since(version = 0.2.0) 6 | use types.{incoming-request, response-outparam}; 7 | 8 | /// This function is invoked with an incoming HTTP Request, and a resource 9 | /// `response-outparam` which provides the capability to reply with an HTTP 10 | /// Response. The response is sent by calling the `response-outparam.set` 11 | /// method, which allows execution to continue after the response has been 12 | /// sent. This enables both streaming to the response body, and performing other 13 | /// work. 14 | /// 15 | /// The implementor of this function must write a response to the 16 | /// `response-outparam` before returning, or else the caller will respond 17 | /// with an error on its behalf. 18 | @since(version = 0.2.0) 19 | handle: func( 20 | request: incoming-request, 21 | response-out: response-outparam 22 | ); 23 | } 24 | 25 | /// This interface defines a handler of outgoing HTTP Requests. It should be 26 | /// imported by components which wish to make HTTP Requests. 27 | @since(version = 0.2.0) 28 | interface outgoing-handler { 29 | @since(version = 0.2.0) 30 | use types.{ 31 | outgoing-request, request-options, future-incoming-response, error-code 32 | }; 33 | 34 | /// This function is invoked with an outgoing HTTP Request, and it returns 35 | /// a resource `future-incoming-response` which represents an HTTP Response 36 | /// which may arrive in the future. 37 | /// 38 | /// The `options` argument accepts optional parameters for the HTTP 39 | /// protocol's transport layer. 40 | /// 41 | /// This function may return an error if the `outgoing-request` is invalid 42 | /// or not allowed to be made. Otherwise, protocol errors are reported 43 | /// through the `future-incoming-response`. 44 | @since(version = 0.2.0) 45 | handle: func( 46 | request: outgoing-request, 47 | options: option 48 | ) -> result; 49 | } 50 | -------------------------------------------------------------------------------- /wit/deps/http/proxy.wit: -------------------------------------------------------------------------------- 1 | package wasi:http@0.2.1; 2 | 3 | /// The `wasi:http/imports` world imports all the APIs for HTTP proxies. 4 | /// It is intended to be `include`d in other worlds. 5 | @since(version = 0.2.0) 6 | world imports { 7 | /// HTTP proxies have access to time and randomness. 8 | @since(version = 0.2.0) 9 | import wasi:clocks/monotonic-clock@0.2.1; 10 | @since(version = 0.2.0) 11 | import wasi:clocks/wall-clock@0.2.1; 12 | @since(version = 0.2.0) 13 | import wasi:random/random@0.2.1; 14 | 15 | /// Proxies have standard output and error streams which are expected to 16 | /// terminate in a developer-facing console provided by the host. 17 | @since(version = 0.2.0) 18 | import wasi:cli/stdout@0.2.1; 19 | @since(version = 0.2.0) 20 | import wasi:cli/stderr@0.2.1; 21 | 22 | /// TODO: this is a temporary workaround until component tooling is able to 23 | /// gracefully handle the absence of stdin. Hosts must return an eof stream 24 | /// for this import, which is what wasi-libc + tooling will do automatically 25 | /// when this import is properly removed. 26 | @since(version = 0.2.0) 27 | import wasi:cli/stdin@0.2.1; 28 | 29 | /// This is the default handler to use when user code simply wants to make an 30 | /// HTTP request (e.g., via `fetch()`). 31 | @since(version = 0.2.0) 32 | import outgoing-handler; 33 | } 34 | 35 | /// The `wasi:http/proxy` world captures a widely-implementable intersection of 36 | /// hosts that includes HTTP forward and reverse proxies. Components targeting 37 | /// this world may concurrently stream in and out any number of incoming and 38 | /// outgoing HTTP requests. 39 | @since(version = 0.2.0) 40 | world proxy { 41 | @since(version = 0.2.0) 42 | include imports; 43 | 44 | /// The host delivers incoming HTTP requests to a component by calling the 45 | /// `handle` function of this exported interface. A host may arbitrarily reuse 46 | /// or not reuse component instance when delivering incoming HTTP requests and 47 | /// thus a component must be able to handle 0..N calls to `handle`. 48 | @since(version = 0.2.0) 49 | export incoming-handler; 50 | } 51 | -------------------------------------------------------------------------------- /wit/deps/http/types.wit: -------------------------------------------------------------------------------- 1 | /// This interface defines all of the types and methods for implementing 2 | /// HTTP Requests and Responses, both incoming and outgoing, as well as 3 | /// their headers, trailers, and bodies. 4 | @since(version = 0.2.0) 5 | interface types { 6 | @since(version = 0.2.0) 7 | use wasi:clocks/monotonic-clock@0.2.1.{duration}; 8 | @since(version = 0.2.0) 9 | use wasi:io/streams@0.2.1.{input-stream, output-stream}; 10 | @since(version = 0.2.0) 11 | use wasi:io/error@0.2.1.{error as io-error}; 12 | @since(version = 0.2.0) 13 | use wasi:io/poll@0.2.1.{pollable}; 14 | 15 | /// This type corresponds to HTTP standard Methods. 16 | @since(version = 0.2.0) 17 | variant method { 18 | get, 19 | head, 20 | post, 21 | put, 22 | delete, 23 | connect, 24 | options, 25 | trace, 26 | patch, 27 | other(string) 28 | } 29 | 30 | /// This type corresponds to HTTP standard Related Schemes. 31 | @since(version = 0.2.0) 32 | variant scheme { 33 | HTTP, 34 | HTTPS, 35 | other(string) 36 | } 37 | 38 | /// These cases are inspired by the IANA HTTP Proxy Error Types: 39 | /// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types 40 | @since(version = 0.2.0) 41 | variant error-code { 42 | DNS-timeout, 43 | DNS-error(DNS-error-payload), 44 | destination-not-found, 45 | destination-unavailable, 46 | destination-IP-prohibited, 47 | destination-IP-unroutable, 48 | connection-refused, 49 | connection-terminated, 50 | connection-timeout, 51 | connection-read-timeout, 52 | connection-write-timeout, 53 | connection-limit-reached, 54 | TLS-protocol-error, 55 | TLS-certificate-error, 56 | TLS-alert-received(TLS-alert-received-payload), 57 | HTTP-request-denied, 58 | HTTP-request-length-required, 59 | HTTP-request-body-size(option), 60 | HTTP-request-method-invalid, 61 | HTTP-request-URI-invalid, 62 | HTTP-request-URI-too-long, 63 | HTTP-request-header-section-size(option), 64 | HTTP-request-header-size(option), 65 | HTTP-request-trailer-section-size(option), 66 | HTTP-request-trailer-size(field-size-payload), 67 | HTTP-response-incomplete, 68 | HTTP-response-header-section-size(option), 69 | HTTP-response-header-size(field-size-payload), 70 | HTTP-response-body-size(option), 71 | HTTP-response-trailer-section-size(option), 72 | HTTP-response-trailer-size(field-size-payload), 73 | HTTP-response-transfer-coding(option), 74 | HTTP-response-content-coding(option), 75 | HTTP-response-timeout, 76 | HTTP-upgrade-failed, 77 | HTTP-protocol-error, 78 | loop-detected, 79 | configuration-error, 80 | /// This is a catch-all error for anything that doesn't fit cleanly into a 81 | /// more specific case. It also includes an optional string for an 82 | /// unstructured description of the error. Users should not depend on the 83 | /// string for diagnosing errors, as it's not required to be consistent 84 | /// between implementations. 85 | internal-error(option) 86 | } 87 | 88 | /// Defines the case payload type for `DNS-error` above: 89 | @since(version = 0.2.0) 90 | record DNS-error-payload { 91 | rcode: option, 92 | info-code: option 93 | } 94 | 95 | /// Defines the case payload type for `TLS-alert-received` above: 96 | @since(version = 0.2.0) 97 | record TLS-alert-received-payload { 98 | alert-id: option, 99 | alert-message: option 100 | } 101 | 102 | /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: 103 | @since(version = 0.2.0) 104 | record field-size-payload { 105 | field-name: option, 106 | field-size: option 107 | } 108 | 109 | /// Attempts to extract a http-related `error` from the wasi:io `error` 110 | /// provided. 111 | /// 112 | /// Stream operations which return 113 | /// `wasi:io/stream/stream-error::last-operation-failed` have a payload of 114 | /// type `wasi:io/error/error` with more information about the operation 115 | /// that failed. This payload can be passed through to this function to see 116 | /// if there's http-related information about the error to return. 117 | /// 118 | /// Note that this function is fallible because not all io-errors are 119 | /// http-related errors. 120 | @since(version = 0.2.0) 121 | http-error-code: func(err: borrow) -> option; 122 | 123 | /// This type enumerates the different kinds of errors that may occur when 124 | /// setting or appending to a `fields` resource. 125 | @since(version = 0.2.0) 126 | variant header-error { 127 | /// This error indicates that a `field-name` or `field-value` was 128 | /// syntactically invalid when used with an operation that sets headers in a 129 | /// `fields`. 130 | invalid-syntax, 131 | 132 | /// This error indicates that a forbidden `field-name` was used when trying 133 | /// to set a header in a `fields`. 134 | forbidden, 135 | 136 | /// This error indicates that the operation on the `fields` was not 137 | /// permitted because the fields are immutable. 138 | immutable, 139 | } 140 | 141 | /// Field names are always strings. 142 | /// 143 | /// Field names should always be treated as case insensitive by the `fields` 144 | /// resource for the purposes of equality checking. 145 | @since(version = 0.2.1) 146 | type field-name = field-key; 147 | 148 | /// Field keys are always strings. 149 | /// 150 | /// Field keys should always be treated as case insensitive by the `fields` 151 | /// resource for the purposes of equality checking. 152 | /// 153 | /// # Deprecation 154 | /// 155 | /// This type has been deprecated in favor of the `field-name` type. 156 | @since(version = 0.2.0) 157 | @deprecated(version = 0.2.2) 158 | type field-key = string; 159 | 160 | /// Field values should always be ASCII strings. However, in 161 | /// reality, HTTP implementations often have to interpret malformed values, 162 | /// so they are provided as a list of bytes. 163 | @since(version = 0.2.0) 164 | type field-value = list; 165 | 166 | /// This following block defines the `fields` resource which corresponds to 167 | /// HTTP standard Fields. Fields are a common representation used for both 168 | /// Headers and Trailers. 169 | /// 170 | /// A `fields` may be mutable or immutable. A `fields` created using the 171 | /// constructor, `from-list`, or `clone` will be mutable, but a `fields` 172 | /// resource given by other means (including, but not limited to, 173 | /// `incoming-request.headers`, `outgoing-request.headers`) might be be 174 | /// immutable. In an immutable fields, the `set`, `append`, and `delete` 175 | /// operations will fail with `header-error.immutable`. 176 | @since(version = 0.2.0) 177 | resource fields { 178 | 179 | /// Construct an empty HTTP Fields. 180 | /// 181 | /// The resulting `fields` is mutable. 182 | @since(version = 0.2.0) 183 | constructor(); 184 | 185 | /// Construct an HTTP Fields. 186 | /// 187 | /// The resulting `fields` is mutable. 188 | /// 189 | /// The list represents each name-value pair in the Fields. Names 190 | /// which have multiple values are represented by multiple entries in this 191 | /// list with the same name. 192 | /// 193 | /// The tuple is a pair of the field name, represented as a string, and 194 | /// Value, represented as a list of bytes. 195 | /// 196 | /// An error result will be returned if any `field-name` or `field-value` is 197 | /// syntactically invalid, or if a field is forbidden. 198 | @since(version = 0.2.0) 199 | from-list: static func( 200 | entries: list> 201 | ) -> result; 202 | 203 | /// Get all of the values corresponding to a name. If the name is not present 204 | /// in this `fields` or is syntactically invalid, an empty list is returned. 205 | /// However, if the name is present but empty, this is represented by a list 206 | /// with one or more empty field-values present. 207 | @since(version = 0.2.0) 208 | get: func(name: field-name) -> list; 209 | 210 | /// Returns `true` when the name is present in this `fields`. If the name is 211 | /// syntactically invalid, `false` is returned. 212 | @since(version = 0.2.0) 213 | has: func(name: field-name) -> bool; 214 | 215 | /// Set all of the values for a name. Clears any existing values for that 216 | /// name, if they have been set. 217 | /// 218 | /// Fails with `header-error.immutable` if the `fields` are immutable. 219 | /// 220 | /// Fails with `header-error.invalid-syntax` if the `field-name` or any of 221 | /// the `field-value`s are syntactically invalid. 222 | @since(version = 0.2.0) 223 | set: func(name: field-name, value: list) -> result<_, header-error>; 224 | 225 | /// Delete all values for a name. Does nothing if no values for the name 226 | /// exist. 227 | /// 228 | /// Fails with `header-error.immutable` if the `fields` are immutable. 229 | /// 230 | /// Fails with `header-error.invalid-syntax` if the `field-name` is 231 | /// syntactically invalid. 232 | @since(version = 0.2.0) 233 | delete: func(name: field-name) -> result<_, header-error>; 234 | 235 | /// Append a value for a name. Does not change or delete any existing 236 | /// values for that name. 237 | /// 238 | /// Fails with `header-error.immutable` if the `fields` are immutable. 239 | /// 240 | /// Fails with `header-error.invalid-syntax` if the `field-name` or 241 | /// `field-value` are syntactically invalid. 242 | @since(version = 0.2.0) 243 | append: func(name: field-name, value: field-value) -> result<_, header-error>; 244 | 245 | /// Retrieve the full set of names and values in the Fields. Like the 246 | /// constructor, the list represents each name-value pair. 247 | /// 248 | /// The outer list represents each name-value pair in the Fields. Names 249 | /// which have multiple values are represented by multiple entries in this 250 | /// list with the same name. 251 | /// 252 | /// The names and values are always returned in the original casing and in 253 | /// the order in which they will be serialized for transport. 254 | @since(version = 0.2.0) 255 | entries: func() -> list>; 256 | 257 | /// Make a deep copy of the Fields. Equivalent in behavior to calling the 258 | /// `fields` constructor on the return value of `entries`. The resulting 259 | /// `fields` is mutable. 260 | @since(version = 0.2.0) 261 | clone: func() -> fields; 262 | } 263 | 264 | /// Headers is an alias for Fields. 265 | @since(version = 0.2.0) 266 | type headers = fields; 267 | 268 | /// Trailers is an alias for Fields. 269 | @since(version = 0.2.0) 270 | type trailers = fields; 271 | 272 | /// Represents an incoming HTTP Request. 273 | @since(version = 0.2.0) 274 | resource incoming-request { 275 | 276 | /// Returns the method of the incoming request. 277 | @since(version = 0.2.0) 278 | method: func() -> method; 279 | 280 | /// Returns the path with query parameters from the request, as a string. 281 | @since(version = 0.2.0) 282 | path-with-query: func() -> option; 283 | 284 | /// Returns the protocol scheme from the request. 285 | @since(version = 0.2.0) 286 | scheme: func() -> option; 287 | 288 | /// Returns the authority of the Request's target URI, if present. 289 | @since(version = 0.2.0) 290 | authority: func() -> option; 291 | 292 | /// Get the `headers` associated with the request. 293 | /// 294 | /// The returned `headers` resource is immutable: `set`, `append`, and 295 | /// `delete` operations will fail with `header-error.immutable`. 296 | /// 297 | /// The `headers` returned are a child resource: it must be dropped before 298 | /// the parent `incoming-request` is dropped. Dropping this 299 | /// `incoming-request` before all children are dropped will trap. 300 | @since(version = 0.2.0) 301 | headers: func() -> headers; 302 | 303 | /// Gives the `incoming-body` associated with this request. Will only 304 | /// return success at most once, and subsequent calls will return error. 305 | @since(version = 0.2.0) 306 | consume: func() -> result; 307 | } 308 | 309 | /// Represents an outgoing HTTP Request. 310 | @since(version = 0.2.0) 311 | resource outgoing-request { 312 | 313 | /// Construct a new `outgoing-request` with a default `method` of `GET`, and 314 | /// `none` values for `path-with-query`, `scheme`, and `authority`. 315 | /// 316 | /// * `headers` is the HTTP Headers for the Request. 317 | /// 318 | /// It is possible to construct, or manipulate with the accessor functions 319 | /// below, an `outgoing-request` with an invalid combination of `scheme` 320 | /// and `authority`, or `headers` which are not permitted to be sent. 321 | /// It is the obligation of the `outgoing-handler.handle` implementation 322 | /// to reject invalid constructions of `outgoing-request`. 323 | @since(version = 0.2.0) 324 | constructor( 325 | headers: headers 326 | ); 327 | 328 | /// Returns the resource corresponding to the outgoing Body for this 329 | /// Request. 330 | /// 331 | /// Returns success on the first call: the `outgoing-body` resource for 332 | /// this `outgoing-request` can be retrieved at most once. Subsequent 333 | /// calls will return error. 334 | @since(version = 0.2.0) 335 | body: func() -> result; 336 | 337 | /// Get the Method for the Request. 338 | @since(version = 0.2.0) 339 | method: func() -> method; 340 | /// Set the Method for the Request. Fails if the string present in a 341 | /// `method.other` argument is not a syntactically valid method. 342 | @since(version = 0.2.0) 343 | set-method: func(method: method) -> result; 344 | 345 | /// Get the combination of the HTTP Path and Query for the Request. 346 | /// When `none`, this represents an empty Path and empty Query. 347 | @since(version = 0.2.0) 348 | path-with-query: func() -> option; 349 | /// Set the combination of the HTTP Path and Query for the Request. 350 | /// When `none`, this represents an empty Path and empty Query. Fails is the 351 | /// string given is not a syntactically valid path and query uri component. 352 | @since(version = 0.2.0) 353 | set-path-with-query: func(path-with-query: option) -> result; 354 | 355 | /// Get the HTTP Related Scheme for the Request. When `none`, the 356 | /// implementation may choose an appropriate default scheme. 357 | @since(version = 0.2.0) 358 | scheme: func() -> option; 359 | /// Set the HTTP Related Scheme for the Request. When `none`, the 360 | /// implementation may choose an appropriate default scheme. Fails if the 361 | /// string given is not a syntactically valid uri scheme. 362 | @since(version = 0.2.0) 363 | set-scheme: func(scheme: option) -> result; 364 | 365 | /// Get the authority of the Request's target URI. A value of `none` may be used 366 | /// with Related Schemes which do not require an authority. The HTTP and 367 | /// HTTPS schemes always require an authority. 368 | @since(version = 0.2.0) 369 | authority: func() -> option; 370 | /// Set the authority of the Request's target URI. A value of `none` may be used 371 | /// with Related Schemes which do not require an authority. The HTTP and 372 | /// HTTPS schemes always require an authority. Fails if the string given is 373 | /// not a syntactically valid URI authority. 374 | @since(version = 0.2.0) 375 | set-authority: func(authority: option) -> result; 376 | 377 | /// Get the headers associated with the Request. 378 | /// 379 | /// The returned `headers` resource is immutable: `set`, `append`, and 380 | /// `delete` operations will fail with `header-error.immutable`. 381 | /// 382 | /// This headers resource is a child: it must be dropped before the parent 383 | /// `outgoing-request` is dropped, or its ownership is transferred to 384 | /// another component by e.g. `outgoing-handler.handle`. 385 | @since(version = 0.2.0) 386 | headers: func() -> headers; 387 | } 388 | 389 | /// Parameters for making an HTTP Request. Each of these parameters is 390 | /// currently an optional timeout applicable to the transport layer of the 391 | /// HTTP protocol. 392 | /// 393 | /// These timeouts are separate from any the user may use to bound a 394 | /// blocking call to `wasi:io/poll.poll`. 395 | @since(version = 0.2.0) 396 | resource request-options { 397 | /// Construct a default `request-options` value. 398 | @since(version = 0.2.0) 399 | constructor(); 400 | 401 | /// The timeout for the initial connect to the HTTP Server. 402 | @since(version = 0.2.0) 403 | connect-timeout: func() -> option; 404 | 405 | /// Set the timeout for the initial connect to the HTTP Server. An error 406 | /// return value indicates that this timeout is not supported. 407 | @since(version = 0.2.0) 408 | set-connect-timeout: func(duration: option) -> result; 409 | 410 | /// The timeout for receiving the first byte of the Response body. 411 | @since(version = 0.2.0) 412 | first-byte-timeout: func() -> option; 413 | 414 | /// Set the timeout for receiving the first byte of the Response body. An 415 | /// error return value indicates that this timeout is not supported. 416 | @since(version = 0.2.0) 417 | set-first-byte-timeout: func(duration: option) -> result; 418 | 419 | /// The timeout for receiving subsequent chunks of bytes in the Response 420 | /// body stream. 421 | @since(version = 0.2.0) 422 | between-bytes-timeout: func() -> option; 423 | 424 | /// Set the timeout for receiving subsequent chunks of bytes in the Response 425 | /// body stream. An error return value indicates that this timeout is not 426 | /// supported. 427 | @since(version = 0.2.0) 428 | set-between-bytes-timeout: func(duration: option) -> result; 429 | } 430 | 431 | /// Represents the ability to send an HTTP Response. 432 | /// 433 | /// This resource is used by the `wasi:http/incoming-handler` interface to 434 | /// allow a Response to be sent corresponding to the Request provided as the 435 | /// other argument to `incoming-handler.handle`. 436 | @since(version = 0.2.0) 437 | resource response-outparam { 438 | 439 | /// Set the value of the `response-outparam` to either send a response, 440 | /// or indicate an error. 441 | /// 442 | /// This method consumes the `response-outparam` to ensure that it is 443 | /// called at most once. If it is never called, the implementation 444 | /// will respond with an error. 445 | /// 446 | /// The user may provide an `error` to `response` to allow the 447 | /// implementation determine how to respond with an HTTP error response. 448 | @since(version = 0.2.0) 449 | set: static func( 450 | param: response-outparam, 451 | response: result, 452 | ); 453 | } 454 | 455 | /// This type corresponds to the HTTP standard Status Code. 456 | @since(version = 0.2.0) 457 | type status-code = u16; 458 | 459 | /// Represents an incoming HTTP Response. 460 | @since(version = 0.2.0) 461 | resource incoming-response { 462 | 463 | /// Returns the status code from the incoming response. 464 | @since(version = 0.2.0) 465 | status: func() -> status-code; 466 | 467 | /// Returns the headers from the incoming response. 468 | /// 469 | /// The returned `headers` resource is immutable: `set`, `append`, and 470 | /// `delete` operations will fail with `header-error.immutable`. 471 | /// 472 | /// This headers resource is a child: it must be dropped before the parent 473 | /// `incoming-response` is dropped. 474 | @since(version = 0.2.0) 475 | headers: func() -> headers; 476 | 477 | /// Returns the incoming body. May be called at most once. Returns error 478 | /// if called additional times. 479 | @since(version = 0.2.0) 480 | consume: func() -> result; 481 | } 482 | 483 | /// Represents an incoming HTTP Request or Response's Body. 484 | /// 485 | /// A body has both its contents - a stream of bytes - and a (possibly 486 | /// empty) set of trailers, indicating that the full contents of the 487 | /// body have been received. This resource represents the contents as 488 | /// an `input-stream` and the delivery of trailers as a `future-trailers`, 489 | /// and ensures that the user of this interface may only be consuming either 490 | /// the body contents or waiting on trailers at any given time. 491 | @since(version = 0.2.0) 492 | resource incoming-body { 493 | 494 | /// Returns the contents of the body, as a stream of bytes. 495 | /// 496 | /// Returns success on first call: the stream representing the contents 497 | /// can be retrieved at most once. Subsequent calls will return error. 498 | /// 499 | /// The returned `input-stream` resource is a child: it must be dropped 500 | /// before the parent `incoming-body` is dropped, or consumed by 501 | /// `incoming-body.finish`. 502 | /// 503 | /// This invariant ensures that the implementation can determine whether 504 | /// the user is consuming the contents of the body, waiting on the 505 | /// `future-trailers` to be ready, or neither. This allows for network 506 | /// backpressure is to be applied when the user is consuming the body, 507 | /// and for that backpressure to not inhibit delivery of the trailers if 508 | /// the user does not read the entire body. 509 | @since(version = 0.2.0) 510 | %stream: func() -> result; 511 | 512 | /// Takes ownership of `incoming-body`, and returns a `future-trailers`. 513 | /// This function will trap if the `input-stream` child is still alive. 514 | @since(version = 0.2.0) 515 | finish: static func(this: incoming-body) -> future-trailers; 516 | } 517 | 518 | /// Represents a future which may eventually return trailers, or an error. 519 | /// 520 | /// In the case that the incoming HTTP Request or Response did not have any 521 | /// trailers, this future will resolve to the empty set of trailers once the 522 | /// complete Request or Response body has been received. 523 | @since(version = 0.2.0) 524 | resource future-trailers { 525 | 526 | /// Returns a pollable which becomes ready when either the trailers have 527 | /// been received, or an error has occurred. When this pollable is ready, 528 | /// the `get` method will return `some`. 529 | @since(version = 0.2.0) 530 | subscribe: func() -> pollable; 531 | 532 | /// Returns the contents of the trailers, or an error which occurred, 533 | /// once the future is ready. 534 | /// 535 | /// The outer `option` represents future readiness. Users can wait on this 536 | /// `option` to become `some` using the `subscribe` method. 537 | /// 538 | /// The outer `result` is used to retrieve the trailers or error at most 539 | /// once. It will be success on the first call in which the outer option 540 | /// is `some`, and error on subsequent calls. 541 | /// 542 | /// The inner `result` represents that either the HTTP Request or Response 543 | /// body, as well as any trailers, were received successfully, or that an 544 | /// error occurred receiving them. The optional `trailers` indicates whether 545 | /// or not trailers were present in the body. 546 | /// 547 | /// When some `trailers` are returned by this method, the `trailers` 548 | /// resource is immutable, and a child. Use of the `set`, `append`, or 549 | /// `delete` methods will return an error, and the resource must be 550 | /// dropped before the parent `future-trailers` is dropped. 551 | @since(version = 0.2.0) 552 | get: func() -> option, error-code>>>; 553 | } 554 | 555 | /// Represents an outgoing HTTP Response. 556 | @since(version = 0.2.0) 557 | resource outgoing-response { 558 | 559 | /// Construct an `outgoing-response`, with a default `status-code` of `200`. 560 | /// If a different `status-code` is needed, it must be set via the 561 | /// `set-status-code` method. 562 | /// 563 | /// * `headers` is the HTTP Headers for the Response. 564 | @since(version = 0.2.0) 565 | constructor(headers: headers); 566 | 567 | /// Get the HTTP Status Code for the Response. 568 | @since(version = 0.2.0) 569 | status-code: func() -> status-code; 570 | 571 | /// Set the HTTP Status Code for the Response. Fails if the status-code 572 | /// given is not a valid http status code. 573 | @since(version = 0.2.0) 574 | set-status-code: func(status-code: status-code) -> result; 575 | 576 | /// Get the headers associated with the Request. 577 | /// 578 | /// The returned `headers` resource is immutable: `set`, `append`, and 579 | /// `delete` operations will fail with `header-error.immutable`. 580 | /// 581 | /// This headers resource is a child: it must be dropped before the parent 582 | /// `outgoing-request` is dropped, or its ownership is transferred to 583 | /// another component by e.g. `outgoing-handler.handle`. 584 | @since(version = 0.2.0) 585 | headers: func() -> headers; 586 | 587 | /// Returns the resource corresponding to the outgoing Body for this Response. 588 | /// 589 | /// Returns success on the first call: the `outgoing-body` resource for 590 | /// this `outgoing-response` can be retrieved at most once. Subsequent 591 | /// calls will return error. 592 | @since(version = 0.2.0) 593 | body: func() -> result; 594 | } 595 | 596 | /// Represents an outgoing HTTP Request or Response's Body. 597 | /// 598 | /// A body has both its contents - a stream of bytes - and a (possibly 599 | /// empty) set of trailers, inducating the full contents of the body 600 | /// have been sent. This resource represents the contents as an 601 | /// `output-stream` child resource, and the completion of the body (with 602 | /// optional trailers) with a static function that consumes the 603 | /// `outgoing-body` resource, and ensures that the user of this interface 604 | /// may not write to the body contents after the body has been finished. 605 | /// 606 | /// If the user code drops this resource, as opposed to calling the static 607 | /// method `finish`, the implementation should treat the body as incomplete, 608 | /// and that an error has occurred. The implementation should propagate this 609 | /// error to the HTTP protocol by whatever means it has available, 610 | /// including: corrupting the body on the wire, aborting the associated 611 | /// Request, or sending a late status code for the Response. 612 | @since(version = 0.2.0) 613 | resource outgoing-body { 614 | 615 | /// Returns a stream for writing the body contents. 616 | /// 617 | /// The returned `output-stream` is a child resource: it must be dropped 618 | /// before the parent `outgoing-body` resource is dropped (or finished), 619 | /// otherwise the `outgoing-body` drop or `finish` will trap. 620 | /// 621 | /// Returns success on the first call: the `output-stream` resource for 622 | /// this `outgoing-body` may be retrieved at most once. Subsequent calls 623 | /// will return error. 624 | @since(version = 0.2.0) 625 | write: func() -> result; 626 | 627 | /// Finalize an outgoing body, optionally providing trailers. This must be 628 | /// called to signal that the response is complete. If the `outgoing-body` 629 | /// is dropped without calling `outgoing-body.finalize`, the implementation 630 | /// should treat the body as corrupted. 631 | /// 632 | /// Fails if the body's `outgoing-request` or `outgoing-response` was 633 | /// constructed with a Content-Length header, and the contents written 634 | /// to the body (via `write`) does not match the value given in the 635 | /// Content-Length. 636 | @since(version = 0.2.0) 637 | finish: static func( 638 | this: outgoing-body, 639 | trailers: option 640 | ) -> result<_, error-code>; 641 | } 642 | 643 | /// Represents a future which may eventually return an incoming HTTP 644 | /// Response, or an error. 645 | /// 646 | /// This resource is returned by the `wasi:http/outgoing-handler` interface to 647 | /// provide the HTTP Response corresponding to the sent Request. 648 | @since(version = 0.2.0) 649 | resource future-incoming-response { 650 | /// Returns a pollable which becomes ready when either the Response has 651 | /// been received, or an error has occurred. When this pollable is ready, 652 | /// the `get` method will return `some`. 653 | @since(version = 0.2.0) 654 | subscribe: func() -> pollable; 655 | 656 | /// Returns the incoming HTTP Response, or an error, once one is ready. 657 | /// 658 | /// The outer `option` represents future readiness. Users can wait on this 659 | /// `option` to become `some` using the `subscribe` method. 660 | /// 661 | /// The outer `result` is used to retrieve the response or error at most 662 | /// once. It will be success on the first call in which the outer option 663 | /// is `some`, and error on subsequent calls. 664 | /// 665 | /// The inner `result` represents that either the incoming HTTP Response 666 | /// status and headers have received successfully, or that an error 667 | /// occurred. Errors may also occur while consuming the response body, 668 | /// but those will be reported by the `incoming-body` and its 669 | /// `output-stream` child. 670 | @since(version = 0.2.0) 671 | get: func() -> option>>; 672 | } 673 | } 674 | -------------------------------------------------------------------------------- /wit/deps/io/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// offer functions to "downcast" this error into more specific types. For example, 15 | /// errors returned from streams derived from filesystem types can be described using 16 | /// the filesystem's own error-code type. This is done using the function 17 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow` 18 | /// parameter and returns an `option`. 19 | /// 20 | /// The set of functions which can "downcast" an `error` into a more 21 | /// concrete type is open. 22 | @since(version = 0.2.0) 23 | resource error { 24 | /// Returns a string that is suitable to assist humans in debugging 25 | /// this error. 26 | /// 27 | /// WARNING: The returned string should not be consumed mechanically! 28 | /// It may change across platforms, hosts, or other implementation 29 | /// details. Parsing this string is a major platform-compatibility 30 | /// hazard. 31 | @since(version = 0.2.0) 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wit/deps/io/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | @since(version = 0.2.0) 6 | interface poll { 7 | /// `pollable` represents a single I/O event which may be ready, or not. 8 | @since(version = 0.2.0) 9 | resource pollable { 10 | 11 | /// Return the readiness of a pollable. This function never blocks. 12 | /// 13 | /// Returns `true` when the pollable is ready, and `false` otherwise. 14 | @since(version = 0.2.0) 15 | ready: func() -> bool; 16 | 17 | /// `block` returns immediately if the pollable is ready, and otherwise 18 | /// blocks until ready. 19 | /// 20 | /// This function is equivalent to calling `poll.poll` on a list 21 | /// containing only this pollable. 22 | @since(version = 0.2.0) 23 | block: func(); 24 | } 25 | 26 | /// Poll for completion on a set of pollables. 27 | /// 28 | /// This function takes a list of pollables, which identify I/O sources of 29 | /// interest, and waits until one or more of the events is ready for I/O. 30 | /// 31 | /// The result `list` contains one or more indices of handles in the 32 | /// argument list that is ready for I/O. 33 | /// 34 | /// This function traps if either: 35 | /// - the list is empty, or: 36 | /// - the list contains more elements than can be indexed with a `u32` value. 37 | /// 38 | /// A timeout can be implemented by adding a pollable from the 39 | /// wasi-clocks API to the list. 40 | /// 41 | /// This function does not return a `result`; polling in itself does not 42 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 43 | /// the pollables has an error, it is indicated by marking the source as 44 | /// being ready for I/O. 45 | @since(version = 0.2.0) 46 | poll: func(in: list>) -> list; 47 | } 48 | -------------------------------------------------------------------------------- /wit/deps/io/streams.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | /// WASI I/O is an I/O abstraction API which is currently focused on providing 4 | /// stream types. 5 | /// 6 | /// In the future, the component model is expected to add built-in stream types; 7 | /// when it does, they are expected to subsume this API. 8 | @since(version = 0.2.0) 9 | interface streams { 10 | @since(version = 0.2.0) 11 | use error.{error}; 12 | @since(version = 0.2.0) 13 | use poll.{pollable}; 14 | 15 | /// An error for input-stream and output-stream operations. 16 | @since(version = 0.2.0) 17 | variant stream-error { 18 | /// The last operation (a write or flush) failed before completion. 19 | /// 20 | /// More information is available in the `error` payload. 21 | /// 22 | /// After this, the stream will be closed. All future operations return 23 | /// `stream-error::closed`. 24 | last-operation-failed(error), 25 | /// The stream is closed: no more input will be accepted by the 26 | /// stream. A closed output-stream will return this error on all 27 | /// future operations. 28 | closed 29 | } 30 | 31 | /// An input bytestream. 32 | /// 33 | /// `input-stream`s are *non-blocking* to the extent practical on underlying 34 | /// platforms. I/O operations always return promptly; if fewer bytes are 35 | /// promptly available than requested, they return the number of bytes promptly 36 | /// available, which could even be zero. To wait for data to be available, 37 | /// use the `subscribe` function to obtain a `pollable` which can be polled 38 | /// for using `wasi:io/poll`. 39 | @since(version = 0.2.0) 40 | resource input-stream { 41 | /// Perform a non-blocking read from the stream. 42 | /// 43 | /// When the source of a `read` is binary data, the bytes from the source 44 | /// are returned verbatim. When the source of a `read` is known to the 45 | /// implementation to be text, bytes containing the UTF-8 encoding of the 46 | /// text are returned. 47 | /// 48 | /// This function returns a list of bytes containing the read data, 49 | /// when successful. The returned list will contain up to `len` bytes; 50 | /// it may return fewer than requested, but not more. The list is 51 | /// empty when no bytes are available for reading at this time. The 52 | /// pollable given by `subscribe` will be ready when more bytes are 53 | /// available. 54 | /// 55 | /// This function fails with a `stream-error` when the operation 56 | /// encounters an error, giving `last-operation-failed`, or when the 57 | /// stream is closed, giving `closed`. 58 | /// 59 | /// When the caller gives a `len` of 0, it represents a request to 60 | /// read 0 bytes. If the stream is still open, this call should 61 | /// succeed and return an empty list, or otherwise fail with `closed`. 62 | /// 63 | /// The `len` parameter is a `u64`, which could represent a list of u8 which 64 | /// is not possible to allocate in wasm32, or not desirable to allocate as 65 | /// as a return value by the callee. The callee may return a list of bytes 66 | /// less than `len` in size while more bytes are available for reading. 67 | @since(version = 0.2.0) 68 | read: func( 69 | /// The maximum number of bytes to read 70 | len: u64 71 | ) -> result, stream-error>; 72 | 73 | /// Read bytes from a stream, after blocking until at least one byte can 74 | /// be read. Except for blocking, behavior is identical to `read`. 75 | @since(version = 0.2.0) 76 | blocking-read: func( 77 | /// The maximum number of bytes to read 78 | len: u64 79 | ) -> result, stream-error>; 80 | 81 | /// Skip bytes from a stream. Returns number of bytes skipped. 82 | /// 83 | /// Behaves identical to `read`, except instead of returning a list 84 | /// of bytes, returns the number of bytes consumed from the stream. 85 | @since(version = 0.2.0) 86 | skip: func( 87 | /// The maximum number of bytes to skip. 88 | len: u64, 89 | ) -> result; 90 | 91 | /// Skip bytes from a stream, after blocking until at least one byte 92 | /// can be skipped. Except for blocking behavior, identical to `skip`. 93 | @since(version = 0.2.0) 94 | blocking-skip: func( 95 | /// The maximum number of bytes to skip. 96 | len: u64, 97 | ) -> result; 98 | 99 | /// Create a `pollable` which will resolve once either the specified stream 100 | /// has bytes available to read or the other end of the stream has been 101 | /// closed. 102 | /// The created `pollable` is a child resource of the `input-stream`. 103 | /// Implementations may trap if the `input-stream` is dropped before 104 | /// all derived `pollable`s created with this function are dropped. 105 | @since(version = 0.2.0) 106 | subscribe: func() -> pollable; 107 | } 108 | 109 | 110 | /// An output bytestream. 111 | /// 112 | /// `output-stream`s are *non-blocking* to the extent practical on 113 | /// underlying platforms. Except where specified otherwise, I/O operations also 114 | /// always return promptly, after the number of bytes that can be written 115 | /// promptly, which could even be zero. To wait for the stream to be ready to 116 | /// accept data, the `subscribe` function to obtain a `pollable` which can be 117 | /// polled for using `wasi:io/poll`. 118 | /// 119 | /// Dropping an `output-stream` while there's still an active write in 120 | /// progress may result in the data being lost. Before dropping the stream, 121 | /// be sure to fully flush your writes. 122 | @since(version = 0.2.0) 123 | resource output-stream { 124 | /// Check readiness for writing. This function never blocks. 125 | /// 126 | /// Returns the number of bytes permitted for the next call to `write`, 127 | /// or an error. Calling `write` with more bytes than this function has 128 | /// permitted will trap. 129 | /// 130 | /// When this function returns 0 bytes, the `subscribe` pollable will 131 | /// become ready when this function will report at least 1 byte, or an 132 | /// error. 133 | @since(version = 0.2.0) 134 | check-write: func() -> result; 135 | 136 | /// Perform a write. This function never blocks. 137 | /// 138 | /// When the destination of a `write` is binary data, the bytes from 139 | /// `contents` are written verbatim. When the destination of a `write` is 140 | /// known to the implementation to be text, the bytes of `contents` are 141 | /// transcoded from UTF-8 into the encoding of the destination and then 142 | /// written. 143 | /// 144 | /// Precondition: check-write gave permit of Ok(n) and contents has a 145 | /// length of less than or equal to n. Otherwise, this function will trap. 146 | /// 147 | /// returns Err(closed) without writing if the stream has closed since 148 | /// the last call to check-write provided a permit. 149 | @since(version = 0.2.0) 150 | write: func( 151 | contents: list 152 | ) -> result<_, stream-error>; 153 | 154 | /// Perform a write of up to 4096 bytes, and then flush the stream. Block 155 | /// until all of these operations are complete, or an error occurs. 156 | /// 157 | /// This is a convenience wrapper around the use of `check-write`, 158 | /// `subscribe`, `write`, and `flush`, and is implemented with the 159 | /// following pseudo-code: 160 | /// 161 | /// ```text 162 | /// let pollable = this.subscribe(); 163 | /// while !contents.is_empty() { 164 | /// // Wait for the stream to become writable 165 | /// pollable.block(); 166 | /// let Ok(n) = this.check-write(); // eliding error handling 167 | /// let len = min(n, contents.len()); 168 | /// let (chunk, rest) = contents.split_at(len); 169 | /// this.write(chunk ); // eliding error handling 170 | /// contents = rest; 171 | /// } 172 | /// this.flush(); 173 | /// // Wait for completion of `flush` 174 | /// pollable.block(); 175 | /// // Check for any errors that arose during `flush` 176 | /// let _ = this.check-write(); // eliding error handling 177 | /// ``` 178 | @since(version = 0.2.0) 179 | blocking-write-and-flush: func( 180 | contents: list 181 | ) -> result<_, stream-error>; 182 | 183 | /// Request to flush buffered output. This function never blocks. 184 | /// 185 | /// This tells the output-stream that the caller intends any buffered 186 | /// output to be flushed. the output which is expected to be flushed 187 | /// is all that has been passed to `write` prior to this call. 188 | /// 189 | /// Upon calling this function, the `output-stream` will not accept any 190 | /// writes (`check-write` will return `ok(0)`) until the flush has 191 | /// completed. The `subscribe` pollable will become ready when the 192 | /// flush has completed and the stream can accept more writes. 193 | @since(version = 0.2.0) 194 | flush: func() -> result<_, stream-error>; 195 | 196 | /// Request to flush buffered output, and block until flush completes 197 | /// and stream is ready for writing again. 198 | @since(version = 0.2.0) 199 | blocking-flush: func() -> result<_, stream-error>; 200 | 201 | /// Create a `pollable` which will resolve once the output-stream 202 | /// is ready for more writing, or an error has occurred. When this 203 | /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an 204 | /// error. 205 | /// 206 | /// If the stream is closed, this pollable is always ready immediately. 207 | /// 208 | /// The created `pollable` is a child resource of the `output-stream`. 209 | /// Implementations may trap if the `output-stream` is dropped before 210 | /// all derived `pollable`s created with this function are dropped. 211 | @since(version = 0.2.0) 212 | subscribe: func() -> pollable; 213 | 214 | /// Write zeroes to a stream. 215 | /// 216 | /// This should be used precisely like `write` with the exact same 217 | /// preconditions (must use check-write first), but instead of 218 | /// passing a list of bytes, you simply pass the number of zero-bytes 219 | /// that should be written. 220 | @since(version = 0.2.0) 221 | write-zeroes: func( 222 | /// The number of zero-bytes to write 223 | len: u64 224 | ) -> result<_, stream-error>; 225 | 226 | /// Perform a write of up to 4096 zeroes, and then flush the stream. 227 | /// Block until all of these operations are complete, or an error 228 | /// occurs. 229 | /// 230 | /// This is a convenience wrapper around the use of `check-write`, 231 | /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with 232 | /// the following pseudo-code: 233 | /// 234 | /// ```text 235 | /// let pollable = this.subscribe(); 236 | /// while num_zeroes != 0 { 237 | /// // Wait for the stream to become writable 238 | /// pollable.block(); 239 | /// let Ok(n) = this.check-write(); // eliding error handling 240 | /// let len = min(n, num_zeroes); 241 | /// this.write-zeroes(len); // eliding error handling 242 | /// num_zeroes -= len; 243 | /// } 244 | /// this.flush(); 245 | /// // Wait for completion of `flush` 246 | /// pollable.block(); 247 | /// // Check for any errors that arose during `flush` 248 | /// let _ = this.check-write(); // eliding error handling 249 | /// ``` 250 | @since(version = 0.2.0) 251 | blocking-write-zeroes-and-flush: func( 252 | /// The number of zero-bytes to write 253 | len: u64 254 | ) -> result<_, stream-error>; 255 | 256 | /// Read from one stream and write to another. 257 | /// 258 | /// The behavior of splice is equivalent to: 259 | /// 1. calling `check-write` on the `output-stream` 260 | /// 2. calling `read` on the `input-stream` with the smaller of the 261 | /// `check-write` permitted length and the `len` provided to `splice` 262 | /// 3. calling `write` on the `output-stream` with that read data. 263 | /// 264 | /// Any error reported by the call to `check-write`, `read`, or 265 | /// `write` ends the splice and reports that error. 266 | /// 267 | /// This function returns the number of bytes transferred; it may be less 268 | /// than `len`. 269 | @since(version = 0.2.0) 270 | splice: func( 271 | /// The stream to read from 272 | src: borrow, 273 | /// The number of bytes to splice 274 | len: u64, 275 | ) -> result; 276 | 277 | /// Read from one stream and write to another, with blocking. 278 | /// 279 | /// This is similar to `splice`, except that it blocks until the 280 | /// `output-stream` is ready for writing, and the `input-stream` 281 | /// is ready for reading, before performing the `splice`. 282 | @since(version = 0.2.0) 283 | blocking-splice: func( 284 | /// The stream to read from 285 | src: borrow, 286 | /// The number of bytes to splice 287 | len: u64, 288 | ) -> result; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /wit/deps/io/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import streams; 7 | 8 | @since(version = 0.2.0) 9 | import poll; 10 | } 11 | -------------------------------------------------------------------------------- /wit/deps/keyvalue/atomic.wit: -------------------------------------------------------------------------------- 1 | /// A keyvalue interface that provides atomic operations. 2 | /// 3 | /// Atomic operations are single, indivisible operations. When a fault causes an atomic operation to 4 | /// fail, it will appear to the invoker of the atomic operation that the action either completed 5 | /// successfully or did nothing at all. 6 | /// 7 | /// Please note that this interface is bare functions that take a reference to a bucket. This is to 8 | /// get around the current lack of a way to "extend" a resource with additional methods inside of 9 | /// wit. Future version of the interface will instead extend these methods on the base `bucket` 10 | /// resource. 11 | interface atomics { 12 | use store.{bucket, error}; 13 | 14 | /// The error returned by a CAS operation 15 | variant cas-error { 16 | /// A store error occurred when performing the operation 17 | store-error(error), 18 | /// The CAS operation failed because the value was too old. This returns a new CAS handle 19 | /// for easy retries. Implementors MUST return a CAS handle that has been updated to the 20 | /// latest version or transaction. 21 | cas-failed(cas), 22 | } 23 | 24 | /// A handle to a CAS (compare-and-swap) operation. 25 | resource cas { 26 | /// Construct a new CAS operation. Implementors can map the underlying functionality 27 | /// (transactions, versions, etc) as desired. 28 | new: static func(bucket: borrow, key: string) -> result; 29 | /// Get the current value of the key (if it exists). This allows for avoiding reads if all 30 | /// that is needed to ensure the atomicity of the operation 31 | current: func() -> result>, error>; 32 | } 33 | 34 | /// Atomically increment the value associated with the key in the store by the given delta. It 35 | /// returns the new value. 36 | /// 37 | /// If the key does not exist in the store, it creates a new key-value pair with the value set 38 | /// to the given delta. 39 | /// 40 | /// If any other error occurs, it returns an `Err(error)`. 41 | increment: func(bucket: borrow, key: string, delta: s64) -> result; 42 | 43 | /// Perform the swap on a CAS operation. This consumes the CAS handle and returns an error if 44 | /// the CAS operation failed. 45 | swap: func(cas: cas, value: list) -> result<_, cas-error>; 46 | } -------------------------------------------------------------------------------- /wit/deps/keyvalue/batch.wit: -------------------------------------------------------------------------------- 1 | /// A keyvalue interface that provides batch operations. 2 | /// 3 | /// A batch operation is an operation that operates on multiple keys at once. 4 | /// 5 | /// Batch operations are useful for reducing network round-trip time. For example, if you want to 6 | /// get the values associated with 100 keys, you can either do 100 get operations or you can do 1 7 | /// batch get operation. The batch operation is faster because it only needs to make 1 network call 8 | /// instead of 100. 9 | /// 10 | /// A batch operation does not guarantee atomicity, meaning that if the batch operation fails, some 11 | /// of the keys may have been modified and some may not. 12 | /// 13 | /// This interface does has the same consistency guarantees as the `store` interface, meaning that 14 | /// you should be able to "read your writes." 15 | /// 16 | /// Please note that this interface is bare functions that take a reference to a bucket. This is to 17 | /// get around the current lack of a way to "extend" a resource with additional methods inside of 18 | /// wit. Future version of the interface will instead extend these methods on the base `bucket` 19 | /// resource. 20 | interface batch { 21 | use store.{bucket, error}; 22 | 23 | /// Get the key-value pairs associated with the keys in the store. It returns a list of 24 | /// key-value pairs. 25 | /// 26 | /// If any of the keys do not exist in the store, it returns a `none` value for that pair in the 27 | /// list. 28 | /// 29 | /// MAY show an out-of-date value if there are concurrent writes to the store. 30 | /// 31 | /// If any other error occurs, it returns an `Err(error)`. 32 | get-many: func(bucket: borrow, keys: list) -> result>>>, error>; 33 | 34 | /// Set the values associated with the keys in the store. If the key already exists in the 35 | /// store, it overwrites the value. 36 | /// 37 | /// Note that the key-value pairs are not guaranteed to be set in the order they are provided. 38 | /// 39 | /// If any of the keys do not exist in the store, it creates a new key-value pair. 40 | /// 41 | /// If any other error occurs, it returns an `Err(error)`. When an error occurs, it does not 42 | /// rollback the key-value pairs that were already set. Thus, this batch operation does not 43 | /// guarantee atomicity, implying that some key-value pairs could be set while others might 44 | /// fail. 45 | /// 46 | /// Other concurrent operations may also be able to see the partial results. 47 | set-many: func(bucket: borrow, key-values: list>>) -> result<_, error>; 48 | 49 | /// Delete the key-value pairs associated with the keys in the store. 50 | /// 51 | /// Note that the key-value pairs are not guaranteed to be deleted in the order they are 52 | /// provided. 53 | /// 54 | /// If any of the keys do not exist in the store, it skips the key. 55 | /// 56 | /// If any other error occurs, it returns an `Err(error)`. When an error occurs, it does not 57 | /// rollback the key-value pairs that were already deleted. Thus, this batch operation does not 58 | /// guarantee atomicity, implying that some key-value pairs could be deleted while others might 59 | /// fail. 60 | /// 61 | /// Other concurrent operations may also be able to see the partial results. 62 | delete-many: func(bucket: borrow, keys: list) -> result<_, error>; 63 | } 64 | -------------------------------------------------------------------------------- /wit/deps/keyvalue/store.wit: -------------------------------------------------------------------------------- 1 | /// A keyvalue interface that provides eventually consistent key-value operations. 2 | /// 3 | /// Each of these operations acts on a single key-value pair. 4 | /// 5 | /// The value in the key-value pair is defined as a `u8` byte array and the intention is that it is 6 | /// the common denominator for all data types defined by different key-value stores to handle data, 7 | /// ensuring compatibility between different key-value stores. Note: the clients will be expecting 8 | /// serialization/deserialization overhead to be handled by the key-value store. The value could be 9 | /// a serialized object from JSON, HTML or vendor-specific data types like AWS S3 objects. 10 | /// 11 | /// Data consistency in a key value store refers to the guarantee that once a write operation 12 | /// completes, all subsequent read operations will return the value that was written. 13 | /// 14 | /// Any implementation of this interface must have enough consistency to guarantee "reading your 15 | /// writes." In particular, this means that the client should never get a value that is older than 16 | /// the one it wrote, but it MAY get a newer value if one was written around the same time. These 17 | /// guarantees only apply to the same client (which will likely be provided by the host or an 18 | /// external capability of some kind). In this context a "client" is referring to the caller or 19 | /// guest that is consuming this interface. Once a write request is committed by a specific client, 20 | /// all subsequent read requests by the same client will reflect that write or any subsequent 21 | /// writes. Another client running in a different context may or may not immediately see the result 22 | /// due to the replication lag. As an example of all of this, if a value at a given key is A, and 23 | /// the client writes B, then immediately reads, it should get B. If something else writes C in 24 | /// quick succession, then the client may get C. However, a client running in a separate context may 25 | /// still see A or B 26 | interface store { 27 | /// The set of errors which may be raised by functions in this package 28 | variant error { 29 | /// The host does not recognize the store identifier requested. 30 | no-such-store, 31 | 32 | /// The requesting component does not have access to the specified store 33 | /// (which may or may not exist). 34 | access-denied, 35 | 36 | /// Some implementation-specific error has occurred (e.g. I/O) 37 | other(string) 38 | } 39 | 40 | /// A response to a `list-keys` operation. 41 | record key-response { 42 | /// The list of keys returned by the query. 43 | keys: list, 44 | /// The continuation token to use to fetch the next page of keys. If this is `null`, then 45 | /// there are no more keys to fetch. 46 | cursor: option 47 | } 48 | 49 | /// Get the bucket with the specified identifier. 50 | /// 51 | /// `identifier` must refer to a bucket provided by the host. 52 | /// 53 | /// `error::no-such-store` will be raised if the `identifier` is not recognized. 54 | open: func(identifier: string) -> result; 55 | 56 | /// A bucket is a collection of key-value pairs. Each key-value pair is stored as a entry in the 57 | /// bucket, and the bucket itself acts as a collection of all these entries. 58 | /// 59 | /// It is worth noting that the exact terminology for bucket in key-value stores can very 60 | /// depending on the specific implementation. For example: 61 | /// 62 | /// 1. Amazon DynamoDB calls a collection of key-value pairs a table 63 | /// 2. Redis has hashes, sets, and sorted sets as different types of collections 64 | /// 3. Cassandra calls a collection of key-value pairs a column family 65 | /// 4. MongoDB calls a collection of key-value pairs a collection 66 | /// 5. Riak calls a collection of key-value pairs a bucket 67 | /// 6. Memcached calls a collection of key-value pairs a slab 68 | /// 7. Azure Cosmos DB calls a collection of key-value pairs a container 69 | /// 70 | /// In this interface, we use the term `bucket` to refer to a collection of key-value pairs 71 | resource bucket { 72 | /// Get the value associated with the specified `key` 73 | /// 74 | /// The value is returned as an option. If the key-value pair exists in the 75 | /// store, it returns `Ok(value)`. If the key does not exist in the 76 | /// store, it returns `Ok(none)`. 77 | /// 78 | /// If any other error occurs, it returns an `Err(error)`. 79 | get: func(key: string) -> result>, error>; 80 | 81 | /// Set the value associated with the key in the store. If the key already 82 | /// exists in the store, it overwrites the value. 83 | /// 84 | /// If the key does not exist in the store, it creates a new key-value pair. 85 | /// 86 | /// If any other error occurs, it returns an `Err(error)`. 87 | set: func(key: string, value: list) -> result<_, error>; 88 | 89 | /// Delete the key-value pair associated with the key in the store. 90 | /// 91 | /// If the key does not exist in the store, it does nothing. 92 | /// 93 | /// If any other error occurs, it returns an `Err(error)`. 94 | delete: func(key: string) -> result<_, error>; 95 | 96 | /// Check if the key exists in the store. 97 | /// 98 | /// If the key exists in the store, it returns `Ok(true)`. If the key does 99 | /// not exist in the store, it returns `Ok(false)`. 100 | /// 101 | /// If any other error occurs, it returns an `Err(error)`. 102 | exists: func(key: string) -> result; 103 | 104 | /// Get all the keys in the store with an optional cursor (for use in pagination). It 105 | /// returns a list of keys. Please note that for most KeyValue implementations, this is a 106 | /// can be a very expensive operation and so it should be used judiciously. Implementations 107 | /// can return any number of keys in a single response, but they should never attempt to 108 | /// send more data than is reasonable (i.e. on a small edge device, this may only be a few 109 | /// KB, while on a large machine this could be several MB). Any response should also return 110 | /// a cursor that can be used to fetch the next page of keys. See the `key-response` record 111 | /// for more information. 112 | /// 113 | /// Note that the keys are not guaranteed to be returned in any particular order. 114 | /// 115 | /// If the store is empty, it returns an empty list. 116 | /// 117 | /// MAY show an out-of-date list of keys if there are concurrent writes to the store. 118 | /// 119 | /// If any error occurs, it returns an `Err(error)`. 120 | list-keys: func(cursor: option) -> result; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /wit/deps/keyvalue/watch.wit: -------------------------------------------------------------------------------- 1 | /// A keyvalue interface that provides watch operations. 2 | /// 3 | /// This interface is used to provide event-driven mechanisms to handle 4 | /// keyvalue changes. 5 | interface watcher { 6 | /// A keyvalue interface that provides handle-watch operations. 7 | use store.{bucket}; 8 | 9 | /// Handle the `set` event for the given bucket and key. It includes a reference to the `bucket` 10 | /// that can be used to interact with the store. 11 | on-set: func(bucket: bucket, key: string, value: list); 12 | 13 | /// Handle the `delete` event for the given bucket and key. It includes a reference to the 14 | /// `bucket` that can be used to interact with the store. 15 | on-delete: func(bucket: bucket, key: string); 16 | } -------------------------------------------------------------------------------- /wit/deps/keyvalue/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:keyvalue@0.2.0-draft2; 2 | 3 | /// The `wasi:keyvalue/imports` world provides common APIs for interacting with key-value stores. 4 | /// Components targeting this world will be able to do: 5 | /// 6 | /// 1. CRUD (create, read, update, delete) operations on key-value stores. 7 | /// 2. Atomic `increment` and CAS (compare-and-swap) operations. 8 | /// 3. Batch operations that can reduce the number of round trips to the network. 9 | world imports { 10 | /// The `store` capability allows the component to perform eventually consistent operations on 11 | /// the key-value store. 12 | import store; 13 | 14 | /// The `atomic` capability allows the component to perform atomic / `increment` and CAS 15 | /// (compare-and-swap) operations. 16 | import atomics; 17 | 18 | /// The `batch` capability allows the component to perform eventually consistent batch 19 | /// operations that can reduce the number of round trips to the network. 20 | import batch; 21 | } 22 | 23 | world watch-service { 24 | include imports; 25 | export watcher; 26 | } -------------------------------------------------------------------------------- /wit/deps/messaging/consumer.wit: -------------------------------------------------------------------------------- 1 | interface consumer { 2 | // {client, message, channel, error, guest-configuration} 3 | use messaging-types.{client, message, channel, error, guest-configuration}; 4 | 5 | /// Blocking receive for t-milliseconds with ephemeral subscription – if no message is received, returns None 6 | subscribe-try-receive: func(c: client, ch: channel, t-milliseconds: u32) -> result>, error>; 7 | 8 | /// Blocking receive until message with ephemeral subscription 9 | subscribe-receive: func(c: client, ch: channel) -> result, error>; 10 | 11 | /// 'Fit-all' type function for updating a guest's configuration – this could be useful for: 12 | /// - unsubscribing from a channel, 13 | /// - checkpointing, 14 | /// - etc.. 15 | update-guest-configuration: func(gc: guest-configuration) -> result<_, error>; 16 | 17 | /// A message can exist under several statuses: 18 | /// (1) available: the message is ready to be read, 19 | /// (2) acquired: the message has been sent to a consumer (but still exists in the queue), 20 | /// (3) accepted (result of complete-message): the message has been received and ACK-ed by a consumer and can be safely removed from the queue, 21 | /// (4) rejected (result of abandon-message): the message has been received and NACK-ed by a consumer, at which point it can be: 22 | /// - deleted, 23 | /// - sent to a dead-letter queue, or 24 | /// - kept in the queue for further processing. 25 | complete-message: func(m: message) -> result<_, error>; 26 | abandon-message: func(m: message) -> result<_, error>; 27 | } 28 | -------------------------------------------------------------------------------- /wit/deps/messaging/guest.wit: -------------------------------------------------------------------------------- 1 | interface messaging-guest { 2 | use messaging-types.{message, guest-configuration, error}; 3 | 4 | /// Returns the list of channels (and extension metadata within guest-configuration) that 5 | /// this component should subscribe to and be handled by the subsequent handler within guest-configuration 6 | configure: func() -> result; 7 | 8 | /// Whenever this guest receives a message in one of the subscribed channels, the message is sent to this handler 9 | handler: func(ms: list) -> result<_, error>; 10 | } 11 | -------------------------------------------------------------------------------- /wit/deps/messaging/messaging.wit: -------------------------------------------------------------------------------- 1 | package wasi:messaging@0.2.0-draft; 2 | 3 | world imports { 4 | import producer; 5 | import consumer; 6 | } 7 | 8 | world messaging { 9 | include imports; 10 | export messaging-guest; 11 | } -------------------------------------------------------------------------------- /wit/deps/messaging/producer.wit: -------------------------------------------------------------------------------- 1 | interface producer { 2 | use messaging-types.{client, channel, message, error}; 3 | 4 | send: func(c: client, ch: channel, m: list) -> result<_, error>; 5 | } 6 | -------------------------------------------------------------------------------- /wit/deps/messaging/types.wit: -------------------------------------------------------------------------------- 1 | interface messaging-types { 2 | /// A connection to a message-exchange service (e.g., buffer, broker, etc.). 3 | resource client { 4 | connect: static func(name: string) -> result; 5 | } 6 | 7 | /// TODO(danbugs): This should be eventually extracted as an underlying type for other wasi-cloud-core interfaces. 8 | resource error { 9 | trace: static func() -> string; 10 | } 11 | 12 | /// There are two types of channels: 13 | /// - publish-subscribe channel, which is a broadcast channel, and 14 | /// - point-to-point channel, which is a unicast channel. 15 | /// 16 | /// The interface doesn't highlight this difference in the type itself as that's uniquely a consumer issue. 17 | type channel = string; 18 | 19 | /// Configuration includes a required list of channels the guest is subscribing to, and an optional list of extensions key-value pairs 20 | /// (e.g., partitions/offsets to read from in Kafka/EventHubs, QoS etc.). 21 | record guest-configuration { 22 | channels: list, 23 | extensions: option>> 24 | } 25 | 26 | /// Format specification for messages 27 | /// - more info: https://github.com/clemensv/spec/blob/registry-extensions/registry/spec.md#message-formats 28 | /// - message metadata can further decorate w/ things like format version, and so on. 29 | enum format-spec { 30 | cloudevents, 31 | http, 32 | amqp, 33 | mqtt, 34 | kafka, 35 | raw 36 | } 37 | 38 | /// A message with a binary payload, a format specification, and decorative metadata. 39 | record message { 40 | data: list, 41 | format: format-spec, 42 | metadata: option>> 43 | } 44 | } -------------------------------------------------------------------------------- /wit/deps/random/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// The insecure-seed interface for seeding hash-map DoS resistance. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure-seed { 8 | /// Return a 128-bit value that may contain a pseudo-random value. 9 | /// 10 | /// The returned value is not required to be computed from a CSPRNG, and may 11 | /// even be entirely deterministic. Host implementations are encouraged to 12 | /// provide pseudo-random values to any program exposed to 13 | /// attacker-controlled content, to enable DoS protection built into many 14 | /// languages' hash-map implementations. 15 | /// 16 | /// This function is intended to only be called once, by a source language 17 | /// to initialize Denial Of Service (DoS) protection in its hash-map 18 | /// implementation. 19 | /// 20 | /// # Expected future evolution 21 | /// 22 | /// This will likely be changed to a value import, to prevent it from being 23 | /// called multiple times and potentially used for purposes other than DoS 24 | /// protection. 25 | @since(version = 0.2.0) 26 | insecure-seed: func() -> tuple; 27 | } 28 | -------------------------------------------------------------------------------- /wit/deps/random/insecure.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// The insecure interface for insecure pseudo-random numbers. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure { 8 | /// Return `len` insecure pseudo-random bytes. 9 | /// 10 | /// This function is not cryptographically secure. Do not use it for 11 | /// anything related to security. 12 | /// 13 | /// There are no requirements on the values of the returned bytes, however 14 | /// implementations are encouraged to return evenly distributed values with 15 | /// a long period. 16 | @since(version = 0.2.0) 17 | get-insecure-random-bytes: func(len: u64) -> list; 18 | 19 | /// Return an insecure pseudo-random `u64` value. 20 | /// 21 | /// This function returns the same type of pseudo-random data as 22 | /// `get-insecure-random-bytes`, represented as a `u64`. 23 | @since(version = 0.2.0) 24 | get-insecure-random-u64: func() -> u64; 25 | } 26 | -------------------------------------------------------------------------------- /wit/deps/random/random.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | /// WASI Random is a random data API. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface random { 8 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 9 | /// 10 | /// This function must produce data at least as cryptographically secure and 11 | /// fast as an adequately seeded cryptographically-secure pseudo-random 12 | /// number generator (CSPRNG). It must not block, from the perspective of 13 | /// the calling program, under any circumstances, including on the first 14 | /// request and on requests for numbers of bytes. The returned data must 15 | /// always be unpredictable. 16 | /// 17 | /// This function must always return fresh data. Deterministic environments 18 | /// must omit this function, rather than implementing it with deterministic 19 | /// data. 20 | @since(version = 0.2.0) 21 | get-random-bytes: func(len: u64) -> list; 22 | 23 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 24 | /// 25 | /// This function returns the same type of data as `get-random-bytes`, 26 | /// represented as a `u64`. 27 | @since(version = 0.2.0) 28 | get-random-u64: func() -> u64; 29 | } 30 | -------------------------------------------------------------------------------- /wit/deps/random/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import random; 7 | 8 | @since(version = 0.2.0) 9 | import insecure; 10 | 11 | @since(version = 0.2.0) 12 | import insecure-seed; 13 | } 14 | -------------------------------------------------------------------------------- /wit/deps/runtime-config/store.wit: -------------------------------------------------------------------------------- 1 | interface store { 2 | /// An error type that encapsulates the different errors that can occur fetching configuration values. 3 | variant error { 4 | /// This indicates an error from an "upstream" config source. 5 | /// As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue buckets, etc), 6 | /// the error message is a string. 7 | upstream(string), 8 | /// This indicates an error from an I/O operation. 9 | /// As this could be almost _anything_ (such as a file read, network connection, etc), 10 | /// the error message is a string. 11 | /// Depending on how this ends up being consumed, 12 | /// we may consider moving this to use the `wasi:io/error` type instead. 13 | /// For simplicity right now in supporting multiple implementations, it is being left as a string. 14 | io(string), 15 | } 16 | 17 | /// Gets a configuration value of type `string` associated with the `key`. 18 | /// 19 | /// The value is returned as an `option`. If the key is not found, 20 | /// `Ok(none)` is returned. If an error occurs, an `Err(error)` is returned. 21 | get: func( 22 | /// A string key to fetch 23 | key: string 24 | ) -> result, error>; 25 | 26 | /// Gets a list of configuration key-value pairs of type `string`. 27 | /// 28 | /// If an error occurs, an `Err(error)` is returned. 29 | get-all: func() -> result>, error>; 30 | } 31 | -------------------------------------------------------------------------------- /wit/deps/runtime-config/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:config@0.2.0-draft; 2 | 3 | world imports { 4 | /// The interface for wasi:config/store 5 | import store; 6 | } -------------------------------------------------------------------------------- /wit/deps/sockets/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | @since(version = 0.2.0) 4 | interface instance-network { 5 | @since(version = 0.2.0) 6 | use network.{network}; 7 | 8 | /// Get a handle to the default network. 9 | @since(version = 0.2.0) 10 | instance-network: func() -> network; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/sockets/ip-name-lookup.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface ip-name-lookup { 3 | @since(version = 0.2.0) 4 | use wasi:io/poll@0.2.1.{pollable}; 5 | @since(version = 0.2.0) 6 | use network.{network, error-code, ip-address}; 7 | 8 | /// Resolve an internet host name to a list of IP addresses. 9 | /// 10 | /// Unicode domain names are automatically converted to ASCII using IDNA encoding. 11 | /// If the input is an IP address string, the address is parsed and returned 12 | /// as-is without making any external requests. 13 | /// 14 | /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. 15 | /// 16 | /// This function never blocks. It either immediately fails or immediately 17 | /// returns successfully with a `resolve-address-stream` that can be used 18 | /// to (asynchronously) fetch the results. 19 | /// 20 | /// # Typical errors 21 | /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. 22 | /// 23 | /// # References: 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | resolve-addresses: func(network: borrow, name: string) -> result; 30 | 31 | @since(version = 0.2.0) 32 | resource resolve-address-stream { 33 | /// Returns the next address from the resolver. 34 | /// 35 | /// This function should be called multiple times. On each call, it will 36 | /// return the next address in connection order preference. If all 37 | /// addresses have been exhausted, this function returns `none`. 38 | /// 39 | /// This function never returns IPv4-mapped IPv6 addresses. 40 | /// 41 | /// # Typical errors 42 | /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) 43 | /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) 44 | /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) 45 | /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) 46 | @since(version = 0.2.0) 47 | resolve-next-address: func() -> result, error-code>; 48 | 49 | /// Create a `pollable` which will resolve once the stream is ready for I/O. 50 | /// 51 | /// Note: this function is here for WASI Preview2 only. 52 | /// It's planned to be removed when `future` is natively supported in Preview3. 53 | @since(version = 0.2.0) 54 | subscribe: func() -> pollable; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /wit/deps/sockets/network.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface network { 3 | /// An opaque resource that represents access to (a subset of) the network. 4 | /// This enables context-based security for networking. 5 | /// There is no need for this to map 1:1 to a physical network interface. 6 | @since(version = 0.2.0) 7 | resource network; 8 | 9 | /// Error codes. 10 | /// 11 | /// In theory, every API can return any error code. 12 | /// In practice, API's typically only return the errors documented per API 13 | /// combined with a couple of errors that are always possible: 14 | /// - `unknown` 15 | /// - `access-denied` 16 | /// - `not-supported` 17 | /// - `out-of-memory` 18 | /// - `concurrency-conflict` 19 | /// 20 | /// See each individual API for what the POSIX equivalents are. They sometimes differ per API. 21 | @since(version = 0.2.0) 22 | enum error-code { 23 | /// Unknown error 24 | unknown, 25 | 26 | /// Access denied. 27 | /// 28 | /// POSIX equivalent: EACCES, EPERM 29 | access-denied, 30 | 31 | /// The operation is not supported. 32 | /// 33 | /// POSIX equivalent: EOPNOTSUPP 34 | not-supported, 35 | 36 | /// One of the arguments is invalid. 37 | /// 38 | /// POSIX equivalent: EINVAL 39 | invalid-argument, 40 | 41 | /// Not enough memory to complete the operation. 42 | /// 43 | /// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY 44 | out-of-memory, 45 | 46 | /// The operation timed out before it could finish completely. 47 | timeout, 48 | 49 | /// This operation is incompatible with another asynchronous operation that is already in progress. 50 | /// 51 | /// POSIX equivalent: EALREADY 52 | concurrency-conflict, 53 | 54 | /// Trying to finish an asynchronous operation that: 55 | /// - has not been started yet, or: 56 | /// - was already finished by a previous `finish-*` call. 57 | /// 58 | /// Note: this is scheduled to be removed when `future`s are natively supported. 59 | not-in-progress, 60 | 61 | /// The operation has been aborted because it could not be completed immediately. 62 | /// 63 | /// Note: this is scheduled to be removed when `future`s are natively supported. 64 | would-block, 65 | 66 | 67 | /// The operation is not valid in the socket's current state. 68 | invalid-state, 69 | 70 | /// A new socket resource could not be created because of a system limit. 71 | new-socket-limit, 72 | 73 | /// A bind operation failed because the provided address is not an address that the `network` can bind to. 74 | address-not-bindable, 75 | 76 | /// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. 77 | address-in-use, 78 | 79 | /// The remote address is not reachable 80 | remote-unreachable, 81 | 82 | 83 | /// The TCP connection was forcefully rejected 84 | connection-refused, 85 | 86 | /// The TCP connection was reset. 87 | connection-reset, 88 | 89 | /// A TCP connection was aborted. 90 | connection-aborted, 91 | 92 | 93 | /// The size of a datagram sent to a UDP socket exceeded the maximum 94 | /// supported size. 95 | datagram-too-large, 96 | 97 | 98 | /// Name does not exist or has no suitable associated IP addresses. 99 | name-unresolvable, 100 | 101 | /// A temporary failure in name resolution occurred. 102 | temporary-resolver-failure, 103 | 104 | /// A permanent failure in name resolution occurred. 105 | permanent-resolver-failure, 106 | } 107 | 108 | @since(version = 0.2.0) 109 | enum ip-address-family { 110 | /// Similar to `AF_INET` in POSIX. 111 | ipv4, 112 | 113 | /// Similar to `AF_INET6` in POSIX. 114 | ipv6, 115 | } 116 | 117 | @since(version = 0.2.0) 118 | type ipv4-address = tuple; 119 | @since(version = 0.2.0) 120 | type ipv6-address = tuple; 121 | 122 | @since(version = 0.2.0) 123 | variant ip-address { 124 | ipv4(ipv4-address), 125 | ipv6(ipv6-address), 126 | } 127 | 128 | @since(version = 0.2.0) 129 | record ipv4-socket-address { 130 | /// sin_port 131 | port: u16, 132 | /// sin_addr 133 | address: ipv4-address, 134 | } 135 | 136 | @since(version = 0.2.0) 137 | record ipv6-socket-address { 138 | /// sin6_port 139 | port: u16, 140 | /// sin6_flowinfo 141 | flow-info: u32, 142 | /// sin6_addr 143 | address: ipv6-address, 144 | /// sin6_scope_id 145 | scope-id: u32, 146 | } 147 | 148 | @since(version = 0.2.0) 149 | variant ip-socket-address { 150 | ipv4(ipv4-socket-address), 151 | ipv6(ipv6-socket-address), 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /wit/deps/sockets/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface tcp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use tcp.{tcp-socket}; 7 | 8 | /// Create a new TCP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` 15 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-tcp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /wit/deps/sockets/tcp.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface tcp { 3 | @since(version = 0.2.0) 4 | use wasi:io/streams@0.2.1.{input-stream, output-stream}; 5 | @since(version = 0.2.0) 6 | use wasi:io/poll@0.2.1.{pollable}; 7 | @since(version = 0.2.0) 8 | use wasi:clocks/monotonic-clock@0.2.1.{duration}; 9 | @since(version = 0.2.0) 10 | use network.{network, error-code, ip-socket-address, ip-address-family}; 11 | 12 | @since(version = 0.2.0) 13 | enum shutdown-type { 14 | /// Similar to `SHUT_RD` in POSIX. 15 | receive, 16 | 17 | /// Similar to `SHUT_WR` in POSIX. 18 | send, 19 | 20 | /// Similar to `SHUT_RDWR` in POSIX. 21 | both, 22 | } 23 | 24 | /// A TCP socket resource. 25 | /// 26 | /// The socket can be in one of the following states: 27 | /// - `unbound` 28 | /// - `bind-in-progress` 29 | /// - `bound` (See note below) 30 | /// - `listen-in-progress` 31 | /// - `listening` 32 | /// - `connect-in-progress` 33 | /// - `connected` 34 | /// - `closed` 35 | /// See 36 | /// for more information. 37 | /// 38 | /// Note: Except where explicitly mentioned, whenever this documentation uses 39 | /// the term "bound" without backticks it actually means: in the `bound` state *or higher*. 40 | /// (i.e. `bound`, `listen-in-progress`, `listening`, `connect-in-progress` or `connected`) 41 | /// 42 | /// In addition to the general error codes documented on the 43 | /// `network::error-code` type, TCP socket methods may always return 44 | /// `error(invalid-state)` when in the `closed` state. 45 | @since(version = 0.2.0) 46 | resource tcp-socket { 47 | /// Bind the socket to a specific network on the provided IP address and port. 48 | /// 49 | /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which 50 | /// network interface(s) to bind to. 51 | /// If the TCP/UDP port is zero, the socket will be bound to a random free port. 52 | /// 53 | /// Bind can be attempted multiple times on the same socket, even with 54 | /// different arguments on each iteration. But never concurrently and 55 | /// only as long as the previous bind failed. Once a bind succeeds, the 56 | /// binding can't be changed anymore. 57 | /// 58 | /// # Typical errors 59 | /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) 60 | /// - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) 61 | /// - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL) 62 | /// - `invalid-state`: The socket is already bound. (EINVAL) 63 | /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) 64 | /// - `address-in-use`: Address is already in use. (EADDRINUSE) 65 | /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) 66 | /// - `not-in-progress`: A `bind` operation is not in progress. 67 | /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) 68 | /// 69 | /// # Implementors note 70 | /// When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT 71 | /// state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR 72 | /// socket option should be set implicitly on all platforms, except on Windows where this is the default behavior 73 | /// and SO_REUSEADDR performs something different entirely. 74 | /// 75 | /// Unlike in POSIX, in WASI the bind operation is async. This enables 76 | /// interactive WASI hosts to inject permission prompts. Runtimes that 77 | /// don't want to make use of this ability can simply call the native 78 | /// `bind` as part of either `start-bind` or `finish-bind`. 79 | /// 80 | /// # References 81 | /// - 82 | /// - 83 | /// - 84 | /// - 85 | @since(version = 0.2.0) 86 | start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; 87 | @since(version = 0.2.0) 88 | finish-bind: func() -> result<_, error-code>; 89 | 90 | /// Connect to a remote endpoint. 91 | /// 92 | /// On success: 93 | /// - the socket is transitioned into the `connected` state. 94 | /// - a pair of streams is returned that can be used to read & write to the connection 95 | /// 96 | /// After a failed connection attempt, the socket will be in the `closed` 97 | /// state and the only valid action left is to `drop` the socket. A single 98 | /// socket can not be used to connect more than once. 99 | /// 100 | /// # Typical errors 101 | /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) 102 | /// - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) 103 | /// - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos) 104 | /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) 105 | /// - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) 106 | /// - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. 107 | /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN) 108 | /// - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows) 109 | /// - `timeout`: Connection timed out. (ETIMEDOUT) 110 | /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) 111 | /// - `connection-reset`: The connection was reset. (ECONNRESET) 112 | /// - `connection-aborted`: The connection was aborted. (ECONNABORTED) 113 | /// - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) 114 | /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) 115 | /// - `not-in-progress`: A connect operation is not in progress. 116 | /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) 117 | /// 118 | /// # Implementors note 119 | /// The POSIX equivalent of `start-connect` is the regular `connect` syscall. 120 | /// Because all WASI sockets are non-blocking this is expected to return 121 | /// EINPROGRESS, which should be translated to `ok()` in WASI. 122 | /// 123 | /// The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT` 124 | /// with a timeout of 0 on the socket descriptor. Followed by a check for 125 | /// the `SO_ERROR` socket option, in case the poll signaled readiness. 126 | /// 127 | /// # References 128 | /// - 129 | /// - 130 | /// - 131 | /// - 132 | @since(version = 0.2.0) 133 | start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; 134 | @since(version = 0.2.0) 135 | finish-connect: func() -> result, error-code>; 136 | 137 | /// Start listening for new connections. 138 | /// 139 | /// Transitions the socket into the `listening` state. 140 | /// 141 | /// Unlike POSIX, the socket must already be explicitly bound. 142 | /// 143 | /// # Typical errors 144 | /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) 145 | /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD) 146 | /// - `invalid-state`: The socket is already in the `listening` state. 147 | /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) 148 | /// - `not-in-progress`: A listen operation is not in progress. 149 | /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) 150 | /// 151 | /// # Implementors note 152 | /// Unlike in POSIX, in WASI the listen operation is async. This enables 153 | /// interactive WASI hosts to inject permission prompts. Runtimes that 154 | /// don't want to make use of this ability can simply call the native 155 | /// `listen` as part of either `start-listen` or `finish-listen`. 156 | /// 157 | /// # References 158 | /// - 159 | /// - 160 | /// - 161 | /// - 162 | @since(version = 0.2.0) 163 | start-listen: func() -> result<_, error-code>; 164 | @since(version = 0.2.0) 165 | finish-listen: func() -> result<_, error-code>; 166 | 167 | /// Accept a new client socket. 168 | /// 169 | /// The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket: 170 | /// - `address-family` 171 | /// - `keep-alive-enabled` 172 | /// - `keep-alive-idle-time` 173 | /// - `keep-alive-interval` 174 | /// - `keep-alive-count` 175 | /// - `hop-limit` 176 | /// - `receive-buffer-size` 177 | /// - `send-buffer-size` 178 | /// 179 | /// On success, this function returns the newly accepted client socket along with 180 | /// a pair of streams that can be used to read & write to the connection. 181 | /// 182 | /// # Typical errors 183 | /// - `invalid-state`: Socket is not in the `listening` state. (EINVAL) 184 | /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) 185 | /// - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) 186 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 187 | /// 188 | /// # References 189 | /// - 190 | /// - 191 | /// - 192 | /// - 193 | @since(version = 0.2.0) 194 | accept: func() -> result, error-code>; 195 | 196 | /// Get the bound local address. 197 | /// 198 | /// POSIX mentions: 199 | /// > If the socket has not been bound to a local name, the value 200 | /// > stored in the object pointed to by `address` is unspecified. 201 | /// 202 | /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. 203 | /// 204 | /// # Typical errors 205 | /// - `invalid-state`: The socket is not bound to any local address. 206 | /// 207 | /// # References 208 | /// - 209 | /// - 210 | /// - 211 | /// - 212 | @since(version = 0.2.0) 213 | local-address: func() -> result; 214 | 215 | /// Get the remote address. 216 | /// 217 | /// # Typical errors 218 | /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) 219 | /// 220 | /// # References 221 | /// - 222 | /// - 223 | /// - 224 | /// - 225 | @since(version = 0.2.0) 226 | remote-address: func() -> result; 227 | 228 | /// Whether the socket is in the `listening` state. 229 | /// 230 | /// Equivalent to the SO_ACCEPTCONN socket option. 231 | @since(version = 0.2.0) 232 | is-listening: func() -> bool; 233 | 234 | /// Whether this is a IPv4 or IPv6 socket. 235 | /// 236 | /// Equivalent to the SO_DOMAIN socket option. 237 | @since(version = 0.2.0) 238 | address-family: func() -> ip-address-family; 239 | 240 | /// Hints the desired listen queue size. Implementations are free to ignore this. 241 | /// 242 | /// If the provided value is 0, an `invalid-argument` error is returned. 243 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 244 | /// 245 | /// # Typical errors 246 | /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. 247 | /// - `invalid-argument`: (set) The provided value was 0. 248 | /// - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state. 249 | @since(version = 0.2.0) 250 | set-listen-backlog-size: func(value: u64) -> result<_, error-code>; 251 | 252 | /// Enables or disables keepalive. 253 | /// 254 | /// The keepalive behavior can be adjusted using: 255 | /// - `keep-alive-idle-time` 256 | /// - `keep-alive-interval` 257 | /// - `keep-alive-count` 258 | /// These properties can be configured while `keep-alive-enabled` is false, but only come into effect when `keep-alive-enabled` is true. 259 | /// 260 | /// Equivalent to the SO_KEEPALIVE socket option. 261 | @since(version = 0.2.0) 262 | keep-alive-enabled: func() -> result; 263 | @since(version = 0.2.0) 264 | set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; 265 | 266 | /// Amount of time the connection has to be idle before TCP starts sending keepalive packets. 267 | /// 268 | /// If the provided value is 0, an `invalid-argument` error is returned. 269 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 270 | /// I.e. after setting a value, reading the same setting back may return a different value. 271 | /// 272 | /// Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS) 273 | /// 274 | /// # Typical errors 275 | /// - `invalid-argument`: (set) The provided value was 0. 276 | @since(version = 0.2.0) 277 | keep-alive-idle-time: func() -> result; 278 | @since(version = 0.2.0) 279 | set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; 280 | 281 | /// The time between keepalive packets. 282 | /// 283 | /// If the provided value is 0, an `invalid-argument` error is returned. 284 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 285 | /// I.e. after setting a value, reading the same setting back may return a different value. 286 | /// 287 | /// Equivalent to the TCP_KEEPINTVL socket option. 288 | /// 289 | /// # Typical errors 290 | /// - `invalid-argument`: (set) The provided value was 0. 291 | @since(version = 0.2.0) 292 | keep-alive-interval: func() -> result; 293 | @since(version = 0.2.0) 294 | set-keep-alive-interval: func(value: duration) -> result<_, error-code>; 295 | 296 | /// The maximum amount of keepalive packets TCP should send before aborting the connection. 297 | /// 298 | /// If the provided value is 0, an `invalid-argument` error is returned. 299 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 300 | /// I.e. after setting a value, reading the same setting back may return a different value. 301 | /// 302 | /// Equivalent to the TCP_KEEPCNT socket option. 303 | /// 304 | /// # Typical errors 305 | /// - `invalid-argument`: (set) The provided value was 0. 306 | @since(version = 0.2.0) 307 | keep-alive-count: func() -> result; 308 | @since(version = 0.2.0) 309 | set-keep-alive-count: func(value: u32) -> result<_, error-code>; 310 | 311 | /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. 312 | /// 313 | /// If the provided value is 0, an `invalid-argument` error is returned. 314 | /// 315 | /// # Typical errors 316 | /// - `invalid-argument`: (set) The TTL value must be 1 or higher. 317 | @since(version = 0.2.0) 318 | hop-limit: func() -> result; 319 | @since(version = 0.2.0) 320 | set-hop-limit: func(value: u8) -> result<_, error-code>; 321 | 322 | /// The kernel buffer space reserved for sends/receives on this socket. 323 | /// 324 | /// If the provided value is 0, an `invalid-argument` error is returned. 325 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 326 | /// I.e. after setting a value, reading the same setting back may return a different value. 327 | /// 328 | /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. 329 | /// 330 | /// # Typical errors 331 | /// - `invalid-argument`: (set) The provided value was 0. 332 | @since(version = 0.2.0) 333 | receive-buffer-size: func() -> result; 334 | @since(version = 0.2.0) 335 | set-receive-buffer-size: func(value: u64) -> result<_, error-code>; 336 | @since(version = 0.2.0) 337 | send-buffer-size: func() -> result; 338 | @since(version = 0.2.0) 339 | set-send-buffer-size: func(value: u64) -> result<_, error-code>; 340 | 341 | /// Create a `pollable` which can be used to poll for, or block on, 342 | /// completion of any of the asynchronous operations of this socket. 343 | /// 344 | /// When `finish-bind`, `finish-listen`, `finish-connect` or `accept` 345 | /// return `error(would-block)`, this pollable can be used to wait for 346 | /// their success or failure, after which the method can be retried. 347 | /// 348 | /// The pollable is not limited to the async operation that happens to be 349 | /// in progress at the time of calling `subscribe` (if any). Theoretically, 350 | /// `subscribe` only has to be called once per socket and can then be 351 | /// (re)used for the remainder of the socket's lifetime. 352 | /// 353 | /// See 354 | /// for more information. 355 | /// 356 | /// Note: this function is here for WASI Preview2 only. 357 | /// It's planned to be removed when `future` is natively supported in Preview3. 358 | @since(version = 0.2.0) 359 | subscribe: func() -> pollable; 360 | 361 | /// Initiate a graceful shutdown. 362 | /// 363 | /// - `receive`: The socket is not expecting to receive any data from 364 | /// the peer. The `input-stream` associated with this socket will be 365 | /// closed. Any data still in the receive queue at time of calling 366 | /// this method will be discarded. 367 | /// - `send`: The socket has no more data to send to the peer. The `output-stream` 368 | /// associated with this socket will be closed and a FIN packet will be sent. 369 | /// - `both`: Same effect as `receive` & `send` combined. 370 | /// 371 | /// This function is idempotent; shutting down a direction more than once 372 | /// has no effect and returns `ok`. 373 | /// 374 | /// The shutdown function does not close (drop) the socket. 375 | /// 376 | /// # Typical errors 377 | /// - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN) 378 | /// 379 | /// # References 380 | /// - 381 | /// - 382 | /// - 383 | /// - 384 | @since(version = 0.2.0) 385 | shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /wit/deps/sockets/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface udp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use udp.{udp-socket}; 7 | 8 | /// Create a new UDP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 15 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References: 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-udp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /wit/deps/sockets/udp.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface udp { 3 | @since(version = 0.2.0) 4 | use wasi:io/poll@0.2.1.{pollable}; 5 | @since(version = 0.2.0) 6 | use network.{network, error-code, ip-socket-address, ip-address-family}; 7 | 8 | /// A received datagram. 9 | @since(version = 0.2.0) 10 | record incoming-datagram { 11 | /// The payload. 12 | /// 13 | /// Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. 14 | data: list, 15 | 16 | /// The source address. 17 | /// 18 | /// This field is guaranteed to match the remote address the stream was initialized with, if any. 19 | /// 20 | /// Equivalent to the `src_addr` out parameter of `recvfrom`. 21 | remote-address: ip-socket-address, 22 | } 23 | 24 | /// A datagram to be sent out. 25 | @since(version = 0.2.0) 26 | record outgoing-datagram { 27 | /// The payload. 28 | data: list, 29 | 30 | /// The destination address. 31 | /// 32 | /// The requirements on this field depend on how the stream was initialized: 33 | /// - with a remote address: this field must be None or match the stream's remote address exactly. 34 | /// - without a remote address: this field is required. 35 | /// 36 | /// If this value is None, the send operation is equivalent to `send` in POSIX. Otherwise it is equivalent to `sendto`. 37 | remote-address: option, 38 | } 39 | 40 | /// A UDP socket handle. 41 | @since(version = 0.2.0) 42 | resource udp-socket { 43 | /// Bind the socket to a specific network on the provided IP address and port. 44 | /// 45 | /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which 46 | /// network interface(s) to bind to. 47 | /// If the port is zero, the socket will be bound to a random free port. 48 | /// 49 | /// # Typical errors 50 | /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) 51 | /// - `invalid-state`: The socket is already bound. (EINVAL) 52 | /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) 53 | /// - `address-in-use`: Address is already in use. (EADDRINUSE) 54 | /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) 55 | /// - `not-in-progress`: A `bind` operation is not in progress. 56 | /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) 57 | /// 58 | /// # Implementors note 59 | /// Unlike in POSIX, in WASI the bind operation is async. This enables 60 | /// interactive WASI hosts to inject permission prompts. Runtimes that 61 | /// don't want to make use of this ability can simply call the native 62 | /// `bind` as part of either `start-bind` or `finish-bind`. 63 | /// 64 | /// # References 65 | /// - 66 | /// - 67 | /// - 68 | /// - 69 | @since(version = 0.2.0) 70 | start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; 71 | @since(version = 0.2.0) 72 | finish-bind: func() -> result<_, error-code>; 73 | 74 | /// Set up inbound & outbound communication channels, optionally to a specific peer. 75 | /// 76 | /// This function only changes the local socket configuration and does not generate any network traffic. 77 | /// On success, the `remote-address` of the socket is updated. The `local-address` may be updated as well, 78 | /// based on the best network path to `remote-address`. 79 | /// 80 | /// When a `remote-address` is provided, the returned streams are limited to communicating with that specific peer: 81 | /// - `send` can only be used to send to this destination. 82 | /// - `receive` will only return datagrams sent from the provided `remote-address`. 83 | /// 84 | /// This method may be called multiple times on the same socket to change its association, but 85 | /// only the most recently returned pair of streams will be operational. Implementations may trap if 86 | /// the streams returned by a previous invocation haven't been dropped yet before calling `stream` again. 87 | /// 88 | /// The POSIX equivalent in pseudo-code is: 89 | /// ```text 90 | /// if (was previously connected) { 91 | /// connect(s, AF_UNSPEC) 92 | /// } 93 | /// if (remote_address is Some) { 94 | /// connect(s, remote_address) 95 | /// } 96 | /// ``` 97 | /// 98 | /// Unlike in POSIX, the socket must already be explicitly bound. 99 | /// 100 | /// # Typical errors 101 | /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) 102 | /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) 103 | /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) 104 | /// - `invalid-state`: The socket is not bound. 105 | /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) 106 | /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) 107 | /// - `connection-refused`: The connection was refused. (ECONNREFUSED) 108 | /// 109 | /// # References 110 | /// - 111 | /// - 112 | /// - 113 | /// - 114 | @since(version = 0.2.0) 115 | %stream: func(remote-address: option) -> result, error-code>; 116 | 117 | /// Get the current bound address. 118 | /// 119 | /// POSIX mentions: 120 | /// > If the socket has not been bound to a local name, the value 121 | /// > stored in the object pointed to by `address` is unspecified. 122 | /// 123 | /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. 124 | /// 125 | /// # Typical errors 126 | /// - `invalid-state`: The socket is not bound to any local address. 127 | /// 128 | /// # References 129 | /// - 130 | /// - 131 | /// - 132 | /// - 133 | @since(version = 0.2.0) 134 | local-address: func() -> result; 135 | 136 | /// Get the address the socket is currently streaming to. 137 | /// 138 | /// # Typical errors 139 | /// - `invalid-state`: The socket is not streaming to a specific remote address. (ENOTCONN) 140 | /// 141 | /// # References 142 | /// - 143 | /// - 144 | /// - 145 | /// - 146 | @since(version = 0.2.0) 147 | remote-address: func() -> result; 148 | 149 | /// Whether this is a IPv4 or IPv6 socket. 150 | /// 151 | /// Equivalent to the SO_DOMAIN socket option. 152 | @since(version = 0.2.0) 153 | address-family: func() -> ip-address-family; 154 | 155 | /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. 156 | /// 157 | /// If the provided value is 0, an `invalid-argument` error is returned. 158 | /// 159 | /// # Typical errors 160 | /// - `invalid-argument`: (set) The TTL value must be 1 or higher. 161 | @since(version = 0.2.0) 162 | unicast-hop-limit: func() -> result; 163 | @since(version = 0.2.0) 164 | set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; 165 | 166 | /// The kernel buffer space reserved for sends/receives on this socket. 167 | /// 168 | /// If the provided value is 0, an `invalid-argument` error is returned. 169 | /// Any other value will never cause an error, but it might be silently clamped and/or rounded. 170 | /// I.e. after setting a value, reading the same setting back may return a different value. 171 | /// 172 | /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. 173 | /// 174 | /// # Typical errors 175 | /// - `invalid-argument`: (set) The provided value was 0. 176 | @since(version = 0.2.0) 177 | receive-buffer-size: func() -> result; 178 | @since(version = 0.2.0) 179 | set-receive-buffer-size: func(value: u64) -> result<_, error-code>; 180 | @since(version = 0.2.0) 181 | send-buffer-size: func() -> result; 182 | @since(version = 0.2.0) 183 | set-send-buffer-size: func(value: u64) -> result<_, error-code>; 184 | 185 | /// Create a `pollable` which will resolve once the socket is ready for I/O. 186 | /// 187 | /// Note: this function is here for WASI Preview2 only. 188 | /// It's planned to be removed when `future` is natively supported in Preview3. 189 | @since(version = 0.2.0) 190 | subscribe: func() -> pollable; 191 | } 192 | 193 | @since(version = 0.2.0) 194 | resource incoming-datagram-stream { 195 | /// Receive messages on the socket. 196 | /// 197 | /// This function attempts to receive up to `max-results` datagrams on the socket without blocking. 198 | /// The returned list may contain fewer elements than requested, but never more. 199 | /// 200 | /// This function returns successfully with an empty list when either: 201 | /// - `max-results` is 0, or: 202 | /// - `max-results` is greater than 0, but no results are immediately available. 203 | /// This function never returns `error(would-block)`. 204 | /// 205 | /// # Typical errors 206 | /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) 207 | /// - `connection-refused`: The connection was refused. (ECONNREFUSED) 208 | /// 209 | /// # References 210 | /// - 211 | /// - 212 | /// - 213 | /// - 214 | /// - 215 | /// - 216 | /// - 217 | /// - 218 | @since(version = 0.2.0) 219 | receive: func(max-results: u64) -> result, error-code>; 220 | 221 | /// Create a `pollable` which will resolve once the stream is ready to receive again. 222 | /// 223 | /// Note: this function is here for WASI Preview2 only. 224 | /// It's planned to be removed when `future` is natively supported in Preview3. 225 | @since(version = 0.2.0) 226 | subscribe: func() -> pollable; 227 | } 228 | 229 | @since(version = 0.2.0) 230 | resource outgoing-datagram-stream { 231 | /// Check readiness for sending. This function never blocks. 232 | /// 233 | /// Returns the number of datagrams permitted for the next call to `send`, 234 | /// or an error. Calling `send` with more datagrams than this function has 235 | /// permitted will trap. 236 | /// 237 | /// When this function returns ok(0), the `subscribe` pollable will 238 | /// become ready when this function will report at least ok(1), or an 239 | /// error. 240 | /// 241 | /// Never returns `would-block`. 242 | check-send: func() -> result; 243 | 244 | /// Send messages on the socket. 245 | /// 246 | /// This function attempts to send all provided `datagrams` on the socket without blocking and 247 | /// returns how many messages were actually sent (or queued for sending). This function never 248 | /// returns `error(would-block)`. If none of the datagrams were able to be sent, `ok(0)` is returned. 249 | /// 250 | /// This function semantically behaves the same as iterating the `datagrams` list and sequentially 251 | /// sending each individual datagram until either the end of the list has been reached or the first error occurred. 252 | /// If at least one datagram has been sent successfully, this function never returns an error. 253 | /// 254 | /// If the input list is empty, the function returns `ok(0)`. 255 | /// 256 | /// Each call to `send` must be permitted by a preceding `check-send`. Implementations must trap if 257 | /// either `check-send` was not called or `datagrams` contains more items than `check-send` permitted. 258 | /// 259 | /// # Typical errors 260 | /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) 261 | /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) 262 | /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) 263 | /// - `invalid-argument`: The socket is in "connected" mode and `remote-address` is `some` value that does not match the address passed to `stream`. (EISCONN) 264 | /// - `invalid-argument`: The socket is not "connected" and no value for `remote-address` was provided. (EDESTADDRREQ) 265 | /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) 266 | /// - `connection-refused`: The connection was refused. (ECONNREFUSED) 267 | /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) 268 | /// 269 | /// # References 270 | /// - 271 | /// - 272 | /// - 273 | /// - 274 | /// - 275 | /// - 276 | /// - 277 | /// - 278 | @since(version = 0.2.0) 279 | send: func(datagrams: list) -> result; 280 | 281 | /// Create a `pollable` which will resolve once the stream is ready to send again. 282 | /// 283 | /// Note: this function is here for WASI Preview2 only. 284 | /// It's planned to be removed when `future` is natively supported in Preview3. 285 | @since(version = 0.2.0) 286 | subscribe: func() -> pollable; 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /wit/deps/sockets/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.1; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import instance-network; 7 | @since(version = 0.2.0) 8 | import network; 9 | @since(version = 0.2.0) 10 | import udp; 11 | @since(version = 0.2.0) 12 | import udp-create-socket; 13 | @since(version = 0.2.0) 14 | import tcp; 15 | @since(version = 0.2.0) 16 | import tcp-create-socket; 17 | @since(version = 0.2.0) 18 | import ip-name-lookup; 19 | } 20 | -------------------------------------------------------------------------------- /wit/deps/sql/readwrite.wit: -------------------------------------------------------------------------------- 1 | interface readwrite { 2 | use types.{statement, row, error, connection}; 3 | 4 | /// query is optimized for querying data, and 5 | /// implementors can make use of that fact to optimize 6 | /// the performance of query execution (e.g., using 7 | /// indexes). 8 | query: func(c: borrow, q: borrow) -> result, error>; 9 | 10 | /// exec is for modifying data in the database. 11 | exec: func(c: borrow, q: borrow) -> result; 12 | } -------------------------------------------------------------------------------- /wit/deps/sql/sql.wit: -------------------------------------------------------------------------------- 1 | package wasi:sql@0.2.0-draft; 2 | 3 | world imports { 4 | import readwrite; 5 | } -------------------------------------------------------------------------------- /wit/deps/sql/types.wit: -------------------------------------------------------------------------------- 1 | interface types { 2 | /// one single row item 3 | record row { 4 | field-name: string, 5 | value: data-type, 6 | } 7 | 8 | /// common data types 9 | variant data-type { 10 | int32(s32), 11 | int64(s64), 12 | uint32(u32), 13 | uint64(u64), 14 | float(float64), 15 | double(float64), 16 | str(string), 17 | boolean(bool), 18 | date(string), 19 | time(string), 20 | timestamp(string), 21 | binary(list), 22 | null 23 | } 24 | 25 | /// allows parameterized queries 26 | /// e.g., prepare("SELECT * FROM users WHERE name = ? AND age = ?", vec!["John Doe", "32"]) 27 | resource statement { 28 | prepare: static func(query: string, params: list) -> result; 29 | } 30 | /// An error resource type. 31 | /// Currently, this provides only one function to return a string representation 32 | /// of the error. In the future, this will be extended to provide more information. 33 | resource error { 34 | trace: func() -> string; 35 | } 36 | 37 | /// A connection to a sql store. 38 | resource connection { 39 | open: static func(name: string) -> result; 40 | } 41 | } -------------------------------------------------------------------------------- /wit/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:cloud-core@0.2.0-draft2; 2 | 3 | /// The `import` world imports every API that `wasi-cloud-core` 4 | /// expects. It is intended to be `include`d into worlds that 5 | /// export interfaces. 6 | world imports { 7 | /// The capability to interact with key-value stores 8 | include wasi:keyvalue/imports@0.2.0-draft2; 9 | 10 | /// The capability to interact with blob stores 11 | include wasi:blobstore/imports@0.2.0-draft; 12 | 13 | /// The capability to send and receive messages to message broker proiders 14 | include wasi:messaging/imports@0.2.0-draft; 15 | 16 | /// The capability to interact with runtime configuration providers 17 | include wasi:config/imports@0.2.0-draft; 18 | 19 | /// The capability to send HTTP requests (e.g. via `fetch()`) 20 | include wasi:http/imports@0.2.1; 21 | } 22 | 23 | /// The `http-service` world is a world that exports a single HTTP 24 | /// handler that can be used to handle HTTP requests, and 25 | /// a set of capabilities that can be used to interact with 26 | /// the platform / runtime. 27 | world http-service { 28 | include imports; 29 | 30 | /// The capability to send/receive HTTP requests 31 | include wasi:http/proxy@0.2.1; 32 | } 33 | 34 | /// The `messaging-service` world is a world that exports a single 35 | /// asyncrhonous messaging handler that can be used to 36 | /// handle incoming messages from some message broker provider, 37 | /// and a set of capabilities that can be used to interact with 38 | /// the platform / runtime. 39 | world messaging-service { 40 | include imports; 41 | 42 | /// The capability to send and receive messages from message broker providers 43 | include wasi:messaging/messaging@0.2.0-draft; 44 | } 45 | 46 | 47 | /// The `service` world that exports all the services. 48 | /// TODO: The host is expected to treat all exports as 49 | /// **optional** until the `option` semantics was 50 | /// added to the component model and WIT specification. 51 | world service { 52 | include http-service; 53 | include messaging-service; 54 | } --------------------------------------------------------------------------------