diff --git a/examples/wasm_component/Cargo.toml b/examples/wasm_component/Cargo.toml
new file mode 100644
index 000000000..82ac769ed
--- /dev/null
+++ b/examples/wasm_component/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "http-reqwest"
+edition = "2021"
+version = "0.1.0"
+
+[workspace]
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+futures = "0.3.30"
+reqwest = { version = "0.12.4", path = "../../", features = [ "wasm-component" ] }
+wit-bindgen = { version = "0.24", features = ["default"] }
\ No newline at end of file
diff --git a/examples/wasm_component/README.md b/examples/wasm_component/README.md
new file mode 100644
index 000000000..cfb3be0b6
--- /dev/null
+++ b/examples/wasm_component/README.md
@@ -0,0 +1,37 @@
+# HTTP Reqwest
+
+This is a simple Rust Wasm example that sends an outgoing http request using the `reqwest` library to [https://example.com](https://example.com).
+
+## Prerequisites
+
+- `cargo` 1.75+
+- [wasm-tools](https://github.com/bytecodealliance/wasm-tools)
+- [wasmtime](https://github.com/bytecodealliance/wasmtime) >=20.0.0
+- `wasi_snapshot_preview1.reactor.wasm` adapter, downloaded from [wasmtime release](https://github.com/bytecodealliance/wasmtime/releases/tag/v20.0.0)
+
+## Building
+
+```bash
+# Build Wasm module
+cargo build --release --target wasm32-wasi
+# Create a Wasm component from the Wasm module by using the adapter
+wasm-tools component new ./target/wasm32-wasi/release/http_reqwest.wasm -o ./component.wasm --adapt ./wasi_snapshot_preview1.reactor.wasm
+```
+
+## Running with wasmtime
+
+```bash
+wasmtime serve -Scommon ./component.wasm
+```
+
+Then send a request to `localhost:8080`
+
+```bash
+> curl localhost:8080
+
+
+
+
+ Example Domain
+....
+```
diff --git a/examples/wasm_component/src/lib.rs b/examples/wasm_component/src/lib.rs
new file mode 100644
index 000000000..ffea1e5a1
--- /dev/null
+++ b/examples/wasm_component/src/lib.rs
@@ -0,0 +1,28 @@
+wit_bindgen::generate!();
+
+use exports::wasi::http::incoming_handler::Guest;
+use wasi::http::types::*;
+
+struct ReqwestComponent;
+
+impl Guest for ReqwestComponent {
+ fn handle(_request: IncomingRequest, response_out: ResponseOutparam) {
+ let response = OutgoingResponse::new(Fields::new());
+ response.set_status_code(200).unwrap();
+ let response_body = response.body().unwrap();
+ ResponseOutparam::set(response_out, Ok(response));
+
+ let exampledotcom = reqwest::Client::new().get("http://example.com").send();
+ let response = futures::executor::block_on(exampledotcom).expect("should get response");
+ let bytes = futures::executor::block_on(response.bytes()).expect("should get bytes");
+
+ response_body
+ .write()
+ .unwrap()
+ .blocking_write_and_flush(&bytes)
+ .unwrap();
+ OutgoingBody::finish(response_body, None).expect("failed to finish response body");
+ }
+}
+
+export!(ReqwestComponent);
diff --git a/examples/wasm_component/wasi_snapshot_preview1.reactor.wasm b/examples/wasm_component/wasi_snapshot_preview1.reactor.wasm
new file mode 100644
index 000000000..34c4917f8
Binary files /dev/null and b/examples/wasm_component/wasi_snapshot_preview1.reactor.wasm differ
diff --git a/examples/wasm_component/wit/deps.lock b/examples/wasm_component/wit/deps.lock
new file mode 100644
index 000000000..5bd958bd5
--- /dev/null
+++ b/examples/wasm_component/wit/deps.lock
@@ -0,0 +1,29 @@
+[cli]
+sha256 = "285865a31d777181b075f39e92bcfe59c89cd6bacce660be1b9a627646956258"
+sha512 = "da2622210a9e3eea82b99f1a5b8a44ce5443d009cb943f7bca0bf9cf4360829b289913d7ee727c011f0f72994ea7dc8e661ebcc0a6b34b587297d80cd9b3f7e8"
+
+[clocks]
+sha256 = "468b4d12892fe926b8eb5d398dbf579d566c93231fa44f415440572c695b7613"
+sha512 = "e6b53a07221f1413953c9797c68f08b815fdaebf66419bbc1ea3e8b7dece73731062693634731f311a03957b268cf9cc509c518bd15e513c318aa04a8459b93a"
+
+[filesystem]
+sha256 = "498c465cfd04587db40f970fff2185daa597d074c20b68a8bcbae558f261499b"
+sha512 = "ead452f9b7bfb88593a502ec00d76d4228003d51c40fd0408aebc32d35c94673551b00230d730873361567cc209ec218c41fb4e95bad194268592c49e7964347"
+
+[http]
+url = "https://github.com/WebAssembly/wasi-http/archive/v0.2.0.tar.gz"
+sha256 = "8f44402bde16c48e28c47dc53eab0b26af5b3b3482a1852cf77673e0880ba1c1"
+sha512 = "760695f9a25c25bf75a25b731cb21c3bda9e288e450edda823324ecbc73d5d798bbb5de2edad999566980836f037463ee9e57d61789d04b3f3e381475b1a9a0f"
+deps = ["cli", "clocks", "filesystem", "io", "random", "sockets"]
+
+[io]
+sha256 = "7210e5653539a15478f894d4da24cc69d61924cbcba21d2804d69314a88e5a4c"
+sha512 = "49184a1b0945a889abd52d25271172ed3dc2db6968fcdddb1bab7ee0081f4a3eeee0977ad2291126a37631c0d86eeea75d822fa8af224c422134500bf9f0f2bb"
+
+[random]
+sha256 = "7371d03c037d924caba2587fb2e7c5773a0d3c5fcecbf7971e0e0ba57973c53d"
+sha512 = "964c4e8925a53078e4d94ba907b54f89a0b7e154f46823a505391471466c17f53c8692682e5c85771712acd88b348686173fc07c53a3cfe3d301b8cd8ddd0de4"
+
+[sockets]
+sha256 = "622bd28bbeb43736375dc02bd003fd3a016ff8ee91e14bab488325c6b38bf966"
+sha512 = "5a63c1f36de0c4548e1d2297bdbededb28721cbad94ef7825c469eae29d7451c97e00b4c1d6730ee1ec0c4a5aac922961a2795762d4a0c3bb54e30a391a84bae"
diff --git a/examples/wasm_component/wit/deps.toml b/examples/wasm_component/wit/deps.toml
new file mode 100644
index 000000000..1b375eef8
--- /dev/null
+++ b/examples/wasm_component/wit/deps.toml
@@ -0,0 +1 @@
+http = "https://github.com/WebAssembly/wasi-http/archive/v0.2.0.tar.gz"
diff --git a/examples/wasm_component/wit/deps/cli/command.wit b/examples/wasm_component/wit/deps/cli/command.wit
new file mode 100644
index 000000000..d8005bd38
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/command.wit
@@ -0,0 +1,7 @@
+package wasi:cli@0.2.0;
+
+world command {
+ include imports;
+
+ export run;
+}
diff --git a/examples/wasm_component/wit/deps/cli/environment.wit b/examples/wasm_component/wit/deps/cli/environment.wit
new file mode 100644
index 000000000..70065233e
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/environment.wit
@@ -0,0 +1,18 @@
+interface environment {
+ /// Get the POSIX-style environment variables.
+ ///
+ /// Each environment variable is provided as a pair of string variable names
+ /// and string value.
+ ///
+ /// Morally, these are a value import, but until value imports are available
+ /// in the component model, this import function should return the same
+ /// values each time it is called.
+ get-environment: func() -> list>;
+
+ /// Get the POSIX-style arguments to the program.
+ get-arguments: func() -> list;
+
+ /// Return a path that programs should use as their initial current working
+ /// directory, interpreting `.` as shorthand for this.
+ initial-cwd: func() -> option;
+}
diff --git a/examples/wasm_component/wit/deps/cli/exit.wit b/examples/wasm_component/wit/deps/cli/exit.wit
new file mode 100644
index 000000000..d0c2b82ae
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/exit.wit
@@ -0,0 +1,4 @@
+interface exit {
+ /// Exit the current instance and any linked instances.
+ exit: func(status: result);
+}
diff --git a/examples/wasm_component/wit/deps/cli/imports.wit b/examples/wasm_component/wit/deps/cli/imports.wit
new file mode 100644
index 000000000..083b84a03
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/imports.wit
@@ -0,0 +1,20 @@
+package wasi:cli@0.2.0;
+
+world imports {
+ include wasi:clocks/imports@0.2.0;
+ include wasi:filesystem/imports@0.2.0;
+ include wasi:sockets/imports@0.2.0;
+ include wasi:random/imports@0.2.0;
+ include wasi:io/imports@0.2.0;
+
+ import environment;
+ import exit;
+ import stdin;
+ import stdout;
+ import stderr;
+ import terminal-input;
+ import terminal-output;
+ import terminal-stdin;
+ import terminal-stdout;
+ import terminal-stderr;
+}
diff --git a/examples/wasm_component/wit/deps/cli/run.wit b/examples/wasm_component/wit/deps/cli/run.wit
new file mode 100644
index 000000000..a70ee8c03
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/run.wit
@@ -0,0 +1,4 @@
+interface run {
+ /// Run the program.
+ run: func() -> result;
+}
diff --git a/examples/wasm_component/wit/deps/cli/stdio.wit b/examples/wasm_component/wit/deps/cli/stdio.wit
new file mode 100644
index 000000000..31ef35b5a
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/stdio.wit
@@ -0,0 +1,17 @@
+interface stdin {
+ use wasi:io/streams@0.2.0.{input-stream};
+
+ get-stdin: func() -> input-stream;
+}
+
+interface stdout {
+ use wasi:io/streams@0.2.0.{output-stream};
+
+ get-stdout: func() -> output-stream;
+}
+
+interface stderr {
+ use wasi:io/streams@0.2.0.{output-stream};
+
+ get-stderr: func() -> output-stream;
+}
diff --git a/examples/wasm_component/wit/deps/cli/terminal.wit b/examples/wasm_component/wit/deps/cli/terminal.wit
new file mode 100644
index 000000000..38c724efc
--- /dev/null
+++ b/examples/wasm_component/wit/deps/cli/terminal.wit
@@ -0,0 +1,49 @@
+/// Terminal input.
+///
+/// In the future, this may include functions for disabling echoing,
+/// disabling input buffering so that keyboard events are sent through
+/// immediately, querying supported features, and so on.
+interface terminal-input {
+ /// The input side of a terminal.
+ resource terminal-input;
+}
+
+/// Terminal output.
+///
+/// In the future, this may include functions for querying the terminal
+/// size, being notified of terminal size changes, querying supported
+/// features, and so on.
+interface terminal-output {
+ /// The output side of a terminal.
+ resource terminal-output;
+}
+
+/// An interface providing an optional `terminal-input` for stdin as a
+/// link-time authority.
+interface terminal-stdin {
+ use terminal-input.{terminal-input};
+
+ /// If stdin is connected to a terminal, return a `terminal-input` handle
+ /// allowing further interaction with it.
+ get-terminal-stdin: func() -> option;
+}
+
+/// An interface providing an optional `terminal-output` for stdout as a
+/// link-time authority.
+interface terminal-stdout {
+ use terminal-output.{terminal-output};
+
+ /// If stdout is connected to a terminal, return a `terminal-output` handle
+ /// allowing further interaction with it.
+ get-terminal-stdout: func() -> option;
+}
+
+/// An interface providing an optional `terminal-output` for stderr as a
+/// link-time authority.
+interface terminal-stderr {
+ use terminal-output.{terminal-output};
+
+ /// If stderr is connected to a terminal, return a `terminal-output` handle
+ /// allowing further interaction with it.
+ get-terminal-stderr: func() -> option;
+}
diff --git a/examples/wasm_component/wit/deps/clocks/monotonic-clock.wit b/examples/wasm_component/wit/deps/clocks/monotonic-clock.wit
new file mode 100644
index 000000000..4e4dc3a19
--- /dev/null
+++ b/examples/wasm_component/wit/deps/clocks/monotonic-clock.wit
@@ -0,0 +1,45 @@
+package wasi:clocks@0.2.0;
+/// WASI Monotonic Clock is a clock API intended to let users measure elapsed
+/// time.
+///
+/// It is intended to be portable at least between Unix-family platforms and
+/// Windows.
+///
+/// A monotonic clock is a clock which has an unspecified initial value, and
+/// successive reads of the clock will produce non-decreasing values.
+///
+/// It is intended for measuring elapsed time.
+interface monotonic-clock {
+ use wasi:io/poll@0.2.0.{pollable};
+
+ /// An instant in time, in nanoseconds. An instant is relative to an
+ /// unspecified initial value, and can only be compared to instances from
+ /// the same monotonic-clock.
+ type instant = u64;
+
+ /// A duration of time, in nanoseconds.
+ type duration = u64;
+
+ /// Read the current value of the clock.
+ ///
+ /// The clock is monotonic, therefore calling this function repeatedly will
+ /// produce a sequence of non-decreasing values.
+ now: func() -> instant;
+
+ /// Query the resolution of the clock. Returns the duration of time
+ /// corresponding to a clock tick.
+ resolution: func() -> duration;
+
+ /// Create a `pollable` which will resolve once the specified instant
+ /// occured.
+ subscribe-instant: func(
+ when: instant,
+ ) -> pollable;
+
+ /// Create a `pollable` which will resolve once the given duration has
+ /// elapsed, starting at the time at which this function was called.
+ /// occured.
+ subscribe-duration: func(
+ when: duration,
+ ) -> pollable;
+}
diff --git a/examples/wasm_component/wit/deps/clocks/wall-clock.wit b/examples/wasm_component/wit/deps/clocks/wall-clock.wit
new file mode 100644
index 000000000..440ca0f33
--- /dev/null
+++ b/examples/wasm_component/wit/deps/clocks/wall-clock.wit
@@ -0,0 +1,42 @@
+package wasi:clocks@0.2.0;
+/// WASI Wall Clock is a clock API intended to let users query the current
+/// time. The name "wall" makes an analogy to a "clock on the wall", which
+/// is not necessarily monotonic as it may be reset.
+///
+/// It is intended to be portable at least between Unix-family platforms and
+/// Windows.
+///
+/// A wall clock is a clock which measures the date and time according to
+/// some external reference.
+///
+/// External references may be reset, so this clock is not necessarily
+/// monotonic, making it unsuitable for measuring elapsed time.
+///
+/// It is intended for reporting the current date and time for humans.
+interface wall-clock {
+ /// A time and date in seconds plus nanoseconds.
+ record datetime {
+ seconds: u64,
+ nanoseconds: u32,
+ }
+
+ /// Read the current value of the clock.
+ ///
+ /// This clock is not monotonic, therefore calling this function repeatedly
+ /// will not necessarily produce a sequence of non-decreasing values.
+ ///
+ /// The returned timestamps represent the number of seconds since
+ /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
+ /// also known as [Unix Time].
+ ///
+ /// The nanoseconds field of the output is always less than 1000000000.
+ ///
+ /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
+ /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
+ now: func() -> datetime;
+
+ /// Query the resolution of the clock.
+ ///
+ /// The nanoseconds field of the output is always less than 1000000000.
+ resolution: func() -> datetime;
+}
diff --git a/examples/wasm_component/wit/deps/clocks/world.wit b/examples/wasm_component/wit/deps/clocks/world.wit
new file mode 100644
index 000000000..c0224572a
--- /dev/null
+++ b/examples/wasm_component/wit/deps/clocks/world.wit
@@ -0,0 +1,6 @@
+package wasi:clocks@0.2.0;
+
+world imports {
+ import monotonic-clock;
+ import wall-clock;
+}
diff --git a/examples/wasm_component/wit/deps/filesystem/preopens.wit b/examples/wasm_component/wit/deps/filesystem/preopens.wit
new file mode 100644
index 000000000..da801f6d6
--- /dev/null
+++ b/examples/wasm_component/wit/deps/filesystem/preopens.wit
@@ -0,0 +1,8 @@
+package wasi:filesystem@0.2.0;
+
+interface preopens {
+ use types.{descriptor};
+
+ /// Return the set of preopened directories, and their path.
+ get-directories: func() -> list>;
+}
diff --git a/examples/wasm_component/wit/deps/filesystem/types.wit b/examples/wasm_component/wit/deps/filesystem/types.wit
new file mode 100644
index 000000000..11108fcda
--- /dev/null
+++ b/examples/wasm_component/wit/deps/filesystem/types.wit
@@ -0,0 +1,634 @@
+package wasi:filesystem@0.2.0;
+/// WASI filesystem is a filesystem API primarily intended to let users run WASI
+/// programs that access their files on their existing filesystems, without
+/// significant overhead.
+///
+/// It is intended to be roughly portable between Unix-family platforms and
+/// Windows, though it does not hide many of the major differences.
+///
+/// Paths are passed as interface-type `string`s, meaning they must consist of
+/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain
+/// paths which are not accessible by this API.
+///
+/// The directory separator in WASI is always the forward-slash (`/`).
+///
+/// All paths in WASI are relative paths, and are interpreted relative to a
+/// `descriptor` referring to a base directory. If a `path` argument to any WASI
+/// function starts with `/`, or if any step of resolving a `path`, including
+/// `..` and symbolic link steps, reaches a directory outside of the base
+/// directory, or reaches a symlink to an absolute or rooted path in the
+/// underlying filesystem, the function fails with `error-code::not-permitted`.
+///
+/// For more information about WASI path resolution and sandboxing, see
+/// [WASI filesystem path resolution].
+///
+/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md
+interface types {
+ use wasi:io/streams@0.2.0.{input-stream, output-stream, error};
+ use wasi:clocks/wall-clock@0.2.0.{datetime};
+
+ /// File size or length of a region within a file.
+ type filesize = u64;
+
+ /// The type of a filesystem object referenced by a descriptor.
+ ///
+ /// Note: This was called `filetype` in earlier versions of WASI.
+ enum descriptor-type {
+ /// The type of the descriptor or file is unknown or is different from
+ /// any of the other types specified.
+ unknown,
+ /// The descriptor refers to a block device inode.
+ block-device,
+ /// The descriptor refers to a character device inode.
+ character-device,
+ /// The descriptor refers to a directory inode.
+ directory,
+ /// The descriptor refers to a named pipe.
+ fifo,
+ /// The file refers to a symbolic link inode.
+ symbolic-link,
+ /// The descriptor refers to a regular file inode.
+ regular-file,
+ /// The descriptor refers to a socket.
+ socket,
+ }
+
+ /// Descriptor flags.
+ ///
+ /// Note: This was called `fdflags` in earlier versions of WASI.
+ flags descriptor-flags {
+ /// Read mode: Data can be read.
+ read,
+ /// Write mode: Data can be written to.
+ write,
+ /// Request that writes be performed according to synchronized I/O file
+ /// integrity completion. The data stored in the file and the file's
+ /// metadata are synchronized. This is similar to `O_SYNC` in POSIX.
+ ///
+ /// The precise semantics of this operation have not yet been defined for
+ /// WASI. At this time, it should be interpreted as a request, and not a
+ /// requirement.
+ file-integrity-sync,
+ /// Request that writes be performed according to synchronized I/O data
+ /// integrity completion. Only the data stored in the file is
+ /// synchronized. This is similar to `O_DSYNC` in POSIX.
+ ///
+ /// The precise semantics of this operation have not yet been defined for
+ /// WASI. At this time, it should be interpreted as a request, and not a
+ /// requirement.
+ data-integrity-sync,
+ /// Requests that reads be performed at the same level of integrety
+ /// requested for writes. This is similar to `O_RSYNC` in POSIX.
+ ///
+ /// The precise semantics of this operation have not yet been defined for
+ /// WASI. At this time, it should be interpreted as a request, and not a
+ /// requirement.
+ requested-write-sync,
+ /// Mutating directories mode: Directory contents may be mutated.
+ ///
+ /// When this flag is unset on a descriptor, operations using the
+ /// descriptor which would create, rename, delete, modify the data or
+ /// metadata of filesystem objects, or obtain another handle which
+ /// would permit any of those, shall fail with `error-code::read-only` if
+ /// they would otherwise succeed.
+ ///
+ /// This may only be set on directories.
+ mutate-directory,
+ }
+
+ /// File attributes.
+ ///
+ /// Note: This was called `filestat` in earlier versions of WASI.
+ record descriptor-stat {
+ /// File type.
+ %type: descriptor-type,
+ /// Number of hard links to the file.
+ link-count: link-count,
+ /// For regular files, the file size in bytes. For symbolic links, the
+ /// length in bytes of the pathname contained in the symbolic link.
+ size: filesize,
+ /// Last data access timestamp.
+ ///
+ /// If the `option` is none, the platform doesn't maintain an access
+ /// timestamp for this file.
+ data-access-timestamp: option,
+ /// Last data modification timestamp.
+ ///
+ /// If the `option` is none, the platform doesn't maintain a
+ /// modification timestamp for this file.
+ data-modification-timestamp: option,
+ /// Last file status-change timestamp.
+ ///
+ /// If the `option` is none, the platform doesn't maintain a
+ /// status-change timestamp for this file.
+ status-change-timestamp: option,
+ }
+
+ /// Flags determining the method of how paths are resolved.
+ flags path-flags {
+ /// As long as the resolved path corresponds to a symbolic link, it is
+ /// expanded.
+ symlink-follow,
+ }
+
+ /// Open flags used by `open-at`.
+ flags open-flags {
+ /// Create file if it does not exist, similar to `O_CREAT` in POSIX.
+ create,
+ /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX.
+ directory,
+ /// Fail if file already exists, similar to `O_EXCL` in POSIX.
+ exclusive,
+ /// Truncate file to size 0, similar to `O_TRUNC` in POSIX.
+ truncate,
+ }
+
+ /// Number of hard links to an inode.
+ type link-count = u64;
+
+ /// When setting a timestamp, this gives the value to set it to.
+ variant new-timestamp {
+ /// Leave the timestamp set to its previous value.
+ no-change,
+ /// Set the timestamp to the current time of the system clock associated
+ /// with the filesystem.
+ now,
+ /// Set the timestamp to the given value.
+ timestamp(datetime),
+ }
+
+ /// A directory entry.
+ record directory-entry {
+ /// The type of the file referred to by this directory entry.
+ %type: descriptor-type,
+
+ /// The name of the object.
+ name: string,
+ }
+
+ /// Error codes returned by functions, similar to `errno` in POSIX.
+ /// Not all of these error codes are returned by the functions provided by this
+ /// API; some are used in higher-level library layers, and others are provided
+ /// merely for alignment with POSIX.
+ enum error-code {
+ /// Permission denied, similar to `EACCES` in POSIX.
+ access,
+ /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX.
+ would-block,
+ /// Connection already in progress, similar to `EALREADY` in POSIX.
+ already,
+ /// Bad descriptor, similar to `EBADF` in POSIX.
+ bad-descriptor,
+ /// Device or resource busy, similar to `EBUSY` in POSIX.
+ busy,
+ /// Resource deadlock would occur, similar to `EDEADLK` in POSIX.
+ deadlock,
+ /// Storage quota exceeded, similar to `EDQUOT` in POSIX.
+ quota,
+ /// File exists, similar to `EEXIST` in POSIX.
+ exist,
+ /// File too large, similar to `EFBIG` in POSIX.
+ file-too-large,
+ /// Illegal byte sequence, similar to `EILSEQ` in POSIX.
+ illegal-byte-sequence,
+ /// Operation in progress, similar to `EINPROGRESS` in POSIX.
+ in-progress,
+ /// Interrupted function, similar to `EINTR` in POSIX.
+ interrupted,
+ /// Invalid argument, similar to `EINVAL` in POSIX.
+ invalid,
+ /// I/O error, similar to `EIO` in POSIX.
+ io,
+ /// Is a directory, similar to `EISDIR` in POSIX.
+ is-directory,
+ /// Too many levels of symbolic links, similar to `ELOOP` in POSIX.
+ loop,
+ /// Too many links, similar to `EMLINK` in POSIX.
+ too-many-links,
+ /// Message too large, similar to `EMSGSIZE` in POSIX.
+ message-size,
+ /// Filename too long, similar to `ENAMETOOLONG` in POSIX.
+ name-too-long,
+ /// No such device, similar to `ENODEV` in POSIX.
+ no-device,
+ /// No such file or directory, similar to `ENOENT` in POSIX.
+ no-entry,
+ /// No locks available, similar to `ENOLCK` in POSIX.
+ no-lock,
+ /// Not enough space, similar to `ENOMEM` in POSIX.
+ insufficient-memory,
+ /// No space left on device, similar to `ENOSPC` in POSIX.
+ insufficient-space,
+ /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX.
+ not-directory,
+ /// Directory not empty, similar to `ENOTEMPTY` in POSIX.
+ not-empty,
+ /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX.
+ not-recoverable,
+ /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX.
+ unsupported,
+ /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX.
+ no-tty,
+ /// No such device or address, similar to `ENXIO` in POSIX.
+ no-such-device,
+ /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX.
+ overflow,
+ /// Operation not permitted, similar to `EPERM` in POSIX.
+ not-permitted,
+ /// Broken pipe, similar to `EPIPE` in POSIX.
+ pipe,
+ /// Read-only file system, similar to `EROFS` in POSIX.
+ read-only,
+ /// Invalid seek, similar to `ESPIPE` in POSIX.
+ invalid-seek,
+ /// Text file busy, similar to `ETXTBSY` in POSIX.
+ text-file-busy,
+ /// Cross-device link, similar to `EXDEV` in POSIX.
+ cross-device,
+ }
+
+ /// File or memory access pattern advisory information.
+ enum advice {
+ /// The application has no advice to give on its behavior with respect
+ /// to the specified data.
+ normal,
+ /// The application expects to access the specified data sequentially
+ /// from lower offsets to higher offsets.
+ sequential,
+ /// The application expects to access the specified data in a random
+ /// order.
+ random,
+ /// The application expects to access the specified data in the near
+ /// future.
+ will-need,
+ /// The application expects that it will not access the specified data
+ /// in the near future.
+ dont-need,
+ /// The application expects to access the specified data once and then
+ /// not reuse it thereafter.
+ no-reuse,
+ }
+
+ /// A 128-bit hash value, split into parts because wasm doesn't have a
+ /// 128-bit integer type.
+ record metadata-hash-value {
+ /// 64 bits of a 128-bit hash value.
+ lower: u64,
+ /// Another 64 bits of a 128-bit hash value.
+ upper: u64,
+ }
+
+ /// A descriptor is a reference to a filesystem object, which may be a file,
+ /// directory, named pipe, special file, or other object on which filesystem
+ /// calls may be made.
+ resource descriptor {
+ /// Return a stream for reading from a file, if available.
+ ///
+ /// May fail with an error-code describing why the file cannot be read.
+ ///
+ /// Multiple read, write, and append streams may be active on the same open
+ /// file and they do not interfere with each other.
+ ///
+ /// Note: This allows using `read-stream`, which is similar to `read` in POSIX.
+ read-via-stream: func(
+ /// The offset within the file at which to start reading.
+ offset: filesize,
+ ) -> result;
+
+ /// Return a stream for writing to a file, if available.
+ ///
+ /// May fail with an error-code describing why the file cannot be written.
+ ///
+ /// Note: This allows using `write-stream`, which is similar to `write` in
+ /// POSIX.
+ write-via-stream: func(
+ /// The offset within the file at which to start writing.
+ offset: filesize,
+ ) -> result;
+
+ /// Return a stream for appending to a file, if available.
+ ///
+ /// May fail with an error-code describing why the file cannot be appended.
+ ///
+ /// Note: This allows using `write-stream`, which is similar to `write` with
+ /// `O_APPEND` in in POSIX.
+ append-via-stream: func() -> result;
+
+ /// Provide file advisory information on a descriptor.
+ ///
+ /// This is similar to `posix_fadvise` in POSIX.
+ advise: func(
+ /// The offset within the file to which the advisory applies.
+ offset: filesize,
+ /// The length of the region to which the advisory applies.
+ length: filesize,
+ /// The advice.
+ advice: advice
+ ) -> result<_, error-code>;
+
+ /// Synchronize the data of a file to disk.
+ ///
+ /// This function succeeds with no effect if the file descriptor is not
+ /// opened for writing.
+ ///
+ /// Note: This is similar to `fdatasync` in POSIX.
+ sync-data: func() -> result<_, error-code>;
+
+ /// Get flags associated with a descriptor.
+ ///
+ /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX.
+ ///
+ /// Note: This returns the value that was the `fs_flags` value returned
+ /// from `fdstat_get` in earlier versions of WASI.
+ get-flags: func() -> result;
+
+ /// Get the dynamic type of a descriptor.
+ ///
+ /// Note: This returns the same value as the `type` field of the `fd-stat`
+ /// returned by `stat`, `stat-at` and similar.
+ ///
+ /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided
+ /// by `fstat` in POSIX.
+ ///
+ /// Note: This returns the value that was the `fs_filetype` value returned
+ /// from `fdstat_get` in earlier versions of WASI.
+ get-type: func() -> result;
+
+ /// Adjust the size of an open file. If this increases the file's size, the
+ /// extra bytes are filled with zeros.
+ ///
+ /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI.
+ set-size: func(size: filesize) -> result<_, error-code>;
+
+ /// Adjust the timestamps of an open file or directory.
+ ///
+ /// Note: This is similar to `futimens` in POSIX.
+ ///
+ /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI.
+ set-times: func(
+ /// The desired values of the data access timestamp.
+ data-access-timestamp: new-timestamp,
+ /// The desired values of the data modification timestamp.
+ data-modification-timestamp: new-timestamp,
+ ) -> result<_, error-code>;
+
+ /// Read from a descriptor, without using and updating the descriptor's offset.
+ ///
+ /// 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
+ /// file was reached. The returned list will contain up to `length` bytes; it
+ /// may return fewer than requested, if the end of the file is reached or
+ /// if the I/O operation is interrupted.
+ ///
+ /// In the future, this may change to return a `stream`.
+ ///
+ /// Note: This is similar to `pread` in POSIX.
+ read: func(
+ /// The maximum number of bytes to read.
+ length: filesize,
+ /// The offset within the file at which to read.
+ offset: filesize,
+ ) -> result, bool>, error-code>;
+
+ /// Write to a descriptor, without using and updating the descriptor's offset.
+ ///
+ /// It is valid to write past the end of a file; the file is extended to the
+ /// extent of the write, with bytes between the previous end and the start of
+ /// the write set to zero.
+ ///
+ /// In the future, this may change to take a `stream`.
+ ///
+ /// Note: This is similar to `pwrite` in POSIX.
+ write: func(
+ /// Data to write
+ buffer: list,
+ /// The offset within the file at which to write.
+ offset: filesize,
+ ) -> result;
+
+ /// Read directory entries from a directory.
+ ///
+ /// On filesystems where directories contain entries referring to themselves
+ /// and their parents, often named `.` and `..` respectively, these entries
+ /// are omitted.
+ ///
+ /// This always returns a new stream which starts at the beginning of the
+ /// directory. Multiple streams may be active on the same directory, and they
+ /// do not interfere with each other.
+ read-directory: func() -> result;
+
+ /// Synchronize the data and metadata of a file to disk.
+ ///
+ /// This function succeeds with no effect if the file descriptor is not
+ /// opened for writing.
+ ///
+ /// Note: This is similar to `fsync` in POSIX.
+ sync: func() -> result<_, error-code>;
+
+ /// Create a directory.
+ ///
+ /// Note: This is similar to `mkdirat` in POSIX.
+ create-directory-at: func(
+ /// The relative path at which to create the directory.
+ path: string,
+ ) -> result<_, error-code>;
+
+ /// Return the attributes of an open file or directory.
+ ///
+ /// Note: This is similar to `fstat` in POSIX, except that it does not return
+ /// device and inode information. For testing whether two descriptors refer to
+ /// the same underlying filesystem object, use `is-same-object`. To obtain
+ /// additional data that can be used do determine whether a file has been
+ /// modified, use `metadata-hash`.
+ ///
+ /// Note: This was called `fd_filestat_get` in earlier versions of WASI.
+ stat: func() -> result;
+
+ /// Return the attributes of a file or directory.
+ ///
+ /// Note: This is similar to `fstatat` in POSIX, except that it does not
+ /// return device and inode information. See the `stat` description for a
+ /// discussion of alternatives.
+ ///
+ /// Note: This was called `path_filestat_get` in earlier versions of WASI.
+ stat-at: func(
+ /// Flags determining the method of how the path is resolved.
+ path-flags: path-flags,
+ /// The relative path of the file or directory to inspect.
+ path: string,
+ ) -> result;
+
+ /// Adjust the timestamps of a file or directory.
+ ///
+ /// Note: This is similar to `utimensat` in POSIX.
+ ///
+ /// Note: This was called `path_filestat_set_times` in earlier versions of
+ /// WASI.
+ set-times-at: func(
+ /// Flags determining the method of how the path is resolved.
+ path-flags: path-flags,
+ /// The relative path of the file or directory to operate on.
+ path: string,
+ /// The desired values of the data access timestamp.
+ data-access-timestamp: new-timestamp,
+ /// The desired values of the data modification timestamp.
+ data-modification-timestamp: new-timestamp,
+ ) -> result<_, error-code>;
+
+ /// Create a hard link.
+ ///
+ /// Note: This is similar to `linkat` in POSIX.
+ link-at: func(
+ /// Flags determining the method of how the path is resolved.
+ old-path-flags: path-flags,
+ /// The relative source path from which to link.
+ old-path: string,
+ /// The base directory for `new-path`.
+ new-descriptor: borrow,
+ /// The relative destination path at which to create the hard link.
+ new-path: string,
+ ) -> result<_, error-code>;
+
+ /// Open a file or directory.
+ ///
+ /// The returned descriptor is not guaranteed to be the lowest-numbered
+ /// descriptor not currently open/ it is randomized to prevent applications
+ /// from depending on making assumptions about indexes, since this is
+ /// error-prone in multi-threaded contexts. The returned descriptor is
+ /// guaranteed to be less than 2**31.
+ ///
+ /// If `flags` contains `descriptor-flags::mutate-directory`, and the base
+ /// descriptor doesn't have `descriptor-flags::mutate-directory` set,
+ /// `open-at` fails with `error-code::read-only`.
+ ///
+ /// If `flags` contains `write` or `mutate-directory`, or `open-flags`
+ /// contains `truncate` or `create`, and the base descriptor doesn't have
+ /// `descriptor-flags::mutate-directory` set, `open-at` fails with
+ /// `error-code::read-only`.
+ ///
+ /// Note: This is similar to `openat` in POSIX.
+ open-at: func(
+ /// Flags determining the method of how the path is resolved.
+ path-flags: path-flags,
+ /// The relative path of the object to open.
+ path: string,
+ /// The method by which to open the file.
+ open-flags: open-flags,
+ /// Flags to use for the resulting descriptor.
+ %flags: descriptor-flags,
+ ) -> result;
+
+ /// Read the contents of a symbolic link.
+ ///
+ /// If the contents contain an absolute or rooted path in the underlying
+ /// filesystem, this function fails with `error-code::not-permitted`.
+ ///
+ /// Note: This is similar to `readlinkat` in POSIX.
+ readlink-at: func(
+ /// The relative path of the symbolic link from which to read.
+ path: string,
+ ) -> result;
+
+ /// Remove a directory.
+ ///
+ /// Return `error-code::not-empty` if the directory is not empty.
+ ///
+ /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
+ remove-directory-at: func(
+ /// The relative path to a directory to remove.
+ path: string,
+ ) -> result<_, error-code>;
+
+ /// Rename a filesystem object.
+ ///
+ /// Note: This is similar to `renameat` in POSIX.
+ rename-at: func(
+ /// The relative source path of the file or directory to rename.
+ old-path: string,
+ /// The base directory for `new-path`.
+ new-descriptor: borrow,
+ /// The relative destination path to which to rename the file or directory.
+ new-path: string,
+ ) -> result<_, error-code>;
+
+ /// Create a symbolic link (also known as a "symlink").
+ ///
+ /// If `old-path` starts with `/`, the function fails with
+ /// `error-code::not-permitted`.
+ ///
+ /// Note: This is similar to `symlinkat` in POSIX.
+ symlink-at: func(
+ /// The contents of the symbolic link.
+ old-path: string,
+ /// The relative destination path at which to create the symbolic link.
+ new-path: string,
+ ) -> result<_, error-code>;
+
+ /// Unlink a filesystem object that is not a directory.
+ ///
+ /// Return `error-code::is-directory` if the path refers to a directory.
+ /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.
+ unlink-file-at: func(
+ /// The relative path to a file to unlink.
+ path: string,
+ ) -> result<_, error-code>;
+
+ /// Test whether two descriptors refer to the same filesystem object.
+ ///
+ /// In POSIX, this corresponds to testing whether the two descriptors have the
+ /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers.
+ /// wasi-filesystem does not expose device and inode numbers, so this function
+ /// may be used instead.
+ is-same-object: func(other: borrow) -> bool;
+
+ /// Return a hash of the metadata associated with a filesystem object referred
+ /// to by a descriptor.
+ ///
+ /// This returns a hash of the last-modification timestamp and file size, and
+ /// may also include the inode number, device number, birth timestamp, and
+ /// other metadata fields that may change when the file is modified or
+ /// replaced. It may also include a secret value chosen by the
+ /// implementation and not otherwise exposed.
+ ///
+ /// Implementations are encourated to provide the following properties:
+ ///
+ /// - If the file is not modified or replaced, the computed hash value should
+ /// usually not change.
+ /// - If the object is modified or replaced, the computed hash value should
+ /// usually change.
+ /// - The inputs to the hash should not be easily computable from the
+ /// computed hash.
+ ///
+ /// However, none of these is required.
+ metadata-hash: func() -> result;
+
+ /// Return a hash of the metadata associated with a filesystem object referred
+ /// to by a directory descriptor and a relative path.
+ ///
+ /// This performs the same hash computation as `metadata-hash`.
+ metadata-hash-at: func(
+ /// Flags determining the method of how the path is resolved.
+ path-flags: path-flags,
+ /// The relative path of the file or directory to inspect.
+ path: string,
+ ) -> result;
+ }
+
+ /// A stream of directory entries.
+ resource directory-entry-stream {
+ /// Read a single directory entry from a `directory-entry-stream`.
+ read-directory-entry: func() -> result