diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3cba299..5df3460 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -10,14 +10,12 @@ jobs:
name: Check ABI files are up-to-date
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: ensure `./wit/deps` are in sync
run: |
- curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.0/wit-deps-x86_64-unknown-linux-musl
+ curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.3/wit-deps-x86_64-unknown-linux-musl
chmod +x wit-deps
./wit-deps lock
git add -N wit/deps
git diff --exit-code
- - uses: WebAssembly/wit-abi-up-to-date@v13
- with:
- wit-abi-tag: wit-abi-0.11.0
+ - uses: WebAssembly/wit-abi-up-to-date@v15
diff --git a/example-world.md b/imports.md
similarity index 74%
rename from example-world.md
rename to imports.md
index f716f89..f82d3c1 100644
--- a/example-world.md
+++ b/imports.md
@@ -1,60 +1,51 @@
-
+
-
+
A poll API intended to let users wait for I/O events on multiple handles
at once.
Types
-
-u32
-A "pollable" handle.
-
This is conceptually represents a stream<_, _>
, or in other words,
-a stream that one can wait on, repeatedly, but which does not itself
-produce any data. It's temporary scaffolding until component-model's
-async features are ready.
-And at present, it is a u32
instead of being an actual handle, until
-the wit-bindgen implementation of handles and resources is ready.
-pollable
lifetimes are not automatically managed. Users must ensure
-that they do not outlive the resource they reference.
-This represents a resource.
+
Functions
-
-Dispose of the specified pollable
, after which it may no longer
-be used.
-Params
-
-
+
Poll for completion on a set of pollables.
-The "oneoff" in the name refers to the fact that this function must do a
-linear scan through the entire list of subscriptions, which may be
-inefficient if the number is large and the same subscriptions are used
-many times. In the future, this is expected to be obsoleted by the
-component model async proposal, which will include a scalable waiting
-facility.
-Note that the return type would ideally be list<bool>
, but that would
-be more difficult to polyfill given the current state of wit-bindgen
.
-See https://github.com/bytecodealliance/preview2-prototyping/pull/11#issuecomment-1329873061
-for details. For now, we use zero to mean "not ready" and non-zero to
-mean "ready".
+This function takes a list of pollables, which identify I/O sources of
+interest, and waits until one or more of the events is ready for I/O.
+The result list<u32>
contains one or more indices of handles in the
+argument list that is ready for I/O.
+If the list contains more elements than can be indexed with a u32
+value, this function traps.
+A timeout can be implemented by adding a pollable from the
+wasi-clocks API to the list.
+This function does not return a result
; polling in itself does not
+do any I/O so it doesn't fail. If any of the I/O sources identified by
+the pollables has an error, it is indicated by marking the source as
+being reaedy for I/O.
Params
Return values
+
+Poll for completion on a single pollable.
+This function is similar to poll-list
, but operates on only a single
+pollable. When it returns, the handle is ready for I/O.
+Params
+
WASI Monotonic Clock is a clock API intended to let users measure elapsed
@@ -98,7 +89,7 @@ reached.
Return values
WASI Wall Clock is a clock API intended to let users query the current
diff --git a/wit/deps.lock b/wit/deps.lock
index 6babe9f..41d5cbb 100644
--- a/wit/deps.lock
+++ b/wit/deps.lock
@@ -1,4 +1,4 @@
-[poll]
-url = "https://github.com/WebAssembly/wasi-poll/archive/main.tar.gz"
-sha256 = "d4c27124f4c137eb538b5c92ba5858ed9042e11b24a2eef85d14becd0b7f55de"
-sha512 = "422c01b273b4b1377ece6f2e4ba0dfc609ca8ef30a3e0be0e172e1303fcf7b3ca4c470f4dea6c51bdf114b0f5c871ebc4934dfe3bf217d66ea689748df2b1e55"
+[io]
+url = "https://github.com/WebAssembly/wasi-io/archive/main.tar.gz"
+sha256 = "6e20bcf4d4f5466b60c05ea8da7289ca361a7febdd22ab1a531e5ef7e394ab8d"
+sha512 = "21f6689bce6ed6d9e3bd96372e5c7ed003a7aefbf8d49b4eea949dfbd265cf57a0d7dc67aa71e3de75d48fcc2c0cfe5f06f7e9e7959a23bc98f77da85f4161b9"
diff --git a/wit/deps.toml b/wit/deps.toml
index cefc393..f29c61c 100644
--- a/wit/deps.toml
+++ b/wit/deps.toml
@@ -1 +1,2 @@
-poll = "https://github.com/WebAssembly/wasi-poll/archive/main.tar.gz"
+# Temporarily use the resources branch.
+io = "https://github.com/WebAssembly/wasi-io/archive/main.tar.gz"
diff --git a/wit/deps/io/poll.wit b/wit/deps/io/poll.wit
new file mode 100644
index 0000000..e95762b
--- /dev/null
+++ b/wit/deps/io/poll.wit
@@ -0,0 +1,34 @@
+package wasi:io
+
+/// A poll API intended to let users wait for I/O events on multiple handles
+/// at once.
+interface poll {
+ /// A "pollable" handle.
+ resource pollable
+
+ /// Poll for completion on a set of pollables.
+ ///
+ /// This function takes a list of pollables, which identify I/O sources of
+ /// interest, and waits until one or more of the events is ready for I/O.
+ ///
+ /// The result `list` contains one or more indices of handles in the
+ /// argument list that is ready for I/O.
+ ///
+ /// If the list contains more elements than can be indexed with a `u32`
+ /// value, this function traps.
+ ///
+ /// A timeout can be implemented by adding a pollable from the
+ /// wasi-clocks API to the list.
+ ///
+ /// This function does not return a `result`; polling in itself does not
+ /// do any I/O so it doesn't fail. If any of the I/O sources identified by
+ /// the pollables has an error, it is indicated by marking the source as
+ /// being reaedy for I/O.
+ poll-list: func(in: list>) -> list
+
+ /// Poll for completion on a single pollable.
+ ///
+ /// This function is similar to `poll-list`, but operates on only a single
+ /// pollable. When it returns, the handle is ready for I/O.
+ poll-one: func(in: borrow)
+}
diff --git a/wit/deps/io/streams.wit b/wit/deps/io/streams.wit
new file mode 100644
index 0000000..eeeff50
--- /dev/null
+++ b/wit/deps/io/streams.wit
@@ -0,0 +1,285 @@
+package wasi:io
+
+/// WASI I/O is an I/O abstraction API which is currently focused on providing
+/// stream types.
+///
+/// In the future, the component model is expected to add built-in stream types;
+/// when it does, they are expected to subsume this API.
+interface streams {
+ use poll.{pollable}
+
+ /// Streams provide a sequence of data and then end; once they end, they
+ /// no longer provide any further data.
+ ///
+ /// For example, a stream reading from a file ends when the stream reaches
+ /// the end of the file. For another example, a stream reading from a
+ /// socket ends when the socket is closed.
+ enum stream-status {
+ /// The stream is open and may produce further data.
+ open,
+ /// When reading, this indicates that the stream will not produce
+ /// further data.
+ /// When writing, this indicates that the stream will no longer be read.
+ /// Further writes are still permitted.
+ ended,
+ }
+
+ /// An input bytestream.
+ ///
+ /// `input-stream`s are *non-blocking* to the extent practical on underlying
+ /// platforms. I/O operations always return promptly; if fewer bytes are
+ /// promptly available than requested, they return the number of bytes promptly
+ /// available, which could even be zero. To wait for data to be available,
+ /// use the `subscribe` function to obtain a `pollable` which can be polled
+ /// for using `wasi:io/poll`.
+ resource input-stream {
+ /// Perform a non-blocking read from the stream.
+ ///
+ /// This function returns a list of bytes containing the data that was
+ /// read, along with a `stream-status` which, indicates whether further
+ /// reads are expected to produce data. The returned list will contain up to
+ /// `len` bytes; it may return fewer than requested, but not more. An
+ /// empty list and `stream-status:open` indicates no more data is
+ /// available at this time, and that the pollable given by `subscribe`
+ /// will be ready when more data is available.
+ ///
+ /// Once a stream has reached the end, subsequent calls to `read` or
+ /// `skip` will always report `stream-status:ended` rather than producing more
+ /// data.
+ ///
+ /// When the caller gives a `len` of 0, it represents a request to read 0
+ /// bytes. This read should always succeed and return an empty list and
+ /// the current `stream-status`.
+ ///
+ /// The `len` parameter is a `u64`, which could represent a list of u8 which
+ /// is not possible to allocate in wasm32, or not desirable to allocate as
+ /// as a return value by the callee. The callee may return a list of bytes
+ /// less than `len` in size while more bytes are available for reading.
+ read: func(
+ /// The maximum number of bytes to read
+ len: u64
+ ) -> result, stream-status>>
+
+ /// Read bytes from a stream, after blocking until at least one byte can
+ /// be read. Except for blocking, identical to `read`.
+ blocking-read: func(
+ /// The maximum number of bytes to read
+ len: u64
+ ) -> result, stream-status>>
+
+ /// Skip bytes from a stream.
+ ///
+ /// This is similar to the `read` function, but avoids copying the
+ /// bytes into the instance.
+ ///
+ /// Once a stream has reached the end, subsequent calls to read or
+ /// `skip` will always report end-of-stream rather than producing more
+ /// data.
+ ///
+ /// This function returns the number of bytes skipped, along with a
+ /// `stream-status` indicating whether the end of the stream was
+ /// reached. The returned value will be at most `len`; it may be less.
+ skip: func(
+ /// The maximum number of bytes to skip.
+ len: u64,
+ ) -> result>
+
+ /// Skip bytes from a stream, after blocking until at least one byte
+ /// can be skipped. Except for blocking behavior, identical to `skip`.
+ blocking-skip: func(
+ /// The maximum number of bytes to skip.
+ len: u64,
+ ) -> result>
+
+ /// Create a `pollable` which will resolve once either the specified stream
+ /// has bytes available to read or the other end of the stream has been
+ /// closed.
+ /// The created `pollable` is a child resource of the `input-stream`.
+ /// Implementations may trap if the `input-stream` is dropped before
+ /// all derived `pollable`s created with this function are dropped.
+ subscribe: func() -> pollable
+ }
+
+ /// An error for output-stream operations.
+ ///
+ /// Contrary to input-streams, a closed output-stream is reported using
+ /// an error.
+ enum write-error {
+ /// The last operation (a write or flush) failed before completion.
+ last-operation-failed,
+ /// The stream is closed: no more input will be accepted by the
+ /// stream. A closed output-stream will return this error on all
+ /// future operations.
+ closed
+ }
+
+ /// An output bytestream.
+ ///
+ /// `output-stream`s are *non-blocking* to the extent practical on
+ /// underlying platforms. Except where specified otherwise, I/O operations also
+ /// always return promptly, after the number of bytes that can be written
+ /// promptly, which could even be zero. To wait for the stream to be ready to
+ /// accept data, the `subscribe` function to obtain a `pollable` which can be
+ /// polled for using `wasi:io/poll`.
+ resource output-stream {
+ /// Check readiness for writing. This function never blocks.
+ ///
+ /// Returns the number of bytes permitted for the next call to `write`,
+ /// or an error. Calling `write` with more bytes than this function has
+ /// permitted will trap.
+ ///
+ /// When this function returns 0 bytes, the `subscribe` pollable will
+ /// become ready when this function will report at least 1 byte, or an
+ /// error.
+ check-write: func() -> result
+
+ /// Perform a write. This function never blocks.
+ ///
+ /// Precondition: check-write gave permit of Ok(n) and contents has a
+ /// length of less than or equal to n. Otherwise, this function will trap.
+ ///
+ /// returns Err(closed) without writing if the stream has closed since
+ /// the last call to check-write provided a permit.
+ write: func(
+ contents: list
+ ) -> result<_, write-error>
+
+ /// Perform a write of up to 4096 bytes, and then flush the stream. Block
+ /// until all of these operations are complete, or an error occurs.
+ ///
+ /// This is a convenience wrapper around the use of `check-write`,
+ /// `subscribe`, `write`, and `flush`, and is implemented with the
+ /// following pseudo-code:
+ ///
+ /// ```text
+ /// let pollable = this.subscribe();
+ /// while !contents.is_empty() {
+ /// // Wait for the stream to become writable
+ /// poll-one(pollable);
+ /// let Ok(n) = this.check-write(); // eliding error handling
+ /// let len = min(n, contents.len());
+ /// let (chunk, rest) = contents.split_at(len);
+ /// this.write(chunk ); // eliding error handling
+ /// contents = rest;
+ /// }
+ /// this.flush();
+ /// // Wait for completion of `flush`
+ /// poll-one(pollable);
+ /// // Check for any errors that arose during `flush`
+ /// let _ = this.check-write(); // eliding error handling
+ /// ```
+ blocking-write-and-flush: func(
+ contents: list
+ ) -> result<_, write-error>
+
+ /// Request to flush buffered output. This function never blocks.
+ ///
+ /// This tells the output-stream that the caller intends any buffered
+ /// output to be flushed. the output which is expected to be flushed
+ /// is all that has been passed to `write` prior to this call.
+ ///
+ /// Upon calling this function, the `output-stream` will not accept any
+ /// writes (`check-write` will return `ok(0)`) until the flush has
+ /// completed. The `subscribe` pollable will become ready when the
+ /// flush has completed and the stream can accept more writes.
+ flush: func() -> result<_, write-error>
+
+ /// Request to flush buffered output, and block until flush completes
+ /// and stream is ready for writing again.
+ blocking-flush: func() -> result<_, write-error>
+
+ /// Create a `pollable` which will resolve once the output-stream
+ /// is ready for more writing, or an error has occured. When this
+ /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an
+ /// error.
+ ///
+ /// If the stream is closed, this pollable is always ready immediately.
+ ///
+ /// The created `pollable` is a child resource of the `output-stream`.
+ /// Implementations may trap if the `output-stream` is dropped before
+ /// all derived `pollable`s created with this function are dropped.
+ subscribe: func() -> pollable
+
+ /// Write zeroes to a stream.
+ ///
+ /// this should be used precisely like `write` with the exact same
+ /// preconditions (must use check-write first), but instead of
+ /// passing a list of bytes, you simply pass the number of zero-bytes
+ /// that should be written.
+ write-zeroes: func(
+ /// The number of zero-bytes to write
+ len: u64
+ ) -> result<_, write-error>
+
+ /// Perform a write of up to 4096 zeroes, and then flush the stream.
+ /// Block until all of these operations are complete, or an error
+ /// occurs.
+ ///
+ /// This is a convenience wrapper around the use of `check-write`,
+ /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with
+ /// the following pseudo-code:
+ ///
+ /// ```text
+ /// let pollable = this.subscribe();
+ /// while num_zeroes != 0 {
+ /// // Wait for the stream to become writable
+ /// poll-one(pollable);
+ /// let Ok(n) = this.check-write(); // eliding error handling
+ /// let len = min(n, num_zeroes);
+ /// this.write-zeroes(len); // eliding error handling
+ /// num_zeroes -= len;
+ /// }
+ /// this.flush();
+ /// // Wait for completion of `flush`
+ /// poll-one(pollable);
+ /// // Check for any errors that arose during `flush`
+ /// let _ = this.check-write(); // eliding error handling
+ /// ```
+ blocking-write-zeroes-and-flush: func(
+ /// The number of zero-bytes to write
+ len: u64
+ ) -> result<_, write-error>
+
+ /// Read from one stream and write to another.
+ ///
+ /// This function returns the number of bytes transferred; it may be less
+ /// than `len`.
+ ///
+ /// Unlike other I/O functions, this function blocks until all the data
+ /// read from the input stream has been written to the output stream.
+ splice: func(
+ /// The stream to read from
+ src: input-stream,
+ /// The number of bytes to splice
+ len: u64,
+ ) -> result>
+
+ /// Read from one stream and write to another, with blocking.
+ ///
+ /// This is similar to `splice`, except that it blocks until at least
+ /// one byte can be read.
+ blocking-splice: func(
+ /// The stream to read from
+ src: input-stream,
+ /// The number of bytes to splice
+ len: u64,
+ ) -> result>
+
+ /// Forward the entire contents of an input stream to an output stream.
+ ///
+ /// This function repeatedly reads from the input stream and writes
+ /// the data to the output stream, until the end of the input stream
+ /// is reached, or an error is encountered.
+ ///
+ /// Unlike other I/O functions, this function blocks until the end
+ /// of the input stream is seen and all the data has been written to
+ /// the output stream.
+ ///
+ /// This function returns the number of bytes transferred, and the status of
+ /// the output stream.
+ forward: func(
+ /// The stream to read from
+ src: input-stream
+ ) -> result>
+ }
+}
diff --git a/wit/deps/io/world.wit b/wit/deps/io/world.wit
new file mode 100644
index 0000000..8738dba
--- /dev/null
+++ b/wit/deps/io/world.wit
@@ -0,0 +1,6 @@
+package wasi:io
+
+world imports {
+ import streams
+ import poll
+}
diff --git a/wit/deps/poll/poll.wit b/wit/deps/poll/poll.wit
deleted file mode 100644
index fa82b60..0000000
--- a/wit/deps/poll/poll.wit
+++ /dev/null
@@ -1,49 +0,0 @@
-/// A poll API intended to let users wait for I/O events on multiple handles
-/// at once.
-interface poll {
- /// A "pollable" handle.
- ///
- /// This is conceptually represents a `stream<_, _>`, or in other words,
- /// a stream that one can wait on, repeatedly, but which does not itself
- /// produce any data. It's temporary scaffolding until component-model's
- /// async features are ready.
- ///
- /// And at present, it is a `u32` instead of being an actual handle, until
- /// the wit-bindgen implementation of handles and resources is ready.
- ///
- /// `pollable` lifetimes are not automatically managed. Users must ensure
- /// that they do not outlive the resource they reference.
- ///
- /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources).
- type pollable = u32
-
- /// Dispose of the specified `pollable`, after which it may no longer
- /// be used.
- drop-pollable: func(this: pollable)
-
- /// Poll for completion on a set of pollables.
- ///
- /// This function takes a list of pollables, which identify I/O sources of
- /// interest, and waits until one or more of the events is ready for I/O.
- ///
- /// The result `list` is the same length as the argument
- /// `list`, and indicates the readiness of each corresponding
- /// element in that list, with true indicating ready. A single call can
- /// return multiple true elements.
- ///
- /// A timeout can be implemented by adding a pollable from the
- /// wasi-clocks API to the list.
- ///
- /// This function does not return a `result`; polling in itself does not
- /// do any I/O so it doesn't fail. If any of the I/O sources identified by
- /// the pollables has an error, it is indicated by marking the source as
- /// ready in the `list`.
- ///
- /// The "oneoff" in the name refers to the fact that this function must do a
- /// linear scan through the entire list of subscriptions, which may be
- /// inefficient if the number is large and the same subscriptions are used
- /// many times. In the future, this is expected to be obsoleted by the
- /// component model async proposal, which will include a scalable waiting
- /// facility.
- poll-oneoff: func(in: list) -> list
-}
diff --git a/wit/deps/poll/world.wit b/wit/deps/poll/world.wit
deleted file mode 100644
index d08cadc..0000000
--- a/wit/deps/poll/world.wit
+++ /dev/null
@@ -1,5 +0,0 @@
-package wasi:poll
-
-world example-world {
- import poll
-}
diff --git a/wit/monotonic-clock.wit b/wit/monotonic-clock.wit
index fb8424e..703a5fb 100644
--- a/wit/monotonic-clock.wit
+++ b/wit/monotonic-clock.wit
@@ -9,7 +9,7 @@
///
/// It is intended for measuring elapsed time.
interface monotonic-clock {
- use wasi:poll/poll.{pollable}
+ use wasi:io/poll.{pollable}
/// A timestamp in nanoseconds.
type instant = u64