From c934e0f6a39b00393847ef16955beb88dda10435 Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Mon, 6 Nov 2023 14:45:45 -0800 Subject: [PATCH 1/4] Move the `error` resource into `wasi:io/error` --- crates/wasi-http/wit/deps/io/error.wit | 26 ++++++++++++++++++++++++ crates/wasi-http/wit/deps/io/streams.wit | 21 +------------------ crates/wasi/src/preview2/command.rs | 2 ++ crates/wasi/src/preview2/host/io.rs | 19 ++++++----------- crates/wasi/src/preview2/mod.rs | 4 ++-- crates/wasi/src/preview2/stream.rs | 2 +- crates/wasi/wit/deps/io/error.wit | 26 ++++++++++++++++++++++++ crates/wasi/wit/deps/io/streams.wit | 21 +------------------ 8 files changed, 65 insertions(+), 56 deletions(-) create mode 100644 crates/wasi-http/wit/deps/io/error.wit create mode 100644 crates/wasi/wit/deps/io/error.wit diff --git a/crates/wasi-http/wit/deps/io/error.wit b/crates/wasi-http/wit/deps/io/error.wit new file mode 100644 index 000000000000..0cc325d7c52d --- /dev/null +++ b/crates/wasi-http/wit/deps/io/error.wit @@ -0,0 +1,26 @@ +package wasi:io@0.2.0-rc-2023-11-05; + + +interface error { + /// TODO: update this comment. + /// + /// Contextual error information about the last failure that happened on + /// a read, write, or flush from an `input-stream` or `output-stream`. + /// + /// This type is returned through the `stream-error` type whenever an + /// operation on a stream directly fails or an error is discovered + /// after-the-fact, for example when a write's failure shows up through a + /// later `flush` or `check-write`. + /// + /// Interfaces such as `wasi:filesystem/types` provide functionality to + /// further "downcast" this error into interface-specific error information. + resource error { + /// Returns a string that's suitable to assist humans in debugging this + /// error. + /// + /// The returned string will change across platforms and hosts which + /// means that parsing it, for example, would be a + /// platform-compatibility hazard. + to-debug-string: func() -> string; + } +} diff --git a/crates/wasi-http/wit/deps/io/streams.wit b/crates/wasi-http/wit/deps/io/streams.wit index 9442f60c0e16..7181e696fc76 100644 --- a/crates/wasi-http/wit/deps/io/streams.wit +++ b/crates/wasi-http/wit/deps/io/streams.wit @@ -6,6 +6,7 @@ package wasi:io@0.2.0-rc-2023-11-05; /// 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 error.{error}; use poll.{pollable}; /// An error for input-stream and output-stream operations. @@ -20,26 +21,6 @@ interface streams { closed } - /// Contextual error information about the last failure that happened on - /// a read, write, or flush from an `input-stream` or `output-stream`. - /// - /// This type is returned through the `stream-error` type whenever an - /// operation on a stream directly fails or an error is discovered - /// after-the-fact, for example when a write's failure shows up through a - /// later `flush` or `check-write`. - /// - /// Interfaces such as `wasi:filesystem/types` provide functionality to - /// further "downcast" this error into interface-specific error information. - resource error { - /// Returns a string that's suitable to assist humans in debugging this - /// error. - /// - /// The returned string will change across platforms and hosts which - /// means that parsing it, for example, would be a - /// platform-compatibility hazard. - to-debug-string: func() -> string; - } - /// An input bytestream. /// /// `input-stream`s are *non-blocking* to the extent practical on underlying diff --git a/crates/wasi/src/preview2/command.rs b/crates/wasi/src/preview2/command.rs index 898311157354..314a1a0796b2 100644 --- a/crates/wasi/src/preview2/command.rs +++ b/crates/wasi/src/preview2/command.rs @@ -33,6 +33,7 @@ pub fn add_to_linker(l: &mut wasmtime::component::Linker) -> any crate::preview2::bindings::clocks::timezone::add_to_linker(l, |t| t)?; crate::preview2::bindings::filesystem::types::add_to_linker(l, |t| t)?; crate::preview2::bindings::filesystem::preopens::add_to_linker(l, |t| t)?; + crate::preview2::bindings::io::error::add_to_linker(l, |t| t)?; crate::preview2::bindings::io::poll::add_to_linker(l, |t| t)?; crate::preview2::bindings::io::streams::add_to_linker(l, |t| t)?; crate::preview2::bindings::random::random::add_to_linker(l, |t| t)?; @@ -95,6 +96,7 @@ pub mod sync { crate::preview2::bindings::clocks::timezone::add_to_linker(l, |t| t)?; crate::preview2::bindings::sync_io::filesystem::types::add_to_linker(l, |t| t)?; crate::preview2::bindings::filesystem::preopens::add_to_linker(l, |t| t)?; + crate::preview2::bindings::io::error::add_to_linker(l, |t| t)?; crate::preview2::bindings::sync_io::io::poll::add_to_linker(l, |t| t)?; crate::preview2::bindings::sync_io::io::streams::add_to_linker(l, |t| t)?; crate::preview2::bindings::random::random::add_to_linker(l, |t| t)?; diff --git a/crates/wasi/src/preview2/host/io.rs b/crates/wasi/src/preview2/host/io.rs index 1ad5b4ccb075..ca5bc44b8d7b 100644 --- a/crates/wasi/src/preview2/host/io.rs +++ b/crates/wasi/src/preview2/host/io.rs @@ -1,10 +1,13 @@ use crate::preview2::{ + bindings::io::error, bindings::io::streams::{self, InputStream, OutputStream}, poll::subscribe, Pollable, StreamError, StreamResult, WasiView, }; use wasmtime::component::Resource; +impl error::Host for T {} + impl streams::Host for T { fn convert_stream_error(&mut self, err: StreamError) -> anyhow::Result { match err { @@ -17,7 +20,7 @@ impl streams::Host for T { } } -impl streams::HostError for T { +impl error::HostError for T { fn drop(&mut self, err: Resource) -> anyhow::Result<()> { self.table_mut().delete(err)?; Ok(()) @@ -226,8 +229,8 @@ impl streams::HostInputStream for T { pub mod sync { use crate::preview2::{ bindings::io::streams::{ - self as async_streams, Host as AsyncHost, HostError as AsyncHostError, - HostInputStream as AsyncHostInputStream, HostOutputStream as AsyncHostOutputStream, + self as async_streams, Host as AsyncHost, HostInputStream as AsyncHostInputStream, + HostOutputStream as AsyncHostOutputStream, }, bindings::sync_io::io::poll::Pollable, bindings::sync_io::io::streams::{self, InputStream, OutputStream}, @@ -253,16 +256,6 @@ pub mod sync { } } - impl streams::HostError for T { - fn drop(&mut self, err: Resource) -> anyhow::Result<()> { - AsyncHostError::drop(self, err) - } - - fn to_debug_string(&mut self, err: Resource) -> anyhow::Result { - AsyncHostError::to_debug_string(self, err) - } - } - impl streams::HostOutputStream for T { fn drop(&mut self, stream: Resource) -> anyhow::Result<()> { AsyncHostOutputStream::drop(self, stream) diff --git a/crates/wasi/src/preview2/mod.rs b/crates/wasi/src/preview2/mod.rs index 957a74a37f0b..102d70fadd3b 100644 --- a/crates/wasi/src/preview2/mod.rs +++ b/crates/wasi/src/preview2/mod.rs @@ -84,7 +84,7 @@ pub mod bindings { "wasi:io/poll/pollable": super::super::io::poll::Pollable, "wasi:io/streams/input-stream": super::super::io::streams::InputStream, "wasi:io/streams/output-stream": super::super::io::streams::OutputStream, - "wasi:io/streams/error": super::super::io::streams::Error, + "wasi:io/error/error": super::super::io::error::Error, } }); } @@ -169,7 +169,7 @@ pub mod bindings { "wasi:filesystem/types/descriptor": super::filesystem::Descriptor, "wasi:io/streams/input-stream": super::stream::InputStream, "wasi:io/streams/output-stream": super::stream::OutputStream, - "wasi:io/streams/error": super::stream::Error, + "wasi:io/error/error": super::stream::Error, "wasi:io/poll/pollable": super::poll::Pollable, "wasi:cli/terminal-input/terminal-input": super::stdio::TerminalInput, "wasi:cli/terminal-output/terminal-output": super::stdio::TerminalOutput, diff --git a/crates/wasi/src/preview2/stream.rs b/crates/wasi/src/preview2/stream.rs index 6200e1226d07..f81f5e2771e9 100644 --- a/crates/wasi/src/preview2/stream.rs +++ b/crates/wasi/src/preview2/stream.rs @@ -32,7 +32,7 @@ pub trait HostInputStream: Subscribe { } } -/// Representation of the `error` resource type in the `wasi:io/streams` +/// Representation of the `error` resource type in the `wasi:io/error` /// interface. /// /// This is currently `anyhow::Error` to retain full type information for diff --git a/crates/wasi/wit/deps/io/error.wit b/crates/wasi/wit/deps/io/error.wit new file mode 100644 index 000000000000..0cc325d7c52d --- /dev/null +++ b/crates/wasi/wit/deps/io/error.wit @@ -0,0 +1,26 @@ +package wasi:io@0.2.0-rc-2023-11-05; + + +interface error { + /// TODO: update this comment. + /// + /// Contextual error information about the last failure that happened on + /// a read, write, or flush from an `input-stream` or `output-stream`. + /// + /// This type is returned through the `stream-error` type whenever an + /// operation on a stream directly fails or an error is discovered + /// after-the-fact, for example when a write's failure shows up through a + /// later `flush` or `check-write`. + /// + /// Interfaces such as `wasi:filesystem/types` provide functionality to + /// further "downcast" this error into interface-specific error information. + resource error { + /// Returns a string that's suitable to assist humans in debugging this + /// error. + /// + /// The returned string will change across platforms and hosts which + /// means that parsing it, for example, would be a + /// platform-compatibility hazard. + to-debug-string: func() -> string; + } +} diff --git a/crates/wasi/wit/deps/io/streams.wit b/crates/wasi/wit/deps/io/streams.wit index 9442f60c0e16..7181e696fc76 100644 --- a/crates/wasi/wit/deps/io/streams.wit +++ b/crates/wasi/wit/deps/io/streams.wit @@ -6,6 +6,7 @@ package wasi:io@0.2.0-rc-2023-11-05; /// 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 error.{error}; use poll.{pollable}; /// An error for input-stream and output-stream operations. @@ -20,26 +21,6 @@ interface streams { closed } - /// Contextual error information about the last failure that happened on - /// a read, write, or flush from an `input-stream` or `output-stream`. - /// - /// This type is returned through the `stream-error` type whenever an - /// operation on a stream directly fails or an error is discovered - /// after-the-fact, for example when a write's failure shows up through a - /// later `flush` or `check-write`. - /// - /// Interfaces such as `wasi:filesystem/types` provide functionality to - /// further "downcast" this error into interface-specific error information. - resource error { - /// Returns a string that's suitable to assist humans in debugging this - /// error. - /// - /// The returned string will change across platforms and hosts which - /// means that parsing it, for example, would be a - /// platform-compatibility hazard. - to-debug-string: func() -> string; - } - /// An input bytestream. /// /// `input-stream`s are *non-blocking* to the extent practical on underlying From f1095638b2c16552565ad769d260168f1b45781d Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 9 Nov 2023 17:24:27 -0800 Subject: [PATCH 2/4] error.wit: update doc comments --- crates/wasi-http/wit/deps/io/error.wit | 38 ++++++++++++++++---------- crates/wasi/wit/deps/io/error.wit | 38 ++++++++++++++++---------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/crates/wasi-http/wit/deps/io/error.wit b/crates/wasi-http/wit/deps/io/error.wit index 0cc325d7c52d..66519efa66dc 100644 --- a/crates/wasi-http/wit/deps/io/error.wit +++ b/crates/wasi-http/wit/deps/io/error.wit @@ -1,26 +1,34 @@ -package wasi:io@0.2.0-rc-2023-11-05; +package wasi:io; interface error { - /// TODO: update this comment. + /// A resource which represents some error information. /// - /// Contextual error information about the last failure that happened on - /// a read, write, or flush from an `input-stream` or `output-stream`. + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. /// - /// This type is returned through the `stream-error` type whenever an - /// operation on a stream directly fails or an error is discovered - /// after-the-fact, for example when a write's failure shows up through a - /// later `flush` or `check-write`. + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams/stream-error` type. /// - /// Interfaces such as `wasi:filesystem/types` provide functionality to - /// further "downcast" this error into interface-specific error information. + /// To provide more specific error information, other interfaces may + /// provide functions to further "downcast" this error into more specific + /// error information. For example, `error`s returned in streams derived + /// from filesystem types to be described using the filesystem's own + /// error-code type, using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter + /// `borrow` and returns + /// `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. resource error { - /// Returns a string that's suitable to assist humans in debugging this - /// error. + /// Returns a string that is suitable to assist humans in debugging + /// this error. /// - /// The returned string will change across platforms and hosts which - /// means that parsing it, for example, would be a - /// platform-compatibility hazard. + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. to-debug-string: func() -> string; } } diff --git a/crates/wasi/wit/deps/io/error.wit b/crates/wasi/wit/deps/io/error.wit index 0cc325d7c52d..66519efa66dc 100644 --- a/crates/wasi/wit/deps/io/error.wit +++ b/crates/wasi/wit/deps/io/error.wit @@ -1,26 +1,34 @@ -package wasi:io@0.2.0-rc-2023-11-05; +package wasi:io; interface error { - /// TODO: update this comment. + /// A resource which represents some error information. /// - /// Contextual error information about the last failure that happened on - /// a read, write, or flush from an `input-stream` or `output-stream`. + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. /// - /// This type is returned through the `stream-error` type whenever an - /// operation on a stream directly fails or an error is discovered - /// after-the-fact, for example when a write's failure shows up through a - /// later `flush` or `check-write`. + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams/stream-error` type. /// - /// Interfaces such as `wasi:filesystem/types` provide functionality to - /// further "downcast" this error into interface-specific error information. + /// To provide more specific error information, other interfaces may + /// provide functions to further "downcast" this error into more specific + /// error information. For example, `error`s returned in streams derived + /// from filesystem types to be described using the filesystem's own + /// error-code type, using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter + /// `borrow` and returns + /// `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. resource error { - /// Returns a string that's suitable to assist humans in debugging this - /// error. + /// Returns a string that is suitable to assist humans in debugging + /// this error. /// - /// The returned string will change across platforms and hosts which - /// means that parsing it, for example, would be a - /// platform-compatibility hazard. + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. to-debug-string: func() -> string; } } From d9b6b45873dde68c8b0b892925faf4c4d64d1442 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 9 Nov 2023 17:29:08 -0800 Subject: [PATCH 3/4] downstream fixes to streams.wit doc comments --- crates/wasi-http/wit/deps/io/streams.wit | 41 +++++++++--------------- crates/wasi/wit/deps/io/streams.wit | 41 +++++++++--------------- 2 files changed, 32 insertions(+), 50 deletions(-) diff --git a/crates/wasi-http/wit/deps/io/streams.wit b/crates/wasi-http/wit/deps/io/streams.wit index 7181e696fc76..45062505b993 100644 --- a/crates/wasi-http/wit/deps/io/streams.wit +++ b/crates/wasi-http/wit/deps/io/streams.wit @@ -32,21 +32,20 @@ interface streams { 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. + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// 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. + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. /// - /// 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`. + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. /// /// 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 @@ -58,24 +57,16 @@ interface streams { ) -> result, stream-error>; /// Read bytes from a stream, after blocking until at least one byte can - /// be read. Except for blocking, identical to `read`. + /// be read. Except for blocking, behavior is identical to `read`. blocking-read: func( /// The maximum number of bytes to read len: u64 ) -> result, stream-error>; - /// Skip bytes from a stream. + /// Skip bytes from a stream. Returns number of bytes skipped. /// - /// 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. + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. skip: func( /// The maximum number of bytes to skip. len: u64, diff --git a/crates/wasi/wit/deps/io/streams.wit b/crates/wasi/wit/deps/io/streams.wit index 7181e696fc76..45062505b993 100644 --- a/crates/wasi/wit/deps/io/streams.wit +++ b/crates/wasi/wit/deps/io/streams.wit @@ -32,21 +32,20 @@ interface streams { 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. + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// 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. + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. /// - /// 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`. + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. /// /// 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 @@ -58,24 +57,16 @@ interface streams { ) -> result, stream-error>; /// Read bytes from a stream, after blocking until at least one byte can - /// be read. Except for blocking, identical to `read`. + /// be read. Except for blocking, behavior is identical to `read`. blocking-read: func( /// The maximum number of bytes to read len: u64 ) -> result, stream-error>; - /// Skip bytes from a stream. + /// Skip bytes from a stream. Returns number of bytes skipped. /// - /// 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. + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. skip: func( /// The maximum number of bytes to skip. len: u64, From 90d5115c752001874f21e0ea401208674d14bd69 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Fri, 10 Nov 2023 09:31:19 -0800 Subject: [PATCH 4/4] fix package name in error.wit --- crates/wasi-http/wit/deps/io/error.wit | 2 +- crates/wasi/wit/deps/io/error.wit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/wasi-http/wit/deps/io/error.wit b/crates/wasi-http/wit/deps/io/error.wit index 66519efa66dc..b45c594e6f83 100644 --- a/crates/wasi-http/wit/deps/io/error.wit +++ b/crates/wasi-http/wit/deps/io/error.wit @@ -1,4 +1,4 @@ -package wasi:io; +package wasi:io@0.2.0-rc-2023-11-05; interface error { diff --git a/crates/wasi/wit/deps/io/error.wit b/crates/wasi/wit/deps/io/error.wit index 66519efa66dc..b45c594e6f83 100644 --- a/crates/wasi/wit/deps/io/error.wit +++ b/crates/wasi/wit/deps/io/error.wit @@ -1,4 +1,4 @@ -package wasi:io; +package wasi:io@0.2.0-rc-2023-11-05; interface error {