diff --git a/wit/deps.lock b/wit/deps.lock index cf11adc..a891468 100644 --- a/wit/deps.lock +++ b/wit/deps.lock @@ -5,10 +5,10 @@ sha512 = "ef1e23704a8a8436fd3718593d4c4d8b6d1c64dad3595b7496c0888ca14b725046f290 [io] url = "https://github.com/WebAssembly/wasi-io/archive/main.tar.gz" -sha256 = "eeb4701c2becafa40a7ee3bf0d2c94e2170e15806b25abdcd1de1ed94f2c1036" -sha512 = "89be853b2acae211570cd6ad0ec9d8132881dafbdea83ac7b4cad600f0627003c61f310427379bf47ecf862724367bd5d6e976db70069f6f90a3c2d9c20dbfb7" +sha256 = "a47690f7d4dba1683a42897cc65fe813409827d72cc93afe03b127ee81763e13" +sha512 = "661aa9cf9c67d7d712caccfbb3c317da01b033764892623c8902d9dcfdb67f3088889102b036d3ed19d818a5c2d151247b25d9f6fd145cdf433f325605a5a747" [poll] url = "https://github.com/WebAssembly/wasi-poll/archive/main.tar.gz" -sha256 = "9f8bb4d9994e9b0684859bb1e8bee2a8b873e04d40695f260446760fc44d0c58" -sha512 = "aa8da395ba6e189ec113296996da5abf28bdc4460e4eb2aacc786698ced892e08f7054fb590fc8809c05554d5c83a11494d4ab68c755746f57d151e212415cfb" +sha256 = "d4c27124f4c137eb538b5c92ba5858ed9042e11b24a2eef85d14becd0b7f55de" +sha512 = "422c01b273b4b1377ece6f2e4ba0dfc609ca8ef30a3e0be0e172e1303fcf7b3ca4c470f4dea6c51bdf114b0f5c871ebc4934dfe3bf217d66ea689748df2b1e55" diff --git a/wit/deps/io/streams.wit b/wit/deps/io/streams.wit index 430c1d4..98df181 100644 --- a/wit/deps/io/streams.wit +++ b/wit/deps/io/streams.wit @@ -1,3 +1,5 @@ +package wasi:io + /// WASI I/O is an I/O abstraction API which is currently focused on providing /// stream types. /// @@ -6,22 +8,31 @@ interface streams { use wasi:poll/poll.{pollable} - /// An error type returned from a stream operation. Currently this - /// doesn't provide any additional information. - record stream-error {} + /// 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. In the future, this will be replaced by handle /// types. /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// /// `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-to-input-stream` function to obtain a `pollable` which - /// can be polled for using `wasi_poll`. + /// can be polled for using `wasi:poll/poll.poll_oneoff`. /// /// And at present, it is a `u32` instead of being an actual handle, until /// the wit-bindgen implementation of handles and resources is ready. @@ -29,39 +40,41 @@ interface streams { /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). type input-stream = u32 - /// Read bytes from a 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 bool which, when true, indicates that the end of the - /// stream was reached. The returned list will contain up to `len` bytes; it - /// may return fewer than requested, but not more. - /// - /// Once a stream has reached the end, subsequent calls to read or - /// `skip` will always report end-of-stream rather than producing more + /// 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-to-input-stream` 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. /// - /// If `len` is 0, it represents a request to read 0 bytes, which should - /// always succeed, assuming the stream hasn't reached its end yet, and - /// return an empty list. + /// 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 here is a `u64`, but some callees may not be able to allocate - /// a buffer as large as that would imply. - /// FIXME: describe what happens if allocation fails. + /// 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( this: input-stream, /// The maximum number of bytes to read len: u64 - ) -> result, bool>, stream-error> + ) -> result, stream-status>> - /// Read bytes from a stream, with blocking. - /// - /// This is similar to `read`, except that it blocks until at least one - /// byte can be read. + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, identical to `read`. blocking-read: func( this: input-stream, /// The maximum number of bytes to read len: u64 - ) -> result, bool>, stream-error> + ) -> result, stream-status>> /// Skip bytes from a stream. /// @@ -72,46 +85,48 @@ interface streams { /// `skip` will always report end-of-stream rather than producing more /// data. /// - /// This function returns the number of bytes skipped, along with a bool - /// indicating whether the end of the stream was reached. The returned - /// value will be at most `len`; it may be less. + /// 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( this: input-stream, /// The maximum number of bytes to skip. len: u64, - ) -> result, stream-error> + ) -> result> - /// Skip bytes from a stream, with blocking. - /// - /// This is similar to `skip`, except that it blocks until at least one - /// byte can be consumed. + /// 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( this: input-stream, /// The maximum number of bytes to skip. len: u64, - ) -> result, stream-error> + ) -> 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-to-input-stream: func(this: input-stream) -> pollable /// Dispose of the specified `input-stream`, after which it may no longer /// be used. + /// Implementations may trap if this `input-stream` is dropped while child + /// `pollable` resources are still alive. + /// After this `input-stream` is dropped, implementations may report any + /// corresponding `output-stream` has `stream-state.closed`. drop-input-stream: func(this: input-stream) /// An output bytestream. In the future, this will be replaced by handle /// types. /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// /// `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-to-output-stream` function to obtain a - /// `pollable` which can be polled for using `wasi_poll`. + /// `pollable` which can be polled for using `wasi:poll`. /// /// And at present, it is a `u32` instead of being an actual handle, until /// the wit-bindgen implementation of handles and resources is ready. @@ -119,17 +134,28 @@ interface streams { /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). type output-stream = u32 - /// Write bytes to a stream. + /// Perform a non-blocking write of bytes to a stream. + /// + /// This function returns a `u64` and a `stream-status`. The `u64` indicates + /// the number of bytes from `buf` that were written, which may be less than + /// the length of `buf`. The `stream-status` indicates if further writes to + /// the stream are expected to be read. /// - /// This function returns a `u64` indicating the number of bytes from - /// `buf` that were written; it may be less than the full list. + /// When the returned `stream-status` is `open`, the `u64` return value may + /// be less than the length of `buf`. This indicates that no more bytes may + /// be written to the stream promptly. In that case the + /// `subscribe-to-output-stream` pollable will indicate when additional bytes + /// may be promptly written. + /// + /// Writing an empty list must return a non-error result with `0` for the + /// `u64` return value, and the current `stream-status`. write: func( this: output-stream, /// Data to write buf: list - ) -> result + ) -> result> - /// Write bytes to a stream, with blocking. + /// Blocking write of bytes to a stream. /// /// This is similar to `write`, except that it blocks until at least one /// byte can be written. @@ -137,27 +163,29 @@ interface streams { this: output-stream, /// Data to write buf: list - ) -> result + ) -> result> - /// Write multiple zero bytes to a stream. + /// Write multiple zero-bytes to a stream. /// - /// This function returns a `u64` indicating the number of zero bytes - /// that were written; it may be less than `len`. + /// This function returns a `u64` indicating the number of zero-bytes + /// that were written; it may be less than `len`. Equivelant to a call to + /// `write` with a list of zeroes of the given length. write-zeroes: func( this: output-stream, - /// The number of zero bytes to write + /// The number of zero-bytes to write len: u64 - ) -> result + ) -> result> /// Write multiple zero bytes to a stream, with blocking. /// /// This is similar to `write-zeroes`, except that it blocks until at least - /// one byte can be written. + /// one byte can be written. Equivelant to a call to `blocking-write` with + /// a list of zeroes of the given length. blocking-write-zeroes: func( this: output-stream, /// The number of zero bytes to write len: u64 - ) -> result + ) -> result> /// Read from one stream and write to another. /// @@ -172,7 +200,7 @@ interface streams { src: input-stream, /// The number of bytes to splice len: u64, - ) -> result, stream-error> + ) -> result> /// Read from one stream and write to another, with blocking. /// @@ -184,7 +212,7 @@ interface streams { src: input-stream, /// The number of bytes to splice len: u64, - ) -> result, stream-error> + ) -> result> /// Forward the entire contents of an input stream to an output stream. /// @@ -196,18 +224,30 @@ interface streams { /// 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. + /// This function returns the number of bytes transferred, and the status of + /// the output stream. forward: func( this: output-stream, /// The stream to read from src: input-stream - ) -> result + ) -> result> /// Create a `pollable` which will resolve once either the specified stream - /// is ready to accept bytes or the other end of the stream has been closed. + /// is ready to accept bytes or the `stream-state` has become closed. + /// + /// Once the stream-state 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-to-output-stream: func(this: output-stream) -> pollable /// Dispose of the specified `output-stream`, after which it may no longer /// be used. + /// Implementations may trap if this `output-stream` is dropped while + /// child `pollable` resources are still alive. + /// After this `output-stream` is dropped, implementations may report any + /// corresponding `input-stream` has `stream-state.closed`. drop-output-stream: func(this: output-stream) } diff --git a/wit/deps/poll/poll.wit b/wit/deps/poll/poll.wit index 55eee00..fa82b60 100644 --- a/wit/deps/poll/poll.wit +++ b/wit/deps/poll/poll.wit @@ -23,17 +23,27 @@ interface poll { /// 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. - /// - /// Note that the return type would ideally be `list`, but that would - /// be more difficult to polyfill given the current state of `wit-bindgen`. - /// See - /// for details. For now, we use zero to mean "not ready" and non-zero to - /// mean "ready". - poll-oneoff: func(in: list) -> list + poll-oneoff: func(in: list) -> list } diff --git a/wit/world.wit b/wit/world.wit index b51f484..5fa7eaf 100644 --- a/wit/world.wit +++ b/wit/world.wit @@ -1,6 +1,6 @@ package wasi:filesystem -world example-world { +world imports { import types import preopens }