├── .gitattributes
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-Apache-2.0_WITH_LLVM-exception
├── LICENSE-MIT
├── ORG_CODE_OF_CONDUCT.md
├── README.md
├── SECURITY.md
├── ci
├── regenerate.sh
└── vendor-wit.sh
├── crates
└── wasi-ext
│ ├── Cargo.toml
│ ├── examples
│ └── rand.rs
│ └── src
│ ├── lib.rs
│ └── rand.rs
├── examples
├── cli-command-no_std.rs
├── cli-command.rs
├── hello-world-no_std.rs
├── hello-world.rs
├── http-proxy-no_std.rs
└── http-proxy.rs
├── src
├── bindings.rs
├── command.rs
├── ext
│ ├── mod.rs
│ └── std.rs
├── lib.rs
└── proxy.rs
└── wit
├── deps
├── cli
│ ├── command.wit
│ ├── environment.wit
│ ├── exit.wit
│ ├── imports.wit
│ ├── run.wit
│ ├── stdio.wit
│ └── terminal.wit
├── clocks
│ ├── monotonic-clock.wit
│ ├── timezone.wit
│ ├── wall-clock.wit
│ └── world.wit
├── filesystem
│ ├── preopens.wit
│ ├── types.wit
│ └── world.wit
├── http
│ ├── handler.wit
│ ├── proxy.wit
│ └── types.wit
├── io
│ ├── error.wit
│ ├── poll.wit
│ ├── streams.wit
│ └── world.wit
├── random
│ ├── insecure-seed.wit
│ ├── insecure.wit
│ ├── random.wit
│ └── world.wit
└── sockets
│ ├── instance-network.wit
│ ├── ip-name-lookup.wit
│ ├── network.wit
│ ├── tcp-create-socket.wit
│ ├── tcp.wit
│ ├── udp-create-socket.wit
│ ├── udp.wit
│ └── world.wit
└── wasi-crate.wit
/.gitattributes:
--------------------------------------------------------------------------------
1 | # These are generated by `wit-bindgen`
2 | src/bindings.rs linguist-generated=true
3 | src/proxy.rs linguist-generated=true
4 | src/command.rs linguist-generated=true
5 |
6 | # This is copied from other repos so diffs aren't super interesting by default
7 | wit/deps linguist-generated=true
8 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | test:
6 | name: Test
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | rust: [stable, beta, nightly]
11 | steps:
12 | - uses: actions/checkout@v4
13 | - name: Install Rust
14 | run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} && rustup component add rustfmt
15 | - run: rustup target add wasm32-wasip1 wasm32-unknown-unknown
16 | - run: cargo build --workspace
17 | - run: cargo build --workspace --no-default-features
18 | - run: cargo build --workspace --target wasm32-wasip1
19 | - run: cargo build --workspace --target wasm32-wasip1 --no-default-features
20 | - run: cargo test --workspace --doc
21 | - name: Install Wasmtime
22 | uses: bytecodealliance/actions/wasmtime/setup@v1
23 | with:
24 | version: "v30.0.2"
25 | - name: Install wasm-tools
26 | uses: bytecodealliance/actions/wasm-tools/setup@v1
27 | with:
28 | version: "1.224.0"
29 | - run: curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v30.0.2/wasi_snapshot_preview1.command.wasm
30 |
31 | - run: cargo build --examples --target wasm32-wasip1 --no-default-features
32 |
33 | - run: wasm-tools component new ./target/wasm32-wasip1/debug/examples/hello-world-no_std.wasm --adapt ./wasi_snapshot_preview1.command.wasm -o component.wasm
34 | - run: wasmtime run component.wasm
35 |
36 | - run: cargo build --examples --target wasm32-unknown-unknown --no-default-features
37 |
38 | - run: wasm-tools component new ./target/wasm32-unknown-unknown/debug/examples/cli_command_no_std.wasm -o component.wasm
39 | - run: wasmtime run component.wasm
40 |
41 | - run: wasm-tools component new ./target/wasm32-unknown-unknown/debug/examples/http_proxy_no_std.wasm -o component.wasm
42 | - run: wasm-tools component targets wit component.wasm -w wasi:http/proxy
43 |
44 | - run: cargo build --examples --target wasm32-wasip1
45 |
46 | - run: wasm-tools component new ./target/wasm32-wasip1/debug/examples/hello-world.wasm --adapt ./wasi_snapshot_preview1.command.wasm -o component.wasm
47 | - run: wasmtime run component.wasm
48 |
49 | - run: cargo build --examples --target wasm32-unknown-unknown
50 |
51 | - run: wasm-tools component new ./target/wasm32-unknown-unknown/debug/examples/cli_command.wasm -o component.wasm
52 | - run: wasmtime run component.wasm
53 |
54 | - run: wasm-tools component new ./target/wasm32-unknown-unknown/debug/examples/http_proxy.wasm -o component.wasm
55 | - run: wasm-tools component targets wit component.wasm -w wasi:http/proxy
56 |
57 | - run: cargo build --examples --workspace --target wasm32-wasip1 --features rand
58 |
59 | - run: wasm-tools component new ./target/wasm32-wasip1/debug/examples/rand.wasm --adapt ./wasi_snapshot_preview1.command.wasm -o component.wasm
60 | - run: wasmtime run component.wasm
61 |
62 | generate:
63 | name: Ensure generated code up-to-date
64 | runs-on: ubuntu-latest
65 | steps:
66 | - uses: actions/checkout@v4
67 | - name: Install Rust
68 | run: rustup update stable && rustup default stable
69 | # Re-vendor all WIT files and ensure that they're all up-to-date by ensuring
70 | # that there's no git changes.
71 | - name: Re-vendor WIT
72 | run: |
73 | ./ci/vendor-wit.sh
74 | git diff --exit-code
75 | - run: cargo install wit-bindgen-cli@0.39.0 --locked
76 | - run: ./ci/regenerate.sh
77 | - run: git diff --exit-code
78 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | **/*.rs.bk
3 | Cargo.lock
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytecodealliance/wasi-rs/039c272625c2ad09ca3b0b63c41b5f79657482d0/.gitmodules
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | *Note*: this Code of Conduct pertains to individuals' behavior. Please also see the [Organizational Code of Conduct][OCoC].
4 |
5 | ## Our Pledge
6 |
7 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
8 |
9 | ## Our Standards
10 |
11 | Examples of behavior that contributes to creating a positive environment include:
12 |
13 | * Using welcoming and inclusive language
14 | * Being respectful of differing viewpoints and experiences
15 | * Gracefully accepting constructive criticism
16 | * Focusing on what is best for the community
17 | * Showing empathy towards other community members
18 |
19 | Examples of unacceptable behavior by participants include:
20 |
21 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
22 | * Trolling, insulting/derogatory comments, and personal or political attacks
23 | * Public or private harassment
24 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
25 | * Other conduct which could reasonably be considered inappropriate in a professional setting
26 |
27 | ## Our Responsibilities
28 |
29 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
30 |
31 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
32 |
33 | ## Scope
34 |
35 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
36 |
37 | ## Enforcement
38 |
39 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Bytecode Alliance CoC team at [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The CoC team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The CoC team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
40 |
41 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the Bytecode Alliance's leadership.
42 |
43 | ## Attribution
44 |
45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
46 |
47 | [OCoC]: ORG_CODE_OF_CONDUCT.md
48 | [homepage]: https://www.contributor-covenant.org
49 | [version]: https://www.contributor-covenant.org/version/1/4/
50 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to wasi-core
2 |
3 | wasi-core follows the same development style as Cranelift, so checkout
4 | [Cranelift's CONTRIBUTING.md]. Of course, for wasi-core-specific issues, please
5 | use the [wasi-core issue tracker].
6 |
7 | [Cranelift's CONTRIBUTING.md]: https://github.com/CraneStation/cranelift/blob/master/CONTRIBUTING.md
8 | [wasi-core issue tracker]: https://github.com/CraneStation/wasi-core/issues/new
9 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wasi"
3 | version = "0.14.2+wasi-0.2.4"
4 | authors = ["The Cranelift Project Developers"]
5 | description = "WASI API bindings for Rust"
6 | categories = ["no-std", "wasm"]
7 | keywords = ["webassembly", "wasm"]
8 | readme = "README.md"
9 | documentation = "https://docs.rs/wasi"
10 | license.workspace = true
11 | edition.workspace = true
12 | repository.workspace = true
13 |
14 | [workspace.package]
15 | edition = "2021"
16 | license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT"
17 | repository = "https://github.com/bytecodealliance/wasi-rs"
18 |
19 | [workspace.dependencies]
20 | rand = { version = "0.8.5", default-features = false }
21 | wasi = { version = "0.14", path = ".", default-features = false }
22 |
23 | [workspace]
24 | members = ["./crates/*"]
25 |
26 | [dependencies]
27 | wit-bindgen-rt = { version = "0.39.0", features = ["bitflags"] }
28 |
29 | # When built as part of libstd
30 | compiler_builtins = { version = "0.1", optional = true }
31 | core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" }
32 | rustc-std-workspace-alloc = { version = "1.0", optional = true }
33 |
34 | [features]
35 | default = ["std"]
36 | std = []
37 | # Unstable feature to support being a libstd dependency
38 | rustc-dep-of-std = ["compiler_builtins", "core", "rustc-std-workspace-alloc"]
39 |
40 | [[example]]
41 | name = "cli-command-no_std"
42 | crate-type = ["cdylib"]
43 |
44 | [[example]]
45 | name = "cli-command"
46 | crate-type = ["cdylib"]
47 | required-features = ["std"]
48 |
49 | [[example]]
50 | name = "hello-world"
51 | required-features = ["std"]
52 |
53 | [[example]]
54 | name = "http-proxy-no_std"
55 | crate-type = ["cdylib"]
56 |
57 | [[example]]
58 | name = "http-proxy"
59 | crate-type = ["cdylib"]
60 | required-features = ["std"]
61 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/LICENSE-Apache-2.0_WITH_LLVM-exception:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
204 |
205 | --- LLVM Exceptions to the Apache 2.0 License ----
206 |
207 | As an exception, if, as a result of your compiling your source code, portions
208 | of this Software are embedded into an Object form of such source code, you
209 | may redistribute such embedded portions in such Object form without complying
210 | with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
211 |
212 | In addition, if you combine or link compiled forms of this Software with
213 | software that is licensed under the GPLv2 ("Combined Software") and if a
214 | court of competent jurisdiction determines that the patent provision (Section
215 | 3), the indemnity provision (Section 9) or other Section of the License
216 | conflicts with the conditions of the GPLv2, you may retroactively and
217 | prospectively choose to deem waived or otherwise exclude such Section(s) of
218 | the License, but only in their entirety and only with respect to the Combined
219 | Software.
220 |
221 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Permission is hereby granted, free of charge, to any
2 | person obtaining a copy of this software and associated
3 | documentation files (the "Software"), to deal in the
4 | Software without restriction, including without
5 | limitation the rights to use, copy, modify, merge,
6 | publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software
8 | is furnished to do so, subject to the following
9 | conditions:
10 |
11 | The above copyright notice and this permission notice
12 | shall be included in all copies or substantial portions
13 | of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/ORG_CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Bytecode Alliance Organizational Code of Conduct (OCoC)
2 |
3 | *Note*: this Code of Conduct pertains to organizations' behavior. Please also see the [Individual Code of Conduct](CODE_OF_CONDUCT.md).
4 |
5 | ## Preamble
6 |
7 | The Bytecode Alliance (BA) welcomes involvement from organizations,
8 | including commercial organizations. This document is an
9 | *organizational* code of conduct, intended particularly to provide
10 | guidance to commercial organizations. It is distinct from the
11 | [Individual Code of Conduct (ICoC)](CODE_OF_CONDUCT.md), and does not
12 | replace the ICoC. This OCoC applies to any group of people acting in
13 | concert as a BA member or as a participant in BA activities, whether
14 | or not that group is formally incorporated in some jurisdiction.
15 |
16 | The code of conduct described below is not a set of rigid rules, and
17 | we did not write it to encompass every conceivable scenario that might
18 | arise. For example, it is theoretically possible there would be times
19 | when asserting patents is in the best interest of the BA community as
20 | a whole. In such instances, consult with the BA, strive for
21 | consensus, and interpret these rules with an intent that is generous
22 | to the community the BA serves.
23 |
24 | While we may revise these guidelines from time to time based on
25 | real-world experience, overall they are based on a simple principle:
26 |
27 | *Bytecode Alliance members should observe the distinction between
28 | public community functions and private functions — especially
29 | commercial ones — and should ensure that the latter support, or at
30 | least do not harm, the former.*
31 |
32 | ## Guidelines
33 |
34 | * **Do not cause confusion about Wasm standards or interoperability.**
35 |
36 | Having an interoperable WebAssembly core is a high priority for
37 | the BA, and members should strive to preserve that core. It is fine
38 | to develop additional non-standard features or APIs, but they
39 | should always be clearly distinguished from the core interoperable
40 | Wasm.
41 |
42 | Treat the WebAssembly name and any BA-associated names with
43 | respect, and follow BA trademark and branding guidelines. If you
44 | distribute a customized version of software originally produced by
45 | the BA, or if you build a product or service using BA-derived
46 | software, use names that clearly distinguish your work from the
47 | original. (You should still provide proper attribution to the
48 | original, of course, wherever such attribution would normally be
49 | given.)
50 |
51 | Further, do not use the WebAssembly name or BA-associated names in
52 | other public namespaces in ways that could cause confusion, e.g.,
53 | in company names, names of commercial service offerings, domain
54 | names, publicly-visible social media accounts or online service
55 | accounts, etc. It may sometimes be reasonable, however, to
56 | register such a name in a new namespace and then immediately donate
57 | control of that account to the BA, because that would help the project
58 | maintain its identity.
59 |
60 | For further guidance, see the BA Trademark and Branding Policy
61 | [TODO: create policy, then insert link].
62 |
63 | * **Do not restrict contributors.** If your company requires
64 | employees or contractors to sign non-compete agreements, those
65 | agreements must not prevent people from participating in the BA or
66 | contributing to related projects.
67 |
68 | This does not mean that all non-compete agreements are incompatible
69 | with this code of conduct. For example, a company may restrict an
70 | employee's ability to solicit the company's customers. However, an
71 | agreement must not block any form of technical or social
72 | participation in BA activities, including but not limited to the
73 | implementation of particular features.
74 |
75 | The accumulation of experience and expertise in individual persons,
76 | who are ultimately free to direct their energy and attention as
77 | they decide, is one of the most important drivers of progress in
78 | open source projects. A company that limits this freedom may hinder
79 | the success of the BA's efforts.
80 |
81 | * **Do not use patents as offensive weapons.** If any BA participant
82 | prevents the adoption or development of BA technologies by
83 | asserting its patents, that undermines the purpose of the
84 | coalition. The collaboration fostered by the BA cannot include
85 | members who act to undermine its work.
86 |
87 | * **Practice responsible disclosure** for security vulnerabilities.
88 | Use designated, non-public reporting channels to disclose technical
89 | vulnerabilities, and give the project a reasonable period to
90 | respond, remediate, and patch. [TODO: optionally include the
91 | security vulnerability reporting URL here.]
92 |
93 | Vulnerability reporters may patch their company's own offerings, as
94 | long as that patching does not significantly delay the reporting of
95 | the vulnerability. Vulnerability information should never be used
96 | for unilateral commercial advantage. Vendors may legitimately
97 | compete on the speed and reliability with which they deploy
98 | security fixes, but withholding vulnerability information damages
99 | everyone in the long run by risking harm to the BA project's
100 | reputation and to the security of all users.
101 |
102 | * **Respect the letter and spirit of open source practice.** While
103 | there is not space to list here all possible aspects of standard
104 | open source practice, some examples will help show what we mean:
105 |
106 | * Abide by all applicable open source license terms. Do not engage
107 | in copyright violation or misattribution of any kind.
108 |
109 | * Do not claim others' ideas or designs as your own.
110 |
111 | * When others engage in publicly visible work (e.g., an upcoming
112 | demo that is coordinated in a public issue tracker), do not
113 | unilaterally announce early releases or early demonstrations of
114 | that work ahead of their schedule in order to secure private
115 | advantage (such as marketplace advantage) for yourself.
116 |
117 | The BA reserves the right to determine what constitutes good open
118 | source practices and to take action as it deems appropriate to
119 | encourage, and if necessary enforce, such practices.
120 |
121 | ## Enforcement
122 |
123 | Instances of organizational behavior in violation of the OCoC may
124 | be reported by contacting the Bytecode Alliance CoC team at
125 | [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The
126 | CoC team will review and investigate all complaints, and will respond
127 | in a way that it deems appropriate to the circumstances. The CoC team
128 | is obligated to maintain confidentiality with regard to the reporter of
129 | an incident. Further details of specific enforcement policies may be
130 | posted separately.
131 |
132 | When the BA deems an organization in violation of this OCoC, the BA
133 | will, at its sole discretion, determine what action to take. The BA
134 | will decide what type, degree, and duration of corrective action is
135 | needed, if any, before a violating organization can be considered for
136 | membership (if it was not already a member) or can have its membership
137 | reinstated (if it was a member and the BA canceled its membership due
138 | to the violation).
139 |
140 | In practice, the BA's first approach will be to start a conversation,
141 | with punitive enforcement used only as a last resort. Violations
142 | often turn out to be unintentional and swiftly correctable with all
143 | parties acting in good faith.
144 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
16 |
17 | This crate contains bindings for [WASI](https://github.com/WebAssembly/WASI)
18 | APIs for the worlds:
19 |
20 | * [`wasi:cli/command`]
21 | * [`wasi:http/proxy`]
22 |
23 | This crate is procedurally generated from [WIT] files using [`wit-bindgen`].
24 |
25 | [`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli
26 | [`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http
27 | [WIT]: https://component-model.bytecodealliance.org/design/wit.html
28 | [`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen
29 | [components]: https://component-model.bytecodealliance.org/
30 | [`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools
31 |
32 | # Usage
33 |
34 | Depending on this crate can be done by adding it to your dependencies:
35 |
36 | ```sh
37 | $ cargo add wasi
38 | ```
39 |
40 | Next you can use the APIs in the root of the module like so:
41 |
42 | ```rust
43 | fn main() {
44 | let stdout = wasi::cli::stdout::get_stdout();
45 | stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap();
46 | }
47 | ```
48 |
49 | This crate can currently be used in three main ways.
50 |
51 | - One is to use it and compile for the [`wasm32-wasip2` target] in Rust 1.82 and later.
52 | This is the simplest approach, as all the tools needed are included in the
53 | Rust tooling, however it doesn't yet support some of the features of the
54 | other approaches.
55 |
56 | - Another is to use it and compile using [`cargo component`]. This is essentially
57 | the same as the next option, except that `cargo component` handles most of the
58 | steps for you. `cargo component` also has a number of additional features for
59 | working with dependencies and custom WIT interfaces.
60 |
61 | - And the third is to compile for the `wasm32-wasip1` target, and then adapt
62 | the resulting modules into component using `wasm-tools component new`; see
63 | the next section here for details.
64 |
65 | [`wasm32-wasip2` target]: https://blog.rust-lang.org/2024/11/26/wasip2-tier-2.html
66 | [`cargo component`]: https://github.com/bytecodealliance/cargo-component
67 |
68 | ## Building with wasm32-wasip1 and `cargo component new`.
69 |
70 | The `wasm32-wasip2` target works with a simple `cargo build --target=wasm32-wasip2`
71 | and doesn't need a lot of documentation here, and `cargo component` has its own
72 | documentation, so here we have some documentation for the `wasm32-wasip1` way.
73 |
74 | ```
75 | $ cargo build --target wasm32-wasip1
76 | ```
77 |
78 | Next you'll want an "adapter" to convert the Rust standard library's usage of
79 | `wasi_snapshot_preview1` to the component model. An example adapter can be found
80 | from [Wasmtime's release page](https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm).
81 |
82 | ```
83 | $ curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm
84 | ```
85 |
86 | Next to create a component you'll use the [`wasm-tools`] CLI to create a
87 | component:
88 |
89 | ```
90 | $ cargo install wasm-tools
91 | $ wasm-tools component new target/wasm32-wasip1/debug/foo.wasm \
92 | --adapt ./wasi_snapshot_preview1.command.wasm \
93 | -o component.wasm
94 | ```
95 |
96 | And finally the component can be run by a runtime that has Component Model
97 | support, such as [Wasmtime]:
98 |
99 | ```
100 | $ wasmtime run component.wasm
101 | Hello, world!
102 | ```
103 |
104 | [Wasmtime]: https://github.com/bytecodealliance/wasmtime
105 |
106 | # WASIp2 vs WASIp1
107 |
108 | In January 2024 the WASI subgroup published WASI 0.2.0, colloquially known as
109 | "WASIp2". Around the same time the subgroup additionally decided to name the
110 | previous iteration of WASI as "WASIp1", historically known as "WASI preview1".
111 | This now-historical snapshot of WASI was defined with an entirely different set
112 | of primitives and worked very differently. This crate now targets WASIp2 and no
113 | longer targets WASIp1.
114 |
115 | ## Support for WASIp1
116 |
117 | The last version of the `wasi` crate to support WASIp1 was the
118 | [0.11.0+wasi-snapshot-preview1
119 | version](https://crates.io/crates/wasi/0.11.0+wasi-snapshot-preview1). This
120 | version of the crate supported all WASIp1 APIs. WASIp1 was historically defined
121 | with `*.witx` files and used a bindings generator called `witx-bindgen`.
122 |
123 | ## Should I use WASIp1 or WASIp2?
124 |
125 | This is a bit of a nuanced question/answer but the short answer is to probably
126 | use the 0.11.0 release of `wasi` for now if you're unsure.
127 |
128 | The longer-form answer of this is that it depends on the Rust targets that you
129 | want to support. Rust WebAssembly targets include:
130 |
131 | * `wasm32-unknown-unknown` - do not use this crate because this target indicates
132 | that WASI is not desired.
133 | * `wasm32-wasip1` - this target has been present in Rust for quite some time and
134 | was previously known as `wasm32-wasi`. For this target you probably want the
135 | 0.11.0 track of this crate.
136 | * `wasm32-wasip2` - this target is a recent addition to rustc (as of the time of
137 | this writing it's not merged yet into rustc). This is what the 0.12.0 version
138 | of the crate is intended for.
139 |
140 | Note that if you use `wasm32-wasip1` it's not necessarily guaranteed you want
141 | 0.11.0 of this crate. If your users are producing components then you probably
142 | want 0.12.0 instead. If you don't know what your users are producing then you
143 | should probably stick with 0.11.0.
144 |
145 | Long story short, it's a bit complicated. We're in a transition period from
146 | WASIp1 to WASIp2 and things aren't going to be perfect every step of the way, so
147 | understanding is appreciated!
148 |
149 | # Development
150 |
151 | The bulk of the `wasi` crate is generated by the [`wit-bindgen`] tool. The
152 | `src/bindings.rs` file can be regenerated with:
153 |
154 | ```
155 | $ ./ci/regenerate.sh
156 | ```
157 |
158 | WASI definitions are located in the `wit` directory of this repository.
159 | Currently they're copied from upstream repositories but are hoped to be better
160 | managed in the future.
161 |
162 | # License
163 |
164 | This project is triple licenced under the Apache 2/ Apache 2 with LLVM exceptions/ MIT licences. The reasoning for this is:
165 | - Apache 2/ MIT is common in the rust ecosystem.
166 | - Apache 2/ MIT is used in the rust standard library, and some of this code may be migrated there.
167 | - Some of this code may be used in compiler output, and the Apache 2 with LLVM exceptions licence is useful for this.
168 |
169 | For more details see
170 | - [Apache 2 Licence](LICENSE-APACHE)
171 | - [Apache 2 Licence with LLVM exceptions](LICENSE-Apache-2.0_WITH_LLVM-exception)
172 | - [MIT Licence](LICENSE-MIT)
173 |
174 | ### Contribution
175 |
176 | Unless you explicitly state otherwise, any contribution intentionally submitted
177 | for inclusion in this project by you, as defined in the Apache 2/ Apache 2 with LLVM exceptions/ MIT licenses,
178 | shall be licensed as above, without any additional terms or conditions.
179 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | Building secure foundations for software development is at the core of what we do in the Bytecode Alliance. Contributions of external security researchers are a vital part of that.
4 |
5 | ## Scope
6 |
7 | If you believe you've found a security issue in any website, service, or software owned or operated by the Bytecode Alliance, we encourage you to notify us.
8 |
9 | ## How to Submit a Report
10 |
11 | To submit a vulnerability report to the Bytecode Alliance, please contact us at [security@bytecodealliance.org](mailto:security@bytecodealliance.org). Your submission will be reviewed and validated by a member of our security team.
12 |
13 | ## Safe Harbor
14 |
15 | The Bytecode Alliance supports safe harbor for security researchers who:
16 |
17 | * Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services.
18 | * Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information.
19 | * Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party.
20 |
21 | We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you.
22 |
23 | Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy.
24 |
25 | ## Preferences
26 |
27 | * Please provide detailed reports with reproducible steps and a clearly defined impact.
28 | * Submit one vulnerability per report.
29 | * Social engineering (e.g. phishing, vishing, smishing) is prohibited.
30 |
--------------------------------------------------------------------------------
/ci/regenerate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ex
4 |
5 | generate() {
6 | file="$1"
7 | shift
8 | wit-bindgen rust wit --async none --out-dir src --std-feature "$@" --format \
9 | --runtime-path wit_bindgen_rt
10 | }
11 |
12 | # Generate the main body of the bindings which includes all imports from the two
13 | # worlds below.
14 | generate src/bindings.rs --type-section-suffix rust-wasi-from-crates-io \
15 | --generate-all
16 |
17 | # Generate bindings for the `wasi:cli/command` world specifically, namely the
18 | # macro `export_command`.
19 | #
20 | # Note that `--with` is used to point at the previously generated bindings.
21 | with="wasi:cli/environment@0.2.4=crate::cli::environment"
22 | with="$with,wasi:cli/exit@0.2.4=crate::cli::exit"
23 | with="$with,wasi:cli/stdin@0.2.4=crate::cli::stdin"
24 | with="$with,wasi:cli/stdout@0.2.4=crate::cli::stdout"
25 | with="$with,wasi:cli/stderr@0.2.4=crate::cli::stderr"
26 | with="$with,wasi:cli/terminal-input@0.2.4=crate::cli::terminal_input"
27 | with="$with,wasi:cli/terminal-output@0.2.4=crate::cli::terminal_output"
28 | with="$with,wasi:cli/terminal-stdin@0.2.4=crate::cli::terminal_stdin"
29 | with="$with,wasi:cli/terminal-stdout@0.2.4=crate::cli::terminal_stdout"
30 | with="$with,wasi:cli/terminal-stderr@0.2.4=crate::cli::terminal_stderr"
31 | with="$with,wasi:clocks/monotonic-clock@0.2.4=crate::clocks::monotonic_clock"
32 | with="$with,wasi:clocks/wall-clock@0.2.4=crate::clocks::wall_clock"
33 | with="$with,wasi:filesystem/types@0.2.4=crate::filesystem::types"
34 | with="$with,wasi:filesystem/preopens@0.2.4=crate::filesystem::preopens"
35 | with="$with,wasi:io/error@0.2.4=crate::io::error"
36 | with="$with,wasi:io/poll@0.2.4=crate::io::poll"
37 | with="$with,wasi:io/streams@0.2.4=crate::io::streams"
38 | with="$with,wasi:random/random@0.2.4=crate::random::random"
39 | with="$with,wasi:random/insecure@0.2.4=crate::random::insecure"
40 | with="$with,wasi:random/insecure-seed@0.2.4=crate::random::insecure_seed"
41 | with="$with,wasi:sockets/network@0.2.4=crate::sockets::network"
42 | with="$with,wasi:sockets/instance-network@0.2.4=crate::sockets::instance_network"
43 | with="$with,wasi:sockets/tcp@0.2.4=crate::sockets::tcp"
44 | with="$with,wasi:sockets/tcp-create-socket@0.2.4=crate::sockets::tcp_create_socket"
45 | with="$with,wasi:sockets/udp@0.2.4=crate::sockets::udp"
46 | with="$with,wasi:sockets/udp-create-socket@0.2.4=crate::sockets::udp_create_socket"
47 | with="$with,wasi:sockets/ip-name-lookup@0.2.4=crate::sockets::ip_name_lookup"
48 | generate src/command.rs \
49 | --world wasi:cli/command \
50 | --with "$with" \
51 | --type-section-suffix rust-wasi-from-crates-io-command-world \
52 | --default-bindings-module wasi \
53 | --pub-export-macro \
54 | --export-macro-name _export_command
55 |
56 | # Same as the `command` world, but for the proxy world.
57 | with="wasi:cli/stdin@0.2.4=crate::cli::stdin"
58 | with="$with,wasi:cli/stdout@0.2.4=crate::cli::stdout"
59 | with="$with,wasi:cli/stderr@0.2.4=crate::cli::stderr"
60 | with="$with,wasi:clocks/monotonic-clock@0.2.4=crate::clocks::monotonic_clock"
61 | with="$with,wasi:clocks/wall-clock@0.2.4=crate::clocks::wall_clock"
62 | with="$with,wasi:io/error@0.2.4=crate::io::error"
63 | with="$with,wasi:io/poll@0.2.4=crate::io::poll"
64 | with="$with,wasi:io/streams@0.2.4=crate::io::streams"
65 | with="$with,wasi:random/random@0.2.4=crate::random::random"
66 | with="$with,wasi:http/types@0.2.4=crate::http::types"
67 | with="$with,wasi:http/outgoing-handler@0.2.4=crate::http::outgoing_handler"
68 | generate src/proxy.rs \
69 | --world wasi:http/proxy \
70 | --with "$with" \
71 | --type-section-suffix rust-wasi-from-crates-io-proxy-world \
72 | --default-bindings-module wasi \
73 | --pub-export-macro \
74 | --export-macro-name _export_proxy
75 |
--------------------------------------------------------------------------------
/ci/vendor-wit.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Script to re-vendor the WIT files that wasi-rs uses as defined by a
4 | # particular tag in upstream repositories.
5 | #
6 | # This script is executed on CI to ensure that everything is up-to-date.
7 | set -ex
8 |
9 | # Space-separated list of wasi proposals that are vendored here along with the
10 | # tag that they're all vendored at.
11 | #
12 | # This assumes that the repositories all have the pattern:
13 | # https://github.com/WebAssembly/wasi-$repo
14 | # and every repository has a tag `v$tag` here. That is currently done as part
15 | # of the WASI release process.
16 | repos="cli clocks filesystem http io random sockets"
17 | tag=0.2.4
18 | dst=wit/deps
19 |
20 | rm -rf $dst
21 | mkdir -p $dst
22 |
23 | for repo in $repos; do
24 | mkdir $dst/$repo
25 | curl -L https://github.com/WebAssembly/wasi-$repo/archive/refs/tags/v$tag.tar.gz | \
26 | tar xzf - --strip-components=2 -C $dst/$repo wasi-$repo-$tag/wit
27 | rm -rf $dst/$repo/deps*
28 | done
29 |
--------------------------------------------------------------------------------
/crates/wasi-ext/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wasi-ext"
3 | version = "0.1.0"
4 | authors = ["Roman Volosatovs "]
5 | description = "Third-party crate integrations for WASI"
6 |
7 | license.workspace = true
8 | edition.workspace = true
9 | repository.workspace = true
10 |
11 | [features]
12 | default = ["std"]
13 | std = ["wasi/std"]
14 |
15 | [dependencies]
16 | rand = { workspace = true, optional = true }
17 | wasi = { workspace = true }
18 |
19 | [[example]]
20 | name = "rand"
21 | required-features = ["rand", "std"]
22 |
--------------------------------------------------------------------------------
/crates/wasi-ext/examples/rand.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write as _;
2 |
3 | use wasi_ext::rand::rand::Rng as _;
4 | use wasi_ext::rand::{HostInsecureRng, HostRng};
5 |
6 | fn main() {
7 | let mut stdout = wasi::cli::stdout::get_stdout();
8 |
9 | let r: u64 = HostRng.gen();
10 | writeln!(stdout, "Cryptographically-secure random u64 is {r}").unwrap();
11 |
12 | let r: u64 = HostInsecureRng.gen();
13 | writeln!(stdout, "Pseudo-random u64 is {r}").unwrap();
14 |
15 | stdout.flush().unwrap();
16 | }
17 |
--------------------------------------------------------------------------------
/crates/wasi-ext/src/lib.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "rand")]
2 | pub mod rand;
3 |
--------------------------------------------------------------------------------
/crates/wasi-ext/src/rand.rs:
--------------------------------------------------------------------------------
1 | pub use rand;
2 |
3 | use rand::{CryptoRng, RngCore};
4 |
5 | /// The secure interface for cryptographically-secure random numbers
6 | pub struct HostRng;
7 |
8 | impl CryptoRng for HostRng {}
9 |
10 | impl RngCore for HostRng {
11 | #[inline]
12 | fn next_u32(&mut self) -> u32 {
13 | wasi::random::random::get_random_u64() as _
14 | }
15 |
16 | #[inline]
17 | fn next_u64(&mut self) -> u64 {
18 | wasi::random::random::get_random_u64()
19 | }
20 |
21 | fn fill_bytes(&mut self, dest: &mut [u8]) {
22 | let n = dest.len();
23 | if usize::BITS <= u64::BITS || n <= u64::MAX as _ {
24 | dest.copy_from_slice(&wasi::random::random::get_random_bytes(n as _));
25 | } else {
26 | let (head, tail) = dest.split_at_mut(u64::MAX as _);
27 | head.copy_from_slice(&wasi::random::random::get_random_bytes(u64::MAX));
28 | self.fill_bytes(tail);
29 | }
30 | }
31 |
32 | #[inline]
33 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
34 | self.fill_bytes(dest);
35 | Ok(())
36 | }
37 | }
38 |
39 | /// The insecure interface for insecure pseudo-random numbers
40 | pub struct HostInsecureRng;
41 |
42 | impl RngCore for HostInsecureRng {
43 | #[inline]
44 | fn next_u32(&mut self) -> u32 {
45 | wasi::random::insecure::get_insecure_random_u64() as _
46 | }
47 |
48 | #[inline]
49 | fn next_u64(&mut self) -> u64 {
50 | wasi::random::insecure::get_insecure_random_u64()
51 | }
52 |
53 | fn fill_bytes(&mut self, dest: &mut [u8]) {
54 | let n = dest.len();
55 | if usize::BITS <= u64::BITS || n <= u64::MAX as _ {
56 | dest.copy_from_slice(&wasi::random::insecure::get_insecure_random_bytes(n as _));
57 | } else {
58 | let (head, tail) = dest.split_at_mut(u64::MAX as _);
59 | head.copy_from_slice(&wasi::random::insecure::get_insecure_random_bytes(u64::MAX));
60 | self.fill_bytes(tail);
61 | }
62 | }
63 |
64 | #[inline]
65 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
66 | self.fill_bytes(dest);
67 | Ok(())
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/examples/cli-command-no_std.rs:
--------------------------------------------------------------------------------
1 | wasi::cli::command::export!(Example);
2 |
3 | struct Example;
4 |
5 | impl wasi::exports::cli::run::Guest for Example {
6 | fn run() -> Result<(), ()> {
7 | let stdout = wasi::cli::stdout::get_stdout();
8 | stdout.blocking_write_and_flush(b"Hello, WASI!").unwrap();
9 | Ok(())
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/cli-command.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write as _;
2 |
3 | wasi::cli::command::export!(Example);
4 |
5 | struct Example;
6 |
7 | impl wasi::exports::cli::run::Guest for Example {
8 | fn run() -> Result<(), ()> {
9 | let mut stdout = wasi::cli::stdout::get_stdout();
10 | stdout.write_all(b"Hello, WASI!").unwrap();
11 | stdout.flush().unwrap();
12 | Ok(())
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/hello-world-no_std.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | let stdout = wasi::cli::stdout::get_stdout();
3 | stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap();
4 | }
5 |
--------------------------------------------------------------------------------
/examples/hello-world.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write as _;
2 |
3 | fn main() {
4 | let mut stdout = wasi::cli::stdout::get_stdout();
5 | stdout.write_all(b"Hello, world!\n").unwrap();
6 | stdout.flush().unwrap();
7 | }
8 |
--------------------------------------------------------------------------------
/examples/http-proxy-no_std.rs:
--------------------------------------------------------------------------------
1 | use wasi::http::types::{
2 | Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam,
3 | };
4 |
5 | wasi::http::proxy::export!(Example);
6 |
7 | struct Example;
8 |
9 | impl wasi::exports::http::incoming_handler::Guest for Example {
10 | fn handle(_request: IncomingRequest, response_out: ResponseOutparam) {
11 | let resp = OutgoingResponse::new(Fields::new());
12 | let body = resp.body().unwrap();
13 |
14 | ResponseOutparam::set(response_out, Ok(resp));
15 |
16 | let out = body.write().unwrap();
17 | out.blocking_write_and_flush(b"Hello, WASI!").unwrap();
18 | drop(out);
19 |
20 | OutgoingBody::finish(body, None).unwrap();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/http-proxy.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write as _;
2 |
3 | use wasi::http::types::{
4 | Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam,
5 | };
6 |
7 | wasi::http::proxy::export!(Example);
8 |
9 | struct Example;
10 |
11 | impl wasi::exports::http::incoming_handler::Guest for Example {
12 | fn handle(_request: IncomingRequest, response_out: ResponseOutparam) {
13 | let resp = OutgoingResponse::new(Fields::new());
14 | let body = resp.body().unwrap();
15 |
16 | ResponseOutparam::set(response_out, Ok(resp));
17 |
18 | let mut out = body.write().unwrap();
19 | out.write_all(b"Hello, WASI!").unwrap();
20 | out.flush().unwrap();
21 | drop(out);
22 |
23 | OutgoingBody::finish(body, None).unwrap();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ext/mod.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "std")]
2 | mod std;
3 |
4 | impl core::fmt::Display for crate::io::error::Error {
5 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6 | f.write_str(&self.to_debug_string())
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ext/std.rs:
--------------------------------------------------------------------------------
1 | use std::error::Error;
2 | use std::io;
3 | use std::num::NonZeroU64;
4 |
5 | use crate::io::streams::StreamError;
6 |
7 | impl Error for crate::io::error::Error {}
8 |
9 | impl io::Read for crate::io::streams::InputStream {
10 | fn read(&mut self, buf: &mut [u8]) -> io::Result {
11 | let n = buf
12 | .len()
13 | .try_into()
14 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
15 | match self.blocking_read(n) {
16 | Ok(chunk) => {
17 | let n = chunk.len();
18 | if n > buf.len() {
19 | return Err(io::Error::new(
20 | io::ErrorKind::Other,
21 | "more bytes read than requested",
22 | ));
23 | }
24 | buf[..n].copy_from_slice(&chunk);
25 | Ok(n)
26 | }
27 | Err(StreamError::Closed) => Ok(0),
28 | Err(StreamError::LastOperationFailed(e)) => {
29 | Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string()))
30 | }
31 | }
32 | }
33 | }
34 |
35 | impl io::Write for crate::io::streams::OutputStream {
36 | fn write(&mut self, buf: &[u8]) -> io::Result {
37 | let n = loop {
38 | match self.check_write().map(NonZeroU64::new) {
39 | Ok(Some(n)) => {
40 | break n;
41 | }
42 | Ok(None) => {
43 | self.subscribe().block();
44 | }
45 | Err(StreamError::Closed) => return Ok(0),
46 | Err(StreamError::LastOperationFailed(e)) => {
47 | return Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string()))
48 | }
49 | };
50 | };
51 | let n = n
52 | .get()
53 | .try_into()
54 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
55 | let n = buf.len().min(n);
56 | crate::io::streams::OutputStream::write(self, &buf[..n]).map_err(|e| match e {
57 | StreamError::Closed => io::ErrorKind::UnexpectedEof.into(),
58 | StreamError::LastOperationFailed(e) => {
59 | io::Error::new(io::ErrorKind::Other, e.to_debug_string())
60 | }
61 | })?;
62 | Ok(n)
63 | }
64 |
65 | fn flush(&mut self) -> io::Result<()> {
66 | self.blocking_flush()
67 | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! Raw API bindings to the [WebAssembly System Interface (WASI)][WASI]
2 | //!
3 | //! [WASI]: https://github.com/WebAssembly/WASI
4 | //!
5 | //! This crate provides Rust API bindings to the imports of [WASI] [worlds] such
6 | //! as:
7 | //!
8 | //! * [`wasi:cli/command`]
9 | //! * [`wasi:http/proxy`]
10 | //!
11 | //! This crate is procedurally generated with the [`wit-bindgen`] bindings
12 | //! generator. Note that generated code is published to crates.io to slim this
13 | //! crate down in terms of build dependencies and resources.
14 | //!
15 | //! # What is WASI?
16 | //!
17 | //! [WASI] is a set of APIs defined for the WebAssembly [Component Model] to
18 | //! help components interact with the outside world. Core WebAssembly has no
19 | //! intrinsic ability to access the host, for example `println!` don't work, but
20 | //! [WASI] defines how to do so with the [`wasi:cli/stdio`] package.
21 | //!
22 | //! [WASI] is defined by an IDL called [WIT] using files that have the extension
23 | //! `*.wit`. [WASI] and [WIT] are themselves then both defined in terms of the
24 | //! [Component Model] in terms of types available and base semantics for APIs.
25 | //!
26 | //! [WASI] defines a number of standard "worlds" which are a description of a
27 | //! what a WebAssembly component can import from an embedding and must export to
28 | //! an embedding. An example world is [`wasi:cli/command`] which is a world for
29 | //! running CLI applications. This world provides basic system utilities such as
30 | //! clocks, a filesystem, CLI arguments, etc. The one required export is a main
31 | //! function.
32 | //!
33 | //! The purpose of this crate is to provide pregenerated bindings to access
34 | //! [WASI]-defined imports available to components.
35 | //!
36 | //! # What is a Component?
37 | //!
38 | //! An important aspect of [WASI] is that it is defined in terms of the
39 | //! [Component Model]. The [Component Model] is a proposal for WebAssembly which
40 | //! is a new format for wasm binaries, a component. A component contains "core"
41 | //! WebAssembly modules (which are [standard WebAssembly modules]) but also has
42 | //! the ability to do more:
43 | //!
44 | //! * A component can contain multiple core WebAssembly modules.
45 | //! * Types used with component imports and exports are more comprehensive than
46 | //! core WebAssembly. Core WebAssembly provides integers and floats, for
47 | //! example, and components build on this and add strings, records (aka a Rust
48 | //! `struct`), variants (aka a Rust `enum`), and resources (think a file
49 | //! descriptor on Unix).
50 | //! * A component provides procedural instructions of how to instantiate its
51 | //! internal core WebAssembly modules with the imports it has.
52 | //!
53 | //! The [Component Model] is a not considered an official WebAssembly standard
54 | //! at this time. It has been in development for 5 years (as of January 2024),
55 | //! however, and the WASI 0.2.0 milestone (more on versioning in a moment) in
56 | //! January 2024 represents a concrete target for ecosystems to use. Runtimes
57 | //! such as [Wasmtime] support the [Component Model] for out-of-browser usage
58 | //! and [jco] is an example of how components can be run in a browser.
59 | //!
60 | //! A full description of the component model is out of scope for this crate's
61 | //! documentation but it suffices to say that [WASI], and this crate, are
62 | //! intended to target components. Components use core WebAssembly modules as an
63 | //! important technical detail, but the final output of this crate is intended
64 | //! to be a component.
65 | //!
66 | //! # What are generated bindings?
67 | //!
68 | //! Above it was seen that [WASI] is defined with [WIT]. These programmatic
69 | //! descriptions of [WASI] APIs are not suitable for use directly in Rust,
70 | //! however these descriptions define how Rust can use them. Each [WIT] function
71 | //! has a defined meaning in core WebAssembly via the [Canonical ABI]. This is a
72 | //! lower level than most users want to operate at, however, so the generated
73 | //! bindings in this crate serve as the bridge.
74 | //!
75 | //! More specifically the generated functions in this crate take the [Canonical
76 | //! ABI] format of [WIT] functions and provide idiomatic Rust functions to call.
77 | //! For example the [`wasi:cli/environment`] definition includes:
78 | //!
79 | //! ```wit
80 | //! interface environment {
81 | //! // ...
82 | //! get-environment: func() -> list>;
83 | //! // ...
84 | //! }
85 | //! ```
86 | //!
87 | //! This corresponds to
88 | //! [`wasi::cli::environment::get_environment`](crate::cli::environment::get_environment).
89 | //!
90 | //! Bindings are pre-generated in this crate with the [`wit-bindgen`] tool. You
91 | //! can also generate your own bindings with [`wit-bindgen`] and [WASI] [WIT]
92 | //! files too, but that's not covered by this crate.
93 | //!
94 | //! # WASI Today and `wasi_snapshot_preview1`
95 | //!
96 | //! This crate is based on the 0.2.0 version of [WASI] APIs. This version of
97 | //! [WASI] was declared "phase 3" (suitable for general use and testing) in
98 | //! January of 2024. Prior to this 0.2.0 "preview2" release of [WASI] there was
99 | //! `wasi_snapshot_preview1`. This previous "preview1" release of [WASI] was
100 | //! circa 2019 and was the initial vision for [WASI] as a standard. Development
101 | //! of [WASI] migrated to the [Component Model] in the meantime.
102 | //!
103 | //! This means that the old `wasi_snapshot_preview1` interfaces are no longer
104 | //! provided by this crate because [WASI] is no longer defined by those
105 | //! interfaces. This includes the historical `*.witx` format which has now been
106 | //! sueprseded. Note that the 0.11.x release series of this crate contains
107 | //! bindings to the historical `wasi_snapshot_preview1` APIs if you're
108 | //! interested in using them.
109 | //!
110 | //! # Crate Organization
111 | //!
112 | //! This crate is currently entirely generated by [`wit-bindgen`] which has the
113 | //! following structure:
114 | //!
115 | //! * Each [WIT] package with bindings corresponds to a top-level module. For
116 | //! example [`wasi:random`] can be found in the [`random`] module.
117 | //! * Each [WIT] interface then corresponds to a submodule of its package's
118 | //! module. For example [`wasi:random/insecure`] can be found in the
119 | //! [`random::insecure`] module.
120 | //! * Each [WIT] function has a Rust function with an idiomatic signature.
121 | //! module. For example [`random::insecure::get_insecure_random_u64`].
122 | //!
123 | //! Note that [WIT] documentation is rendered as rustdoc documentation in these
124 | //! APIs as well.
125 | //!
126 | //! # Using this Crate
127 | //!
128 | //! This crate is intended to be easiest to use with a future
129 | //! `wasm32-wasip2` target added to the Rust compiler. In the meantime
130 | //! it's recommended to use the `wasm32-wasip1` target instead:
131 | //!
132 | //! ```sh
133 | //! $ cargo build --target wasm32-wasip1
134 | //! ```
135 | //!
136 | //! Note that the output of the `wasm32-wasip1` target is a core wasm module, not
137 | //! a component, so to turn it into a component you can use the [`wasm-tools`]
138 | //! CLI in combination with an "adapter module" for the `wasi_snapshot_preview1`
139 | //! APIs that the Rust standard library uses (example adapters can be found on
140 | //! [Wasmtime's release page][adapters] as
141 | //! [`wasi_snapshot_preview1.command.wasm`] for example)
142 | //!
143 | //! ```sh
144 | //! $ wasm-tools component new ./target/wasm32-wasip1/debug/my-app.wasm \
145 | //! --adapt ./wasi_snapshot_preview1.command.wasm \
146 | //! -o my-component.wasm
147 | //! ```
148 | //!
149 | //! ## Export Macros
150 | //!
151 | //! In addition to providing bindings for imports this crate also provides
152 | //! macros to export the `wasi:cli/run` and `wasi:http/proxy` worlds, see their
153 | //! respective documentation for more information:
154 | //!
155 | //! - [`wasi::cli::command::export!`](crate::cli::command::export)
156 | //! - [`wasi::http::proxy::export!`](crate::http::proxy::export)
157 | //!
158 | //! [worlds]: https://component-model.bytecodealliance.org/design/worlds.html
159 | //! [`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli/
160 | //! [`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http
161 | //! [`wasi:cli/stdio`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/stdio.wit
162 | //! [`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen/
163 | //! [Component Model]: https://component-model.bytecodealliance.org/
164 | //! [WIT]: https://component-model.bytecodealliance.org/design/wit.html
165 | //! [standard WebAssembly modules]: https://webassembly.github.io/spec/
166 | //! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
167 | //! [jco]: https://github.com/bytecodealliance/jco
168 | //! [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
169 | //! [`wasi:cli/environment`]: https://github.com/WebAssembly/wasi-cli/blob/main/wit/environment.wit
170 | //! [`wasi:random`]: https://github.com/WebAssembly/wasi-random
171 | //! [`wasi:random/insecure`]: https://github.com/WebAssembly/wasi-random/blob/main/wit/insecure.wit
172 | //! [`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools
173 | //! [adapters]: https://github.com/bytecodealliance/wasmtime/releases
174 | //! [`wasi_snapshot_preview1.command.wasm`]: https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm
175 |
176 | #![no_std]
177 |
178 | #[cfg(feature = "std")]
179 | extern crate std;
180 |
181 | pub mod ext;
182 |
183 | // These modules are all auto-generated by `./ci/regenerate.sh`
184 | mod bindings;
185 | #[allow(unused_imports)]
186 | mod command;
187 | #[allow(unused_imports)]
188 | mod proxy;
189 |
190 | // generated bindings start with the package namespace, which in this case is
191 | // `wasi`, but the crate is already called wasi, so lift everything up one level
192 | // to the root of this crate.
193 | pub use bindings::wasi::*;
194 |
195 | // Expand the `cli` and `http` modules with `export!` macros for the
196 | // command/proxy worlds, but also retain all the contents defined in the
197 | // `bindings` module as well.
198 | pub mod cli {
199 | pub use super::bindings::wasi::cli::*;
200 |
201 | pub mod command {
202 | /// Generate an exported instance of the `wasi:cli/command` world.
203 | ///
204 | /// This macro generate the `#[no_mangle]` functions necessary to
205 | /// export this interface. It takes an argument which is a type that
206 | /// must implement the
207 | /// [`exports::cli::run::Guest`](crate::exports::cli::run::Guest)
208 | /// trait.
209 | ///
210 | /// ```
211 | /// struct MyCliRunner;
212 | ///
213 | /// impl wasi::exports::cli::run::Guest for MyCliRunner {
214 | /// fn run() -> Result<(), ()> {
215 | /// // ...
216 | /// # panic!();
217 | /// }
218 | /// }
219 | ///
220 | /// wasi::cli::command::export!(MyCliRunner);
221 | /// ```
222 | ///
223 | /// ## Compatibility with `wasm32-wasip1` targets
224 | ///
225 | /// This macro is not compatible with `wasm32-wasip1` `bin` targets
226 | /// which instead use a `fn main()` with the
227 | /// `wasi_snapshot_preview1.command.wasm` adapter. This macro _can_ be
228 | /// used with the `reactor` or `proxy` adapters.
229 | ///
230 | ///
234 | #[doc(inline)]
235 | pub use crate::command::_export_command as export;
236 | }
237 | }
238 |
239 | pub mod http {
240 | pub use super::bindings::wasi::http::*;
241 |
242 | pub mod proxy {
243 | /// Generate an exported instance of the `wasi:http/proxy` world.
244 | ///
245 | /// This macro will generate `#[no_mangle]` functions as necessary to
246 | /// export an implementation of the
247 | /// [`exports::http::incoming_handler::Guest`](crate::exports::http::incoming_handler::Guest)
248 | /// trait. This macro takes
249 | /// an argument which is a type that implements this trait:
250 | ///
251 | /// ```
252 | /// use wasi::http::types::{IncomingRequest, ResponseOutparam};
253 | ///
254 | /// struct MyIncomingHandler;
255 | ///
256 | /// impl wasi::exports::http::incoming_handler::Guest for MyIncomingHandler {
257 | /// fn handle(request: IncomingRequest, response_out: ResponseOutparam) {
258 | /// // ...
259 | /// # panic!();
260 | /// }
261 | /// }
262 | ///
263 | /// wasi::http::proxy::export!(MyIncomingHandler);
264 | /// ```
265 | ///
266 | ///
270 | #[doc(inline)]
271 | pub use crate::proxy::_export_proxy as export;
272 | }
273 | }
274 |
275 | pub mod exports {
276 | // This is required by the `export!` macros of this crate which assume that
277 | // the types it's referring to show up as `exports::wasi::...`.
278 | //
279 | // This isn't part of the public interface, though, so hide this.
280 | #[doc(hidden)]
281 | pub mod wasi {
282 | pub use crate::command::exports::wasi::*;
283 | pub use crate::proxy::exports::wasi::*;
284 | }
285 |
286 | // These are the restructured public interface of this crate.
287 | pub use crate::command::exports::wasi::cli;
288 | pub use crate::proxy::exports::wasi::http;
289 | }
290 |
291 | // These macros are used by recursive invocations of the macro, but they're
292 | // `#[doc(hidden)]` as it's not part of the public interface.
293 | #[doc(hidden)]
294 | pub use crate::command::_export_command;
295 | #[doc(hidden)]
296 | pub use crate::proxy::_export_proxy;
297 |
--------------------------------------------------------------------------------
/wit/deps/cli/command.wit:
--------------------------------------------------------------------------------
1 | package wasi:cli@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world command {
5 | @since(version = 0.2.0)
6 | include imports;
7 |
8 | @since(version = 0.2.0)
9 | export run;
10 | }
11 |
--------------------------------------------------------------------------------
/wit/deps/cli/environment.wit:
--------------------------------------------------------------------------------
1 | @since(version = 0.2.0)
2 | interface environment {
3 | /// Get the POSIX-style environment variables.
4 | ///
5 | /// Each environment variable is provided as a pair of string variable names
6 | /// and string value.
7 | ///
8 | /// Morally, these are a value import, but until value imports are available
9 | /// in the component model, this import function should return the same
10 | /// values each time it is called.
11 | @since(version = 0.2.0)
12 | get-environment: func() -> list>;
13 |
14 | /// Get the POSIX-style arguments to the program.
15 | @since(version = 0.2.0)
16 | get-arguments: func() -> list;
17 |
18 | /// Return a path that programs should use as their initial current working
19 | /// directory, interpreting `.` as shorthand for this.
20 | @since(version = 0.2.0)
21 | initial-cwd: func() -> option;
22 | }
23 |
--------------------------------------------------------------------------------
/wit/deps/cli/exit.wit:
--------------------------------------------------------------------------------
1 | @since(version = 0.2.0)
2 | interface exit {
3 | /// Exit the current instance and any linked instances.
4 | @since(version = 0.2.0)
5 | exit: func(status: result);
6 |
7 | /// Exit the current instance and any linked instances, reporting the
8 | /// specified status code to the host.
9 | ///
10 | /// The meaning of the code depends on the context, with 0 usually meaning
11 | /// "success", and other values indicating various types of failure.
12 | ///
13 | /// This function does not return; the effect is analogous to a trap, but
14 | /// without the connotation that something bad has happened.
15 | @unstable(feature = cli-exit-with-code)
16 | exit-with-code: func(status-code: u8);
17 | }
18 |
--------------------------------------------------------------------------------
/wit/deps/cli/imports.wit:
--------------------------------------------------------------------------------
1 | package wasi:cli@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world imports {
5 | @since(version = 0.2.0)
6 | include wasi:clocks/imports@0.2.4;
7 | @since(version = 0.2.0)
8 | include wasi:filesystem/imports@0.2.4;
9 | @since(version = 0.2.0)
10 | include wasi:sockets/imports@0.2.4;
11 | @since(version = 0.2.0)
12 | include wasi:random/imports@0.2.4;
13 | @since(version = 0.2.0)
14 | include wasi:io/imports@0.2.4;
15 |
16 | @since(version = 0.2.0)
17 | import environment;
18 | @since(version = 0.2.0)
19 | import exit;
20 | @since(version = 0.2.0)
21 | import stdin;
22 | @since(version = 0.2.0)
23 | import stdout;
24 | @since(version = 0.2.0)
25 | import stderr;
26 | @since(version = 0.2.0)
27 | import terminal-input;
28 | @since(version = 0.2.0)
29 | import terminal-output;
30 | @since(version = 0.2.0)
31 | import terminal-stdin;
32 | @since(version = 0.2.0)
33 | import terminal-stdout;
34 | @since(version = 0.2.0)
35 | import terminal-stderr;
36 | }
37 |
--------------------------------------------------------------------------------
/wit/deps/cli/run.wit:
--------------------------------------------------------------------------------
1 | @since(version = 0.2.0)
2 | interface run {
3 | /// Run the program.
4 | @since(version = 0.2.0)
5 | run: func() -> result;
6 | }
7 |
--------------------------------------------------------------------------------
/wit/deps/cli/stdio.wit:
--------------------------------------------------------------------------------
1 | @since(version = 0.2.0)
2 | interface stdin {
3 | @since(version = 0.2.0)
4 | use wasi:io/streams@0.2.4.{input-stream};
5 |
6 | @since(version = 0.2.0)
7 | get-stdin: func() -> input-stream;
8 | }
9 |
10 | @since(version = 0.2.0)
11 | interface stdout {
12 | @since(version = 0.2.0)
13 | use wasi:io/streams@0.2.4.{output-stream};
14 |
15 | @since(version = 0.2.0)
16 | get-stdout: func() -> output-stream;
17 | }
18 |
19 | @since(version = 0.2.0)
20 | interface stderr {
21 | @since(version = 0.2.0)
22 | use wasi:io/streams@0.2.4.{output-stream};
23 |
24 | @since(version = 0.2.0)
25 | get-stderr: func() -> output-stream;
26 | }
27 |
--------------------------------------------------------------------------------
/wit/deps/cli/terminal.wit:
--------------------------------------------------------------------------------
1 | /// Terminal input.
2 | ///
3 | /// In the future, this may include functions for disabling echoing,
4 | /// disabling input buffering so that keyboard events are sent through
5 | /// immediately, querying supported features, and so on.
6 | @since(version = 0.2.0)
7 | interface terminal-input {
8 | /// The input side of a terminal.
9 | @since(version = 0.2.0)
10 | resource terminal-input;
11 | }
12 |
13 | /// Terminal output.
14 | ///
15 | /// In the future, this may include functions for querying the terminal
16 | /// size, being notified of terminal size changes, querying supported
17 | /// features, and so on.
18 | @since(version = 0.2.0)
19 | interface terminal-output {
20 | /// The output side of a terminal.
21 | @since(version = 0.2.0)
22 | resource terminal-output;
23 | }
24 |
25 | /// An interface providing an optional `terminal-input` for stdin as a
26 | /// link-time authority.
27 | @since(version = 0.2.0)
28 | interface terminal-stdin {
29 | @since(version = 0.2.0)
30 | use terminal-input.{terminal-input};
31 |
32 | /// If stdin is connected to a terminal, return a `terminal-input` handle
33 | /// allowing further interaction with it.
34 | @since(version = 0.2.0)
35 | get-terminal-stdin: func() -> option;
36 | }
37 |
38 | /// An interface providing an optional `terminal-output` for stdout as a
39 | /// link-time authority.
40 | @since(version = 0.2.0)
41 | interface terminal-stdout {
42 | @since(version = 0.2.0)
43 | use terminal-output.{terminal-output};
44 |
45 | /// If stdout is connected to a terminal, return a `terminal-output` handle
46 | /// allowing further interaction with it.
47 | @since(version = 0.2.0)
48 | get-terminal-stdout: func() -> option;
49 | }
50 |
51 | /// An interface providing an optional `terminal-output` for stderr as a
52 | /// link-time authority.
53 | @since(version = 0.2.0)
54 | interface terminal-stderr {
55 | @since(version = 0.2.0)
56 | use terminal-output.{terminal-output};
57 |
58 | /// If stderr is connected to a terminal, return a `terminal-output` handle
59 | /// allowing further interaction with it.
60 | @since(version = 0.2.0)
61 | get-terminal-stderr: func() -> option;
62 | }
63 |
--------------------------------------------------------------------------------
/wit/deps/clocks/monotonic-clock.wit:
--------------------------------------------------------------------------------
1 | package wasi:clocks@0.2.4;
2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed
3 | /// time.
4 | ///
5 | /// It is intended to be portable at least between Unix-family platforms and
6 | /// Windows.
7 | ///
8 | /// A monotonic clock is a clock which has an unspecified initial value, and
9 | /// successive reads of the clock will produce non-decreasing values.
10 | @since(version = 0.2.0)
11 | interface monotonic-clock {
12 | @since(version = 0.2.0)
13 | use wasi:io/poll@0.2.4.{pollable};
14 |
15 | /// An instant in time, in nanoseconds. An instant is relative to an
16 | /// unspecified initial value, and can only be compared to instances from
17 | /// the same monotonic-clock.
18 | @since(version = 0.2.0)
19 | type instant = u64;
20 |
21 | /// A duration of time, in nanoseconds.
22 | @since(version = 0.2.0)
23 | type duration = u64;
24 |
25 | /// Read the current value of the clock.
26 | ///
27 | /// The clock is monotonic, therefore calling this function repeatedly will
28 | /// produce a sequence of non-decreasing values.
29 | @since(version = 0.2.0)
30 | now: func() -> instant;
31 |
32 | /// Query the resolution of the clock. Returns the duration of time
33 | /// corresponding to a clock tick.
34 | @since(version = 0.2.0)
35 | resolution: func() -> duration;
36 |
37 | /// Create a `pollable` which will resolve once the specified instant
38 | /// has occurred.
39 | @since(version = 0.2.0)
40 | subscribe-instant: func(
41 | when: instant,
42 | ) -> pollable;
43 |
44 | /// Create a `pollable` that will resolve after the specified duration has
45 | /// elapsed from the time this function is invoked.
46 | @since(version = 0.2.0)
47 | subscribe-duration: func(
48 | when: duration,
49 | ) -> pollable;
50 | }
51 |
--------------------------------------------------------------------------------
/wit/deps/clocks/timezone.wit:
--------------------------------------------------------------------------------
1 | package wasi:clocks@0.2.4;
2 |
3 | @unstable(feature = clocks-timezone)
4 | interface timezone {
5 | @unstable(feature = clocks-timezone)
6 | use wall-clock.{datetime};
7 |
8 | /// Return information needed to display the given `datetime`. This includes
9 | /// the UTC offset, the time zone name, and a flag indicating whether
10 | /// daylight saving time is active.
11 | ///
12 | /// If the timezone cannot be determined for the given `datetime`, return a
13 | /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight
14 | /// saving time.
15 | @unstable(feature = clocks-timezone)
16 | display: func(when: datetime) -> timezone-display;
17 |
18 | /// The same as `display`, but only return the UTC offset.
19 | @unstable(feature = clocks-timezone)
20 | utc-offset: func(when: datetime) -> s32;
21 |
22 | /// Information useful for displaying the timezone of a specific `datetime`.
23 | ///
24 | /// This information may vary within a single `timezone` to reflect daylight
25 | /// saving time adjustments.
26 | @unstable(feature = clocks-timezone)
27 | record timezone-display {
28 | /// The number of seconds difference between UTC time and the local
29 | /// time of the timezone.
30 | ///
31 | /// The returned value will always be less than 86400 which is the
32 | /// number of seconds in a day (24*60*60).
33 | ///
34 | /// In implementations that do not expose an actual time zone, this
35 | /// should return 0.
36 | utc-offset: s32,
37 |
38 | /// The abbreviated name of the timezone to display to a user. The name
39 | /// `UTC` indicates Coordinated Universal Time. Otherwise, this should
40 | /// reference local standards for the name of the time zone.
41 | ///
42 | /// In implementations that do not expose an actual time zone, this
43 | /// should be the string `UTC`.
44 | ///
45 | /// In time zones that do not have an applicable name, a formatted
46 | /// representation of the UTC offset may be returned, such as `-04:00`.
47 | name: string,
48 |
49 | /// Whether daylight saving time is active.
50 | ///
51 | /// In implementations that do not expose an actual time zone, this
52 | /// should return false.
53 | in-daylight-saving-time: bool,
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/wit/deps/clocks/wall-clock.wit:
--------------------------------------------------------------------------------
1 | package wasi:clocks@0.2.4;
2 | /// WASI Wall Clock is a clock API intended to let users query the current
3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which
4 | /// is not necessarily monotonic as it may be reset.
5 | ///
6 | /// It is intended to be portable at least between Unix-family platforms and
7 | /// Windows.
8 | ///
9 | /// A wall clock is a clock which measures the date and time according to
10 | /// some external reference.
11 | ///
12 | /// External references may be reset, so this clock is not necessarily
13 | /// monotonic, making it unsuitable for measuring elapsed time.
14 | ///
15 | /// It is intended for reporting the current date and time for humans.
16 | @since(version = 0.2.0)
17 | interface wall-clock {
18 | /// A time and date in seconds plus nanoseconds.
19 | @since(version = 0.2.0)
20 | record datetime {
21 | seconds: u64,
22 | nanoseconds: u32,
23 | }
24 |
25 | /// Read the current value of the clock.
26 | ///
27 | /// This clock is not monotonic, therefore calling this function repeatedly
28 | /// will not necessarily produce a sequence of non-decreasing values.
29 | ///
30 | /// The returned timestamps represent the number of seconds since
31 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
32 | /// also known as [Unix Time].
33 | ///
34 | /// The nanoseconds field of the output is always less than 1000000000.
35 | ///
36 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
37 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
38 | @since(version = 0.2.0)
39 | now: func() -> datetime;
40 |
41 | /// Query the resolution of the clock.
42 | ///
43 | /// The nanoseconds field of the output is always less than 1000000000.
44 | @since(version = 0.2.0)
45 | resolution: func() -> datetime;
46 | }
47 |
--------------------------------------------------------------------------------
/wit/deps/clocks/world.wit:
--------------------------------------------------------------------------------
1 | package wasi:clocks@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world imports {
5 | @since(version = 0.2.0)
6 | import monotonic-clock;
7 | @since(version = 0.2.0)
8 | import wall-clock;
9 | @unstable(feature = clocks-timezone)
10 | import timezone;
11 | }
12 |
--------------------------------------------------------------------------------
/wit/deps/filesystem/preopens.wit:
--------------------------------------------------------------------------------
1 | package wasi:filesystem@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | interface preopens {
5 | @since(version = 0.2.0)
6 | use types.{descriptor};
7 |
8 | /// Return the set of preopened directories, and their paths.
9 | @since(version = 0.2.0)
10 | get-directories: func() -> list>;
11 | }
12 |
--------------------------------------------------------------------------------
/wit/deps/filesystem/world.wit:
--------------------------------------------------------------------------------
1 | package wasi:filesystem@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world imports {
5 | @since(version = 0.2.0)
6 | import types;
7 | @since(version = 0.2.0)
8 | import preopens;
9 | }
10 |
--------------------------------------------------------------------------------
/wit/deps/http/handler.wit:
--------------------------------------------------------------------------------
1 | /// This interface defines a handler of incoming HTTP Requests. It should
2 | /// be exported by components which can respond to HTTP Requests.
3 | @since(version = 0.2.0)
4 | interface incoming-handler {
5 | @since(version = 0.2.0)
6 | use types.{incoming-request, response-outparam};
7 |
8 | /// This function is invoked with an incoming HTTP Request, and a resource
9 | /// `response-outparam` which provides the capability to reply with an HTTP
10 | /// Response. The response is sent by calling the `response-outparam.set`
11 | /// method, which allows execution to continue after the response has been
12 | /// sent. This enables both streaming to the response body, and performing other
13 | /// work.
14 | ///
15 | /// The implementor of this function must write a response to the
16 | /// `response-outparam` before returning, or else the caller will respond
17 | /// with an error on its behalf.
18 | @since(version = 0.2.0)
19 | handle: func(
20 | request: incoming-request,
21 | response-out: response-outparam
22 | );
23 | }
24 |
25 | /// This interface defines a handler of outgoing HTTP Requests. It should be
26 | /// imported by components which wish to make HTTP Requests.
27 | @since(version = 0.2.0)
28 | interface outgoing-handler {
29 | @since(version = 0.2.0)
30 | use types.{
31 | outgoing-request, request-options, future-incoming-response, error-code
32 | };
33 |
34 | /// This function is invoked with an outgoing HTTP Request, and it returns
35 | /// a resource `future-incoming-response` which represents an HTTP Response
36 | /// which may arrive in the future.
37 | ///
38 | /// The `options` argument accepts optional parameters for the HTTP
39 | /// protocol's transport layer.
40 | ///
41 | /// This function may return an error if the `outgoing-request` is invalid
42 | /// or not allowed to be made. Otherwise, protocol errors are reported
43 | /// through the `future-incoming-response`.
44 | @since(version = 0.2.0)
45 | handle: func(
46 | request: outgoing-request,
47 | options: option
48 | ) -> result;
49 | }
50 |
--------------------------------------------------------------------------------
/wit/deps/http/proxy.wit:
--------------------------------------------------------------------------------
1 | package wasi:http@0.2.4;
2 |
3 | /// The `wasi:http/imports` world imports all the APIs for HTTP proxies.
4 | /// It is intended to be `include`d in other worlds.
5 | @since(version = 0.2.0)
6 | world imports {
7 | /// HTTP proxies have access to time and randomness.
8 | @since(version = 0.2.0)
9 | import wasi:clocks/monotonic-clock@0.2.4;
10 | @since(version = 0.2.0)
11 | import wasi:clocks/wall-clock@0.2.4;
12 | @since(version = 0.2.0)
13 | import wasi:random/random@0.2.4;
14 |
15 | /// Proxies have standard output and error streams which are expected to
16 | /// terminate in a developer-facing console provided by the host.
17 | @since(version = 0.2.0)
18 | import wasi:cli/stdout@0.2.4;
19 | @since(version = 0.2.0)
20 | import wasi:cli/stderr@0.2.4;
21 |
22 | /// TODO: this is a temporary workaround until component tooling is able to
23 | /// gracefully handle the absence of stdin. Hosts must return an eof stream
24 | /// for this import, which is what wasi-libc + tooling will do automatically
25 | /// when this import is properly removed.
26 | @since(version = 0.2.0)
27 | import wasi:cli/stdin@0.2.4;
28 |
29 | /// This is the default handler to use when user code simply wants to make an
30 | /// HTTP request (e.g., via `fetch()`).
31 | @since(version = 0.2.0)
32 | import outgoing-handler;
33 | }
34 |
35 | /// The `wasi:http/proxy` world captures a widely-implementable intersection of
36 | /// hosts that includes HTTP forward and reverse proxies. Components targeting
37 | /// this world may concurrently stream in and out any number of incoming and
38 | /// outgoing HTTP requests.
39 | @since(version = 0.2.0)
40 | world proxy {
41 | @since(version = 0.2.0)
42 | include imports;
43 |
44 | /// The host delivers incoming HTTP requests to a component by calling the
45 | /// `handle` function of this exported interface. A host may arbitrarily reuse
46 | /// or not reuse component instance when delivering incoming HTTP requests and
47 | /// thus a component must be able to handle 0..N calls to `handle`.
48 | @since(version = 0.2.0)
49 | export incoming-handler;
50 | }
51 |
--------------------------------------------------------------------------------
/wit/deps/http/types.wit:
--------------------------------------------------------------------------------
1 | /// This interface defines all of the types and methods for implementing
2 | /// HTTP Requests and Responses, both incoming and outgoing, as well as
3 | /// their headers, trailers, and bodies.
4 | @since(version = 0.2.0)
5 | interface types {
6 | @since(version = 0.2.0)
7 | use wasi:clocks/monotonic-clock@0.2.4.{duration};
8 | @since(version = 0.2.0)
9 | use wasi:io/streams@0.2.4.{input-stream, output-stream};
10 | @since(version = 0.2.0)
11 | use wasi:io/error@0.2.4.{error as io-error};
12 | @since(version = 0.2.0)
13 | use wasi:io/poll@0.2.4.{pollable};
14 |
15 | /// This type corresponds to HTTP standard Methods.
16 | @since(version = 0.2.0)
17 | variant method {
18 | get,
19 | head,
20 | post,
21 | put,
22 | delete,
23 | connect,
24 | options,
25 | trace,
26 | patch,
27 | other(string)
28 | }
29 |
30 | /// This type corresponds to HTTP standard Related Schemes.
31 | @since(version = 0.2.0)
32 | variant scheme {
33 | HTTP,
34 | HTTPS,
35 | other(string)
36 | }
37 |
38 | /// These cases are inspired by the IANA HTTP Proxy Error Types:
39 | ///
40 | @since(version = 0.2.0)
41 | variant error-code {
42 | DNS-timeout,
43 | DNS-error(DNS-error-payload),
44 | destination-not-found,
45 | destination-unavailable,
46 | destination-IP-prohibited,
47 | destination-IP-unroutable,
48 | connection-refused,
49 | connection-terminated,
50 | connection-timeout,
51 | connection-read-timeout,
52 | connection-write-timeout,
53 | connection-limit-reached,
54 | TLS-protocol-error,
55 | TLS-certificate-error,
56 | TLS-alert-received(TLS-alert-received-payload),
57 | HTTP-request-denied,
58 | HTTP-request-length-required,
59 | HTTP-request-body-size(option),
60 | HTTP-request-method-invalid,
61 | HTTP-request-URI-invalid,
62 | HTTP-request-URI-too-long,
63 | HTTP-request-header-section-size(option),
64 | HTTP-request-header-size(option),
65 | HTTP-request-trailer-section-size(option),
66 | HTTP-request-trailer-size(field-size-payload),
67 | HTTP-response-incomplete,
68 | HTTP-response-header-section-size(option),
69 | HTTP-response-header-size(field-size-payload),
70 | HTTP-response-body-size(option),
71 | HTTP-response-trailer-section-size(option),
72 | HTTP-response-trailer-size(field-size-payload),
73 | HTTP-response-transfer-coding(option),
74 | HTTP-response-content-coding(option),
75 | HTTP-response-timeout,
76 | HTTP-upgrade-failed,
77 | HTTP-protocol-error,
78 | loop-detected,
79 | configuration-error,
80 | /// This is a catch-all error for anything that doesn't fit cleanly into a
81 | /// more specific case. It also includes an optional string for an
82 | /// unstructured description of the error. Users should not depend on the
83 | /// string for diagnosing errors, as it's not required to be consistent
84 | /// between implementations.
85 | internal-error(option)
86 | }
87 |
88 | /// Defines the case payload type for `DNS-error` above:
89 | @since(version = 0.2.0)
90 | record DNS-error-payload {
91 | rcode: option,
92 | info-code: option
93 | }
94 |
95 | /// Defines the case payload type for `TLS-alert-received` above:
96 | @since(version = 0.2.0)
97 | record TLS-alert-received-payload {
98 | alert-id: option,
99 | alert-message: option
100 | }
101 |
102 | /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above:
103 | @since(version = 0.2.0)
104 | record field-size-payload {
105 | field-name: option,
106 | field-size: option
107 | }
108 |
109 | /// Attempts to extract a http-related `error` from the wasi:io `error`
110 | /// provided.
111 | ///
112 | /// Stream operations which return
113 | /// `wasi:io/stream/stream-error::last-operation-failed` have a payload of
114 | /// type `wasi:io/error/error` with more information about the operation
115 | /// that failed. This payload can be passed through to this function to see
116 | /// if there's http-related information about the error to return.
117 | ///
118 | /// Note that this function is fallible because not all io-errors are
119 | /// http-related errors.
120 | @since(version = 0.2.0)
121 | http-error-code: func(err: borrow) -> option;
122 |
123 | /// This type enumerates the different kinds of errors that may occur when
124 | /// setting or appending to a `fields` resource.
125 | @since(version = 0.2.0)
126 | variant header-error {
127 | /// This error indicates that a `field-name` or `field-value` was
128 | /// syntactically invalid when used with an operation that sets headers in a
129 | /// `fields`.
130 | invalid-syntax,
131 |
132 | /// This error indicates that a forbidden `field-name` was used when trying
133 | /// to set a header in a `fields`.
134 | forbidden,
135 |
136 | /// This error indicates that the operation on the `fields` was not
137 | /// permitted because the fields are immutable.
138 | immutable,
139 | }
140 |
141 | /// Field names are always strings.
142 | ///
143 | /// Field names should always be treated as case insensitive by the `fields`
144 | /// resource for the purposes of equality checking.
145 | @since(version = 0.2.1)
146 | type field-name = field-key;
147 |
148 | /// Field keys are always strings.
149 | ///
150 | /// Field keys should always be treated as case insensitive by the `fields`
151 | /// resource for the purposes of equality checking.
152 | ///
153 | /// # Deprecation
154 | ///
155 | /// This type has been deprecated in favor of the `field-name` type.
156 | @since(version = 0.2.0)
157 | @deprecated(version = 0.2.2)
158 | type field-key = string;
159 |
160 | /// Field values should always be ASCII strings. However, in
161 | /// reality, HTTP implementations often have to interpret malformed values,
162 | /// so they are provided as a list of bytes.
163 | @since(version = 0.2.0)
164 | type field-value = list;
165 |
166 | /// This following block defines the `fields` resource which corresponds to
167 | /// HTTP standard Fields. Fields are a common representation used for both
168 | /// Headers and Trailers.
169 | ///
170 | /// A `fields` may be mutable or immutable. A `fields` created using the
171 | /// constructor, `from-list`, or `clone` will be mutable, but a `fields`
172 | /// resource given by other means (including, but not limited to,
173 | /// `incoming-request.headers`, `outgoing-request.headers`) might be
174 | /// immutable. In an immutable fields, the `set`, `append`, and `delete`
175 | /// operations will fail with `header-error.immutable`.
176 | @since(version = 0.2.0)
177 | resource fields {
178 |
179 | /// Construct an empty HTTP Fields.
180 | ///
181 | /// The resulting `fields` is mutable.
182 | @since(version = 0.2.0)
183 | constructor();
184 |
185 | /// Construct an HTTP Fields.
186 | ///
187 | /// The resulting `fields` is mutable.
188 | ///
189 | /// The list represents each name-value pair in the Fields. Names
190 | /// which have multiple values are represented by multiple entries in this
191 | /// list with the same name.
192 | ///
193 | /// The tuple is a pair of the field name, represented as a string, and
194 | /// Value, represented as a list of bytes.
195 | ///
196 | /// An error result will be returned if any `field-name` or `field-value` is
197 | /// syntactically invalid, or if a field is forbidden.
198 | @since(version = 0.2.0)
199 | from-list: static func(
200 | entries: list>
201 | ) -> result;
202 |
203 | /// Get all of the values corresponding to a name. If the name is not present
204 | /// in this `fields` or is syntactically invalid, an empty list is returned.
205 | /// However, if the name is present but empty, this is represented by a list
206 | /// with one or more empty field-values present.
207 | @since(version = 0.2.0)
208 | get: func(name: field-name) -> list;
209 |
210 | /// Returns `true` when the name is present in this `fields`. If the name is
211 | /// syntactically invalid, `false` is returned.
212 | @since(version = 0.2.0)
213 | has: func(name: field-name) -> bool;
214 |
215 | /// Set all of the values for a name. Clears any existing values for that
216 | /// name, if they have been set.
217 | ///
218 | /// Fails with `header-error.immutable` if the `fields` are immutable.
219 | ///
220 | /// Fails with `header-error.invalid-syntax` if the `field-name` or any of
221 | /// the `field-value`s are syntactically invalid.
222 | @since(version = 0.2.0)
223 | set: func(name: field-name, value: list) -> result<_, header-error>;
224 |
225 | /// Delete all values for a name. Does nothing if no values for the name
226 | /// exist.
227 | ///
228 | /// Fails with `header-error.immutable` if the `fields` are immutable.
229 | ///
230 | /// Fails with `header-error.invalid-syntax` if the `field-name` is
231 | /// syntactically invalid.
232 | @since(version = 0.2.0)
233 | delete: func(name: field-name) -> result<_, header-error>;
234 |
235 | /// Append a value for a name. Does not change or delete any existing
236 | /// values for that name.
237 | ///
238 | /// Fails with `header-error.immutable` if the `fields` are immutable.
239 | ///
240 | /// Fails with `header-error.invalid-syntax` if the `field-name` or
241 | /// `field-value` are syntactically invalid.
242 | @since(version = 0.2.0)
243 | append: func(name: field-name, value: field-value) -> result<_, header-error>;
244 |
245 | /// Retrieve the full set of names and values in the Fields. Like the
246 | /// constructor, the list represents each name-value pair.
247 | ///
248 | /// The outer list represents each name-value pair in the Fields. Names
249 | /// which have multiple values are represented by multiple entries in this
250 | /// list with the same name.
251 | ///
252 | /// The names and values are always returned in the original casing and in
253 | /// the order in which they will be serialized for transport.
254 | @since(version = 0.2.0)
255 | entries: func() -> list>;
256 |
257 | /// Make a deep copy of the Fields. Equivalent in behavior to calling the
258 | /// `fields` constructor on the return value of `entries`. The resulting
259 | /// `fields` is mutable.
260 | @since(version = 0.2.0)
261 | clone: func() -> fields;
262 | }
263 |
264 | /// Headers is an alias for Fields.
265 | @since(version = 0.2.0)
266 | type headers = fields;
267 |
268 | /// Trailers is an alias for Fields.
269 | @since(version = 0.2.0)
270 | type trailers = fields;
271 |
272 | /// Represents an incoming HTTP Request.
273 | @since(version = 0.2.0)
274 | resource incoming-request {
275 |
276 | /// Returns the method of the incoming request.
277 | @since(version = 0.2.0)
278 | method: func() -> method;
279 |
280 | /// Returns the path with query parameters from the request, as a string.
281 | @since(version = 0.2.0)
282 | path-with-query: func() -> option;
283 |
284 | /// Returns the protocol scheme from the request.
285 | @since(version = 0.2.0)
286 | scheme: func() -> option;
287 |
288 | /// Returns the authority of the Request's target URI, if present.
289 | @since(version = 0.2.0)
290 | authority: func() -> option;
291 |
292 | /// Get the `headers` associated with the request.
293 | ///
294 | /// The returned `headers` resource is immutable: `set`, `append`, and
295 | /// `delete` operations will fail with `header-error.immutable`.
296 | ///
297 | /// The `headers` returned are a child resource: it must be dropped before
298 | /// the parent `incoming-request` is dropped. Dropping this
299 | /// `incoming-request` before all children are dropped will trap.
300 | @since(version = 0.2.0)
301 | headers: func() -> headers;
302 |
303 | /// Gives the `incoming-body` associated with this request. Will only
304 | /// return success at most once, and subsequent calls will return error.
305 | @since(version = 0.2.0)
306 | consume: func() -> result;
307 | }
308 |
309 | /// Represents an outgoing HTTP Request.
310 | @since(version = 0.2.0)
311 | resource outgoing-request {
312 |
313 | /// Construct a new `outgoing-request` with a default `method` of `GET`, and
314 | /// `none` values for `path-with-query`, `scheme`, and `authority`.
315 | ///
316 | /// * `headers` is the HTTP Headers for the Request.
317 | ///
318 | /// It is possible to construct, or manipulate with the accessor functions
319 | /// below, an `outgoing-request` with an invalid combination of `scheme`
320 | /// and `authority`, or `headers` which are not permitted to be sent.
321 | /// It is the obligation of the `outgoing-handler.handle` implementation
322 | /// to reject invalid constructions of `outgoing-request`.
323 | @since(version = 0.2.0)
324 | constructor(
325 | headers: headers
326 | );
327 |
328 | /// Returns the resource corresponding to the outgoing Body for this
329 | /// Request.
330 | ///
331 | /// Returns success on the first call: the `outgoing-body` resource for
332 | /// this `outgoing-request` can be retrieved at most once. Subsequent
333 | /// calls will return error.
334 | @since(version = 0.2.0)
335 | body: func() -> result;
336 |
337 | /// Get the Method for the Request.
338 | @since(version = 0.2.0)
339 | method: func() -> method;
340 | /// Set the Method for the Request. Fails if the string present in a
341 | /// `method.other` argument is not a syntactically valid method.
342 | @since(version = 0.2.0)
343 | set-method: func(method: method) -> result;
344 |
345 | /// Get the combination of the HTTP Path and Query for the Request.
346 | /// When `none`, this represents an empty Path and empty Query.
347 | @since(version = 0.2.0)
348 | path-with-query: func() -> option;
349 | /// Set the combination of the HTTP Path and Query for the Request.
350 | /// When `none`, this represents an empty Path and empty Query. Fails is the
351 | /// string given is not a syntactically valid path and query uri component.
352 | @since(version = 0.2.0)
353 | set-path-with-query: func(path-with-query: option) -> result;
354 |
355 | /// Get the HTTP Related Scheme for the Request. When `none`, the
356 | /// implementation may choose an appropriate default scheme.
357 | @since(version = 0.2.0)
358 | scheme: func() -> option;
359 | /// Set the HTTP Related Scheme for the Request. When `none`, the
360 | /// implementation may choose an appropriate default scheme. Fails if the
361 | /// string given is not a syntactically valid uri scheme.
362 | @since(version = 0.2.0)
363 | set-scheme: func(scheme: option) -> result;
364 |
365 | /// Get the authority of the Request's target URI. A value of `none` may be used
366 | /// with Related Schemes which do not require an authority. The HTTP and
367 | /// HTTPS schemes always require an authority.
368 | @since(version = 0.2.0)
369 | authority: func() -> option;
370 | /// Set the authority of the Request's target URI. A value of `none` may be used
371 | /// with Related Schemes which do not require an authority. The HTTP and
372 | /// HTTPS schemes always require an authority. Fails if the string given is
373 | /// not a syntactically valid URI authority.
374 | @since(version = 0.2.0)
375 | set-authority: func(authority: option) -> result;
376 |
377 | /// Get the headers associated with the Request.
378 | ///
379 | /// The returned `headers` resource is immutable: `set`, `append`, and
380 | /// `delete` operations will fail with `header-error.immutable`.
381 | ///
382 | /// This headers resource is a child: it must be dropped before the parent
383 | /// `outgoing-request` is dropped, or its ownership is transferred to
384 | /// another component by e.g. `outgoing-handler.handle`.
385 | @since(version = 0.2.0)
386 | headers: func() -> headers;
387 | }
388 |
389 | /// Parameters for making an HTTP Request. Each of these parameters is
390 | /// currently an optional timeout applicable to the transport layer of the
391 | /// HTTP protocol.
392 | ///
393 | /// These timeouts are separate from any the user may use to bound a
394 | /// blocking call to `wasi:io/poll.poll`.
395 | @since(version = 0.2.0)
396 | resource request-options {
397 | /// Construct a default `request-options` value.
398 | @since(version = 0.2.0)
399 | constructor();
400 |
401 | /// The timeout for the initial connect to the HTTP Server.
402 | @since(version = 0.2.0)
403 | connect-timeout: func() -> option;
404 |
405 | /// Set the timeout for the initial connect to the HTTP Server. An error
406 | /// return value indicates that this timeout is not supported.
407 | @since(version = 0.2.0)
408 | set-connect-timeout: func(duration: option) -> result;
409 |
410 | /// The timeout for receiving the first byte of the Response body.
411 | @since(version = 0.2.0)
412 | first-byte-timeout: func() -> option;
413 |
414 | /// Set the timeout for receiving the first byte of the Response body. An
415 | /// error return value indicates that this timeout is not supported.
416 | @since(version = 0.2.0)
417 | set-first-byte-timeout: func(duration: option) -> result;
418 |
419 | /// The timeout for receiving subsequent chunks of bytes in the Response
420 | /// body stream.
421 | @since(version = 0.2.0)
422 | between-bytes-timeout: func() -> option;
423 |
424 | /// Set the timeout for receiving subsequent chunks of bytes in the Response
425 | /// body stream. An error return value indicates that this timeout is not
426 | /// supported.
427 | @since(version = 0.2.0)
428 | set-between-bytes-timeout: func(duration: option) -> result;
429 | }
430 |
431 | /// Represents the ability to send an HTTP Response.
432 | ///
433 | /// This resource is used by the `wasi:http/incoming-handler` interface to
434 | /// allow a Response to be sent corresponding to the Request provided as the
435 | /// other argument to `incoming-handler.handle`.
436 | @since(version = 0.2.0)
437 | resource response-outparam {
438 | /// Send an HTTP 1xx response.
439 | ///
440 | /// Unlike `response-outparam.set`, this does not consume the
441 | /// `response-outparam`, allowing the guest to send an arbitrary number of
442 | /// informational responses before sending the final response using
443 | /// `response-outparam.set`.
444 | ///
445 | /// This will return an `HTTP-protocol-error` if `status` is not in the
446 | /// range [100-199], or an `internal-error` if the implementation does not
447 | /// support informational responses.
448 | @unstable(feature = informational-outbound-responses)
449 | send-informational: func(
450 | status: u16,
451 | headers: headers
452 | ) -> result<_, error-code>;
453 |
454 | /// Set the value of the `response-outparam` to either send a response,
455 | /// or indicate an error.
456 | ///
457 | /// This method consumes the `response-outparam` to ensure that it is
458 | /// called at most once. If it is never called, the implementation
459 | /// will respond with an error.
460 | ///
461 | /// The user may provide an `error` to `response` to allow the
462 | /// implementation determine how to respond with an HTTP error response.
463 | @since(version = 0.2.0)
464 | set: static func(
465 | param: response-outparam,
466 | response: result,
467 | );
468 | }
469 |
470 | /// This type corresponds to the HTTP standard Status Code.
471 | @since(version = 0.2.0)
472 | type status-code = u16;
473 |
474 | /// Represents an incoming HTTP Response.
475 | @since(version = 0.2.0)
476 | resource incoming-response {
477 |
478 | /// Returns the status code from the incoming response.
479 | @since(version = 0.2.0)
480 | status: func() -> status-code;
481 |
482 | /// Returns the headers from the incoming response.
483 | ///
484 | /// The returned `headers` resource is immutable: `set`, `append`, and
485 | /// `delete` operations will fail with `header-error.immutable`.
486 | ///
487 | /// This headers resource is a child: it must be dropped before the parent
488 | /// `incoming-response` is dropped.
489 | @since(version = 0.2.0)
490 | headers: func() -> headers;
491 |
492 | /// Returns the incoming body. May be called at most once. Returns error
493 | /// if called additional times.
494 | @since(version = 0.2.0)
495 | consume: func() -> result;
496 | }
497 |
498 | /// Represents an incoming HTTP Request or Response's Body.
499 | ///
500 | /// A body has both its contents - a stream of bytes - and a (possibly
501 | /// empty) set of trailers, indicating that the full contents of the
502 | /// body have been received. This resource represents the contents as
503 | /// an `input-stream` and the delivery of trailers as a `future-trailers`,
504 | /// and ensures that the user of this interface may only be consuming either
505 | /// the body contents or waiting on trailers at any given time.
506 | @since(version = 0.2.0)
507 | resource incoming-body {
508 |
509 | /// Returns the contents of the body, as a stream of bytes.
510 | ///
511 | /// Returns success on first call: the stream representing the contents
512 | /// can be retrieved at most once. Subsequent calls will return error.
513 | ///
514 | /// The returned `input-stream` resource is a child: it must be dropped
515 | /// before the parent `incoming-body` is dropped, or consumed by
516 | /// `incoming-body.finish`.
517 | ///
518 | /// This invariant ensures that the implementation can determine whether
519 | /// the user is consuming the contents of the body, waiting on the
520 | /// `future-trailers` to be ready, or neither. This allows for network
521 | /// backpressure is to be applied when the user is consuming the body,
522 | /// and for that backpressure to not inhibit delivery of the trailers if
523 | /// the user does not read the entire body.
524 | @since(version = 0.2.0)
525 | %stream: func() -> result;
526 |
527 | /// Takes ownership of `incoming-body`, and returns a `future-trailers`.
528 | /// This function will trap if the `input-stream` child is still alive.
529 | @since(version = 0.2.0)
530 | finish: static func(this: incoming-body) -> future-trailers;
531 | }
532 |
533 | /// Represents a future which may eventually return trailers, or an error.
534 | ///
535 | /// In the case that the incoming HTTP Request or Response did not have any
536 | /// trailers, this future will resolve to the empty set of trailers once the
537 | /// complete Request or Response body has been received.
538 | @since(version = 0.2.0)
539 | resource future-trailers {
540 |
541 | /// Returns a pollable which becomes ready when either the trailers have
542 | /// been received, or an error has occurred. When this pollable is ready,
543 | /// the `get` method will return `some`.
544 | @since(version = 0.2.0)
545 | subscribe: func() -> pollable;
546 |
547 | /// Returns the contents of the trailers, or an error which occurred,
548 | /// once the future is ready.
549 | ///
550 | /// The outer `option` represents future readiness. Users can wait on this
551 | /// `option` to become `some` using the `subscribe` method.
552 | ///
553 | /// The outer `result` is used to retrieve the trailers or error at most
554 | /// once. It will be success on the first call in which the outer option
555 | /// is `some`, and error on subsequent calls.
556 | ///
557 | /// The inner `result` represents that either the HTTP Request or Response
558 | /// body, as well as any trailers, were received successfully, or that an
559 | /// error occurred receiving them. The optional `trailers` indicates whether
560 | /// or not trailers were present in the body.
561 | ///
562 | /// When some `trailers` are returned by this method, the `trailers`
563 | /// resource is immutable, and a child. Use of the `set`, `append`, or
564 | /// `delete` methods will return an error, and the resource must be
565 | /// dropped before the parent `future-trailers` is dropped.
566 | @since(version = 0.2.0)
567 | get: func() -> option, error-code>>>;
568 | }
569 |
570 | /// Represents an outgoing HTTP Response.
571 | @since(version = 0.2.0)
572 | resource outgoing-response {
573 |
574 | /// Construct an `outgoing-response`, with a default `status-code` of `200`.
575 | /// If a different `status-code` is needed, it must be set via the
576 | /// `set-status-code` method.
577 | ///
578 | /// * `headers` is the HTTP Headers for the Response.
579 | @since(version = 0.2.0)
580 | constructor(headers: headers);
581 |
582 | /// Get the HTTP Status Code for the Response.
583 | @since(version = 0.2.0)
584 | status-code: func() -> status-code;
585 |
586 | /// Set the HTTP Status Code for the Response. Fails if the status-code
587 | /// given is not a valid http status code.
588 | @since(version = 0.2.0)
589 | set-status-code: func(status-code: status-code) -> result;
590 |
591 | /// Get the headers associated with the Request.
592 | ///
593 | /// The returned `headers` resource is immutable: `set`, `append`, and
594 | /// `delete` operations will fail with `header-error.immutable`.
595 | ///
596 | /// This headers resource is a child: it must be dropped before the parent
597 | /// `outgoing-request` is dropped, or its ownership is transferred to
598 | /// another component by e.g. `outgoing-handler.handle`.
599 | @since(version = 0.2.0)
600 | headers: func() -> headers;
601 |
602 | /// Returns the resource corresponding to the outgoing Body for this Response.
603 | ///
604 | /// Returns success on the first call: the `outgoing-body` resource for
605 | /// this `outgoing-response` can be retrieved at most once. Subsequent
606 | /// calls will return error.
607 | @since(version = 0.2.0)
608 | body: func() -> result;
609 | }
610 |
611 | /// Represents an outgoing HTTP Request or Response's Body.
612 | ///
613 | /// A body has both its contents - a stream of bytes - and a (possibly
614 | /// empty) set of trailers, inducating the full contents of the body
615 | /// have been sent. This resource represents the contents as an
616 | /// `output-stream` child resource, and the completion of the body (with
617 | /// optional trailers) with a static function that consumes the
618 | /// `outgoing-body` resource, and ensures that the user of this interface
619 | /// may not write to the body contents after the body has been finished.
620 | ///
621 | /// If the user code drops this resource, as opposed to calling the static
622 | /// method `finish`, the implementation should treat the body as incomplete,
623 | /// and that an error has occurred. The implementation should propagate this
624 | /// error to the HTTP protocol by whatever means it has available,
625 | /// including: corrupting the body on the wire, aborting the associated
626 | /// Request, or sending a late status code for the Response.
627 | @since(version = 0.2.0)
628 | resource outgoing-body {
629 |
630 | /// Returns a stream for writing the body contents.
631 | ///
632 | /// The returned `output-stream` is a child resource: it must be dropped
633 | /// before the parent `outgoing-body` resource is dropped (or finished),
634 | /// otherwise the `outgoing-body` drop or `finish` will trap.
635 | ///
636 | /// Returns success on the first call: the `output-stream` resource for
637 | /// this `outgoing-body` may be retrieved at most once. Subsequent calls
638 | /// will return error.
639 | @since(version = 0.2.0)
640 | write: func() -> result;
641 |
642 | /// Finalize an outgoing body, optionally providing trailers. This must be
643 | /// called to signal that the response is complete. If the `outgoing-body`
644 | /// is dropped without calling `outgoing-body.finalize`, the implementation
645 | /// should treat the body as corrupted.
646 | ///
647 | /// Fails if the body's `outgoing-request` or `outgoing-response` was
648 | /// constructed with a Content-Length header, and the contents written
649 | /// to the body (via `write`) does not match the value given in the
650 | /// Content-Length.
651 | @since(version = 0.2.0)
652 | finish: static func(
653 | this: outgoing-body,
654 | trailers: option
655 | ) -> result<_, error-code>;
656 | }
657 |
658 | /// Represents a future which may eventually return an incoming HTTP
659 | /// Response, or an error.
660 | ///
661 | /// This resource is returned by the `wasi:http/outgoing-handler` interface to
662 | /// provide the HTTP Response corresponding to the sent Request.
663 | @since(version = 0.2.0)
664 | resource future-incoming-response {
665 | /// Returns a pollable which becomes ready when either the Response has
666 | /// been received, or an error has occurred. When this pollable is ready,
667 | /// the `get` method will return `some`.
668 | @since(version = 0.2.0)
669 | subscribe: func() -> pollable;
670 |
671 | /// Returns the incoming HTTP Response, or an error, once one is ready.
672 | ///
673 | /// The outer `option` represents future readiness. Users can wait on this
674 | /// `option` to become `some` using the `subscribe` method.
675 | ///
676 | /// The outer `result` is used to retrieve the response or error at most
677 | /// once. It will be success on the first call in which the outer option
678 | /// is `some`, and error on subsequent calls.
679 | ///
680 | /// The inner `result` represents that either the incoming HTTP Response
681 | /// status and headers have received successfully, or that an error
682 | /// occurred. Errors may also occur while consuming the response body,
683 | /// but those will be reported by the `incoming-body` and its
684 | /// `output-stream` child.
685 | @since(version = 0.2.0)
686 | get: func() -> option>>;
687 | }
688 | }
689 |
--------------------------------------------------------------------------------
/wit/deps/io/error.wit:
--------------------------------------------------------------------------------
1 | package wasi:io@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | interface error {
5 | /// A resource which represents some error information.
6 | ///
7 | /// The only method provided by this resource is `to-debug-string`,
8 | /// which provides some human-readable information about the error.
9 | ///
10 | /// In the `wasi:io` package, this resource is returned through the
11 | /// `wasi:io/streams/stream-error` type.
12 | ///
13 | /// To provide more specific error information, other interfaces may
14 | /// offer functions to "downcast" this error into more specific types. For example,
15 | /// errors returned from streams derived from filesystem types can be described using
16 | /// the filesystem's own error-code type. This is done using the function
17 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow`
18 | /// parameter and returns an `option`.
19 | ///
20 | /// The set of functions which can "downcast" an `error` into a more
21 | /// concrete type is open.
22 | @since(version = 0.2.0)
23 | resource error {
24 | /// Returns a string that is suitable to assist humans in debugging
25 | /// this error.
26 | ///
27 | /// WARNING: The returned string should not be consumed mechanically!
28 | /// It may change across platforms, hosts, or other implementation
29 | /// details. Parsing this string is a major platform-compatibility
30 | /// hazard.
31 | @since(version = 0.2.0)
32 | to-debug-string: func() -> string;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/wit/deps/io/poll.wit:
--------------------------------------------------------------------------------
1 | package wasi:io@0.2.4;
2 |
3 | /// A poll API intended to let users wait for I/O events on multiple handles
4 | /// at once.
5 | @since(version = 0.2.0)
6 | interface poll {
7 | /// `pollable` represents a single I/O event which may be ready, or not.
8 | @since(version = 0.2.0)
9 | resource pollable {
10 |
11 | /// Return the readiness of a pollable. This function never blocks.
12 | ///
13 | /// Returns `true` when the pollable is ready, and `false` otherwise.
14 | @since(version = 0.2.0)
15 | ready: func() -> bool;
16 |
17 | /// `block` returns immediately if the pollable is ready, and otherwise
18 | /// blocks until ready.
19 | ///
20 | /// This function is equivalent to calling `poll.poll` on a list
21 | /// containing only this pollable.
22 | @since(version = 0.2.0)
23 | block: func();
24 | }
25 |
26 | /// Poll for completion on a set of pollables.
27 | ///
28 | /// This function takes a list of pollables, which identify I/O sources of
29 | /// interest, and waits until one or more of the events is ready for I/O.
30 | ///
31 | /// The result `list` contains one or more indices of handles in the
32 | /// argument list that is ready for I/O.
33 | ///
34 | /// This function traps if either:
35 | /// - the list is empty, or:
36 | /// - the list contains more elements than can be indexed with a `u32` value.
37 | ///
38 | /// A timeout can be implemented by adding a pollable from the
39 | /// wasi-clocks API to the list.
40 | ///
41 | /// This function does not return a `result`; polling in itself does not
42 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by
43 | /// the pollables has an error, it is indicated by marking the source as
44 | /// being ready for I/O.
45 | @since(version = 0.2.0)
46 | poll: func(in: list>) -> list;
47 | }
48 |
--------------------------------------------------------------------------------
/wit/deps/io/streams.wit:
--------------------------------------------------------------------------------
1 | package wasi:io@0.2.4;
2 |
3 | /// WASI I/O is an I/O abstraction API which is currently focused on providing
4 | /// stream types.
5 | ///
6 | /// In the future, the component model is expected to add built-in stream types;
7 | /// when it does, they are expected to subsume this API.
8 | @since(version = 0.2.0)
9 | interface streams {
10 | @since(version = 0.2.0)
11 | use error.{error};
12 | @since(version = 0.2.0)
13 | use poll.{pollable};
14 |
15 | /// An error for input-stream and output-stream operations.
16 | @since(version = 0.2.0)
17 | variant stream-error {
18 | /// The last operation (a write or flush) failed before completion.
19 | ///
20 | /// More information is available in the `error` payload.
21 | ///
22 | /// After this, the stream will be closed. All future operations return
23 | /// `stream-error::closed`.
24 | last-operation-failed(error),
25 | /// The stream is closed: no more input will be accepted by the
26 | /// stream. A closed output-stream will return this error on all
27 | /// future operations.
28 | closed
29 | }
30 |
31 | /// An input bytestream.
32 | ///
33 | /// `input-stream`s are *non-blocking* to the extent practical on underlying
34 | /// platforms. I/O operations always return promptly; if fewer bytes are
35 | /// promptly available than requested, they return the number of bytes promptly
36 | /// available, which could even be zero. To wait for data to be available,
37 | /// use the `subscribe` function to obtain a `pollable` which can be polled
38 | /// for using `wasi:io/poll`.
39 | @since(version = 0.2.0)
40 | resource input-stream {
41 | /// Perform a non-blocking read from the stream.
42 | ///
43 | /// When the source of a `read` is binary data, the bytes from the source
44 | /// are returned verbatim. When the source of a `read` is known to the
45 | /// implementation to be text, bytes containing the UTF-8 encoding of the
46 | /// text are returned.
47 | ///
48 | /// This function returns a list of bytes containing the read data,
49 | /// when successful. The returned list will contain up to `len` bytes;
50 | /// it may return fewer than requested, but not more. The list is
51 | /// empty when no bytes are available for reading at this time. The
52 | /// pollable given by `subscribe` will be ready when more bytes are
53 | /// available.
54 | ///
55 | /// This function fails with a `stream-error` when the operation
56 | /// encounters an error, giving `last-operation-failed`, or when the
57 | /// stream is closed, giving `closed`.
58 | ///
59 | /// When the caller gives a `len` of 0, it represents a request to
60 | /// read 0 bytes. If the stream is still open, this call should
61 | /// succeed and return an empty list, or otherwise fail with `closed`.
62 | ///
63 | /// The `len` parameter is a `u64`, which could represent a list of u8 which
64 | /// is not possible to allocate in wasm32, or not desirable to allocate as
65 | /// as a return value by the callee. The callee may return a list of bytes
66 | /// less than `len` in size while more bytes are available for reading.
67 | @since(version = 0.2.0)
68 | read: func(
69 | /// The maximum number of bytes to read
70 | len: u64
71 | ) -> result, stream-error>;
72 |
73 | /// Read bytes from a stream, after blocking until at least one byte can
74 | /// be read. Except for blocking, behavior is identical to `read`.
75 | @since(version = 0.2.0)
76 | blocking-read: func(
77 | /// The maximum number of bytes to read
78 | len: u64
79 | ) -> result, stream-error>;
80 |
81 | /// Skip bytes from a stream. Returns number of bytes skipped.
82 | ///
83 | /// Behaves identical to `read`, except instead of returning a list
84 | /// of bytes, returns the number of bytes consumed from the stream.
85 | @since(version = 0.2.0)
86 | skip: func(
87 | /// The maximum number of bytes to skip.
88 | len: u64,
89 | ) -> result;
90 |
91 | /// Skip bytes from a stream, after blocking until at least one byte
92 | /// can be skipped. Except for blocking behavior, identical to `skip`.
93 | @since(version = 0.2.0)
94 | blocking-skip: func(
95 | /// The maximum number of bytes to skip.
96 | len: u64,
97 | ) -> result;
98 |
99 | /// Create a `pollable` which will resolve once either the specified stream
100 | /// has bytes available to read or the other end of the stream has been
101 | /// closed.
102 | /// The created `pollable` is a child resource of the `input-stream`.
103 | /// Implementations may trap if the `input-stream` is dropped before
104 | /// all derived `pollable`s created with this function are dropped.
105 | @since(version = 0.2.0)
106 | subscribe: func() -> pollable;
107 | }
108 |
109 |
110 | /// An output bytestream.
111 | ///
112 | /// `output-stream`s are *non-blocking* to the extent practical on
113 | /// underlying platforms. Except where specified otherwise, I/O operations also
114 | /// always return promptly, after the number of bytes that can be written
115 | /// promptly, which could even be zero. To wait for the stream to be ready to
116 | /// accept data, the `subscribe` function to obtain a `pollable` which can be
117 | /// polled for using `wasi:io/poll`.
118 | ///
119 | /// Dropping an `output-stream` while there's still an active write in
120 | /// progress may result in the data being lost. Before dropping the stream,
121 | /// be sure to fully flush your writes.
122 | @since(version = 0.2.0)
123 | resource output-stream {
124 | /// Check readiness for writing. This function never blocks.
125 | ///
126 | /// Returns the number of bytes permitted for the next call to `write`,
127 | /// or an error. Calling `write` with more bytes than this function has
128 | /// permitted will trap.
129 | ///
130 | /// When this function returns 0 bytes, the `subscribe` pollable will
131 | /// become ready when this function will report at least 1 byte, or an
132 | /// error.
133 | @since(version = 0.2.0)
134 | check-write: func() -> result;
135 |
136 | /// Perform a write. This function never blocks.
137 | ///
138 | /// When the destination of a `write` is binary data, the bytes from
139 | /// `contents` are written verbatim. When the destination of a `write` is
140 | /// known to the implementation to be text, the bytes of `contents` are
141 | /// transcoded from UTF-8 into the encoding of the destination and then
142 | /// written.
143 | ///
144 | /// Precondition: check-write gave permit of Ok(n) and contents has a
145 | /// length of less than or equal to n. Otherwise, this function will trap.
146 | ///
147 | /// returns Err(closed) without writing if the stream has closed since
148 | /// the last call to check-write provided a permit.
149 | @since(version = 0.2.0)
150 | write: func(
151 | contents: list
152 | ) -> result<_, stream-error>;
153 |
154 | /// Perform a write of up to 4096 bytes, and then flush the stream. Block
155 | /// until all of these operations are complete, or an error occurs.
156 | ///
157 | /// This is a convenience wrapper around the use of `check-write`,
158 | /// `subscribe`, `write`, and `flush`, and is implemented with the
159 | /// following pseudo-code:
160 | ///
161 | /// ```text
162 | /// let pollable = this.subscribe();
163 | /// while !contents.is_empty() {
164 | /// // Wait for the stream to become writable
165 | /// pollable.block();
166 | /// let Ok(n) = this.check-write(); // eliding error handling
167 | /// let len = min(n, contents.len());
168 | /// let (chunk, rest) = contents.split_at(len);
169 | /// this.write(chunk ); // eliding error handling
170 | /// contents = rest;
171 | /// }
172 | /// this.flush();
173 | /// // Wait for completion of `flush`
174 | /// pollable.block();
175 | /// // Check for any errors that arose during `flush`
176 | /// let _ = this.check-write(); // eliding error handling
177 | /// ```
178 | @since(version = 0.2.0)
179 | blocking-write-and-flush: func(
180 | contents: list
181 | ) -> result<_, stream-error>;
182 |
183 | /// Request to flush buffered output. This function never blocks.
184 | ///
185 | /// This tells the output-stream that the caller intends any buffered
186 | /// output to be flushed. the output which is expected to be flushed
187 | /// is all that has been passed to `write` prior to this call.
188 | ///
189 | /// Upon calling this function, the `output-stream` will not accept any
190 | /// writes (`check-write` will return `ok(0)`) until the flush has
191 | /// completed. The `subscribe` pollable will become ready when the
192 | /// flush has completed and the stream can accept more writes.
193 | @since(version = 0.2.0)
194 | flush: func() -> result<_, stream-error>;
195 |
196 | /// Request to flush buffered output, and block until flush completes
197 | /// and stream is ready for writing again.
198 | @since(version = 0.2.0)
199 | blocking-flush: func() -> result<_, stream-error>;
200 |
201 | /// Create a `pollable` which will resolve once the output-stream
202 | /// is ready for more writing, or an error has occurred. When this
203 | /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an
204 | /// error.
205 | ///
206 | /// If the stream is closed, this pollable is always ready immediately.
207 | ///
208 | /// The created `pollable` is a child resource of the `output-stream`.
209 | /// Implementations may trap if the `output-stream` is dropped before
210 | /// all derived `pollable`s created with this function are dropped.
211 | @since(version = 0.2.0)
212 | subscribe: func() -> pollable;
213 |
214 | /// Write zeroes to a stream.
215 | ///
216 | /// This should be used precisely like `write` with the exact same
217 | /// preconditions (must use check-write first), but instead of
218 | /// passing a list of bytes, you simply pass the number of zero-bytes
219 | /// that should be written.
220 | @since(version = 0.2.0)
221 | write-zeroes: func(
222 | /// The number of zero-bytes to write
223 | len: u64
224 | ) -> result<_, stream-error>;
225 |
226 | /// Perform a write of up to 4096 zeroes, and then flush the stream.
227 | /// Block until all of these operations are complete, or an error
228 | /// occurs.
229 | ///
230 | /// This is a convenience wrapper around the use of `check-write`,
231 | /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with
232 | /// the following pseudo-code:
233 | ///
234 | /// ```text
235 | /// let pollable = this.subscribe();
236 | /// while num_zeroes != 0 {
237 | /// // Wait for the stream to become writable
238 | /// pollable.block();
239 | /// let Ok(n) = this.check-write(); // eliding error handling
240 | /// let len = min(n, num_zeroes);
241 | /// this.write-zeroes(len); // eliding error handling
242 | /// num_zeroes -= len;
243 | /// }
244 | /// this.flush();
245 | /// // Wait for completion of `flush`
246 | /// pollable.block();
247 | /// // Check for any errors that arose during `flush`
248 | /// let _ = this.check-write(); // eliding error handling
249 | /// ```
250 | @since(version = 0.2.0)
251 | blocking-write-zeroes-and-flush: func(
252 | /// The number of zero-bytes to write
253 | len: u64
254 | ) -> result<_, stream-error>;
255 |
256 | /// Read from one stream and write to another.
257 | ///
258 | /// The behavior of splice is equivalent to:
259 | /// 1. calling `check-write` on the `output-stream`
260 | /// 2. calling `read` on the `input-stream` with the smaller of the
261 | /// `check-write` permitted length and the `len` provided to `splice`
262 | /// 3. calling `write` on the `output-stream` with that read data.
263 | ///
264 | /// Any error reported by the call to `check-write`, `read`, or
265 | /// `write` ends the splice and reports that error.
266 | ///
267 | /// This function returns the number of bytes transferred; it may be less
268 | /// than `len`.
269 | @since(version = 0.2.0)
270 | splice: func(
271 | /// The stream to read from
272 | src: borrow,
273 | /// The number of bytes to splice
274 | len: u64,
275 | ) -> result;
276 |
277 | /// Read from one stream and write to another, with blocking.
278 | ///
279 | /// This is similar to `splice`, except that it blocks until the
280 | /// `output-stream` is ready for writing, and the `input-stream`
281 | /// is ready for reading, before performing the `splice`.
282 | @since(version = 0.2.0)
283 | blocking-splice: func(
284 | /// The stream to read from
285 | src: borrow,
286 | /// The number of bytes to splice
287 | len: u64,
288 | ) -> result;
289 | }
290 | }
291 |
--------------------------------------------------------------------------------
/wit/deps/io/world.wit:
--------------------------------------------------------------------------------
1 | package wasi:io@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world imports {
5 | @since(version = 0.2.0)
6 | import streams;
7 |
8 | @since(version = 0.2.0)
9 | import poll;
10 | }
11 |
--------------------------------------------------------------------------------
/wit/deps/random/insecure-seed.wit:
--------------------------------------------------------------------------------
1 | package wasi:random@0.2.4;
2 | /// The insecure-seed interface for seeding hash-map DoS resistance.
3 | ///
4 | /// It is intended to be portable at least between Unix-family platforms and
5 | /// Windows.
6 | @since(version = 0.2.0)
7 | interface insecure-seed {
8 | /// Return a 128-bit value that may contain a pseudo-random value.
9 | ///
10 | /// The returned value is not required to be computed from a CSPRNG, and may
11 | /// even be entirely deterministic. Host implementations are encouraged to
12 | /// provide pseudo-random values to any program exposed to
13 | /// attacker-controlled content, to enable DoS protection built into many
14 | /// languages' hash-map implementations.
15 | ///
16 | /// This function is intended to only be called once, by a source language
17 | /// to initialize Denial Of Service (DoS) protection in its hash-map
18 | /// implementation.
19 | ///
20 | /// # Expected future evolution
21 | ///
22 | /// This will likely be changed to a value import, to prevent it from being
23 | /// called multiple times and potentially used for purposes other than DoS
24 | /// protection.
25 | @since(version = 0.2.0)
26 | insecure-seed: func() -> tuple;
27 | }
28 |
--------------------------------------------------------------------------------
/wit/deps/random/insecure.wit:
--------------------------------------------------------------------------------
1 | package wasi:random@0.2.4;
2 | /// The insecure interface for insecure pseudo-random numbers.
3 | ///
4 | /// It is intended to be portable at least between Unix-family platforms and
5 | /// Windows.
6 | @since(version = 0.2.0)
7 | interface insecure {
8 | /// Return `len` insecure pseudo-random bytes.
9 | ///
10 | /// This function is not cryptographically secure. Do not use it for
11 | /// anything related to security.
12 | ///
13 | /// There are no requirements on the values of the returned bytes, however
14 | /// implementations are encouraged to return evenly distributed values with
15 | /// a long period.
16 | @since(version = 0.2.0)
17 | get-insecure-random-bytes: func(len: u64) -> list;
18 |
19 | /// Return an insecure pseudo-random `u64` value.
20 | ///
21 | /// This function returns the same type of pseudo-random data as
22 | /// `get-insecure-random-bytes`, represented as a `u64`.
23 | @since(version = 0.2.0)
24 | get-insecure-random-u64: func() -> u64;
25 | }
26 |
--------------------------------------------------------------------------------
/wit/deps/random/random.wit:
--------------------------------------------------------------------------------
1 | package wasi:random@0.2.4;
2 | /// WASI Random is a random data API.
3 | ///
4 | /// It is intended to be portable at least between Unix-family platforms and
5 | /// Windows.
6 | @since(version = 0.2.0)
7 | interface random {
8 | /// Return `len` cryptographically-secure random or pseudo-random bytes.
9 | ///
10 | /// This function must produce data at least as cryptographically secure and
11 | /// fast as an adequately seeded cryptographically-secure pseudo-random
12 | /// number generator (CSPRNG). It must not block, from the perspective of
13 | /// the calling program, under any circumstances, including on the first
14 | /// request and on requests for numbers of bytes. The returned data must
15 | /// always be unpredictable.
16 | ///
17 | /// This function must always return fresh data. Deterministic environments
18 | /// must omit this function, rather than implementing it with deterministic
19 | /// data.
20 | @since(version = 0.2.0)
21 | get-random-bytes: func(len: u64) -> list;
22 |
23 | /// Return a cryptographically-secure random or pseudo-random `u64` value.
24 | ///
25 | /// This function returns the same type of data as `get-random-bytes`,
26 | /// represented as a `u64`.
27 | @since(version = 0.2.0)
28 | get-random-u64: func() -> u64;
29 | }
30 |
--------------------------------------------------------------------------------
/wit/deps/random/world.wit:
--------------------------------------------------------------------------------
1 | package wasi:random@0.2.4;
2 |
3 | @since(version = 0.2.0)
4 | world imports {
5 | @since(version = 0.2.0)
6 | import random;
7 |
8 | @since(version = 0.2.0)
9 | import insecure;
10 |
11 | @since(version = 0.2.0)
12 | import insecure-seed;
13 | }
14 |
--------------------------------------------------------------------------------
/wit/deps/sockets/instance-network.wit:
--------------------------------------------------------------------------------
1 |
2 | /// This interface provides a value-export of the default network handle..
3 | @since(version = 0.2.0)
4 | interface instance-network {
5 | @since(version = 0.2.0)
6 | use network.{network};
7 |
8 | /// Get a handle to the default network.
9 | @since(version = 0.2.0)
10 | instance-network: func() -> network;
11 | }
12 |
--------------------------------------------------------------------------------
/wit/deps/sockets/ip-name-lookup.wit:
--------------------------------------------------------------------------------
1 | @since(version = 0.2.0)
2 | interface ip-name-lookup {
3 | @since(version = 0.2.0)
4 | use wasi:io/poll@0.2.4.{pollable};
5 | @since(version = 0.2.0)
6 | use network.{network, error-code, ip-address};
7 |
8 | /// Resolve an internet host name to a list of IP addresses.
9 | ///
10 | /// Unicode domain names are automatically converted to ASCII using IDNA encoding.
11 | /// If the input is an IP address string, the address is parsed and returned
12 | /// as-is without making any external requests.
13 | ///
14 | /// See the wasi-socket proposal README.md for a comparison with getaddrinfo.
15 | ///
16 | /// This function never blocks. It either immediately fails or immediately
17 | /// returns successfully with a `resolve-address-stream` that can be used
18 | /// to (asynchronously) fetch the results.
19 | ///
20 | /// # Typical errors
21 | /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address.
22 | ///
23 | /// # References:
24 | /// -
25 | /// -
26 | /// -
27 | /// -
28 | @since(version = 0.2.0)
29 | resolve-addresses: func(network: borrow, name: string) -> result;
30 |
31 | @since(version = 0.2.0)
32 | resource resolve-address-stream {
33 | /// Returns the next address from the resolver.
34 | ///
35 | /// This function should be called multiple times. On each call, it will
36 | /// return the next address in connection order preference. If all
37 | /// addresses have been exhausted, this function returns `none`.
38 | ///
39 | /// This function never returns IPv4-mapped IPv6 addresses.
40 | ///
41 | /// # Typical errors
42 | /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY)
43 | /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN)
44 | /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL)
45 | /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN)
46 | @since(version = 0.2.0)
47 | resolve-next-address: func() -> result