diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c87cd58 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Ensure all text is checked out with Unix EOL +* text=auto eol=lf + +# Ensure binary files aren't considered as text +*.wasm binary + +# Genrated code from cargo-component +component-model/examples/tutorial/*/src/bindings.rs linguist-generated + +Cargo-component.lock linguist-language=toml + diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..6c09b99 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# This file is described here: https://help.github.com/en/articles/about-code-owners + +# Global Owners: These members are Maintainers of the docs +* @itowlson +* @kate-goldenring +* @vados-cosmonic \ No newline at end of file diff --git a/.github/actions/mdbook/action.yml b/.github/actions/mdbook/action.yml new file mode 100644 index 0000000..f3861dd --- /dev/null +++ b/.github/actions/mdbook/action.yml @@ -0,0 +1,98 @@ +name: mdbook + +description: | + Run the mdbook build, optionally outputting a pages artifact + +inputs: + publish-pages-artifact: + type: boolean + required: false + default: false + description: | + Whether to publish a pages artifact + + publish-domain: + type: string + required: false + default: "component-model.bytecodealliance.org" + description: | + Path to which to store the artifac + + mdbook-version: + type: string + required: false + default: "0.4.21" + description: | + Version of mdbook to use (ex. '0.4.21') + + mdbook-alerts-version: + type: string + required: false + default: "0.6.7" + description: | + Version of mdbook-alerts to use (ex. '0.6.7') + + mdbook-linkcheck-version: + type: string + required: false + default: "0.7.7" + description: | + Version of mdbook-linkcheck to use (ex. '0.7.7') + +runs: + using: composite + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: extractions/setup-just@v2 + + - uses: taiki-e/cache-cargo-install-action@4d586f211d9b0bca9e7b59e57e2a0febf36c0929 # v2.1.1 + with: + tool: "mdbook@${{ inputs.mdbook-version }}" + + - uses: taiki-e/cache-cargo-install-action@4d586f211d9b0bca9e7b59e57e2a0febf36c0929 # v2.1.1 + with: + tool: "mdbook-alerts@${{ inputs.mdbook-alerts-version }}" + + - uses: taiki-e/cache-cargo-install-action@4d586f211d9b0bca9e7b59e57e2a0febf36c0929 # v2.1.1 + with: + tool: "mdbook-linkcheck@${{ inputs.mdbook-linkcheck-version }}" + + - name: Setup Python + uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0 + with: + python-version: '3.13' + + - name: Build with mdBook + shell: bash + id: book-build + env: + PUBLISH_DOMAIN: ${{ inputs.publish-domain }} + run: | + just build-book + echo "output-path=$(just print-book-dir)" >> $GITHUB_OUTPUT + + - name: Generate sitemap + shell: bash + run: | + just build-sitemap + + - name: Ensure publish-domain was provided + if: ${{ inputs.publish-pages-artifact }} + shell: bash + run: | + if [ -z "${{ inputs.publish-domain }}" ]; then + echo "[error] publish-domain input is required when publishing"; + exit 1; + fi + + - name: Setup Pages + if: ${{ inputs.publish-pages-artifact }} + id: pages + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 + + - name: Upload artifact + if: ${{ inputs.publish-pages-artifact }} + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 + with: + path: ${{ steps.book-build.outputs.output-path }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..e6af4e8 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,64 @@ +name: Deploy mdBook site to Pages + +on: + push: + branches: + - main + + workflow_dispatch: + inputs: + ref: + required: false + type: string + default: main + description: | + The git ref to deploy (ex. 'main', 'branch', '') + + publish-domain: + required: false + type: string + default: "component-model.bytecodealliance.org" + description: | + The domain to which to publish (ex. 'component-model.bytecodealliance.org') + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +env: + MDBOOK_VERSION: 0.4.21 + MDBOOK_ALERTS_VERSION: 0.6.7 + MDBOOK_LINKCHECK_VERSION: 0.7.7 + ARTIFACT_PATH: ./component-model/book/html + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ inputs.ref || 'main' }} + + - name: build mdbook + uses: ./.github/actions/mdbook + with: + publish-pages-artifact: true + publish-domain: ${{ inputs.publish-domain || 'component-model.bytecodealliance.org' }} + + deploy: + if: ${{ github.repository_owner == 'bytecodealliance' }} + runs-on: ubuntu-latest + needs: + - build + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index e177caf..1ce1e8b 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -1,69 +1,15 @@ -# Sample workflow for building and deploying a mdBook site to GitHub Pages -# -# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html -# -name: Deploy mdBook site to Pages +name: mdbook on: - # Runs on pushes targeting the default branch - push: - branches: ["main"] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: "pages" - cancel-in-progress: false + pull_request: jobs: - # Build job build: runs-on: ubuntu-latest - env: - MDBOOK_VERSION: 0.4.21 - SITEMAP_GEN_VERSION: 0.2.0 - PUBLISH_DOMAIN: component-model.bytecodealliance.org steps: - - uses: actions/checkout@v3 - - name: Install mdBook - run: | - curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh - rustup update - cargo install --version ${MDBOOK_VERSION} mdbook - cargo install --version ${SITEMAP_GEN_VERSION} mdbook-sitemap-generator - - name: Setup Pages - id: pages - uses: actions/configure-pages@v3 - - name: Build with mdBook - run: mdbook build component-model - - name: Generate sitemap - run: | - cd component-model - mdbook-sitemap-generator -d ${PUBLISH_DOMAIN} -o book/sitemap.xml - cd .. - - name: Upload artifact - uses: actions/upload-pages-artifact@v2 - with: - path: ./component-model/book + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - # Deployment job - deploy: - if: ${{ github.repository_owner == 'bytecodealliance' }} - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v2 + - name: build mdbook + uses: ./.github/actions/mdbook + with: + publish-pages-artifact: true diff --git a/.gitignore b/.gitignore index 17b163a..2ac0772 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ **/.vscode *.swp *.swo + +# Build artifacts from examples +**/jco/bindings +**/examples/**/*.wasm diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 586f059..e347452 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,16 @@ You can run the website locally using the [mdBook](https://rust-lang.github.io/m To use this repository, you need [mdBook](https://rust-lang.github.io/mdBook/guide/installation.html) installed on your workstation. +This repository also makes use of mdBook plugins. To install mdBook and the plugins for this project, you can use [`cargo`][cargo]: + +```console +cargo install --version 0.4.21 mdbook +cargo install --version 0.6.7 mdbook-alerts +cargo install --version 0.7.7 mdbook-linkcheck +``` + +[cargo]: https://doc.rust-lang.org/cargo + ### Running the website locally After installing mdBook, you'll need to clone the code via git and navigate to the directory. diff --git a/README.md b/README.md index e98e59f..5630f57 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ This repository contains user-facing documentation for the WebAssembly component The documentation is published at . -It is envisaged to contain two books, one on the component model itself, and one on WASI (WebAssembly System Interface). At the time of writing, the first book is in development, but the second is not yet started. +Documentation on WASI (WebAssembly System Interface) can be found at https://wasi.dev/. See the [`wasi.dev`](https://github.com/bytecodealliance/wasi.dev) repository to contribute to that documentation. Contributions are welcome - see [Contributing](./CONTRIBUTING.md) for more info. Planned work is listed in the Issues section, but if there's content missing that you think would be helpful to gain understanding of the component model, please feel free to add a new issue, or send a PR directly! diff --git a/component-model/book.toml b/component-model/book.toml index 9543b92..72ef7f3 100644 --- a/component-model/book.toml +++ b/component-model/book.toml @@ -8,3 +8,8 @@ title = "The WebAssembly Component Model" [output.html] git-repository-url = "https://github.com/bytecodealliance/component-docs/tree/main/component-model" edit-url-template = "https://github.com/bytecodealliance/component-docs/tree/main/component-model/{path}" +additional-css = ["theme/head.hbs"] + +[preprocessor.alerts] + +[output.linkcheck] diff --git a/component-model/examples/example-host/Cargo.lock b/component-model/examples/example-host/Cargo.lock index fe2db91..8ddce8a 100644 --- a/component-model/examples/example-host/Cargo.lock +++ b/component-model/examples/example-host/Cargo.lock @@ -1,27 +1,27 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -35,65 +35,75 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e1373abdaa212b704512ec2bd8b26bd0b7d5c3f70117411a5d9a451383c859" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" [[package]] name = "async-attributes" @@ -112,31 +122,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", "futures-core", + "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.6.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ - "async-lock", "async-task", "concurrent-queue", - "fastrand 2.0.1", + "fastrand", "futures-lite", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel", + "async-channel 2.3.1", "async-executor", "async-io", "async-lock", @@ -147,41 +168,42 @@ dependencies = [ [[package]] name = "async-io" -version = "1.13.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", - "autocfg", "cfg-if", "concurrent-queue", + "futures-io", "futures-lite", - "log", "parking", "polling", - "rustix 0.37.27", + "rustix", "slab", - "socket2 0.4.10", - "waker-fn", + "tracing", + "windows-sys 0.59.0", ] [[package]] name = "async-lock" -version = "2.8.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener", + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ "async-attributes", - "async-channel", + "async-channel 1.9.0", "async-global-executor", "async-io", "async-lock", @@ -203,19 +225,19 @@ dependencies = [ [[package]] name = "async-task" -version = "4.5.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] @@ -226,51 +248,36 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] name = "base64" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -283,25 +290,22 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.3.1", "async-task", - "fastrand 2.0.1", "futures-io", "futures-lite", "piper", - "tracing", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -311,56 +315,56 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cap-fs-ext" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b779b2d0a001c125b4584ad586268fb4b92d957bff8d26d7fe0dd78283faa814" +checksum = "e16619ada836f12897a72011fe99b03f0025b87a8dbbea4f3c9f89b458a23bf3" dependencies = [ "cap-primitives", "cap-std", - "io-lifetimes 2.0.2", - "windows-sys", + "io-lifetimes", + "windows-sys 0.52.0", ] [[package]] name = "cap-net-ext" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffc30dee200c20b4dcb80572226f42658e1d9c4b668656d7cc59c33d50e396e" +checksum = "710b0eb776410a22c89a98f2f80b2187c2ac3a8206b99f3412332e63c9b09de0" dependencies = [ "cap-primitives", "cap-std", - "rustix 0.38.21", + "rustix", "smallvec", ] [[package]] name = "cap-primitives" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf30c373a3bee22c292b1b6a7a26736a38376840f1af3d2d806455edf8c3899" +checksum = "82fa6c3f9773feab88d844aa50035a33fb6e7e7426105d2f4bb7aadc42a5f89a" dependencies = [ "ambient-authority", "fs-set-times", "io-extras", - "io-lifetimes 2.0.2", + "io-lifetimes", "ipnet", "maybe-owned", - "rustix 0.38.21", - "windows-sys", + "rustix", + "windows-sys 0.52.0", "winx", ] [[package]] name = "cap-rand" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577de6cff7c2a47d6b13efe5dd28bf116bd7f8f7db164ea95b7cc2640711f522" +checksum = "53774d49369892b70184f8312e50c1b87edccb376691de4485b0ff554b27c36c" dependencies = [ "ambient-authority", "rand", @@ -368,36 +372,39 @@ dependencies = [ [[package]] name = "cap-std" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84bade423fa6403efeebeafe568fdb230e8c590a275fba2ba978dd112efcf6e9" +checksum = "7f71b70818556b4fe2a10c7c30baac3f5f45e973f49fc2673d7c75c39d0baf5b" dependencies = [ "cap-primitives", "io-extras", - "io-lifetimes 2.0.2", - "rustix 0.38.21", + "io-lifetimes", + "rustix", ] [[package]] name = "cap-time-ext" -version = "2.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f52b3c8f4abfe3252fd0a071f3004aaa3b18936ec97bdbd8763ce03aff6247" +checksum = "69dd48afa2363f746c93f961c211f6f099fb594a3446b8097bc5f79db51b6816" dependencies = [ + "ambient-authority", "cap-primitives", + "iana-time-zone", "once_cell", - "rustix 0.38.21", + "rustix", "winx", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -408,9 +415,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.7" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -418,9 +425,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -430,117 +437,150 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "cobs" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpp_demangle" -version = "0.3.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] [[package]] name = "cranelift-bforest" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ba4f80548f22dc9c43911907b5e322c5555544ee85f785115701e6a28c9abe1" dependencies = [ "cranelift-entity", ] +[[package]] +name = "cranelift-bitset" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005884e3649c3e5ff2dc79e8a94b138f11569cc08a91244a292714d2a86e9156" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "cranelift-codegen" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4036255ec33ce9a37495dfbcfc4e1118fd34e693eff9a1e106336b7cd16a9b" dependencies = [ "bumpalo", "cranelift-bforest", + "cranelift-bitset", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-control", "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.2", + "hashbrown 0.14.5", "log", "regalloc2", + "rustc-hash", + "serde", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7ca74f4b68319da11d39e894437cb6e20ec7c2e11fbbda823c3bf207beedff7" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897e54f433a0269c4187871aa06d452214d5515d228d5bdc22219585e9eef895" [[package]] name = "cranelift-control" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29cb4018f5bf59fb53f515fa9d80e6f8c5ce19f198dc538984ebd23ecf8965ec" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "305399fd781a2953ac78c1396f02ff53144f39c33eb7fc7789cf4e8936d13a96" dependencies = [ + "cranelift-bitset", "serde", "serde_derive", ] [[package]] name = "cranelift-frontend" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9230b460a128d53653456137751d27baf567947a3ab8c0c4d6e31fd08036d81e" dependencies = [ "cranelift-codegen", "log", @@ -550,75 +590,54 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b961e24ae3ec9813a24a15ae64bbd2a42e4de4d79a7f3225a412e3b94e78d1c8" [[package]] name = "cranelift-native" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "0.114.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5bd76df6c9151188dfa428c863b33da5b34561b67f43c0cf3f24a794f9fa1f" dependencies = [ "cranelift-codegen", "libc", "target-lexicon", ] -[[package]] -name = "cranelift-wasm" -version = "0.101.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "cranelift-codegen", - "cranelift-entity", - "cranelift-frontend", - "itertools", - "log", - "smallvec", - "wasmparser", - "wasmtime-types", -] - [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -690,17 +709,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -713,12 +755,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -727,6 +769,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + [[package]] name = "example-host" version = "0.1.0" @@ -734,7 +797,6 @@ dependencies = [ "anyhow", "async-std", "clap", - "wasi-cap-std-sync", "wasmtime", "wasmtime-wasi", ] @@ -747,55 +809,52 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fd-lock" -version = "4.0.0" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0377f1edc77dbd1118507bc7a66e4ab64d2b90c66f90726dc801e73a8c68f9" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" dependencies = [ "cfg-if", - "rustix 0.38.21", - "windows-sys", + "rustix", + "windows-sys 0.52.0", ] +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs-set-times" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd738b84894214045e8414eaded76359b4a5773f0a0a56b16575110739cdcf39" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" dependencies = [ - "io-lifetimes 2.0.2", - "rustix 0.38.21", - "windows-sys", + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", ] [[package]] name = "futures" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -807,9 +866,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -817,48 +876,46 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "1.13.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ - "fastrand 1.9.0", + "fastrand", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", - "waker-fn", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-sink", @@ -882,7 +939,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.4.1", + "bitflags", "debugid", "fxhash", "serde", @@ -901,9 +958,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -912,9 +969,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator", "indexmap", @@ -923,9 +980,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -935,308 +992,451 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", + "serde", ] [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "ahash", + "foldhash", ] [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] -name = "id-arena" -version = "2.2.1" +name = "hermit-abi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] -name = "idna" -version = "0.4.0" +name = "iana-time-zone" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", ] [[package]] -name = "indexmap" -version = "2.0.2" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "equivalent", - "hashbrown 0.14.2", - "serde", + "cc", ] [[package]] -name = "instant" -version = "0.1.12" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "cfg-if", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "io-extras" -version = "0.18.0" +name = "icu_locid" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d3c230ee517ee76b1cc593b52939ff68deda3fae9e41eca426c6b4993df51c4" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ - "io-lifetimes 2.0.2", - "windows-sys", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "icu_locid_transform" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ - "hermit-abi", - "libc", - "windows-sys", + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "io-lifetimes" -version = "2.0.2" +name = "icu_locid_transform_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb4def18c48926ccac55c1223e02865ce1a821751a95920448662696e7472c" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] -name = "ipnet" -version = "2.9.0" +name = "icu_normalizer" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] [[package]] -name = "itertools" -version = "0.10.5" +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ - "either", + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "itoa" -version = "1.0.9" +name = "icu_properties_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] -name = "ittapi" -version = "0.3.5" +name = "icu_provider" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a5c0b993601cad796222ea076565c5d9f337d35592f8622c753724f06d7271" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ - "anyhow", - "ittapi-sys", - "log", + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "ittapi-sys" -version = "0.3.5" +name = "icu_provider_macros" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7b5e473765060536a660eed127f758cf1a810c73e49063264959c60d1727d9" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ - "cc", + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] -name = "jobserver" -version = "0.1.27" +name = "id-arena" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" -dependencies = [ - "libc", -] +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] -name = "js-sys" -version = "0.3.64" +name = "idna" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "wasm-bindgen", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "kv-log-macro" -version = "1.0.7" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "log", + "icu_normalizer", + "icu_properties", ] [[package]] -name = "leb128" -version = "0.2.5" +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] [[package]] -name = "libc" -version = "0.2.149" +name = "io-extras" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "7d45fd7584f9b67ac37bc041212d06bfac0700b36456b05890d36a3b626260eb" +dependencies = [ + "io-lifetimes", + "windows-sys 0.52.0", +] [[package]] -name = "linux-raw-sys" -version = "0.3.8" +name = "io-lifetimes" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" [[package]] -name = "linux-raw-sys" -version = "0.4.10" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] -name = "log" -version = "0.4.20" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -dependencies = [ - "value-bag", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] -name = "mach" -version = "0.3.2" +name = "itertools" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ - "libc", + "either", ] [[package]] -name = "maybe-owned" -version = "0.3.4" +name = "itoa" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] -name = "memchr" -version = "2.6.4" +name = "ittapi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] [[package]] -name = "memfd" -version = "0.6.4" +name = "ittapi-sys" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" dependencies = [ - "rustix 0.38.21", + "cc", ] [[package]] -name = "memoffset" -version = "0.9.0" +name = "jobserver" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "autocfg", + "libc", ] [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "js-sys" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ - "adler", + "wasm-bindgen", ] [[package]] -name = "mio" -version = "0.8.9" +name = "kv-log-macro" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ + "log", +] + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.166" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", "libc", - "wasi", - "windows-sys", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] + +[[package]] +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ - "hermit-abi", "libc", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "crc32fast", - "hashbrown 0.14.2", + "hashbrown 0.15.2", "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1246,66 +1446,91 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand", "futures-io", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" -version = "2.8.0" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ - "autocfg", - "bitflags 1.3.2", "cfg-if", "concurrent-queue", - "libc", - "log", + "hermit-abi 0.4.0", "pin-project-lite", - "windows-sys", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "postcard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63d01def49fc815900a83e7a4a5083d2abc81b7ddd569a3fa0477778ae9b3ec" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] +[[package]] +name = "pulley-interpreter" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b8d81cf799e20564931e9867ca32de545188c6ee4c2e0f6e41d32f0c7dc6fb" +dependencies = [ + "cranelift-bitset", + "log", + "sptr", +] + [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1342,9 +1567,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1352,41 +1577,32 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "redox_syscall", + "libredox", "thiserror", ] [[package]] name = "regalloc2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.14.5", "log", "rustc-hash", "slice-group-by", @@ -1395,94 +1611,87 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.37.27" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes 1.0.11", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ - "bitflags 2.4.1", + "bitflags", "errno", "itoa", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys", "once_cell", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "scopeguard" -version = "1.2.0" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.190" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1503,6 +1712,12 @@ dependencies = [ "dirs", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "slab" version = "0.4.9" @@ -1520,28 +1735,21 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.4.10" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ - "libc", - "winapi", + "serde", ] [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1558,9 +1766,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -1575,104 +1783,142 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "system-interface" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ce32341b2c0b70c144bbf35627fdc1ef18c76ced5e5e7b3ee8b5ba6b2ab6a0" +checksum = "b858526d22750088a9b3cf2e3c2aacebd5377f13adeec02860c30d09113010a6" dependencies = [ - "bitflags 2.4.1", + "bitflags", "cap-fs-ext", "cap-std", "fd-lock", - "io-lifetimes 2.0.2", - "rustix 0.38.21", - "windows-sys", + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", "winx", ] [[package]] name = "target-lexicon" -version = "0.12.12" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.33.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", - "socket2 0.5.5", - "windows-sys", + "socket2", + "windows-sys 0.52.0", ] [[package]] name = "toml" -version = "0.5.11" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ + "indexmap", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1680,20 +1926,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -1704,79 +1950,70 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" -version = "2.4.1" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.5.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] name = "value-bag" -version = "1.4.2" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1784,77 +2021,37 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi-cap-std-sync" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "anyhow", - "async-trait", - "cap-fs-ext", - "cap-rand", - "cap-std", - "cap-time-ext", - "fs-set-times", - "io-extras", - "io-lifetimes 2.0.2", - "once_cell", - "rustix 0.38.21", - "system-interface", - "tracing", - "wasi-common", - "windows-sys", -] - -[[package]] -name = "wasi-common" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "anyhow", - "bitflags 2.4.1", - "cap-rand", - "cap-std", - "io-extras", - "log", - "rustix 0.38.21", - "thiserror", - "tracing", - "wasmtime", - "wiggle", - "windows-sys", -] - [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -1864,9 +2061,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1874,127 +2071,175 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-encoder" -version = "0.35.0" +version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca90ba1b5b0a70d3d49473c5579951f3bddc78d47b59256d2f9d4922b150aca" +checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54" dependencies = [ "leb128", + "wasmparser 0.219.1", +] + +[[package]] +name = "wasm-encoder" +version = "0.221.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de35b6c3ef1f53ac7a31b5e69bc00f1542ea337e7e7162dc34c68b537ff82690" +dependencies = [ + "leb128", + "wasmparser 0.221.0", +] + +[[package]] +name = "wasmparser" +version = "0.219.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" +dependencies = [ + "ahash", + "bitflags", + "hashbrown 0.14.5", + "indexmap", + "semver", + "serde", ] [[package]] name = "wasmparser" -version = "0.115.0" +version = "0.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e06c0641a4add879ba71ccb3a1e4278fd546f76f1eafb21d8f7b07733b547cd5" +checksum = "8659e755615170cfe20da468865c989da78c5da16d8652e69a75acda02406a92" dependencies = [ + "bitflags", "indexmap", "semver", ] [[package]] name = "wasmprinter" -version = "0.2.70" +version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74458a9bc5cc9c7108abfa0fe4dc88d5abf1f3baf194df3264985f17d559b5e" +checksum = "228cdc1f30c27816da225d239ce4231f28941147d34713dee8f1fff7cb330e54" dependencies = [ "anyhow", - "wasmparser", + "termcolor", + "wasmparser 0.219.1", ] [[package]] name = "wasmtime" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b79302e3e084713249cc5622e8608e7410afdeeea8c8026d04f491d1fab0b4b" dependencies = [ + "addr2line", "anyhow", "async-trait", - "bincode", + "bitflags", "bumpalo", + "cc", "cfg-if", "encoding_rs", "fxprof-processed-profile", + "gimli", + "hashbrown 0.14.5", "indexmap", + "ittapi", "libc", + "libm", "log", + "mach2", + "memfd", "object", "once_cell", "paste", + "postcard", "psm", + "pulley-interpreter", "rayon", + "rustix", + "semver", "serde", "serde_derive", "serde_json", + "smallvec", + "sptr", "target-lexicon", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.219.1", + "wasmparser 0.219.1", + "wasmtime-asm-macros", "wasmtime-cache", "wasmtime-component-macro", "wasmtime-component-util", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-fiber", - "wasmtime-jit", - "wasmtime-runtime", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-slab", + "wasmtime-versioned-export-macros", "wasmtime-winch", "wat", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "wasmtime-asm-macros" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe53a24e7016a5222875d8ca3ad6024b464465985693c42098cd0bb710002c28" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-cache" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0677a7e76c24746b68e3657f7cc50c0ff122ee7e97bbda6e710c1b790ebc93cb" dependencies = [ "anyhow", "base64", - "bincode", "directories-next", "log", - "rustix 0.38.21", + "postcard", + "rustix", "serde", "serde_derive", "sha2", "toml", - "windows-sys", + "windows-sys 0.59.0", "zstd", ] [[package]] name = "wasmtime-component-macro" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e118acbd2bc09b32ad8606bc7cef793bf5019c1b107772e64dc6c76b5055d40b" dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", "wasmtime-component-util", "wasmtime-wit-bindgen", "wit-parser", @@ -2002,13 +2247,15 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6db4f3ee18c699629eabb9c64e77efe5a93a5137f098db7cab295037ba41c2" [[package]] name = "wasmtime-cranelift" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b87e6c78f562b50aff1afd87ff32a57e241424c846c1c8f3c5fd352d2d62906" dependencies = [ "anyhow", "cfg-if", @@ -2017,174 +2264,109 @@ dependencies = [ "cranelift-entity", "cranelift-frontend", "cranelift-native", - "cranelift-wasm", "gimli", + "itertools", "log", "object", + "smallvec", "target-lexicon", "thiserror", - "wasmparser", - "wasmtime-cranelift-shared", + "wasmparser 0.219.1", "wasmtime-environ", "wasmtime-versioned-export-macros", ] -[[package]] -name = "wasmtime-cranelift-shared" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "anyhow", - "cranelift-codegen", - "cranelift-control", - "cranelift-native", - "gimli", - "object", - "target-lexicon", - "wasmtime-environ", -] - [[package]] name = "wasmtime-environ" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c25bfeaa16432d59a0706e2463d315ef4c9ebcfaf5605670b99d46373bdf9f27" dependencies = [ "anyhow", + "cpp_demangle", + "cranelift-bitset", "cranelift-entity", "gimli", "indexmap", "log", "object", + "postcard", + "rustc-demangle", + "semver", "serde", "serde_derive", + "smallvec", "target-lexicon", - "thiserror", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.219.1", + "wasmparser 0.219.1", "wasmprinter", "wasmtime-component-util", - "wasmtime-types", ] [[package]] name = "wasmtime-fiber" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759ab0caa3821a6211743fe1eed448ab9df439e3af6c60dea15486c055611806" dependencies = [ + "anyhow", "cc", "cfg-if", - "rustix 0.38.21", + "rustix", "wasmtime-asm-macros", "wasmtime-versioned-export-macros", - "windows-sys", -] - -[[package]] -name = "wasmtime-jit" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "addr2line", - "anyhow", - "bincode", - "cfg-if", - "cpp_demangle", - "gimli", - "ittapi", - "log", - "object", - "rustc-demangle", - "rustix 0.38.21", - "serde", - "serde_derive", - "target-lexicon", - "wasmtime-environ", - "wasmtime-jit-debug", - "wasmtime-jit-icache-coherence", - "wasmtime-runtime", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "wasmtime-jit-debug" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2a056056e9ac6916c2b8e4743408560300c1355e078c344211f13210d449b3" dependencies = [ "object", - "once_cell", - "rustix 0.38.21", + "rustix", "wasmtime-versioned-export-macros", ] [[package]] name = "wasmtime-jit-icache-coherence" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "cfg-if", - "libc", - "windows-sys", -] - -[[package]] -name = "wasmtime-runtime" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b218a92866f74f35162f5d03a4e0f62cd0e1cc624285b1014275e5d4575fad" dependencies = [ "anyhow", - "cc", "cfg-if", - "encoding_rs", - "indexmap", "libc", - "log", - "mach", - "memfd", - "memoffset", - "paste", - "rand", - "rustix 0.38.21", - "sptr", - "wasm-encoder", - "wasmtime-asm-macros", - "wasmtime-environ", - "wasmtime-fiber", - "wasmtime-jit-debug", - "wasmtime-versioned-export-macros", - "wasmtime-wmemcheck", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] -name = "wasmtime-types" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" -dependencies = [ - "cranelift-entity", - "serde", - "serde_derive", - "thiserror", - "wasmparser", -] +name = "wasmtime-slab" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5f8acf677ee6b3b8ba400dd9753ea4769e56a95c4b30b045ac6d2d54b2f8ea" [[package]] name = "wasmtime-versioned-export-macros" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df09be00c38f49172ca9936998938476e3f2df782673a39ae2ef9fb0838341b6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] name = "wasmtime-wasi" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5cf227161565057fc994edf14180341817372a218f1597db48a43946e5f875" dependencies = [ "anyhow", "async-trait", - "bitflags 2.4.1", + "bitflags", "bytes", "cap-fs-ext", "cap-net-ext", @@ -2194,43 +2376,40 @@ dependencies = [ "fs-set-times", "futures", "io-extras", - "io-lifetimes 2.0.2", - "libc", - "log", - "once_cell", - "rustix 0.38.21", + "io-lifetimes", + "rustix", "system-interface", "thiserror", "tokio", "tracing", "url", - "wasi-cap-std-sync", - "wasi-common", "wasmtime", "wiggle", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "wasmtime-winch" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d6b5297bea14d8387c3974b2b011de628cc9b188f135cec752b74fd368964b" dependencies = [ "anyhow", "cranelift-codegen", "gimli", "object", "target-lexicon", - "wasmparser", - "wasmtime-cranelift-shared", + "wasmparser 0.219.1", + "wasmtime-cranelift", "wasmtime-environ", "winch-codegen", ] [[package]] name = "wasmtime-wit-bindgen" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3963c9c29df91564d8bd181eb00d0dbaeafa1b2a01e15952bb7391166b704e" dependencies = [ "anyhow", "heck", @@ -2238,11 +2417,6 @@ dependencies = [ "wit-parser", ] -[[package]] -name = "wasmtime-wmemcheck" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" - [[package]] name = "wast" version = "35.0.2" @@ -2254,30 +2428,31 @@ dependencies = [ [[package]] name = "wast" -version = "66.0.2" +version = "221.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93cb43b0ac6dd156f2c375735ccfd72b012a7c0a6e6d09503499b8d3cb6e6072" +checksum = "9d8eb1933d493dd07484a255c3f52236123333f5befaa3be36182a50d393ec54" dependencies = [ + "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.221.0", ] [[package]] name = "wat" -version = "1.0.77" +version = "1.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e367582095d2903caeeea9acbb140e1db9c7677001efa4347c3687fd34fe7072" +checksum = "c813fd4e5b2b97242830b56e7b7dc5479bc17aaa8730109be35e61909af83993" dependencies = [ - "wast 66.0.2", + "wast 221.0.0", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -2285,12 +2460,13 @@ dependencies = [ [[package]] name = "wiggle" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e0f6ef83a263c0fa11957c363aeaa76dc84832484d0e119f22810d4d0e09a7" dependencies = [ "anyhow", "async-trait", - "bitflags 2.4.1", + "bitflags", "thiserror", "tracing", "wasmtime", @@ -2299,26 +2475,28 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd266b290a0fdace3af6a05c6ebbcc54de303a774448ecf5a98cd0bc12d89c52" dependencies = [ "anyhow", "heck", "proc-macro2", "quote", "shellexpand", - "syn 2.0.38", + "syn 2.0.89", "witx", ] [[package]] name = "wiggle-macro" -version = "14.0.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b8eb1a5783540696c59cefbfc9e52570c2d5e62bd47bdf0bdcef29231879db2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", "wiggle-generate", ] @@ -2338,6 +2516,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2346,8 +2533,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "0.12.2" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b42b678c8651ec4900d7600037d235429fc985c31cbc33515885ec0d2a9e158" dependencies = [ "anyhow", "cranelift-codegen", @@ -2355,28 +2543,48 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.219.1", + "wasmtime-cranelift", "wasmtime-environ", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -2385,61 +2593,76 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] [[package]] name = "winx" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357bb8e2932df531f83b052264b050b81ba0df90ee5a59b2d1d3949f344f81e5" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" dependencies = [ - "bitflags 2.4.1", - "windows-sys", + "bitflags", + "windows-sys 0.52.0", ] [[package]] name = "wit-parser" -version = "0.12.1" +version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ace9943d89bbf3dbbc71b966da0e7302057b311f36a4ac3d65ddfef17b52cf" +checksum = "4a86f669283257e8e424b9a4fc3518e3ade0b95deb9fbc0f93a1876be3eda598" dependencies = [ "anyhow", "id-arena", @@ -2450,12 +2673,14 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", + "wasmparser 0.219.1", ] [[package]] name = "witx" version = "0.9.1" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=2ade3ad#2ade3adec68caabdf35e778d67fe6343156ce16d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" dependencies = [ "anyhow", "log", @@ -2463,50 +2688,129 @@ dependencies = [ "wast 35.0.2", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.7.15" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ba595b9f2772fbee2312de30eeb80ec773b4cb2f1e8098db024afadda6c06f" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.15" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772666c41fb6dceaf520b564b962d738a8e1a83b41bd48945f50837aed78bb1d" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.89", ] [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ - "libc", "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/component-model/examples/example-host/Cargo.toml b/component-model/examples/example-host/Cargo.toml index 6e49669..b364a90 100644 --- a/component-model/examples/example-host/Cargo.toml +++ b/component-model/examples/example-host/Cargo.toml @@ -2,11 +2,13 @@ name = "example-host" version = "0.1.0" edition = "2021" +description = """ +Example Rust-based WebAssembly host that executes WebAssembly components +""" [dependencies] -async-std = { version = "1.12.0", features = ["attributes"] } -clap = { version = "4.3.19", features = ["derive"] } -wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", rev = "2ade3ad", features = ["component-model"] } -wasmtime-wasi = { git = "https://github.com/bytecodealliance/wasmtime", rev = "2ade3ad" } -wasi-cap-std-sync = { git = "https://github.com/bytecodealliance/wasmtime", rev = "2ade3ad" } anyhow = "1.0.72" +async-std = { version = "1.13", features = ["attributes"] } +clap = { version = "4", features = ["derive"] } +wasmtime = "27.0" +wasmtime-wasi = "27.0" diff --git a/component-model/examples/example-host/README.md b/component-model/examples/example-host/README.md index 43d9a4e..67e543e 100644 --- a/component-model/examples/example-host/README.md +++ b/component-model/examples/example-host/README.md @@ -1,25 +1,47 @@ # Rust Host Application for Example Components -This is a native Rust CLI application that can run components of the following -`example` world, which simply defines an add function that takes in two -parameters. +This is a native Rust CLI application that can run [WebAssembly Components][wasm-components] of the `adder` world, +defined in [`examples/tutorial/wit/adder/world.wit`][adder-wit], using [WebAssembly Interface Types ("WIT")][wit]. + +The `adder` world exports an interface called `add` which defines an function that takes two unsigned and adds them: ```wit -package example:component; +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} -world example { - export add: func(x: s32, y: s32) -> s32; +world adder { + export add; } ``` -The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) -crates to generate Rust bindings, bring in WASI worlds, and executes the `run` -function of the component. +The application uses WebAssembly ecosystem crates (e.g. [`wasmtime`][wasmtime]) to generate Rust bindings, instantiate WASI worlds, and +executes the exported `add` function (`docs:adder/add.add`) of a provided component. + +This host binary takes in two unsigned 32bit integers (`u32`) operands and a path to a component. This host then: -It takes in two operands and a path to a component. It passes the operands to -the component and prints the result generated by the component. +1. Loads the component from the given path +2. Instantiates it as an implementer of the `adder` world +3. Executes the `add` function exported by the component +4. Prints the result -```sh +If running with [`cargo`][cargo] (part of the [Rust toolchain][rust-toolchain]), then you should see output like the following: + +``` $ cargo run --release -- 1 2 add.wasm 1 + 2 = 3 ``` + +> [!NOTE] +> `add.wasm` is available in this folder, but can be replaced with your own built WebAssembly component +> at any time (written in any language that supports WebAssembly Components), given that it satisfies +> the `adder` world described above. + +[wasmtime]: https://github.com/bytecodealliance/wasmtime +[wasm-components]: https://component-model.bytecodealliance.org/design/components.html +[adder-wit]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit +[wit]: https://component-model.bytecodealliance.org/design/wit.html +[cargo]: https://doc.rust-lang.org/cargo/ +[rust-toolchain]: https://www.rust-lang.org/tools/install diff --git a/component-model/examples/example-host/add.wasm b/component-model/examples/example-host/add.wasm index 0149dd4..9b76d06 100755 Binary files a/component-model/examples/example-host/add.wasm and b/component-model/examples/example-host/add.wasm differ diff --git a/component-model/examples/example-host/add.wit b/component-model/examples/example-host/add.wit deleted file mode 100644 index 703ed7e..0000000 --- a/component-model/examples/example-host/add.wit +++ /dev/null @@ -1,5 +0,0 @@ -package example:component; - -world example { - export add: func(x: s32, y: s32) -> s32; -} diff --git a/component-model/examples/example-host/src/add.rs b/component-model/examples/example-host/src/add.rs deleted file mode 100644 index 712ab58..0000000 --- a/component-model/examples/example-host/src/add.rs +++ /dev/null @@ -1,66 +0,0 @@ -use anyhow::Context; -use std::path::PathBuf; -use wasmtime::component::*; -use wasmtime::{Config, Engine, Store}; -use wasmtime_wasi::preview2::{command, Table, WasiCtx, WasiCtxBuilder, WasiView}; - -wasmtime::component::bindgen!({ - path: "add.wit", - world: "example", - async: true -}); - -pub async fn add(path: PathBuf, x: i32, y: i32) -> wasmtime::Result { - let mut config = Config::default(); - config.wasm_component_model(true); - config.async_support(true); - let engine = Engine::new(&config)?; - let mut linker = Linker::new(&engine); - - // Add the command world (aka WASI CLI) to the linker - command::add_to_linker(&mut linker).context("Failed to link command world")?; - let wasi_view = ServerWasiView::new(); - let mut store = Store::new(&engine, wasi_view); - - let component = Component::from_file(&engine, path).context("Component file not found")?; - - let (instance, _) = Example::instantiate_async(&mut store, &component, &linker) - .await - .context("Failed to instantiate the example world")?; - instance - .call_add(&mut store, x, y) - .await - .context("Failed to call add function") -} - -struct ServerWasiView { - table: Table, - ctx: WasiCtx, -} - -impl ServerWasiView { - fn new() -> Self { - let table = Table::new(); - let ctx = WasiCtxBuilder::new().inherit_stdio().build(); - - Self { table, ctx } - } -} - -impl WasiView for ServerWasiView { - fn table(&self) -> &Table { - &self.table - } - - fn table_mut(&mut self) -> &mut Table { - &mut self.table - } - - fn ctx(&self) -> &WasiCtx { - &self.ctx - } - - fn ctx_mut(&mut self) -> &mut WasiCtx { - &mut self.ctx - } -} diff --git a/component-model/examples/example-host/src/async_add.rs b/component-model/examples/example-host/src/async_add.rs new file mode 100644 index 0000000..48ec9ce --- /dev/null +++ b/component-model/examples/example-host/src/async_add.rs @@ -0,0 +1,61 @@ +use std::path::PathBuf; + +use anyhow::Context; +use wasmtime::component::{Component, Linker}; +use wasmtime::{Config, Engine, Store}; + +use crate::state::States; + +mod bindings { + //! Generated code for the + wasmtime::component::bindgen!({ + path: "../tutorial/wit/adder/world.wit", + world: "adder", + async: true + }); +} + +/// Perform the add operation for a given WebAssembly component +/// +/// This operation asynchronously (as opposed to synchronously +/// without an async runtime like `tokio` or `async-std`). +/// +/// # Arguments +/// +/// * `path` - Path to the Wasm component bytes +/// * `x` - The left hand side of the addition +/// * `y` - The right hand side of the addition +/// +pub async fn add(path: PathBuf, x: u32, y: u32) -> wasmtime::Result { + // Construct engine + let mut config = Config::default(); + config.async_support(true); + let engine = Engine::new(&config)?; + + // Construct component + let component = Component::from_file(&engine, path).context("Component file not found")?; + + // Construct store for storing running states of the component + let wasi_view = States::new(); + let mut store = Store::new(&engine, wasi_view); + + // Construct linker for linking interfaces. + let mut linker = Linker::new(&engine); + + // Add wasi exports to linker to support I/O (as in `wasi:io`) interfaces + // see: https://github.com/WebAssembly/wasi-io + wasmtime_wasi::add_to_linker_async(&mut linker)?; + + // Instantiate the component as an instance of the `adder` world, + // with the generated bindings + let instance = bindings::Adder::instantiate_async(&mut store, &component, &linker) + .await + .context("Failed to instantiate the example world")?; + + // Call the add function on instance + instance + .docs_adder_add() + .call_add(&mut store, x, y) + .await + .context("calling add function") +} diff --git a/component-model/examples/example-host/src/main.rs b/component-model/examples/example-host/src/main.rs index 965d477..71c187e 100644 --- a/component-model/examples/example-host/src/main.rs +++ b/component-model/examples/example-host/src/main.rs @@ -1,16 +1,19 @@ -mod add; use clap::Parser; use std::path::PathBuf; +mod async_add; +mod state; +mod sync_add; + /// A CLI for executing WebAssembly components that /// implement the `example` world. #[derive(Parser)] #[clap(name = "add-host", version = env!("CARGO_PKG_VERSION"))] struct AddApp { /// The first operand - x: i32, + x: u32, /// The second operand - y: i32, + y: u32, /// The path to the component. #[clap(value_name = "COMPONENT_PATH")] component: PathBuf, @@ -18,8 +21,10 @@ struct AddApp { impl AddApp { async fn run(self) -> anyhow::Result<()> { - let sum = add::add(self.component, self.x, self.y).await?; - println!("{} + {} = {sum}", self.x, self.y); + let sum1 = async_add::add(self.component.clone(), self.x, self.y).await?; + let sum2 = sync_add::add(self.component, self.x, self.y)?; + assert_eq!(sum1, sum2); + println!("{} + {} = {sum1}", self.x, self.y); Ok(()) } } diff --git a/component-model/examples/example-host/src/state.rs b/component-model/examples/example-host/src/state.rs new file mode 100644 index 0000000..74819bc --- /dev/null +++ b/component-model/examples/example-host/src/state.rs @@ -0,0 +1,25 @@ +use wasmtime::component::ResourceTable; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiView}; + +pub struct States { + table: ResourceTable, + ctx: WasiCtx, +} + +impl States { + pub fn new() -> Self { + let table = ResourceTable::new(); + let ctx = WasiCtxBuilder::new().build(); + Self { table, ctx } + } +} + +impl WasiView for States { + fn table(&mut self) -> &mut ResourceTable { + &mut self.table + } + + fn ctx(&mut self) -> &mut WasiCtx { + &mut self.ctx + } +} diff --git a/component-model/examples/example-host/src/sync_add.rs b/component-model/examples/example-host/src/sync_add.rs new file mode 100644 index 0000000..fa940f1 --- /dev/null +++ b/component-model/examples/example-host/src/sync_add.rs @@ -0,0 +1,57 @@ +use std::path::PathBuf; + +use anyhow::Context; +use wasmtime::component::{Component, Linker}; +use wasmtime::{Engine, Store}; +use wasmtime_wasi; + +use crate::state::States; + +mod bindings { + wasmtime::component::bindgen!({ + path: "../tutorial/wit/adder/world.wit", + world: "adder", + async: false + }); +} + +/// Perform a add operation for a given WebAssembly component +/// +/// This operation happens synchronously (as opposed to asynchronously +/// powered by an async runtime like `tokio` or `async-std`). +/// +/// # Arguments +/// +/// * `path` - Path to the Wasm component bytes +/// * `x` - The left hand side of the addition +/// * `y` - The right hand side of the addition +/// +pub fn add(path: PathBuf, x: u32, y: u32) -> wasmtime::Result { + // Construct engine + let engine = Engine::default(); + + // Construct component + let component = Component::from_file(&engine, path).context("Component file not found")?; + + // Construct store for storing running states of the component + let wasi_view = States::new(); + let mut store = Store::new(&engine, wasi_view); + + // Construct linker for linking interfaces. + let mut linker = Linker::new(&engine); + + // Add wasi exports to linker to support I/O (as in `wasi:io`) interfaces + // see: https://github.com/WebAssembly/wasi-io + wasmtime_wasi::add_to_linker_sync(&mut linker).expect("Could not add wasi to linker"); + + // Instantiate the component as an instance of the `adder` world, + // with the generated bindings + let instance = bindings::Adder::instantiate(&mut store, &component, &linker) + .context("Failed to instantiate the example world")?; + + // Call the add function on instance + instance + .docs_adder_add() + .call_add(&mut store, x, y) + .context("calling add function") +} diff --git a/component-model/examples/tutorial/README.md b/component-model/examples/tutorial/README.md index d16920a..54c37f2 100644 --- a/component-model/examples/tutorial/README.md +++ b/component-model/examples/tutorial/README.md @@ -5,27 +5,36 @@ The WIT package for the calculator consists of a world for each mathematical ope add an `op` enum that delineates each operator. The following example interface only has an `add` operation: -```wit -package docs:calculator@0.1.0; +```wit adder +package docs:adder@0.1.0; -interface calculate { - enum op { - add, - } - eval-expression: func(op: op, x: u32, y: u32) -> u32; -} interface add { - add: func(a: u32, b: u32) -> u32; + add: func(x: u32, y: u32) -> u32; } world adder { export add; } +``` + +```wit calculator +package docs:calculator@0.1.0; + +interface calculate { + enum op { + add, + } + eval-expression: func(op: op, x: u32, y: u32) -> u32; +} world calculator { export calculate; - import add; + import docs:adder/add; +} + +world app { + import calculate; } ``` @@ -33,19 +42,76 @@ To expand the exercise to add more components, add another operator world, expan ## Building and running the example -To compose a calculator component with an add operator, run the following: +Use [`cargo-component`](https://github.com/bytecodealliance/cargo-component) and [`wac`](https://github.com/bytecodealliance/wac) to build and compose the calculator component. ```sh (cd calculator && cargo component build --release) (cd adder && cargo component build --release) (cd command && cargo component build --release) -wasm-tools compose calculator/target/wasm32-wasi/release/calculator.wasm -d adder/target/wasm32-wasi/release/adder.wasm -o composed.wasm -wasm-tools compose command/target/wasm32-wasi/release/command.wasm -d composed.wasm -o command.wasm +wac plug calculator/target/wasm32-wasip1/release/calculator.wasm --plug adder/target/wasm32-wasip1/release/adder.wasm -o composed.wasm +wac plug command/target/wasm32-wasip1/release/command.wasm --plug composed.wasm -o final.wasm +``` + +Now, run the component with Wasmtime: + +```sh +wasmtime run final.wasm 1 2 add +1 + 2 = 3 ``` -Now, run the component with wasmtime: +## Composing with the WAC Language + +`wac plug` is a convenience to achieve a common pattern in component compositions like above. However, composition can be arbitrarily complicated. In cases where `wac plug` is not sufficient, the WAC language can give us the ability to create arbitrarily complex compositions. To get more experience using the WAC language, let's look at how we could use it to create our composition. + +`wac` can compose local components and components hosted in registries. To compose local components, first move the components to a `deps` folder, the default location in which `wac` looks for local components. `wac` infers the subpath to components from the package name of components defined in a WAC file. For example, if the instantiation expression for the adder component in the WAC file is `new docs:adder-impl{}`, the local component is expected to have the following path `deps/docs/adder-impl.wasm`. With this in mind, let's move all out components to a `deps/docs` folder and rename to ease clarifying WAC concepts. + +```sh +mkdir -p deps/docs +cp adder/target/wasm32-wasip1/release/adder.wasm deps/docs/adder-impl.wasm +cp calculator/target/wasm32-wasip1/release/calculator.wasm deps/docs/calculator-impl.wasm +cp command/target/wasm32-wasip1/release/command.wasm deps/docs/command-impl.wasm +``` + +Now we are ready to construct a WAC file to define our composition. Ours instantiates our three components, declaring +which components satisfy each of their imports. It ends with an export of the `wasi:cli/run` interface from the command component. This is the export that the Wasmtime CLI requires in order to execute the final component on the command line. + +```wac +// Provide a package name for the resulting composition +package example:composition; + +// Instantiate the adder-impl component that implements the adder world. +// We are giving this instance the local name `adder-instance`. +let adder-instance = new docs:adder-impl { }; + +// Instantiate the calculator-impl component that implements the calculator world. +// In the `new` expression, specify the source of the `add` import to be `adder-instance`'s `add` export. +let calculator-instance = new docs:calculator-impl { add: adder-instance.add }; + +// Instantiate a command-impl component that implements the app world. +// The command component might import other interfaces, such as WASI interfaces, but we want to leave +// those as imports in the final component, so supply `...` to allow those other imports to remain unresolved. +// The command's exports (in this case, `wasi:cli/run`) remain unaffected in the resulting instance. +let command-instance = new docs:command-impl { calculate: calculator-instance.calculate,... }; + +// Export the `wasi:cli/run` interface from the command instance +// This could also have been expressed using the postfix access expression `command-instance.run` +export command-instance["wasi:cli/run@0.2.0"]; +``` + +Now, perform your composition by passing the WAC file to `wac compose`. + +```sh +wac compose composition.wac -o final.wasm +``` + +> Note, instead of moving all the components to a `deps/docs` directory, you can pass the paths to the components inline +> ```sh +> wac compose --dep docs:adder-impl=./adder/target/wasm32-wasip1/release/adder.wasm --dep docs:calculator-impl=./calculator/target/wasm32-wasip1/release/calculator.wasm --dep docs:command-impl=./command/target/wasm32-wasip1/release/command.wasm -o final.wasm composition.wac +> ``` + +Run the component with Wasmtime: ```sh -wasmtime run --wasm component-model command.wasm 1 2 add +wasmtime run final.wasm 1 2 add 1 + 2 = 3 ``` diff --git a/component-model/examples/tutorial/adder/Cargo-component.lock b/component-model/examples/tutorial/adder/Cargo-component.lock deleted file mode 100644 index 00bc239..0000000 --- a/component-model/examples/tutorial/adder/Cargo-component.lock +++ /dev/null @@ -1,3 +0,0 @@ -# This file is automatically generated by cargo-component. -# It is not intended for manual editing. -version = 1 diff --git a/component-model/examples/tutorial/adder/Cargo.lock b/component-model/examples/tutorial/adder/Cargo.lock index b903bc6..bff0abf 100644 --- a/component-model/examples/tutorial/adder/Cargo.lock +++ b/component-model/examples/tutorial/adder/Cargo.lock @@ -1,26 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adder" version = "0.1.0" dependencies = [ - "cargo-component-bindings", + "wit-bindgen-rt", ] -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.4.0" @@ -28,412 +16,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] -name = "cargo-component-bindings" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "cargo-component-macro", - "wit-bindgen", -] - -[[package]] -name = "cargo-component-macro" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "id-arena" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f478948fd84d9f8e86967bf432640e46adfb5a4bd4f14ef7e864ab38220534ae" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pulldown-cmark" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" -dependencies = [ - "bitflags 1.3.2", - "memchr", - "unicase", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "spdx" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71" -dependencies = [ - "smallvec", -] - -[[package]] -name = "syn" -version = "2.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-encoder" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-metadata" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "serde_json", - "spdx", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.112.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf" -dependencies = [ - "indexmap", - "semver", -] - -[[package]] -name = "wit-bindgen" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a3e8e965dc50e6eb4410d9a11720719fadc6a1713803ea5f3be390b81c8279" -dependencies = [ - "bitflags 2.4.0", - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77255512565dfbd0b61de466e854918041d1da53c7bc049d6188c6e02643dc1e" -dependencies = [ - "anyhow", - "wit-component", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c60e6ea8598d1380e792f13d557007834f0fb799fea6503408cbc5debb4ae" -dependencies = [ - "anyhow", - "heck", - "wasm-metadata", - "wit-bindgen-core", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-lib" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fb7a43c7dc28b0b727d6ae01bf369981229b7539e768fba2b7a4df13feeeb" -dependencies = [ - "heck", - "wit-bindgen-core", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cea5ed784da06da0e55836a6c160e7502dbe28771c2368a595e8606243bf22" -dependencies = [ - "anyhow", - "proc-macro2", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-component" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876" -dependencies = [ - "anyhow", - "bitflags 2.4.0", - "indexmap", - "log", - "serde", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.11.0" +name = "wit-bindgen-rt" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc" +checksum = "fc801b991c56492f87ab3086e786468f75c285a4d73017ab0ebc2fa1aed5d82c" dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "pulldown-cmark", - "semver", - "unicode-xid", - "url", + "bitflags", ] diff --git a/component-model/examples/tutorial/adder/Cargo.toml b/component-model/examples/tutorial/adder/Cargo.toml index b19ae72..7578216 100644 --- a/component-model/examples/tutorial/adder/Cargo.toml +++ b/component-model/examples/tutorial/adder/Cargo.toml @@ -3,19 +3,17 @@ name = "adder" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" } +wit-bindgen-rt = { version = "0.37.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] [package.metadata.component] -package = "docs:calculator" +package = "docs:adder" + +[package.metadata.component.dependencies] [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/adder" world = "adder" - -[package.metadata.component.dependencies] diff --git a/component-model/examples/tutorial/adder/src/bindings.rs b/component-model/examples/tutorial/adder/src/bindings.rs new file mode 100644 index 0000000..52775cd --- /dev/null +++ b/component-model/examples/tutorial/adder/src/bindings.rs @@ -0,0 +1,153 @@ +// Generated by `wit-bindgen` 0.41.0. DO NOT EDIT! +// Options used: +// * runtime_path: "wit_bindgen_rt" +#[rustfmt::skip] +#[allow(dead_code, clippy::all)] +pub mod exports { + pub mod docs { + pub mod adder { + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod add { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_add_cabi(arg0: i32, arg1: i32) -> i32 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::add(arg0 as u32, arg1 as u32); + _rt::as_i32(result0) + } + pub trait Guest { + fn add(x: u32, y: u32) -> u32; + } + #[doc(hidden)] + macro_rules! __export_docs_adder_add_0_1_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "docs:adder/add@0.1.0#add")] unsafe extern "C" fn export_add(arg0 + : i32, arg1 : i32,) -> i32 { unsafe { $($path_to_types)*:: + _export_add_cabi::<$ty > (arg0, arg1) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_docs_adder_add_0_1_0_cabi; + } + } + } +} +#[rustfmt::skip] +mod _rt { + #![allow(dead_code, clippy::all)] + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen_rt::run_ctors_once(); + } + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + pub trait AsI32 { + fn as_i32(self) -> i32; + } + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } +} +/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as +/// the root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! export{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// export!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] +macro_rules! __export_adder_impl { + ($ty:ident) => { + self::export!($ty with_types_in self); + }; + ($ty:ident with_types_in $($path_to_types_root:tt)*) => { + $($path_to_types_root)*:: + exports::docs::adder::add::__export_docs_adder_add_0_1_0_cabi!($ty with_types_in + $($path_to_types_root)*:: exports::docs::adder::add); + }; +} +#[doc(inline)] +pub(crate) use __export_adder_impl as export; +#[cfg(target_arch = "wasm32")] +#[unsafe( + link_section = "component-type:wit-bindgen:0.41.0:docs:adder@0.1.0:adder:encoded world" +)] +#[doc(hidden)] +#[allow(clippy::octal_escapes)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 203] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07P\x01A\x02\x01A\x02\x01\ +B\x02\x01@\x02\x01xy\x01yy\0y\x04\0\x03add\x01\0\x04\0\x14docs:adder/add@0.1.0\x05\ +\0\x04\0\x16docs:adder/adder@0.1.0\x04\0\x0b\x0b\x01\0\x05adder\x03\0\0\0G\x09pr\ +oducers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x06\ +0.41.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/component-model/examples/tutorial/adder/src/lib.rs b/component-model/examples/tutorial/adder/src/lib.rs index 2460a13..20f59a3 100644 --- a/component-model/examples/tutorial/adder/src/lib.rs +++ b/component-model/examples/tutorial/adder/src/lib.rs @@ -1,10 +1,21 @@ -cargo_component_bindings::generate!(); -use bindings::exports::docs::calculator::add::Guest; +#[allow(warnings)] +mod bindings; + +// The comments that follow the `use` declaration below +// correlate the rust module path segments with their +// `world.wit` counterparts: +use bindings::exports::docs::adder::add::Guest; +// <- items bundled with `export` keyword +// <- package namespace +// <- package +// <- interface name struct Component; impl Guest for Component { - fn add(a: u32, b: u32) -> u32 { - a + b + fn add(x: u32, y: u32) -> u32 { + x + y } } + +bindings::export!(Component with_types_in bindings); diff --git a/component-model/examples/tutorial/calculator/Cargo-component.lock b/component-model/examples/tutorial/calculator/Cargo-component.lock deleted file mode 100644 index 00bc239..0000000 --- a/component-model/examples/tutorial/calculator/Cargo-component.lock +++ /dev/null @@ -1,3 +0,0 @@ -# This file is automatically generated by cargo-component. -# It is not intended for manual editing. -version = 1 diff --git a/component-model/examples/tutorial/calculator/Cargo.lock b/component-model/examples/tutorial/calculator/Cargo.lock index 92ae88c..143b7b4 100644 --- a/component-model/examples/tutorial/calculator/Cargo.lock +++ b/component-model/examples/tutorial/calculator/Cargo.lock @@ -2,438 +2,24 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "calculator" version = "0.1.0" dependencies = [ - "cargo-component-bindings", -] - -[[package]] -name = "cargo-component-bindings" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "cargo-component-macro", - "wit-bindgen", -] - -[[package]] -name = "cargo-component-macro" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "id-arena" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f478948fd84d9f8e86967bf432640e46adfb5a4bd4f14ef7e864ab38220534ae" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pulldown-cmark" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" -dependencies = [ - "bitflags 1.3.2", - "memchr", - "unicase", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "spdx" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71" -dependencies = [ - "smallvec", -] - -[[package]] -name = "syn" -version = "2.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-encoder" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-metadata" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "serde_json", - "spdx", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.112.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf" -dependencies = [ - "indexmap", - "semver", -] - -[[package]] -name = "wit-bindgen" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a3e8e965dc50e6eb4410d9a11720719fadc6a1713803ea5f3be390b81c8279" -dependencies = [ - "bitflags 2.4.0", - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77255512565dfbd0b61de466e854918041d1da53c7bc049d6188c6e02643dc1e" -dependencies = [ - "anyhow", - "wit-component", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c60e6ea8598d1380e792f13d557007834f0fb799fea6503408cbc5debb4ae" -dependencies = [ - "anyhow", - "heck", - "wasm-metadata", - "wit-bindgen-core", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-lib" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fb7a43c7dc28b0b727d6ae01bf369981229b7539e768fba2b7a4df13feeeb" -dependencies = [ - "heck", - "wit-bindgen-core", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cea5ed784da06da0e55836a6c160e7502dbe28771c2368a595e8606243bf22" -dependencies = [ - "anyhow", - "proc-macro2", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-component" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876" -dependencies = [ - "anyhow", - "bitflags 2.4.0", - "indexmap", - "log", - "serde", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", + "wit-bindgen-rt", ] [[package]] -name = "wit-parser" -version = "0.11.0" +name = "wit-bindgen-rt" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc" +checksum = "3b0780cf7046630ed70f689a098cd8d56c5c3b22f2a7379bbdb088879963ff96" dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "pulldown-cmark", - "semver", - "unicode-xid", - "url", + "bitflags", ] diff --git a/component-model/examples/tutorial/calculator/Cargo.toml b/component-model/examples/tutorial/calculator/Cargo.toml index 56945ca..6f6f717 100644 --- a/component-model/examples/tutorial/calculator/Cargo.toml +++ b/component-model/examples/tutorial/calculator/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" } +wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] @@ -12,6 +12,11 @@ crate-type = ["cdylib"] [package.metadata.component] package = "docs:calculator" +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } # directory containing the WIT package + [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/calculator" world = "calculator" + +[package.metadata.component.dependencies] diff --git a/component-model/examples/tutorial/calculator/src/bindings.rs b/component-model/examples/tutorial/calculator/src/bindings.rs new file mode 100644 index 0000000..8511915 --- /dev/null +++ b/component-model/examples/tutorial/calculator/src/bindings.rs @@ -0,0 +1,234 @@ +// Generated by `wit-bindgen` 0.25.0. DO NOT EDIT! +// Options used: +#[allow(dead_code)] +pub mod docs { + #[allow(dead_code)] + pub mod adder { + #[allow(dead_code, clippy::all)] + pub mod add { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + pub fn add(x: u32, y: u32) -> u32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "docs:adder/add@0.1.0")] + extern "C" { + #[link_name = "add"] + fn wit_import(_: i32, _: i32) -> i32; + } + + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32, _: i32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&a), _rt::as_i32(&b)); + ret as u32 + } + } + } + } +} +#[allow(dead_code)] +pub mod exports { + #[allow(dead_code)] + pub mod docs { + #[allow(dead_code)] + pub mod calculator { + #[allow(dead_code, clippy::all)] + pub mod calculate { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[repr(u8)] + #[derive(Clone, Copy, Eq, PartialEq)] + pub enum Op { + Add, + } + impl ::core::fmt::Debug for Op { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + match self { + Op::Add => f.debug_tuple("Op::Add").finish(), + } + } + } + + impl Op { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> Op { + if !cfg!(debug_assertions) { + return ::core::mem::transmute(val); + } + + match val { + 0 => Op::Add, + + _ => panic!("invalid enum discriminant"), + } + } + } + + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_eval_expression_cabi( + arg0: i32, + arg1: i32, + arg2: i32, + ) -> i32 { + #[cfg(target_arch = "wasm32")] + _rt::run_ctors_once(); + let result0 = + T::eval_expression(Op::_lift(arg0 as u8), arg1 as u32, arg2 as u32); + _rt::as_i32(result0) + } + pub trait Guest { + fn eval_expression(op: Op, x: u32, y: u32) -> u32; + } + #[doc(hidden)] + + macro_rules! __export_docs_calculator_calculate_0_1_0_cabi{ + ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { + + #[export_name = "docs:calculator/calculate@0.1.0#eval-expression"] + unsafe extern "C" fn export_eval_expression(arg0: i32,arg1: i32,arg2: i32,) -> i32 { + $($path_to_types)*::_export_eval_expression_cabi::<$ty>(arg0, arg1, arg2) + } + };); + } + #[doc(hidden)] + pub(crate) use __export_docs_calculator_calculate_0_1_0_cabi; + } + } + } +} +mod _rt { + + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + + pub trait AsI32 { + fn as_i32(self) -> i32; + } + + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen_rt::run_ctors_once(); + } +} + +/// Generates `#[no_mangle]` functions to export the specified type as the +/// root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! export{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// export!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] + +macro_rules! __export_calculator_impl { + ($ty:ident) => (self::export!($ty with_types_in self);); + ($ty:ident with_types_in $($path_to_types_root:tt)*) => ( + $($path_to_types_root)*::exports::docs::calculator::calculate::__export_docs_calculator_calculate_0_1_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::docs::calculator::calculate); + ) +} +#[doc(inline)] +pub(crate) use __export_calculator_impl as export; + +#[cfg(target_arch = "wasm32")] +#[link_section = "component-type:wit-bindgen:0.25.0:calculator:encoded world"] +#[doc(hidden)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 308] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xb3\x01\x01A\x02\x01\ +A\x04\x01B\x02\x01@\x02\x01ay\x01by\0y\x04\0\x03add\x01\0\x03\x01\x14docs:adder/\ +add@0.1.0\x05\0\x01B\x04\x01m\x01\x03add\x04\0\x02op\x03\0\0\x01@\x03\x02op\x01\x01\ +xy\x01yy\0y\x04\0\x0feval-expression\x01\x02\x04\x01\x1fdocs:calculator/calculat\ +e@0.1.0\x05\x01\x04\x01\x20docs:calculator/calculator@0.1.0\x04\0\x0b\x10\x01\0\x0a\ +calculator\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070\ +.208.1\x10wit-bindgen-rust\x060.25.0"; + +#[inline(never)] +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/component-model/examples/tutorial/calculator/src/lib.rs b/component-model/examples/tutorial/calculator/src/lib.rs index fed827f..9ea0247 100644 --- a/component-model/examples/tutorial/calculator/src/lib.rs +++ b/component-model/examples/tutorial/calculator/src/lib.rs @@ -1,9 +1,10 @@ -cargo_component_bindings::generate!(); +#[allow(warnings)] +mod bindings; use bindings::exports::docs::calculator::calculate::{Guest, Op}; // Bring the imported add function into scope -use bindings::docs::calculator::add::add; +use bindings::docs::adder::add::add; struct Component; @@ -14,3 +15,5 @@ impl Guest for Component { } } } + +bindings::export!(Component with_types_in bindings); diff --git a/component-model/examples/tutorial/command/Cargo-component.lock b/component-model/examples/tutorial/command/Cargo-component.lock deleted file mode 100644 index 00bc239..0000000 --- a/component-model/examples/tutorial/command/Cargo-component.lock +++ /dev/null @@ -1,3 +0,0 @@ -# This file is automatically generated by cargo-component. -# It is not intended for manual editing. -version = 1 diff --git a/component-model/examples/tutorial/command/Cargo.lock b/component-model/examples/tutorial/command/Cargo.lock index 39dbab4..a5dffcc 100644 --- a/component-model/examples/tutorial/command/Cargo.lock +++ b/component-model/examples/tutorial/command/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", @@ -18,33 +18,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys", @@ -52,15 +52,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "bitflags" @@ -68,46 +62,21 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" -[[package]] -name = "cargo-component-bindings" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "cargo-component-macro", - "wit-bindgen", -] - -[[package]] -name = "cargo-component-macro" -version = "0.1.0" -source = "git+https://github.com/bytecodealliance/cargo-component#86ccf3e9e57885784d5a32dcbb162813d5c820ba" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - [[package]] name = "clap" -version = "4.4.1" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.4.1" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", @@ -117,9 +86,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.0" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -129,9 +98,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -144,188 +113,32 @@ name = "command" version = "0.1.0" dependencies = [ "anyhow", - "cargo-component-bindings", "clap", + "wit-bindgen-rt", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "id-arena" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f478948fd84d9f8e86967bf432640e46adfb5a4bd4f14ef7e864ab38220534ae" - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] -[[package]] -name = "pulldown-cmark" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" -dependencies = [ - "bitflags 1.3.2", - "memchr", - "unicase", -] - [[package]] name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "spdx" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71" -dependencies = [ - "smallvec", ] [[package]] @@ -336,143 +149,41 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "url" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-encoder" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-metadata" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08dc59d1fa569150851542143ca79438ca56845ccb31696c70225c638e063471" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "serde_json", - "spdx", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.112.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e986b010f47fcce49cf8ea5d5f9e5d2737832f12b53ae8ae785bbe895d0877bf" -dependencies = [ - "indexmap", - "semver", -] - [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -485,136 +196,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "wit-bindgen" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a3e8e965dc50e6eb4410d9a11720719fadc6a1713803ea5f3be390b81c8279" -dependencies = [ - "bitflags 2.4.0", - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77255512565dfbd0b61de466e854918041d1da53c7bc049d6188c6e02643dc1e" -dependencies = [ - "anyhow", - "wit-component", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c60e6ea8598d1380e792f13d557007834f0fb799fea6503408cbc5debb4ae" -dependencies = [ - "anyhow", - "heck", - "wasm-metadata", - "wit-bindgen-core", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-lib" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fb7a43c7dc28b0b727d6ae01bf369981229b7539e768fba2b7a4df13feeeb" -dependencies = [ - "heck", - "wit-bindgen-core", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.11.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cea5ed784da06da0e55836a6c160e7502dbe28771c2368a595e8606243bf22" -dependencies = [ - "anyhow", - "proc-macro2", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", - "wit-bindgen-rust-lib", - "wit-component", -] - -[[package]] -name = "wit-component" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d9f2d16dd55d1a372dcfd4b7a466ea876682a5a3cb97e71ec9eef04affa876" -dependencies = [ - "anyhow", - "bitflags 2.4.0", - "indexmap", - "log", - "serde", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] -name = "wit-parser" -version = "0.11.0" +name = "wit-bindgen-rt" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e8b849bea13cc2315426b16efe6eb6813466d78f5fde69b0bb150c9c40e0dc" +checksum = "3b0780cf7046630ed70f689a098cd8d56c5c3b22f2a7379bbdb088879963ff96" dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "pulldown-cmark", - "semver", - "unicode-xid", - "url", + "bitflags", ] diff --git a/component-model/examples/tutorial/command/Cargo.toml b/component-model/examples/tutorial/command/Cargo.toml index 1588b3f..98ef459 100644 --- a/component-model/examples/tutorial/command/Cargo.toml +++ b/component-model/examples/tutorial/command/Cargo.toml @@ -3,13 +3,14 @@ name = "command" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] anyhow = "1" -cargo-component-bindings = { git = "https://github.com/bytecodealliance/cargo-component" } +wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] } clap = { version = "4.3.19", features = ["derive"] } [package.metadata.component.target] -path = "../wit/calculator.wit" +path = "../wit/calculator" world = "app" + +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } diff --git a/component-model/examples/tutorial/command/src/bindings.rs b/component-model/examples/tutorial/command/src/bindings.rs new file mode 100644 index 0000000..506e36d --- /dev/null +++ b/component-model/examples/tutorial/command/src/bindings.rs @@ -0,0 +1,153 @@ +// Generated by `wit-bindgen` 0.25.0. DO NOT EDIT! +// Options used: +#[allow(dead_code)] +pub mod docs { + #[allow(dead_code)] + pub mod calculator { + #[allow(dead_code, clippy::all)] + pub mod calculate { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[repr(u8)] + #[derive(Clone, Copy, Eq, PartialEq)] + pub enum Op { + Add, + } + impl ::core::fmt::Debug for Op { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + match self { + Op::Add => f.debug_tuple("Op::Add").finish(), + } + } + } + + impl Op { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> Op { + if !cfg!(debug_assertions) { + return ::core::mem::transmute(val); + } + + match val { + 0 => Op::Add, + + _ => panic!("invalid enum discriminant"), + } + } + } + + #[allow(unused_unsafe, clippy::all)] + pub fn eval_expression(op: Op, x: u32, y: u32) -> u32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "docs:calculator/calculate@0.1.0")] + extern "C" { + #[link_name = "eval-expression"] + fn wit_import(_: i32, _: i32, _: i32) -> i32; + } + + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32, _: i32, _: i32) -> i32 { + unreachable!() + } + let ret = wit_import(op.clone() as i32, _rt::as_i32(&x), _rt::as_i32(&y)); + ret as u32 + } + } + } + } +} +mod _rt { + + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + + pub trait AsI32 { + fn as_i32(self) -> i32; + } + + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } +} + +#[cfg(target_arch = "wasm32")] +#[link_section = "component-type:wit-bindgen:0.25.0:app:encoded world"] +#[doc(hidden)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 246] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07}\x01A\x02\x01A\x02\x01\ +B\x04\x01m\x01\x03add\x04\0\x02op\x03\0\0\x01@\x03\x02op\x01\x01xy\x01yy\0y\x04\0\ +\x0feval-expression\x01\x02\x03\x01\x1fdocs:calculator/calculate@0.1.0\x05\0\x04\ +\x01\x19docs:calculator/app@0.1.0\x04\0\x0b\x09\x01\0\x03app\x03\0\0\0G\x09produ\ +cers\x01\x0cprocessed-by\x02\x0dwit-component\x070.208.1\x10wit-bindgen-rust\x06\ +0.25.0"; + +#[inline(never)] +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/component-model/examples/tutorial/command/src/main.rs b/component-model/examples/tutorial/command/src/main.rs index 9a91fd6..055fffb 100644 --- a/component-model/examples/tutorial/command/src/main.rs +++ b/component-model/examples/tutorial/command/src/main.rs @@ -1,6 +1,7 @@ -cargo_component_bindings::generate!(); +mod bindings; + use clap::Parser; -use std::{fmt}; +use std::fmt; use bindings::docs::calculator::{calculate, calculate::Op}; diff --git a/component-model/examples/tutorial/composition.wac b/component-model/examples/tutorial/composition.wac new file mode 100644 index 0000000..5372746 --- /dev/null +++ b/component-model/examples/tutorial/composition.wac @@ -0,0 +1,20 @@ +// Provide a package name for the resulting composition +package example:composition; + +// Instantiate the adder-impl component that implements the adder world. +// Bind this instance's exports to the local name `adder-instance`. +let adder-instance = new docs:adder-impl { }; + +// Instantiate the calculator-impl component that implements the calculator world. +// In the `new` expression, connect it's `add` import to the `adder-instance`'s `add` export. +let calculator-instance = new docs:calculator-impl { add: adder-instance.add }; + +// Instantiate a command-impl component that implements the app world. +// The command component might import other interfaces, such as WASI interfaces, but we want to leave +// those as imports in the final component, so supply `...` to allow those other imports to remain unresolved. +// The command's exports (in this case, `wasi:cli/run`) remain unaffected in the resulting instance. +let command-instance = new docs:command-impl { calculate: calculator-instance.calculate,... }; + +// Export the `wasi:cli/run` interface from the command instance +// This could also have been expressed using the postfix access expression `command-instance.run` +export command-instance["wasi:cli/run@0.2.0"]; \ No newline at end of file diff --git a/component-model/examples/tutorial/jco/README.md b/component-model/examples/tutorial/jco/README.md new file mode 100644 index 0000000..37875b1 --- /dev/null +++ b/component-model/examples/tutorial/jco/README.md @@ -0,0 +1,20 @@ +# Wasm Component Calculator in JavaScript + +This is a `node` CLI and browser based example implementation of running a component that exports the `calculate` interface from a JavaScript application. It uses [`jco`](https://bytecodealliance.github.io/jco/) to generate JavaScript bindings and shows how the same component can be executed in the browser or locally with Node. For another example of using `jco` with components in multiple environments, see the [`jco` example](https://github.com/bytecodealliance/jco/blob/main/docs/src/example.md). + +```sh +# Wasm referenced here was generated by cargo component. +# See top-level README for commands to generate it. +# +# We want to *omit* wasm requiring Wasi, +# thus use `composed.wasm`, not the `command.wasm`. + +# Transpile to generate bindings for JS: +jco transpile ../composed.wasm -o bindings + +# Serve required files (index.html & jco generated files minimally): +npx live-server . + +# Run CLI example: +node cli-calc.js +``` diff --git a/component-model/examples/tutorial/jco/cli-calc.js b/component-model/examples/tutorial/jco/cli-calc.js new file mode 100644 index 0000000..7c35f36 --- /dev/null +++ b/component-model/examples/tutorial/jco/cli-calc.js @@ -0,0 +1,4 @@ +// See the README for details on *generation* of the required import +import { calculate } from "./bindings/composed.js"; + +console.log("Answer (to life) = " + calculate.evalExpression("add", 21, 21)); diff --git a/component-model/examples/tutorial/jco/index.html b/component-model/examples/tutorial/jco/index.html new file mode 100644 index 0000000..9da9a08 --- /dev/null +++ b/component-model/examples/tutorial/jco/index.html @@ -0,0 +1,27 @@ + + + +

Wasm Component Demo

+ + + + + + +

+ + + + diff --git a/component-model/examples/tutorial/jco/package.json b/component-model/examples/tutorial/jco/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/component-model/examples/tutorial/jco/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/component-model/examples/tutorial/wit/adder/world.wit b/component-model/examples/tutorial/wit/adder/world.wit new file mode 100644 index 0000000..59a4685 --- /dev/null +++ b/component-model/examples/tutorial/wit/adder/world.wit @@ -0,0 +1,9 @@ +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world adder { + export add; +} \ No newline at end of file diff --git a/component-model/examples/tutorial/wit/calculator.wit b/component-model/examples/tutorial/wit/calculator/world.wit similarity index 68% rename from component-model/examples/tutorial/wit/calculator.wit rename to component-model/examples/tutorial/wit/calculator/world.wit index ebfd234..c775b84 100644 --- a/component-model/examples/tutorial/wit/calculator.wit +++ b/component-model/examples/tutorial/wit/calculator/world.wit @@ -7,17 +7,9 @@ interface calculate { eval-expression: func(op: op, x: u32, y: u32) -> u32; } -interface add { - add: func(a: u32, b: u32) -> u32; -} - -world adder { - export add; -} - world calculator { export calculate; - import add; + import docs:adder/add@0.1.0; } world app { diff --git a/component-model/src/SUMMARY.md b/component-model/src/SUMMARY.md index 8101e0f..26fe0bf 100644 --- a/component-model/src/SUMMARY.md +++ b/component-model/src/SUMMARY.md @@ -8,25 +8,35 @@ - [Why the Component Model?](./design/why-component-model.md) - [Components](./design/components.md) - [Interfaces](./design/interfaces.md) -- [WIT](./design/wit.md) - [Worlds](./design/worlds.md) +- [WIT](./design/wit.md) - [Packages](./design/packages.md) -- [Canonical ABI](./design/canonical-abi.md) # Using Component Model - [Language Support for Components](./language-support.md) - - [Rust](./language-support/rust.md) - - [Javascript](./language-support/javascript.md) + - [C/C++](./language-support/c.md) + - [C#](./language-support/csharp.md) + - [Go](./language-support/go.md) + - [JavaScript](./language-support/javascript.md) - [Python](./language-support/python.md) + - [Rust](./language-support/rust.md) - [Creating and Consuming Components](./creating-and-consuming.md) - [Authoring Components](./creating-and-consuming/authoring.md) - [Composing Components](./creating-and-consuming/composing.md) - [Running Components](./creating-and-consuming/running.md) - - [Distributing Components](./creating-and-consuming/distributing.md) + - [Distributing and Fetching Components and WIT](./creating-and-consuming/distributing.md) - [Tutorial](./tutorial.md) # Runtime Support - [Wasmtime](./runtimes/wasmtime.md) - [jco](./runtimes/jco.md) + +# Advanced Topics + +- [Canonical ABI](./advanced/canonical-abi.md) + +# Reference + +- [Useful Links](./reference/useful-links.md) diff --git a/component-model/src/design/canonical-abi.md b/component-model/src/advanced/canonical-abi.md similarity index 51% rename from component-model/src/design/canonical-abi.md rename to component-model/src/advanced/canonical-abi.md index c4d546c..2a5a0e3 100644 --- a/component-model/src/design/canonical-abi.md +++ b/component-model/src/advanced/canonical-abi.md @@ -2,6 +2,6 @@ An ABI is an **application binary interface** - an agreement on how to pass data around in a binary format. ABIs are specifically concerned with data layout at the bits-and-bytes level. For example, an ABI might define how integers are represented (big-endian or little-endian?), how strings are represented (pointer to null-terminated character sequence or length-prefixed? UTF-8 or UTF-16 encoded?), and how composite types are represented (the offsets of each field from the start of the structure). -The component model defines a **canonical ABI** - an ABI to which all [components](./components.md) adhere. This guarantees that components can talk to each other without confusion, even if they are built in different languages. Internally, a C component might represent strings in a quite different way from a Rust component, but the canonical ABI provides a format for them to pass strings across the boundary between them. +The component model defines a **canonical ABI** - an ABI to which all [components](../design/components.md) adhere. This guarantees that components can talk to each other without confusion, even if they are built in different languages. Internally, a C component might represent strings in a quite different way from a Rust component, but the canonical ABI provides a format for them to pass strings across the boundary between them. -> ⓘ For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). +> For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). diff --git a/component-model/src/creating-and-consuming/authoring.md b/component-model/src/creating-and-consuming/authoring.md index f393d4c..4e20718 100644 --- a/component-model/src/creating-and-consuming/authoring.md +++ b/component-model/src/creating-and-consuming/authoring.md @@ -2,4 +2,4 @@ You can write WebAssembly core modules in a wide variety of languages, and the set of languages that can directly create components is growing. See the [Language Support](../language-support.md) section for information on building components directly from source code. -If your preferred language supports WebAssembly but not components, you can still create components using the [`wasm-tools component`](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component) tool. (A future version of this page will cover this in more detail.) +If your preferred language supports WebAssembly but not components, you can still create components using the [`wasm-tools component`](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component) tool. (A future version of this page will cover this in more detail.) \ No newline at end of file diff --git a/component-model/src/creating-and-consuming/composing.md b/component-model/src/creating-and-consuming/composing.md index a91f84e..168cb3f 100644 --- a/component-model/src/creating-and-consuming/composing.md +++ b/component-model/src/creating-and-consuming/composing.md @@ -24,11 +24,13 @@ interface validator { validate-text: func(text: string) -> string; } -world { +world validator { export validator; import docs:regex/match@0.1.0; } +``` +```wit // component 'regex' package docs:regex@0.1.0; @@ -36,7 +38,7 @@ interface match { first-match: func(regex: string, text: string) -> string; } -world { +world regex { export match; } ``` @@ -49,25 +51,58 @@ Component composition tools are in their early stages right now. Here are some * Composition is asymmetrical. It is not just "gluing components together" - it takes a primary component which has imports, and satisfies its imports using dependency components. For example, composing an implementation of `validator` with an implementation of `regex` makes sense because `validator` has a dependency that `regex` can satisfy; doing it the other way round doesn't work, because `regex` doesn't have any dependencies, let alone ones that `validator` can satisfy. * Composition cares about interface versions, and current tools are inconsistent about when they infer or inject versions. For example, if a Rust component exports `test:mypackage`, `cargo component build` will decorate this with the crate version, e.g. `test:mypackage@0.1.0`. If another Rust component _imports_ an interface from `test:mypackage`, that won't match `test:mypackage@0.1.0`. You can use [`wasm-tools component wit`](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component) to view the imports and exports embedded in the `.wasm` files and check whether they match up. -## Composing components with `wasm-tools` +## Composing components with WAC -The [`wasm-tools` suite](https://github.com/bytecodealliance/wasm-tools) includes a `compose` command which can be used to compose components at the command line. +You can use the [WAC](https://github.com/bytecodealliance/wac) CLI to compose components at the command line. -To compose a component with the components it directly depends on, run: +To perform quick and simple compositions, use the `wac plug` command. `wac plug` satisfies the import of a "socket" component by plugging a "plug" component's export into the socket. For example, a component that implements the [`validator` world above](#what-is-composition) needs to satisfy it's `match` import. It is a socket. While a component that implements the `regex` world, exports the `match` interface, and can be used as a plug. `wac plug` can plug a regex component's export into the validator component's import, creating a resultant composition: +```sh +wac plug validator-component.wasm --plug regex-component.wasm -o composed.wasm ``` -wasm-tools compose path/to/component.wasm -d path/to/dep1.wasm -d path/to/dep2.wasm -o composed.wasm + +A component can also be composed with two components it depends on. + +```sh +wac plug path/to/component.wasm --plug path/to/dep1.wasm --plug path/to/dep2.wasm -o composed.wasm ``` Here `component.wasm` is the component that imports interfaces from `dep1.wasm` and `dep2.wasm`, which export them. The composed component, with those dependencies satisfied and tucked away inside it, is saved to `composed.wasm`. -> This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) +The `plug` syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'd need to be deliberate about the order of your composition. You could compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. However, this doesn't scale to lots of transitive dependencies, which is why the WAC language was created. + +### Advanced composition with the WAC language + +`wac plug` is a convenience to achieve a common pattern in component compositions like above. However, composition can be arbitrarily complicated. In cases where `wac plug` is not sufficient, the [WAC language](https://github.com/bytecodealliance/wac/blob/main/LANGUAGE.md) can give us the ability to create arbitrarily complex compositions. + +In a WAC file, you use the WAC language to describe a composition. For example, the following is a WAC file that could be used to create that validator component from [earlier](#what-is-composition). + +``` +//composition.wac +// Provide a package name for the resulting composition +package docs:composition; + +// Instantiate the regex-impl component that implements the `regex` world. Bind this instance's exports to the local name `regex`. +let regex = new docs:regex-impl { }; + +// Instantiate the validator-impl component which implements the `validator` world and imports the match interface from the regex component. +let validator = new docs:validator-impl { match: regex.match, ... }; + +// Export all remaining exports of the validator instance +export validator...; +``` + +Then, `wac compose` can be used to compose the components, passing in the paths to the components. Alternatively, you can place the components in a `deps` directory with an expected structure, and in the near future, you will be able to pull in components from registries. See the [`wac` documentation](https://github.com/bytecodealliance/wac) for more details. + +```sh +wac compose --dep docs:regex-impl=regex-component.wasm --dep docs:validator-impl=validator-component.wasm -o composed.wasm composition.wac +``` -For full information about `wasm-tools compose` including how to configure more advanced scenarios, see [the `wasm-tools compose` documentation](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-compose). +For an in depth description about how to use the wac tool, you can check out the [wac language index](https://github.com/bytecodealliance/wac/blob/main/LANGUAGE.md) and [examples](https://github.com/bytecodealliance/wac/tree/main/examples). ## Composing components with a visual interface -You can compose components visually using the builder app at https://wasmbuilder.app/. +You can compose components visually using the builder app at [wasmbuilder.app](https://wasmbuilder.app/). 1. Use the Add Component Button to upload the `.wasm` component files you want to compose. The components appear in the sidebar. diff --git a/component-model/src/creating-and-consuming/distributing.md b/component-model/src/creating-and-consuming/distributing.md index 3abdc3c..1b7142a 100644 --- a/component-model/src/creating-and-consuming/distributing.md +++ b/component-model/src/creating-and-consuming/distributing.md @@ -1,7 +1,158 @@ -# Distributing Components +# Distributing and Fetching Components and WIT Modern applications rely extensively on third-party packages - so extensively that distributing packages is almost an industry in itself. Traditionally, these have been specific to a language. For example, JavaScript developers are used to using packages from NPM, and Rust developers use `crates.io`. Some runtimes support binary distribution and linking, enabling limited cross-language interop; for example, Maven packages can be written in any language that targets the Java runtime. Services like this are variously referred to as "package managers" or "registries." -Publishing and distribution are not defined by the core component model, but will form an important part of the component ecosystem. For example, if you're writing JavaScript, and want to pull in a highly optimised machine learning algorithm written in C and compiled to Wasm, you should be able to invoke it from a registry, just as easily as you would add a NPM package from the NPM registry. +Publishing and distribution are not defined by the core component model, but form important part of the component ecosystem. For example, if you're writing JavaScript, and want to pull in a highly optimised machine learning algorithm written in C and compiled to Wasm, you can pull it from a registry, ideally just as easily as you would add a NPM package from the NPM registry. -Publishing and distribution is a work in progress. The proposed registry protocol is [warg](https://warg.io/), but this is still in development, and there are no public warg registries as yet. You can find more information about the development of the registry protocol [here](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-Registries/proposal.md). +You can get involved with improving the packaging and hosting of Wasm components by joining the [Bytecode Alliance Packaging Special Interest Group (SIG)](https://github.com/bytecodealliance/governance/blob/main/SIGs/sig-packaging/proposal.md). + +## The `wkg` Registry Tool + +The [`wasm-pkg-tools` project](https://github.com/bytecodealliance/wasm-pkg-tools) enables fetching and publishing Wasm components to OCI registries. It contains a `wkg` CLI tool that eases distributing and fetching components and WIT packages. The usual way of using `wkg` is to address packages by their package name, i.e. `example:adder@1.0.0`. When using `wkg` this way, you don't need to know about the physical location of the package, as the `wkg` configuration handles that for you. If you need to, though, you can also use `wkg` to work with OCI artifacts directly, addressing them by OCI references when using the `wkg oci` subcommand. + +`wkg` contains several subcommand: + +- `wkg oci` - pushes/pulls Wasm artifacts to/from any OCI registry +- `wkg publish` - publish components or WIT packages by package name +- `wkg get` - pulls components or WIT packages by package name +- `wkg wit` - commands for interacting with WIT files and dependencies +- `wkg config` - interact with the `wkg` configuration + +The following sections detail a subset of actions that can be performed with `wkg`. + +## `wkg` Configuration Files + +When you use most `wkg` commands (`wkg oci` being the exception), you don't interact with physical locations, only with package names. The `wkg` configuration file is used to map package naming to physical location. It provides the ability to configure: + +- The default registry for packages in a given namespace. For example, the location for `wasi` packages such as `wasi:clocks` or `wasi:http`. +- Registry overrides for specific packages, or packages not stored in the same place as the rest of their namespace. For example, if `wasi:key-value` were stored in a different registry from other `wasi` packages. +- The default registry for all packages not listed in one of the previous sections + +The configuration file also includes credentials for private registries, or for pushing to registries where you have permission, and other configuration options. See the [`wkg` docs for more configuration options](https://github.com/bytecodealliance/wasm-pkg-tools?tab=readme-ov-file#configuration). + +For example, to fetch WASI packages, such as `wasi:clocks` and `wasi:http`, you can add a line under the `namespace_registries` section for the `wasi` namespace. Specifically, the example below configures `wkg` to fetch WASI packages from the [WebAssembly OCI GitHub Container Registry](https://github.com/orgs/WebAssembly/packages), where the latest interfaces are published upon WASI releases. To edit your `wkg` config file, run `wkg config --edit`. + +> Remember, all package names consist of the a namespace field followed by the package field. The package name `wasi:clocks` has a namespace of `wasi` and package field of `clocks`. In this way, the following configuration ensures that `wkg` will know to route fetches and publishes of any `wasi:` to the configured location. + +```toml +# $XDG_CONFIG_HOME/wasm-pkg/config.toml +default_registry = "ghcr.io" + +[namespace_registries] +# Tell wkg that packages with the `wasi` namespace are in an OCI registry under ghcr.io/webassembly +wasi = { registry = "wasi", metadata = { preferredProtocol = "oci", "oci" = {registry = "ghcr.io", namespacePrefix = "webassembly/" } } } +``` + +As a more generic example, The following configuration, instructs `wkg` to use [ttl.sh](https://ttl.sh/) OCI registry for all packages with the `docs` namespace. + +```toml +# $XDG_CONFIG_HOME/wasm-pkg/config.toml +default_registry = "ghcr.io" + +[namespace_registries] +# Instruct wkg to use the OCI protocol to fetch packages with the `foo` namespace from ttl.sh/wasm-components +docs = { registry = "docs-registry", metadata = { preferredProtocol = "oci", "oci" = {registry = "ttl.sh", namespacePrefix = "wasm-components/" } } } +``` + +> Note: the registry name can be referenced in the `package_registry_overrides` section of the `wkg` config to provide overrides for specific packages of a namespace. + +## Distributing WIT and Components by Package Name with `wkg publish` + +Once you've [configured `wkg`](#wkg-configuration-files) to know where to publish packages to, you can use the `wkg publish` command to publish *components* or *interfaces* to be consumed by others. + +Imagine you have defined the following `adder` world in WIT: + +```wit +package docs:adder@0.1.0; + +interface add { + add: func(a: u32, b: u32) -> u32; +} + +world adder { + export add; +} +``` + +You can publish this *WIT* using `wkg` by wrapping it up as a Wasm component. Yes, you heard that right! We are packaging WIT as Wasm. + +```sh +# Package the contents of add WIT directory as Wasm +wkg wit build --wit-dir tutorial/wit/adder +# Publish the produced component +wkg publish docs:adder@0.1.0.wasm +``` + +If you had configured `wkg` as described in the [`wkg` configuration section](#wkg-configuration-files), this would publish the component to `ttl.sh/wasm-components/docs/adder:0.1.0`. This WIT can then be fetched using `wkg get`, specifying the format `wit`: + +```sh +wkg get --format wit docs:adder@0.1.0 --output adder.wit +``` + +Instead of publishing the WIT interface, you could publish the built component by running: + +```sh +wkg publish adder.wasm --package docs:adder@0.1.0 +``` + +You can then fetch the component by running: + +```sh +wkg get docs:adder@0.1.0 --output adder.wasm +``` + +## More Generic Operations with `wkg oci` + +The `wkg oci` subcommand enables pushing/pulling Wasm artifacts to/from any OCI registry. Unlike `wkg publish` and `wkg get`, providing the WIT package is not required. + +To push a component to an OCI registry, use `wkg oci pull`. The example below pushes a component to a GitHub Container Registry. + +```sh +wkg oci push ghcr.io/user/component:0.1.0 component.wasm +``` + +To pull a component, run: + +```sh +wkg oci pull ghcr.io/user/component:0.1.0 -o component.wasm +``` + +## Fetching WIT Package Dependencies using `wkg` + +Sometimes fetching a single package is not sufficient because it depends on other packages. For example, the following world describes a simple Wasm service which requires `wasi:http/proxy`: + +```wit +package foo:wasi-http-service; + +world target-world { + include wasi:http/proxy@0.2.3; +} +``` + +You may be tempted to simply get the `wasi:http` package with `wkg get --format wit wasi:http@0.2.3 -o wit/deps/http/`. However, `wasi:http` depends on other WASI packages such as `wasi:clocks` and `wasi:io`. To make sure to fetch a package and all its dependencies, use `wkg wit fetch`, which will read the package containing the world(s) you have defined in the given wit directory (`wit` by default). It will then fetch the +dependencies and write them to the `deps` directory along with a lock file. + +After placing the above file in `./wit`, run the following to fetch the dependencies: + +```sh +wkg wit fetch +``` + +The `./wit` directory will be populated as follows: +```sh +wit +├── deps +│ ├── wasi-cli-0.2.3 +│ │ └── package.wit +│ ├── wasi-clocks-0.2.3 +│ │ └── package.wit +│ ├── wasi-http-0.2.3 +│ │ └── package.wit +│ ├── wasi-io-0.2.3 +│ │ └── package.wit +│ └── wasi-random-0.2.3 +│ └── package.wit +└── world.wit +``` + +Now, you can use the language toolchain of your choice to generate bindings and create your component. \ No newline at end of file diff --git a/component-model/src/creating-and-consuming/running.md b/component-model/src/creating-and-consuming/running.md index 41d65ba..a76398b 100644 --- a/component-model/src/creating-and-consuming/running.md +++ b/component-model/src/creating-and-consuming/running.md @@ -6,28 +6,26 @@ You can "run" a component by calling one of its exports. In some cases, this req You must use a recent version of `wasmtime` ([`v14.0.0` or greater](https://github.com/bytecodealliance/wasmtime/releases)), as earlier releases of the `wasmtime` command line do not include component model support. -> If you build the `wasmtime` CLI from source, you must pass `--features component-model` to the build command. - To run your component, run: ```sh -wasmtime run --wasm component-model +wasmtime run ``` ## Running components with custom exports If you're writing a library-style component - that is, one that exports a custom API - then you can run it in `wasmtime` by writing a "command" component that imports and invokes your custom API. By [composing](./composing.md) the command and the library, you can exercise the library in `wasmtime`. -1. Write your library component. The component's world (`.wit` file) must export an interface. (Do not export functions directly, only interfaces.) See the [language support guide](../language-support.md) for how to implement an export. +1. Write your library component. The component's world (`.wit` file) must export an interface and/or one or more functions through which a consumer can call it. See the [language support guide](../language-support.md) for how to implement an export. 2. Build your library component to a `.wasm` file. -3. Write your command component. The component's world (`.wit` file) must import the interface exported from the library. Write the command to call the library's API. See the [language support guide](../language-support.md) for how to call an imported interface. +3. Write your command component. The component's world (`.wit` file) must import the interface or functions exported from the library. Write the command to call the library's API. See the [language support guide](../language-support.md) for how to call an imported interface. 4. Build your command component to a `.wasm` file. You will not be able to run this in `wasmtime` yet, as its imports are not yet satisfied. -5. Compose your command component with your library component by running `wasm-tools compose -d -o main.wasm`. +5. Compose your command component with your library component by running `wac plug --plug -o main.wasm`. -6. Run the composed component using `wasmtime run --wasm component-model main.wasm` +6. Run the composed component using `wasmtime run main.wasm` See [Composing Components](./composing.md) for more details. diff --git a/component-model/src/design/components.md b/component-model/src/design/components.md index ce65626..53cfb1a 100644 --- a/component-model/src/design/components.md +++ b/component-model/src/design/components.md @@ -1,9 +1,9 @@ # Components -* Logically, components are containers for modules - or other components - which express their [interfaces](./interfaces.md) and dependencies via [WIT](./wit.md) and the [Canonical ABI](./canonical-abi.md). +* Logically, components are containers for modules - or other components - which express their [interfaces](./interfaces.md) and dependencies via [WIT](./wit.md). * Conceptually, components are self-describing units of code that interact only through interfaces instead of shared memory. * Physically, a **component** is a specially-formatted WebAssembly file. Internally, the component could include multiple traditional ("core") WebAssembly modules, and sub-components, composed via their imports and exports. The external interface of a component - its imports and exports - corresponds to a [world](./worlds.md). The component, however, internally defines how that world is implemented. -> ⓘ For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). +> For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). diff --git a/component-model/src/design/interfaces.md b/component-model/src/design/interfaces.md index eac851c..69f3c57 100644 --- a/component-model/src/design/interfaces.md +++ b/component-model/src/design/interfaces.md @@ -7,4 +7,4 @@ An **interface** describes a single-focus, composable contract, through which co Interfaces are defined using [the WIT language](./wit.md). -> ⓘ For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/packages.md b/component-model/src/design/packages.md index 3a9a4a3..295c96a 100644 --- a/component-model/src/design/packages.md +++ b/component-model/src/design/packages.md @@ -6,4 +6,4 @@ A WIT package is not a [world](./worlds.md). It's a way of grouping related inte * The WebAssembly System Interface (WASI) defines a number of packages, including one named `wasi:clocks`. Our HTTP proxy world could import the `wall-clock` interface from the `wasi:clocks` package, rather than having to define a custom clock interface. -> ⓘ For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/why-component-model.md b/component-model/src/design/why-component-model.md index 3702fb4..4882d79 100644 --- a/component-model/src/design/why-component-model.md +++ b/component-model/src/design/why-component-model.md @@ -1,19 +1,19 @@ # Why the Component Model? -If you've tried out WebAssembly, you'll be familiar with the concept of a _module_. Roughly speaking, a module corresponds to a single `.wasm` file, with functions, memory, imports and exports, and so on. These "core" modules can run in the browser, or via a separate runtime such as Wasmtime or WAMR. A module is defined by the [WebAssembly Core Specification](https://webassembly.github.io/spec/core/), and if you compile a program written in Rust, C, Go or whatever for the browser, then a core module is what you'll get. +If you've tried out WebAssembly, you'll be familiar with the concept of a _module_. Roughly speaking, a module corresponds to a single `.wasm` file, with functions, memory, imports and exports, and so on. These "core" modules can run in the browser, or via a separate runtime such as Wasmtime or WAMR. A module is defined by the [WebAssembly Core Specification](https://webassembly.github.io/spec/core/), and if you compile a program written in Rust, C, Go or whatever to WebAssembly, then a core module is what you'll get. -Core modules are, however, limited to describing themselves in terms of a small number of core WebAssembly types such as integers and floating-point numbers. Just as in native assembly code, richer types, such as strings or records (structs), have to be represented in terms of integers and floating point numbers, for example by the use of pointers and offsets. And just as in native code, those representations are not interchangeable. A string in C might be represented entirely differently from a string in Rust, or a string in JavaScript. +Core modules are, however, limited in how they expose their functionality to the outside world to functions that take and return only a small number of core WebAssembly types (essentially only integers and floating-point numbers). Richer types, such as strings, lists, records (a.k.a. structs), etc. have to be represented in terms of integers and floating point numbers, for example by the use of pointers and offsets. Those representations are often times not interchangeable across languages. For example, a string in C might be represented entirely differently from a string in Rust or in JavaScript. -For Wasm modules to interoperate, therefore, there needs to be an agreed-upon way for defining those richer types, and an agreed-upon way of expressing them at module boundaries. +For Wasm modules to interoperate, therefore, there needs to be an agreed-upon way for exposing those richer types across module boundaries. -In the component model, these type definitions are written in a language called [WIT (Wasm Interface Type)](./wit.md), and the way they translate into bits and bytes is called the [Canonical ABI (Application Binary Interface)](./canonical-abi.md). A Wasm [component](./components.md) is thus a wrapper around a core module that specifies its imports and outputs using such [Interfaces](./interfaces.md). +In the component model, these type definitions are written in a language called [WIT (Wasm Interface Type)](./wit.md), and the way they translate into bits and bytes is called the [Canonical ABI (Application Binary Interface)](./../advanced/canonical-abi.md). A Wasm [component](./components.md) is thus a wrapper around a core module that specifies its imports and exports using such [Interfaces](./interfaces.md). -The agreement of an interface adds a new dimension to Wasm portability. Not only are components portable across architectures and operating systems, but they are now portable across languages. A Go component can communicate directly and safely with a C or Rust component. It need not even know which language another component was written in - it needs only the component interface, expressed in WIT. Additionally, components can be linked into larger graphs, with one component satisfying another's dependencies, and deployed as units. +The agreement of an interface adds a new dimension to Wasm portability. Not only are components portable across architectures and operating systems, but they are now portable across languages. A Go component can communicate directly and safely with a C or Rust component. It need not even know which language another component was written in - it needs only the component interface, expressed in WIT. Additionally, components can be linked into larger graphs, with one component's exports satisfying another's imports. Combined with Wasm's strong sandboxing, this opens the door to yet further benefits. By expressing higher-level semantics than integers and floats, it becomes possible to statically analyse and reason about a component's behaviour - to enforce and guarantee properties just by looking at the surface of the component. The relationships within a graph of components can be analysed, for example to verify that a component containing business logic has no access to a component containing personally identifiable information. -Moreover, components interact _only_ through the Canonical ABI. Specifically, unlike core modules, components may not export Wasm memory. This not only reinforces sandboxing, but enables interoperation between languages that make different assumptions about memory - for example, allowing a component that relies on Wasm GC (garbage collected) memory to collaborate with one that uses conventional linear memory. +Moreover, a component interacts with a runtime or other components _only_ by calling its imports and having its exports called. Specifically, unlike core modules, a component may not export Wasm memory, and thus it cannot indirectly communicate to others by writing to its memory and having others read from that memory. This not only reinforces sandboxing, but enables interoperation between languages that make different assumptions about memory - for example, allowing a component that relies on Wasm GC (garbage collected) memory to collaborate with one that uses conventional linear memory. Now that you have a better idea about how the component model can help you, take a look at [how to build components](../language-support.md) in your favorite language! -> ⓘ For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). +> For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index c1e0c24..9315c03 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -1,6 +1,6 @@ # An Overview of WIT -The WIT (Wasm Interface Type) language is used to define Component Model interfaces and worlds. WIT isn't a general-purpose coding language and doesn't define behaviour; it defines only _contracts_ between components. This topic provides an overview of key elements of the WIT language. +The WIT (Wasm Interface Type) language is used to define Component Model [interfaces](#interfaces) and [worlds](#worlds). WIT isn't a general-purpose coding language and doesn't define behaviour; it defines only _contracts_ between components. This topic provides an overview of key elements of the WIT language. The official WIT specification and history can be found in the [`WebAssembly/component-model` repository](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). - [An Overview of WIT](#an-overview-of-wit) - [Structure of a WIT file](#structure-of-a-wit-file) @@ -17,6 +17,7 @@ The WIT (Wasm Interface Type) language is used to define Component Model interfa - [Records](#records) - [Variants](#variants) - [Enums](#enums) + - [Resources](#resources) - [Flags](#flags) - [Type aliases](#type-aliases) - [Functions](#functions) @@ -90,27 +91,29 @@ WIT defines the following primitive types: | Identifier | Description | |----------------------------|-------------| -| `bool` | Boolean value - true or false. | -| `s8`, `s16`, `s32`, `s64` | Signed integers of the appropriate width. For example, `s32` is a 32-bit integer. | -| `u8`, `u16`, `u32`, `u64` | Unsigned integers of the appropriate width. For example, `u32` is a 32-bit integer. | -| `float32`, `float64` | Floating-point numbers of the appropriate width. For example, `float64` is a 64-bit (double precision) floating-point number. | +| `bool` | Boolean value `true` or `false`. | +| `s8`, `s16`, `s32`, `s64` | Signed integers of the appropriate width. For example, `s32` is a signed 32-bit integer. | +| `u8`, `u16`, `u32`, `u64` | Unsigned integers of the appropriate width. For example, `u32` is an unsigned 32-bit integer. | +| `f32`, `f64` | Floating-point numbers of the appropriate width. For example, `f64` is a 64-bit (double precision) floating-point number. See the note on `NaN`s below. | | `char` | Unicode character. (Specifically, a [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value).) | | `string` | A Unicode string - that is, a finite sequence of characters. | +> The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. + ### Lists -`list` for any type T denotes an ordered sequence of values of type T. T can be any type, built-in or user-defined: +`list` for any type `T` denotes an ordered sequence of values of type `T`. `T` can be any type, built-in or user-defined: ```wit -list // byte buffer -list // a list of customers +list // byte buffer +list // a list of customers ``` This is similar to Rust `Vec`, or Java `List`. ### Options -`option` for any type T may contain a value of type T, or may contain no value. T can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found: +`option` for any type `T` may contain a value of type `T`, or may contain no value. `T` can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found: ```wit option @@ -122,7 +125,7 @@ This is similar to Rust `Option`, C++ `std::optional`, or Haskell `Maybe`. ### Results -`result` for any types T and E may contain a value of type T _or_ a value of type E (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the T type) representing a HTTP response, and the error case (the E type) representing the various kinds of error that might occur: +`result` for any types `T` and `E `may contain a value of type `T` _or_ a value of type `E` (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the `T` type) representing a HTTP response, and the error case (the `E` type) representing the various kinds of error that might occur: ```wit result @@ -142,11 +145,11 @@ result // no data associated with either case ### Tuples -A tuple type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. +A `tuple` type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. ```wit -tuple // An integer and a string -tuple // An integer, then a string, then an integer +tuple // An integer and a string +tuple // An integer, then a string, then an integer ``` This is similar to tuples in Rust or OCaml. @@ -157,7 +160,7 @@ You can define your own types within an `interface` or `world`. WIT offers sever ### Records -A record type declares a set of named fields, each of the form `name: type`, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows: +A `record` type declares a set of named fields, each of the form `name: type`, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows: ```wit record customer { @@ -174,7 +177,7 @@ Records are similar to C or Rust `struct`s. ### Variants -A variant type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows: +A `variant` type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows: ```wit variant allowed-destinations { @@ -190,7 +193,7 @@ Variants are similar to Rust `enum`s or OCaml discriminated unions. The closest ### Enums -An enum type is a variant type where none of the cases have associated data: +An `enum` type is a variant type where none of the cases have associated data: ```wit enum color { @@ -200,11 +203,61 @@ enum color { } ``` -This can provide a simpler representation in languages without discriminated unions. For example, a WIT enum can translate directly to a C++ `enum`. +This can provide a simpler representation in languages without discriminated unions. For example, a WIT `enum` can translate directly to a C++ `enum`. + +### Resources + +Resources are handles to some entity that lives outside of the component. They +describe things that can't or shouldn't be copied by value; instead, their +ownership or reference can be passed between two components via a handle. Unlike +other WIT types which are simply plain data, resources only expose behavior +through methods. Resources can be thought of as _objects that implement_ an +interface. + +For example, we could model a blob (binary large object) as a resource. The +following WIT defines the `blob` resource type, which contains a constructor, +two methods, and a static function: + +```wit +resource blob { + constructor(init: list); + write: func(bytes: list); + read: func(n: u32) -> list; + merge: static func(lhs: blob, rhs: blob) -> blob; +} +``` + +As shown in the `blob` example, a resource can contain: + +- _methods_: functions that implicitly take a `self` (often called `this` in many languages) +parameter that is a handle +- _static functions_: functions which do not have an implicit `self` parameter +but are meant to be nested in the scope of the resource type +- at most one _constructor_: a function that is syntactic sugar for a function +returning a handle of the containing resource type + +Methods always desugar to a borrowed `self` parameter whereas constructors +always desugar to an owned return value. For example, the `blob` resource +[above](#resources) could be approximated as: + +```wit +resource blob; +blob-constructor: func(bytes: list) -> blob; +blob-write: func(self: borrow, bytes: list); +blob-read: func(self: borrow, n: u32) -> list; +blob-merge: static func(lhs: blob, rhs: blob) -> blob; +``` + +When a `resource` type name is wrapped with `borrow<...>`, it stands for a +"borrowed" resource. A borrowed resource represents a temporary loan of a resource from the +caller to the callee for the duration of the call. In contrast, when the owner +of an owned resource drops that resource, the resource is destroyed. + +> More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). ### Flags -A flags type is a set of named booleans. In an instance of the type, each flag will be either true or false. +A `flags` type is a set of named booleans. In an instance of the type, each flag will be either `true` or `false`. ```wit flags allowed-methods { @@ -215,7 +268,7 @@ flags allowed-methods { } ``` -> A flags type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. +> A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. ### Type aliases @@ -312,8 +365,10 @@ interface error-reporter { world multi-function-device { // The component implements the `printer` interface export printer; + // The component implements the `scan` function export scan: func() -> list; + // The component needs to be supplied with an `error-reporter` import error-reporter; } @@ -352,8 +407,10 @@ You can `include` another world. This causes your world to export all that world ```wit world glow-in-the-dark-multi-function-device { - // The component provides all the same exports, and depends on all the same imports, as a `multi-function-device`... + // The component provides all the same exports, and depends on + // all the same imports, as a `multi-function-device`... include multi-function-device; + // ...but also exports a function to make it glow in the dark export glow: func(brightness: u8); } @@ -400,4 +457,4 @@ world proxy { } ``` -> ⓘ For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/worlds.md b/component-model/src/design/worlds.md index 94a3042..e708c68 100644 --- a/component-model/src/design/worlds.md +++ b/component-model/src/design/worlds.md @@ -2,16 +2,19 @@ A **WIT world** is a higher-level contract that describes a component's capabilities and needs. -In one sense, a world _defines_ a component - it says what interfaces the component exposes for other code to call, and what interfaces the component depends on - but it defines only the surface of a component, not the internal behaviour. This is a useful way to think about "business logic" components, like libraries that export APIs for other components to use. If you're an application or library developer, you'll define custom worlds to expose the functionality of each component you create - and to declare the functionality your component depends on. +On one hand, a world describes the shape of a component - it says which interfaces the component exposes for other code to call (its exports), and which interfaces the component depends on (its imports). A world only defines the surface of a component, not the internal behaviour. If you're an application or library developer creating a component, you'll specify the world your component targets. This world describes the functionality your component exposes and declares the functionality your component depends on in order to be able to run. Your component may target a custom world definition you have created with a unique set of imports and exports tailored just for your use case, or it may target an existing world definition that someone else has already specified. -In another sense, though, a world defines a _hosting environment_ for components. For example, WASI (the WebAssembly System Interface) defines a "command line" world which imports interfaces such as file I/O, random number generation, clocks and so on - the sort of APIs a piece of code running in a POSIX or Win32 environment might want to call. Worlds like this are more akin to operating systems or server frameworks; unless you're building a Wasm host, you'll never define or implement one of these worlds, only _use_ the worlds these environments define for you. The 'world' concept unifies the "library" and "host" senses at a technical level, which enables some powerful techniques, but can also be daunting when first encountering the component model! +On the other hand though, a world defines a _hosting environment_ for components (i.e., an environment in which a component can be instantiated and its functionality can be invoked). An environment supports a world by providing implementations for all of the imports and by optionally invoking one or more of the exports. -A world is composed of interfaces, but each interface is _directional_ - it indicates whether the interface is available for outside code to call (an "export"), or outside code must fulfill the interface for the component to call (an "import"). These interfaces strictly bound the component. A component cannot interact with anything outside itself except by having its exports called, or by calling its imports. This provides very strong sandboxing; for example, if a component does not have an import for a secret store, then it _cannot_ access that secret store, even if the store is running in the same process. +For example, WASI (the WebAssembly System Interface) defines a "command line" world which imports interfaces that command line programs typically expect to have available to them such as file I/O, random number generation, clocks and so on. This world has a single export for running the command line tool. Components targeting this world must provide an implementation for this single export, and they may optionally call any of the imports. On the other hand, environments supporting this world must provide implementations for all of the imports and may invoke the single export. -For a component to run, its imports must be fulfilled, by a host or by other components. Connecting up one component's imports to another component's matching exports is called _composition_. +A world is composed of interfaces, but each interface is _directional_ - it indicates whether the interface is available for outside code to call (an "export"), or whether outside code must fulfill the interface for the component to call (an "import"). These interfaces strictly bound the component. A component cannot interact with anything outside itself except by having its exports called, or by it calling its imports. This provides very strong sandboxing; for example, if a component does not have an import for a secret store, then it _cannot_ access that secret store, even if the store is running in the same process. -* A (trivial) "HTTP proxy" world would export a "receive HTTP requests" interface, and import a "send HTTP requests" interface. A host, or another component, would call the exported "receive" interface, passing an HTTP request; the component would forward it on via the imported "send" interface. To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time - without those imports the component could not perform, for example, on-disk caching. -* The "WASI (WebAssembly System Interface) command line" world is a classic example of a "hosting environment" use of the world concept. This world exports APIs such as file I/O, sockets, random number generation, and other POSIX-style functionality, so that application components that depend on this world - that is, command line applications - can use those familiar capabilities. +For a component to run, its imports must be fulfilled, by a host or by other components. Connecting up some or all of a component's imports to other components' matching exports is called _composition_. + +## Example Worlds + +* A (trivial) "HTTP proxy" world would export a "handle HTTP requests" interface, and import a "send HTTP requests" interface. A host, or another component, would call the exported "handle" interface, passing an HTTP request; the component would forward it on via the imported "send" interface. To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time - without those imports the component could not perform, for example, on-disk caching. * A "regex parser" world would export a "parse regex" function, and would import nothing. This declares not only that the component implementing this world can parse regular expressions, but also that it calls no other APIs. A user of such a parser could know, without looking at the implementation, that is does not access the file system, or send the user's regexes to a network service. -> ⓘ For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). +> For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). diff --git a/component-model/src/implementations/jco.md b/component-model/src/implementations/jco.md deleted file mode 100644 index 0e95fda..0000000 --- a/component-model/src/implementations/jco.md +++ /dev/null @@ -1 +0,0 @@ -# jco diff --git a/component-model/src/implementations/wasmtime.md b/component-model/src/implementations/wasmtime.md deleted file mode 100644 index 900d059..0000000 --- a/component-model/src/implementations/wasmtime.md +++ /dev/null @@ -1 +0,0 @@ -# Wasmtime diff --git a/component-model/src/introduction.md b/component-model/src/introduction.md index 6afc51b..ca1b113 100644 --- a/component-model/src/introduction.md +++ b/component-model/src/introduction.md @@ -4,17 +4,22 @@ The WebAssembly Component Model is a broad-reaching architecture for building in | Understanding components | Building components | Using components | |--------------------------|----------------------|-------------------| -| [Why Components?] | [Javascript] | [Composing] | -| [Components] | [Python] | [Running] | -| [Interfaces] | [Rust] | [Distributing] | -| [Worlds] | | | +| [Why Components?] | [C/C++] | [Composing] | +| [Components] | [C#] | [Running] | +| [Interfaces] | [Go] | [Distributing] | +| [Worlds] | [JavaScript] | | +| | [Python] | | +| | [Rust] | | [Why Components?]: ./design/why-component-model.md [Components]: ./design/components.md [Interfaces]: ./design/interfaces.md [Worlds]: ./design/worlds.md -[Javascript]: ./language-support/javascript.md +[C/C++]: ./language-support/c.md +[C#]: ./language-support/csharp.md +[Go]: ./language-support/go.md +[JavaScript]: ./language-support/javascript.md [Python]: ./language-support/python.md [Rust]: ./language-support/rust.md @@ -22,11 +27,11 @@ The WebAssembly Component Model is a broad-reaching architecture for building in [Running]: ./creating-and-consuming/running.md [Distributing]: ./creating-and-consuming/distributing.md -> ⓘ This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. +> This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. ## Status -The component model is a work in progress. Although the architecture is well-defined, details are still evolving. This version of the guide is current as of late August 2023. +[WASI 0.2.0 was released](https://github.com/WebAssembly/WASI/pull/577) Jan 25, 2024, providing a stable release of WASI and the component model. This [is a stable set of WIT definitions](https://github.com/WebAssembly/WASI/tree/main/wasip2) that components can target. WASI proposals will continue to evolve and new ones will be introduced; however, users of the component model can now pin to the stable 0.2.0 release. ## Contributing diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index 45f07d9..1eb02c5 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -3,33 +3,41 @@ WebAssembly can be targeted by the majority of top programming languages; however, the level of support varies. This document details the subset of languages that target WASI and support -components. This is a living document, so if you are aware of advancements in a toolchain, please do -not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages [here](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md). Each section covers how to build and -run components for a given toolchain. +components. + +> This is a living document, so if you are aware of advancements in a toolchain, please do +not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages in the [Guest Languages Special Interest Group Proposal](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md) document. One of the benefits of components is their portability across host runtimes. The runtime only needs to know what world the component is targeting in order to import or execute the component. This -language guide hopes to demonstrate that with a prevailing `example` world defined in -[`examples/example-host/add.wit`](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/example-host/add.wit). Furthermore, an example host that understands the `example` +language guide hopes to demonstrate that with a prevailing `adder` world defined in +[`examples/tutorial/wit/adder/world.wit`](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/tutorial/wit/adder/world.wit). Furthermore, an example host that understands the `example` world has been provided in [`examples/example-host`](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/example-host/README.md) for running components. Each toolchain section walks through creating a component of this world, which can be run either in the example host or from an application of that toolchain. This aims to provide a full story for using components within and among toolchains. +Each section covers how to build and +run components for a given toolchain: + - [Wasm Language Support](#wasm-language-support) - [Language Agnostic Tooling](#language-agnostic-tooling) - [Building a Component with `wasm-tools`](#building-a-component-with-wasm-tools) - [Running a Component with Wasmtime](#running-a-component-with-wasmtime) - - [Serving a HTTP Component with Wasmtime](#serving-a-http-component-with-wasmtime) - - [Rust Tooling](./language-support/rust.md) - - [Building a Component with `cargo component`](./language-support/rust.md#building-a-component-with-cargo-component) - - [Running a Component from Rust Applications](./language-support/rust.md#running-a-component-from-rust-appliacations) + - [C/C++ Tooling](./language-support/c.md) + - [Building a Component with `wit-bindgen` and `wasm-tools`](./language-support/c.md#building-a-component-with-wit-bindgen-and-wasm-tools) + - [Running a Component from C/C++ Applications](./language-support/c.md#running-a-component-from-cc-applications) + - [C# Tooling](./language-support/csharp.md) + - [Go Tooling](./language-support/go.md) - [JavaScript Tooling](./language-support/javascript.md) - [Building a Component with `jco`](./language-support/javascript.md#building-a-component-with-jco) - - [Running a Component from JavaScript Applications](#./language-support/javascript#running-a-component-from-javascript-applications) + - [Running a Component from JavaScript Applications](./language-support/javascript.md#running-a-component-from-javascript-applications) - [Python Tooling](./language-support/python.md) - [Building a Component with `componentize-py`](./language-support/python.md#building-a-component-with-componentize-py) - [Running components from Python Applications](./language-support/python.md#running-components-from-python-applications) + - [Rust Tooling](./language-support/rust.md) + - [Building a Component with `cargo component`](./language-support/rust.md#building-a-component-with-cargo-component) + - [Running a Component from Rust Applications](./language-support/rust.md#running-a-component-from-rust-appliacations) ## Language Agnostic Tooling @@ -38,17 +46,21 @@ components within and among toolchains. [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools) provides a suite of subcommands for working with WebAssembly modules and components. -`wasm-tools` can be used to create a component from WebAssembly Text (WAT). This walks through creating a component from WAT that implements the [`example` world](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/example-host/add.wit) and simply adds two numbers. +`wasm-tools` can be used to create a component from WebAssembly Text (WAT). This walks through creating a component from WAT that implements the [`adder` world](https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/tutorial/wit/adder/world.wit) and simply adds two numbers. 1. Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools/tree/main#installation), a tool for low-level manipulation of Wasm modules and components. -2. The `add` function is defined inside the following `example` world: +2. The `add` function is defined inside the following `world` world: ```wit - package example:component; + package docs:adder@0.1.0; + + interface add { + add: func(x: u32, y: u32) -> u32; + } - world example { - export add: func(x: s32, y: s32) -> s32; + world adder { + export add; } ``` @@ -60,7 +72,7 @@ working with WebAssembly modules and components. local.get $lhs local.get $rhs i32.add) - (export "add" (func $add)) + (export "docs:adder/add@0.1.0" (func $add)) ) ``` @@ -68,7 +80,7 @@ working with WebAssembly modules and components. inside the core module and then encoding the WAT to a Wasm binary. ```sh - $ wasm-tools component embed add.wit add.wat -o add.wasm + $ wasm-tools component embed adder/world.wit add.wat -o add.wasm $ wasm-tools component new add.wasm -o add.component.wasm ``` diff --git a/component-model/src/language-support/c.md b/component-model/src/language-support/c.md new file mode 100644 index 0000000..a7360b5 --- /dev/null +++ b/component-model/src/language-support/c.md @@ -0,0 +1,221 @@ +# C/C++ Tooling + +WebAssembly components can be built from C and C++ using [`clang`][clang], the C language family frontend for [LLVM][llvm]. + +[`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen) is a tool to generate guest language bindings from a +given `.wit` file. + +Although `wit-bindgen` is a standalone tool (whereas some languages have more integrated toolchains like Rust's [`cargo-component`][cargo-component]), +`wit-bindgen` can generate source-level bindings for `Rust`, `C`, `Java (TeaVM)`, and `TinyGo`, with the ability for more +language generators to be added in the future. + +`wit-bindgen` can be used to build C applications that can be compiled directly to Wasm modules using [`clang`][clang] with a [`wasm32-wasi`][clang-tgt-wasm32-wasi] target. + +[clang]: https://clang.llvm.org/ +[clang-tgt-wasm32-wasi]: https://clang.llvm.org/docs/ClangCommandLineReference.html#webassembly +[llvm]: https://llvm.org/ +[wasi]: https://wasi.dev/ +[cargo-component]: https://crates.io/crates/cargo-component + +## 1. Download dependencies + +First, install the CLI for [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen#cli-installation), [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools), and the [`WASI SDK`](https://github.com/webassembly/wasi-sdk). + +The WASI SDK will install a local version of `clang` configured with a wasi-sysroot. Follow [these instructions](https://github.com/WebAssembly/wasi-sdk#use) to configure it for use. Note that you can also use your installed system or emscripten `clang` by building with `--target=wasm32-wasi` but you will need some artifacts from WASI SDK to enable and link that build target (more information is available in WASI SDK's docs). + +## 2. Generate program skeleton from WIT + +Start by generating a C skeleton from `wit-bindgen` using the [sample `adder/world.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/examples/tutorial/wit/adder/world.wit): + +``` +> wit-bindgen c path/to/adder/world.wit +Generating "adder.c" +Generating "adder.h" +Generating "adder_component_type.o" +``` + +This has generated several files: + +1.`adder.h` (based on the `adder` world) with the prototype of the `add` function (prefixed by `exports_`) - `uint32_t exports_docs_adder_add_add(uint32_t x, uint32_t y);`. +2. `adder.c` that interfaces with the component model ABI to call your function. +3. `adder_component_type.o` which contains object code referenced in `adder.c` from an `extern` that must be linked via `clang`. + +## 3. Write program code + +Next, create an `component.c` that implements the `adder` world (i.e. the interface defined in `adder.h`): + +```c +#include "adder.h" + +uint32_t exports_docs_adder_add_add(uint32_t x, uint32_t y) +{ + return x + y; +} +``` + +## 4. Compile a WebAssembly module (P1) with `clang` + +Now, you can compile the function into a Wasm module via clang: + +```console +clang component.c adder.c adder_component_type.o -o adder.wasm -mexec-model=reactor +``` + +> Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. +> +> Alternatively, you can also use the published [`ghcr.io/webassembly/wasi-sdk` container images][wasi-sdk-images] +> for performing builds. +> +> For example, to enter a container with `wasi-sdk` installed: +> +> ``` +> docker run --rm -it --mount type=bind,src=path/to/app/src,dst=/app ghcr.io/webassembly/wasi-sdk:wasi-sdk-25 +> ``` +> +> See also: [`Dockerfile` in `wasi-sdk`][wasi-sdk-dockerfile] + +[wasi-sdk-images]: https://github.com/WebAssembly/wasi-sdk/pkgs/container/wasi-sdk +[wasi-sdk-dockerfile]: https://github.com/WebAssembly/wasi-sdk/blob/main/docker/Dockerfile + +## 5. Convert the P1 component to a P2 component with `wasm-tools` + +Next, we need to transform the P1 component to a P2 component. To do this, we can use `wasm-tools component new`: + +```console +wasm-tools component new ./adder.wasm -o adder.component.wasm +``` + +> [!NOTE] +> The `.component.` extension has no special meaning -- `.wasm` files can be either modules or components. + +## 6. (optional) Build a WASI-enabled WebAssembly (P2) component with `wasm-tools` + +Do note `wasm-tools component new` may fail if your code references any [WASI][wasi] APIs that must be imported, for +example via standard library imports like `stdio.h`. + +Using WASI interfaces requires an additional step as the WASI SDK still references `wasi_snapshot_preview1` APIs that are not compatible directly with components. + +For example, modifying the above to reference `printf()` would compile: + +```c +#include "adder.h" +#include + +uint32_t exports_docs_adder_add_add(uint32_t x, uint32_t y) +{ + uint32_t result = x + y; + printf("%d", result); + return result; +} +``` + +However, the module would fail to transform to a component: + +``` +>wasm-tools component new ./adder.wasm -o adder.component.wasm +error: failed to encode a component from module + +Caused by: + 0: failed to decode world from module + 1: module was not valid + 2: module requires an import interface named `wasi_snapshot_preview1` +``` + +To build a P2 component that uses [WASI][wasi] interfaces from a P1 component, we'll need to make use of adapter modules. + +Install the appropriate reactor adapter module [as documented here](https://github.com/bytecodealliance/wit-bindgen#creating-components-wasi). + +You can either get [the linked release][wasmtime-releases] of `wasi_snapshot_preview1.reactor.wasm` and rename it to `wasi_snapshot_preview1.wasm`, or build it directly from source in `wasmtime` following the [instructions here](https://github.com/bytecodealliance/wasmtime/tree/main/crates/wasi-preview1-component-adapter) (make sure you `git submodule update --init` first). + +Now, you can adapt preview1 to preview2 to build a component: + +```console +wasm-tools component new adder.wasm --adapt wasi_snapshot_preview1.wasm -o adder.component.wasm +``` + +[wasmtime-releases]: https://github.com/bytecodealliance/wasmtime/releases + +## 7. Inspect the built component + +Finally, you can inspect the embedded wit to see your component (including any WASI imports if necessary): + +``` +>wasm-tools component wit adder.component.wasm +package root:component; + +world root { + import wasi:io/error@0.2.2; + import wasi:io/streams@0.2.2; + import wasi:cli/stdin@0.2.2; + import wasi:cli/stdout@0.2.2; + import wasi:cli/stderr@0.2.2; + import wasi:cli/terminal-input@0.2.2; + import wasi:cli/terminal-output@0.2.2; + import wasi:cli/terminal-stdin@0.2.2; + import wasi:cli/terminal-stdout@0.2.2; + import wasi:cli/terminal-stderr@0.2.2; + import wasi:clocks/wall-clock@0.2.2; + import wasi:filesystem/types@0.2.2; + import wasi:filesystem/preopens@0.2.2; + + export add: func(x: s32, y: s32) -> s32; +} +... +``` + +### 8. Running the component from the example host + +> [!WARNING] +> You must be careful to use a version of the adapter (`wasi_snapshot_preview1.wasm`) that is compatible with the version of +> `wasmtime` that will be used, to ensure that WASI interface versions (and relevant implementation) match. + +This repository contains an [example WebAssembly host][example-host] written in Rust that can run components that implement the `adder` world. + +> [!NOTE] +> When hosts run components that use WASI interfaces, they must *explicitly* [add WASI to the linker][add-to-linker] to run the built component. + +A successful run should show the following output: + +``` +cargo run --release -- 1 2 adder.component.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/debug/example-host 1 2 /tmp/docs/c/adder.component.wasm` +1 + 2 = 3 +``` + +If *not* configured correctly, you may see errors like the following: + +``` +cargo run --release -- 1 2 adder.component.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/release/example-host 1 2 adder.component.wasm` +Error: Failed to instantiate the example world + +Caused by: + 0: component imports instance `wasi:io/error@0.2.2`, but a matching implementation was not found in the linker + 1: instance export `error` has the wrong type + 2: resource implementation is missing +``` + +This kind of error normally indicates that the host in question does not contain satisfy WASI imports. + +[host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +[add-to-linker]: https://docs.wasmtime.dev/api/wasmtime_wasi/fn.add_to_linker_sync.html +[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host + +## 9. Running a Component from C/C++ Applications + +It is not yet possible to run a WebAssembly Component using the C API of `wasmtime` `c-api`. See [`wasmtime` issue #6987](https://github.com/bytecodealliance/wasmtime/issues/6987) for more details. +The c-api is preferred over directly using the example host Rust crate in C++. + +However, C/C++ language guest components can be composed with components written in any other language and +run by their toolchains, or even composed with a C language command component and run via the `wasmtime` CLI +or any other host. + +See the [Rust Tooling guide](../language-support/rust.md#running-a-component-from-rust-applications) for instructions on how to run this component from +the Rust `example-host` (replacing the path to `add.wasm` with your `add-component` above). + +[!NOTE]: # +[!WARNING]: # diff --git a/component-model/src/language-support/csharp.md b/component-model/src/language-support/csharp.md new file mode 100644 index 0000000..abeb242 --- /dev/null +++ b/component-model/src/language-support/csharp.md @@ -0,0 +1,331 @@ +# C# Tooling + +WebAssembly components in C# can be built with [componentize-dotnet][componentize-dotnet], +a a NuGet package that can be used to create a fully AOT-compiled +component, giving .NET developers a component experience comparable to those in Rust and TinyGo. + +[componentize-dotnet]: https://github.com/bytecodealliance/componentize-dotnet + +## Building a Component with `componentize-dotnet` + +[`componentize-dotnet`][componentize-dotnet] serves as a one-stop shop, wrapping several tools into one: + +- [NativeAOT-LLVM](https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM) (compilation) +- [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) (WIT imports and exports) +- [wasm-tools](https://github.com/bytecodealliance/wasm-tools) (component conversion) +- [WASI SDK](https://github.com/WebAssembly/wasi-sdk) (SDK used by NativeAOT-LLVM) +- [Wac](https://github.com/bytecodealliance/wac) (used to compose components) + +First, install the .NET SDK. For this walkthrough, we’ll use the [.NET 10 SDK preview][dotnet-sdk]. +You should also have [wasmtime](https://wasmtime.dev/) installed so you can run the binary that you produce. + +[dotnet-sdk]: https://dotnet.microsoft.com/en-us/download/dotnet/10.0 +[wasmtime]: https://wasmtime.dev/ + +## 1. Create a new project + +Once you have the .NET SDK installed, create a new project: + +```sh +dotnet new install BytecodeAlliance.Componentize.DotNet.Templates +dotnet new componentize.wasi.cli -o adder +cd adder +``` + +## 2. Create or download your WIT world + +Next, create or download the WIT world you would like to target. + +For this example we will use the [`adder` world][adder-world], with an `add` function (e.g. to `wit/component.wit`): + +```wit +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world adder { + export add; +} +``` + +In the `adder.csproj` project file, add a new ``: + +```xml + + + +``` + +Since this component will only export a function dotnet considers this a library project. +Let's update the `` to be a library in the `adder.csproj`: + +```diff +- Exe ++ Library +``` + +And remove the automatically generated `Program.cs` file: + +```bash +rm Program.cs +``` + +[adder-world]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit + +## 3. Write the implementation for the `adder` world + +If you try to build the project with `dotnet build`, you'll get an error like the following: + +``` +➜ dotnet build +Restore complete (8.6s) +You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy + adder failed with 1 error(s) (25.6s) + /path/to/adder/obj/Debug/net10.0/wasi-wasm/wit_bindgen/AdderWorld.wit.exports.docs.adder.v0_1_0.AddInterop.cs(15,19): error CS0103: The name 'AddImpl' does not exist in the current context + +Build failed with 1 error(s) in 34.6s +``` + +This is because we've promised an implementation, but haven't yet written one for the `adder` world. + +To fix this, add the following code to your in a file called `Component.cs`: + +```csharp +namespace AdderWorld; + +public class AddImpl : IAdderWorld +{ + public static uint Add(uint x, uint y) + { + return x + y; + } +} +``` + +Then, we can build our component: + +```sh +dotnet build +``` + +The component will be available at `bin/Debug/net10.0/wasi-wasm/native/adder.wasm`. + +### 5. (optional) the component from the example host + +> [!WARNING] +> You must be careful to use a version of the adapter (`wasi_snapshot_preview1.wasm`) that is compatible with the version of +> `wasmtime` that will be used, to ensure that WASI interface versions (and relevant implementation) match. + +This repository contains an [example WebAssembly host][example-host] written in Rust that can run components that implement the `adder` world. + +> [!NOTE] +> When hosts run components that use WASI interfaces, they must *explicitly* [add WASI to the linker][add-to-linker] to run the built component. + +A successful run should show the following output: + +``` +cargo run --release -- 1 2 adder.component.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/debug/example-host 1 2 /tmp/docs/c/adder.component.wasm` +1 + 2 = 3 +``` + +If *not* configured correctly, you may see errors like the following: + +``` +cargo run --release -- 1 2 adder.component.wasm + Compiling example-host v0.1.0 (/path/to/component-docs/component-model/examples/example-host) + Finished `release` profile [optimized] target(s) in 7.85s + Running `target/release/example-host 1 2 adder.component.wasm` +Error: Failed to instantiate the example world + +Caused by: + 0: component imports instance `wasi:io/error@0.2.2`, but a matching implementation was not found in the linker + 1: instance export `error` has the wrong type + 2: resource implementation is missing +``` + +This kind of error normally indicates that the host in question does not contain satisfy WASI imports. + +[host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +[add-to-linker]: https://docs.wasmtime.dev/api/wasmtime_wasi/fn.add_to_linker_sync.html +[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host + +## Building a component that exports an interface + +The previous example uses a WIT file that exports a function. However, you'll often prefer to export an interface, +either to comply with an existing specification or to capture a set of functions and types that tend to go +together. Let's expand our `example` world to export an interface rather than directly +export the function. We are also adding the `hostapp` world to our WIT file which we will implement +in [the next section](#building-a-component-that-imports-an-interface) to demonstrate how to build a +component that *imports* an interface. + +```wit +// adder/world.wit +package example:component; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world example { + export add; +} + +world hostapp { + import add; +} +``` + +If you peek at the bindings, you'll notice that we now implement a class for the `add` interface +rather than for the `example` world -- this is a consistent pattern. As you export more interfaces +from your world, you implement more classes. + +Our `Component.cs` example gets the slight update of: + +```csharp +namespace ExampleWorld.wit.exports.example.component; + +public class AddImpl : IAdd +{ + public static uint Add(uint x, uint y) + { + return x + y; + } +} +``` + +Once again, compile an application to a Wasm component using `dotnet build`: + +```sh +$ dotnet build +Restore complete (0.4s) +You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy + adder succeeded (1.1s) → bin/Debug/net10.0/wasi-wasm/adder.dll + +Build succeeded in 2.5s +``` + +The component will be available at `bin/Debug/net10.0/wasi-wasm/native/adder.wasm`. + +## Building a component that imports an interface + +So far, we've been dealing with library components. Now we will be creating a command component that +implements the `hostapp` world. This component will import the `add` interface that is exported from +our `adder` component and call the `add` function. We will later compose this command component with +the `adder` library component we just built. + +Now we will be taking the `adder` component and executing it from another WebAssembly component. + +`dotnet new componentize.wasi.cli` creates a new project that creates an executable. + +Back out of the current project and create a new one: + +```sh +cd .. +dotnet new componentize.wasi.cli -o host-app +cd host-app +``` + +Copy the same WIT file as before into your project: + +```wit +// adder/world.wit +package example:component; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world example { + export add; +} + +world hostapp { + import add; +} +``` + +Add it to your `host-app.csproj` project file as a new `ItemGroup`: + +```xml + + + +``` + +Notice how the `World` changed from `example` to `hostapp`. The previous examples focused on +implementing the class library for this WIT file - the `export` functions. Now we'll be focusing on +the executable side of the application - the `hostapp` world. + +Modify `Program.cs` to look like this: + +```csharp +// Pull in all imports of the `hostapp` world, namely the `add` interface. +// example.component refers to the package name defined in the WIT file. +using HostappWorld.wit.imports.example.component; + +uint left = 1; +uint right = 2; +var result = AddInterop.Add(left, right); +Console.WriteLine($"{left} + {right} = {result}"); +``` + +Once again, compile your component with `dotnet build`: + +```sh +$ dotnet build +Restore complete (0.4s) +You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy + host-app succeeded (1.1s) → bin/Debug/net10.0/wasi-wasm/host-app.dll + +Build succeeded in 2.5s +``` + +At this point, you'll have two Webassembly components: + +1. A component that implements the `example` world. +2. A component that implements the `hostapp` world. + +Since the `host-app` component depends on the `add` function which is defined in the `example` +world, it needs to be composed the first component. You can compose your `host-app` component with +your `adder` component by running [`wac plug`](https://github.com/bytecodealliance/wac): + +```sh +wac plug \ + bin/Debug/net10.0/wasi-wasm/native/host-app.wasm \ + --plug ../adder/bin/Debug/net10.0/wasi-wasm/native/adder.wasm \ + -o main.wasm +``` + +You can also automate the process by adding the following to your `host-app.csproj`: + +```xml + + + bin/$(Configuration)/$(TargetFramework)/wasi-wasm/native/host-app.wasm + ../adder/bin/$(Configuration)/$(TargetFramework)/wasi-wasm/native/adder.wasm + + + + +``` + +Run `dotnet build` again you will have a composed component in `./dist/main.wasm` + +Then you can run the composed component: + +```sh +wasmtime run ./dist/main.wasm +1 + 2 = 3 +``` + +Check out the [componentize-dotnet docs][componentize-dotnet-docs] for more configurations options. + +[componentize-dotnet-docs]: https://github.com/bytecodealliance/componentize-dotnet + +[!NOTE]: # +[!WARNING]: # diff --git a/component-model/src/language-support/go.md b/component-model/src/language-support/go.md new file mode 100644 index 0000000..24d36db --- /dev/null +++ b/component-model/src/language-support/go.md @@ -0,0 +1,328 @@ +# Go Tooling + +The [TinyGo compiler](https://tinygo.org/) v0.34.0 and above has native support for the WebAssembly Component Model and WASI 0.2.0. + +This guide walks through building a component that implements `adder` world defined in the [`adder/world.wit` package][adder-wit]. +The component will implement the `adder` world, which contains `add` interface with a `add` function. + +[adder-wit]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit + +## 1. Install the tools + +Follow the [TinyGo installation instructions](https://tinygo.org/getting-started/) to install the TinyGo compiler. + +Additionally, install the `wasm-tools` CLI tool from the [wasm-tools repository](https://github.com/bytecodealliance/wasm-tools/releases). + +> [!WARNING] +> Due to some upstream issues, only `wasm-tools` versions 1.225.0 or earlier can be used with `wit-bindgen-go` +> +> If using the Rust toolchain to install `wasm-tools`, it can be installed like so: +> `cargo install --locked wasm-tools@1.225.0 --force` + +To verify the installation, run the following commands: + +``` +$ tinygo version +tinygo version 0.34.0 ... +$ wasm-tools -V +wasm-tools 1.255.0 ... +``` + +Optional: Install the [`wkg`][wkg] CLI tool to resolve the imports in the WIT file. The `wkg` CLI is a part of the [Wasm Component package manager](https://github.com/bytecodealliance/wasm-pkg-tools/releases) + +[wkg]: https://github.com/bytecodealliance/wasm-pkg-tools/tree/main/crates/wkg + +## 2. Create your Go project + +Now, create your Go project: + +```console +mkdir add && cd add +go mod init example.com +``` + +Ensure that the following `tool`s are installed: + +``` +tool ( + go.bytecodealliance.org/cmd/wit-bindgen-go +) +``` + +> [!NOTE] +> `go tool` was introduced in [Golang 1.24][go-1-24-release] and can be used to manage tooling in Go projects. + +Consider also running `go mod tidy` after adding the above tool. + +[go-1-24-release]: https://go.dev/blog/go1.24 + +## 2. Determine which World the Component will Implement + +Since we will be implementing the [`adder` world][adder-wit], we can copy the WIT to our project, +under the `wit` folder (e.g. `wit/component.wit`): + +```wit +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world adder { + export add; +} +``` + +The `wasip2` target of TinyGo assumes that the component is targeting `wasi:cli/command@0.2.0` world +(part of [`wasi:cli`][wasi-cli]) so it requires the imports of `wasi:cli/imports@0.2.0`. + +We need to include those interfaces as well in `component.wit`, by editing the `adder` world: + +```wit +world adder { + include wasi:cli/imports@0.2.0; + export add; +} +``` + +### Using `wkg` to automatically resolve and download imports + +Tools like [`wkg`][wkg] can be convenient to build a complete WIT package by resolving the imports. + +Running the `wkg wit fetch` command will resolve the imports and populate your `wit` folder with all relevant +imported namespaces and packages. + +``` +$ wkg wit build +WIT package written to docs:adder@0.1.0.wasm +``` + +[wasi-cli]: https://github.com/WebAssembly/wasi-cli + +## 3. Generate bindings for the Wasm component + +Now that we have our WIT definitions bundled together into a WASM file, +we can generate the bindings for our Wasm component, by adding a build directive: + +```console +go tool wit-bindgen-go generate --world adder --out internal ./docs:adder@0.1.0.wasm +``` + +> [!NOTE] +> The `go tool` directive (added in [Golang 1.24][go-1-24-release]) installs and enables use of `wit-bindgen-go`, +> part of the Bytecode Alliance suite of Golang tooling. + +The `internal` directory will contain the generated Go code that WIT package. + +```console +$ tree internal +internal +├── docs +│   └── adder +│   ├── add +│   │   ├── add.exports.go +│   │   ├── add.wasm.go +│   │   ├── add.wit.go +│   │   └── empty.s +│   └── adder +│   └── adder.wit.go +└── wasi + ├── cli + │   ├── environment + │   │   ├── empty.s + │   │   ├── environment.wasm.go + │   │   └── environment.wit.go + │   ├── exit + │   │   ├── empty.s + │   │   ├── exit.wasm.go + │   │   └── exit.wit.go + │   ├── stderr + │   │   ├── empty.s + │   │   ├── stderr.wasm.go + │   │   └── stderr.wit.go + │   ├── stdin + │   │   ├── empty.s + │   │   ├── stdin.wasm.go + │   │   └── stdin.wit.go + │   ├── stdout + │   │   ├── empty.s + │   │   ├── stdout.wasm.go + │   │   └── stdout.wit.go + │   ├── terminal-input + │   │   ├── empty.s + │   │   ├── terminal-input.wasm.go + │   │   └── terminal-input.wit.go + │   ├── terminal-output + │   │   ├── empty.s + │   │   ├── terminal-output.wasm.go + │   │   └── terminal-output.wit.go + │   ├── terminal-stderr + │   │   ├── empty.s + │   │   ├── terminal-stderr.wasm.go + │   │   └── terminal-stderr.wit.go + │   ├── terminal-stdin + │   │   ├── empty.s + │   │   ├── terminal-stdin.wasm.go + │   │   └── terminal-stdin.wit.go + │   └── terminal-stdout + │   ├── empty.s + │   ├── terminal-stdout.wasm.go + │   └── terminal-stdout.wit.go + ├── clocks + │   ├── monotonic-clock + │   │   ├── empty.s + │   │   ├── monotonic-clock.wasm.go + │   │   └── monotonic-clock.wit.go + │   └── wall-clock + │   ├── empty.s + │   ├── wall-clock.wasm.go + │   └── wall-clock.wit.go + ├── filesystem + │   ├── preopens + │   │   ├── empty.s + │   │   ├── preopens.wasm.go + │   │   └── preopens.wit.go + │   └── types + │   ├── abi.go + │   ├── empty.s + │   ├── types.wasm.go + │   └── types.wit.go + ├── io + │   ├── error + │   │   ├── empty.s + │   │   ├── error.wasm.go + │   │   └── error.wit.go + │   ├── poll + │   │   ├── empty.s + │   │   ├── poll.wasm.go + │   │   └── poll.wit.go + │   └── streams + │   ├── empty.s + │   ├── streams.wasm.go + │   └── streams.wit.go + ├── random + │   ├── insecure + │   │   ├── empty.s + │   │   ├── insecure.wasm.go + │   │   └── insecure.wit.go + │   ├── insecure-seed + │   │   ├── empty.s + │   │   ├── insecure-seed.wasm.go + │   │   └── insecure-seed.wit.go + │   └── random + │   ├── empty.s + │   ├── random.wasm.go + │   └── random.wit.go + └── sockets + ├── instance-network + │   ├── empty.s + │   ├── instance-network.wasm.go + │   └── instance-network.wit.go + ├── ip-name-lookup + │   ├── abi.go + │   ├── empty.s + │   ├── ip-name-lookup.wasm.go + │   └── ip-name-lookup.wit.go + ├── network + │   ├── abi.go + │   ├── empty.s + │   ├── network.wasm.go + │   └── network.wit.go + ├── tcp + │   ├── abi.go + │   ├── empty.s + │   ├── tcp.wasm.go + │   └── tcp.wit.go + ├── tcp-create-socket + │   ├── empty.s + │   ├── tcp-create-socket.wasm.go + │   └── tcp-create-socket.wit.go + ├── udp + │   ├── abi.go + │   ├── empty.s + │   ├── udp.wasm.go + │   └── udp.wit.go + └── udp-create-socket + ├── empty.s + ├── udp-create-socket.wasm.go + └── udp-create-socket.wit.go + +39 directories, 91 files +``` + +The `adder.exports.go` file contains the exported functions that need to be implemented in the Go code called `Exports`. + +## 4. Implement the `add` Function + +```Go +//go:generate go tool wit-bindgen-go generate --world adder --out internal ./docs:adder@0.1.0.wasm + +package main + +import ( + "example.com/internal/docs/adder/add" +) + +func init() { + add.Exports.Add = func(x uint32, y uint32) uint32 { + return x + y + } +} + +// main is required for the `wasi` target, even if it isn't used. +func main() {} +``` + +Go's `init` functions are used to do initialization tasks that +should be done before any other tasks. In this case, we are using it to export the `Add` function. + +## 5. Build the Component + +We can build our component using TinyGo by specifying the wit-package to be `add.wit` and the WIT world to be `adder`. + +Under the hood, TinyGo invokes `wasm-tools` to embed the WIT file to the module and componentize it. + +```console +tinygo build -target=wasip2 -o add.wasm --wit-package docs:adder@0.1.0.wasm --wit-world adder main.go +``` + +> **WARNING:** By default, tinygo includes all debug-related information in your .wasm file. That is desirable when prototyping or testing locally to obtain useful backtraces in case of errors (for example, with `wasmtime::WasmBacktraceDetails::Enable`). To remove debug data and optimize your binary file, build with `-no-debug`. The resulting .wasm file will be considerably smaller (up to 75% reduction in size). + +We now have an add component that satisfies our `adder` world, exporting the `add` function, which + +We can confirm using the `wasm-tools component wit` command: + +```console +$ wasm-tools component wit add.wasm +package root:component; + +world root { + import wasi:io/error@0.2.0; + import wasi:io/streams@0.2.0; + import wasi:cli/stdout@0.2.0; + import wasi:random/random@0.2.0; + + export add: func(x: s32, y: s32) -> s32; +} +... +``` + +## 5. Testing the `add` Component + +To run our add component, we need to use a host program with a WASI runtime that understands the +`example` world -- we've provided an [`example-host`][example-host] that does just that. + +The example host calls the `add` function of a passed in component providing two operands. + +To use the example host, clone this repository and run the Rust program: + +```console +git clone git@github.com:bytecodealliance/component-docs.git +cd component-docs/component-model/examples/example-host +cargo run --release -- 1 2 /path/to/add.wasm +``` + +[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host + +[!NOTE]: # +[!WARNING]: # diff --git a/component-model/src/language-support/javascript.md b/component-model/src/language-support/javascript.md index de0062a..0a4fb03 100644 --- a/component-model/src/language-support/javascript.md +++ b/component-model/src/language-support/javascript.md @@ -1,72 +1,556 @@ # JavaScript Tooling -[`jco`](https://github.com/bytecodealliance/jco) is a fully native JS tool for working with the -emerging WebAssembly Components specification in JavaScript. +[WebAssembly][mdn-wasm] was originally developed as a technology for running non-JavaScript workloads in the browser at near-native speed. -### Building a Component with `jco` +JavaScript WebAssembly component model support is provided primarily by [`jco`](https://github.com/bytecodealliance/jco), a command line tool +which provides tooling for building WebAssembly components. -A component can be created from a JS module using `jco componentize`. First, install `jco` and -`componentize-js`: +[Typescript][ts] can *also* be used, given that it is transpiled to JS first by relevant tooling (`tsc`). +`jco` generates [type declaration files (`.d.ts`)][ts-decl-file] by default, and also has a `jco types` +subcommand which generates typings that can be used with a Typescript codebase. -```sh -$ npm install @bytecodealliance/jco -$ npm install @bytecodealliance/componentize-js +> [!WARNING] +> While popular projects like [`emscripten`][emscripten] also build WebAssembly modules, those modules are not Component Model aware. +> +> Core WebAssembly modules do not contain the advanced features (rich types, structured language interoperation, composition) +> that the component model makes available. + +[emscripten]: https://emscripten.org/ +[ts]: https://typescriptlang.org +[mdn-wasm]: https://developer.mozilla.org/en-US/docs/WebAssembly + +## Installing `jco` + +Installing [`jco`][jco] (and its required peer dependency [`componentize-js`][componentize-js]) can be done via NodeJS project tooling: + +```console +npm install -g @bytecodealliance/componentize-js @bytecodealliance/jco +``` + +> [!NOTE] +> `jco` and `componentize-js` can be installed in a project-local manner with `npm install -D` + +[ComponentizeJS][componentize-js] provides tooling used by `jco` to transpile JS to Wasm, so installing both packages is required. + +[jco]: https://github.com/bytecodealliance/jco +[componentize-js]: https://github.com/bytecodealliance/ComponentizeJS + +## Overview of Building a Component with JavaScript + +Building a WebAssembly component with JavaScript often consists of: + +1. Determining which interface our functionality will target (i.e. a [WebAssembly Interface Types ("WIT")][wit] world) +2. Writing JavaScript that satisfies the interface +3. Packaging our project JavaScript as WebAssembly (whether for use in WebAssembly runtimes, other JS projects, or the browser) + +[WebAssembly Interface Types ("WIT")][wit] is a featureful Interface Definition Language ("IDL") for defining functionality, but most +of the time, you shouldn't need to write WIT from scratch. Often, it's sufficient to download a pre-existing interface that defines what +your component should do. + +The [`example` world][wit-example-world] exports a single `add` function that sums two numbers: + +```wit +package example:component; + +world example { + export add: func(x: s32, y: s32) -> s32; +} ``` -Create a JavaScript module that implements the `add` function in [`add.wit`](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit): +> [!NOTE] +> `export`ing the `add` function means that environments that interact with the resulting WebAssembly component +> will be able to *call* the `add` function. +> +> To learn more about the WIT syntax, check out the [WIT explainer][wit-explainer] + +[wit-example-world]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit +[wit-explainer]: https://component-model.bytecodealliance.org/design/wit.html + +## Implementing a JS WebAssembly Component + +To implement the [`example` world][wit-example-world], we must write a [JavaScript module][mdn-js-module] +that implements the exported `add` function: ```js -export function add(x, y) { +export const add = (x, y) => { return x + y; -} +}; ``` -Now, use `jco` to create a component from the JS module: +> [!WARNING] +> When building your JavaScript project, ensure to set the `"type":"module"` option in `package.json`, +> as `jco` works exclusively with JavaScript modules. + +In the code above, the `example` world is analogous to the JavaScript module itself, with the exported `add` function +mirroring `add` function `export`ed in the WIT. -```sh -$ jco componentize add.js --wit add.wit -n example -o add.wasm -OK Successfully written add.wasm with imports (). +With the WIT and JavaScript in place, we can use [`jco`][jco] to create a WebAssembly component from the JS module, using `jco componentize`. + +Our component is *so simple* (reminiscent of [Core WebAssembly][wasm-core], which deals primarily in numeric values) that we're actually *not using* any of the [WebAssembly System Interface][wasi] -- this means that we can `--disable` it when we invoke `jco componentize` + +```console +jco componentize \ + path/to/add.js \ + --wit path/to/add.wit \ + --world-name example \ + --out add.wasm \ + --disable all ``` -Now, run the component using the [Rust `add` host](./rust.md#creating-a-command-component-with-cargo-component): +> [!NOTE] +> If you're using `jco` as a project-local dependency, you can run `npx jco` + +You should see output like the following: -```sh -$ cd component-model/examples/add-host -$ cargo run --release -- 1 2 ../path/to/add.wasm +``` +OK Successfully written add.wasm. +``` + +> **WARNING:** By using `--disable all`, your component won't get access to any WASI interfaces that might be useful for debugging or logging. For example, you can't `console.log(...)` or `console.error(...)` without `stdio`; you can't use `Math.random()` without `random`; and you can't use `Date.now()` or `new Date()` without `clocks`. Please note that calls to `Math.random()` or `Date.now()` will return seemingly valid outputs, but without actual randomness or timestamp correctness. + +[mdn-js-module]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules + +## Running the Component in the `example-host` + +To run the component we've built, we can use the [`example-host` project][example-host]: + +```console +cd component-model/examples/example-host +cargo run --release -- 1 2 ../path/to/add.wasm 1 + 2 = 3 ``` -### Running a Component from JavaScript Applications +> [!WARNING] +> The [`example-host` Rust project][example-host] uses the [Rust toolchain][rust-toolchain], in particular [`cargo`][cargo], +> so to run the code in this section you may need to install some more dependencies. + +While the output isn't exciting, the code contained in `example-host` does a lot to make it happen: + +- Loads the WebAssembly binary at the provided path (in the command above, `../path/to/add.wasm`) +- Calls the `export`ed `add` function with arguments +- Prints the result -As the JavaScript runtime cannot yet execute Wasm components, a component must be transpiled into -JavaScript and a core module and then executed. `jco` automates this transpilation: +The important Rust code looks like this: -```sh -$ jco transpile add.wasm -o out-dir +```rust +let component = Component::from_file(&engine, path).context("Component file not found")?; -Transpiled JS Component Files: +let (instance, _) = Example::instantiate_async(&mut store, &component, &linker) + .await + .context("Failed to instantiate the example world")?; - - out-dir/add.core.wasm 6.72 MiB - - out-dir/add.d.ts 0.05 KiB - - out-dir/add.js 0.8 KiB +instance + .call_add(&mut store, x, y) + .await + .context("Failed to call add function") ``` -A core module and JavaScript bindings have been outputted to the `out-dir`. +A quick reminder on the power and new capabilities afforded by WebAssembly -- we've written, loaded, instantiated and executed JavaScript from Rust with a strict interface, without the need for FFI, subprocesses or a network call. + +[rust-toolchain]: https://www.rust-lang.org/tools/install +[example-host]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host +[wit]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md +[nodejs]: https://nodejs.org/en +[cargo]: https://doc.rust-lang.org/cargo +[wasi]: https://wasi.dev/ +[wasm-core]: https://webassembly.github.io/spec/core/ + +## Running a Component from JavaScript Applications (including the Browser) + +JavaScript runtimes available in browsers cannot yet execute WebAssembly components, so WebAssembly components +(JavaScript or otherwise) must be "transpiled" into a JavaScript wrapper and one or more [WebAssembly core modules][wasm-core-module] +which *can* be run by in-browser WebAssembly runtimes. + +Given an existing WebAssembly component (e.g. `add.wasm` which implements the [`example` world][wit-example-world]), we can "transpile" the component into runnable JavaScript by using `jco tranpsile`: + +```console +jco transpile add.wasm -o dist +``` + +You should see output similar to the following: + +``` + Transpiled JS Component Files: + + - dist/add.core.wasm 10.1 MiB + - dist/add.d.ts 0.1 KiB + - dist/add.js 1.57 KiB +``` + +> [!NOTE] +> To follow along, see the [`jco` example `add` component](https://github.com/bytecodealliance/jco/tree/main/examples/components/add). +> +> With the project pulled locally, you also run `npm run transpile` which outputs to `dist/transpiled` + + +Thanks to `jco` transpilation, you can import the resulting `dist/add.js` file and run it from any JavaScript application +using a runtime that supports the [core WebAssembly specification][core-wasm] as implemented for JavaScript. -Now, you can import the resultant `add.js` file and run it from a JavaScript application. This -example renames it and imports it as an ECMAScript module for ease of running locally with node: +To use this component from [NodeJS][nodejs], you can write code like the following: ```mjs -// app.mjs -import { add } from "./out-dir/add.mjs"; +import { add } from "./dist/add.js"; console.log("1 + 2 = " + add(1, 2)); ``` -The above example : +You can execute the JavaScript module with `node` directly: -```sh -$ mv out-dir/add.js out-dir/add.mjs -$ node app.mjs +```console +node run.js +``` + +You should see output like the following: + +``` 1 + 2 = 3 ``` + +This is directly comparable to the Rust host code mentioned in the previous section. Here, we are able to +use NodeJS as a host for running WebAssembly, thanks to `jco`'s ability to transpile components. + +With `jco transpile` any WebAssembly binary (compiled from any language) can be run in JavaScript natively. + +[wasm-core-module]: https://webassembly.github.io/spec/core/binary/modules.html +[core-wasm]: https://webassembly.github.io/spec/core/ + +## Building Reactor Components with `jco` + +Reactor components are WebAssembly components that are long running and meant to be called repeatedly over time. They're analogous to libraries of functionality rather than an executable (a "command" component). + +Components expose their interfaces via [WebAssembly Interface Types][docs-wit], hand-in-hand with the [Component Model][docs-component-model] which enables components to use higher level types interchangeably. + + +[docs-wit]: ../design/wit.md +[docs-component-model]: ../design/why-component-model.md + +### Exporting WIT Interfaces with `jco` + +Packaging reusable functionality into WebAssembly components isn't useful if we have no way to *expose* that functionality. This section offers a slightly deeper dive into the usage of WIT in WebAssembly components that can use the Component Model. + +As in the previous example, `export`ing WIT interfaces for other components (or a WebAssembly host) to use is fundamental to developing WebAssembly programs. + +Let's examine a [`jco` example project called `string-reverse`][jco-examples-string-reverse] that exposes functionality for reversing a string. + +To build a project like `string-reverse` from the ground up, first we'd start with a WIT like the following: + +```wit +package example:string-reverse@0.1.0 + +@since(version = 0.1.0) +interface reverse { + reverse-string: func(s: string) -> string; +} + +world string-reverse { + export reverse; +} +``` + +As a slightly deeper crash course on [WIT][wit], here's what the above code describes: + +- We've defined a namespace called `example` +- We've defined a package called `string-reverse` inside the `example` namespace +- This WIT file corresponds to version `0.1.0` of `example:string-reverse` package +- We've defined an interface called `reverse` which contains *one* function called `reverse-string` +- We specify that the `reverse` interface has existed *since* the `0.1.0` version +- The `reverse-string` function (AKA. `example:reverse-string/reverse.reverse-string`) takes a string and returns a string +- We've defined a `world` called `string-reverse` which exports the functionality provided by the `reverse` interface + +> [!WARNING] +> How do we *know* that `reverse` actually reverses a string? +> +> Unfortunately, that problem is not really solvable at this level -- this is between you and the writer of the component that implements the WIT interface. +> +> Of course, with WebAssembly, you *can* enforce static checks if you're so inclined, *before* you run any given binary. + +OK now let's see what the JS code looks like to *implement* the `component` world: + +```js +/** + * This module is the JS implementation of the `string-reverse` WIT world + */ + +/** + * This JavaScript will be interpreted by `jco` and turned into a + * WebAssembly binary with a single export (this `reverse` function). + */ +function reverseString(s) { + return s.reverse(); +} + +/** + * The JavaScript export below represents the export of the `reverse` interface, + * which which contains `reverse-string` as it's primary exported function. + */ +export const reverse = { + reverseString, +}; +``` + +> [!NOTE] +> To view the full code listing along with instructions, see the [`examples/tutorials/jco/string-reverse` folder][jco-examples-string-reverse] + +To use `jco` to compile this component, you can run the following from the `string-reverse` folder: + +```console +npx jco componentize \ + string-reverse.mjs \ + --wit wit/component.wit \ + --world-name component \ + --out string-reverse.wasm \ + --disable all +``` + +> [!NOTE] +> Like the previous example, we're not using any of the advanced [WebAssembly System Interface][wasi] features, so we `--disable` all of them +> +> Rather than typing out the `jco componentize` command manually, you can also run +> the build command with [`npm run build` from the `string-reverse` folder](https://github.com/bytecodealliance/jco/blob/main/examples/components/string-reverse/package.json#L6). + +You should see output like the following: + +``` +OK Successfully written string-reverse.wasm. +``` + +Now that we have a WebAssembly binary, we can *also* use `jco` to run it in a native JavaScript context by *transpiling* the WebAssembly binary (which could have come from anywhere!) to a JavaScript module. + +```console +npx jco transpile string-reverse.wasm -o dist/transpiled +``` + +You should see the following output: + +``` + Transpiled JS Component Files: + + - dist/transpiled/interfaces/example-string-reverse-reverse.d.ts 0.1 KiB + - dist/transpiled/string-reverse.core.wasm 10.1 MiB + - dist/transpiled/string-reverse.d.ts 0.15 KiB + - dist/transpiled/string-reverse.js 2.55 KiB +``` + +> [!TIP] +> A gentle reminder that, transpilation *does* produce [Typescript declaration file][ts-decl-file], for use in Typescript projects. + +Now that we have a transpiled module, we can run it from any JavaScript context that supports core WebAssembly (whether NodeJS or the browser). + +For NodeJS, we can use code like the following: + +```mjs +// If this import listed below is missing, please run `npm run transpile` +import { reverse } from "./dist/transpiled/string-reverse.mjs"; + +const reversed = reverse.reverseString("!dlroW olleH"); + +console.log(`reverseString('!dlroW olleH') = ${reversed}`); +``` + +> [!NOTE] +> In the `jco` example project, you can run `npm run transpiled-js` to build the existing code. + +Assuming you have the `dist/transpiled` folder populated (by running `jco transpile` in the previous step), you should see output like the following: + +``` +reverseString('!dlrow olleh') = hello world! +``` + +While it's somewhat redundant in this context, what we've done from NodeJS demonstrates the usefulness of WebAssembly and the `jco` toolchain. With the help of `jco`, we have: + +- Compiled JavaScript to a WebAssembly module (`jco compile`), adhering to an interface defined via WIT +- Converted the compiled WebAssembly module (which could be from *any* language) to a module that can be used from any compliant JS runtime (`jco transpile`) +- Run the transpiled WebAssembly component from a JavaScript native runtime (NodeJS) + +[repo]: https://github.com/bytecodealliance/component-docs +[jco-examples-string-reverse]: https://github.com/bytecodealliance/jco/tree/main/examples/components/string-reverse +[ts-decl-file]: https://www.typescriptlang.org/docs/handbook/declaration-files/deep-dive.html#declaration-file-theory-a-deep-dive + +### Advanced: Importing and Reusing WIT Interfaces via Composition + +Just as `export`ing functionality is core to building useful WebAssembly components, and similarly `import`ing and reusing functionality is key to using the strengths of WebAssembly. + +Restated, **WIT and the Component Model enable WebAssembly to *compose***. This means we can build on top of functionality that already exists and `export` *new* functionality that depends on existing functionality. + +Let's say in addition to the reversing the string (in the previous example) we want to build shared functionality that *also* upper cases the text it receives. + +We can reuse the reversing functionality *and* export a new interface which enables us to reverse and upper-case. + +Let's examine a [`jco` example project called `string-reverse-upper`][jco-examples-string-reverse-upper] that exposes +functionality for reversing *and* upper-casing a string. + +Here's the WIT one might write to enable this functionality: + +```wit +package example:string-reverse-upper@0.1.0; + +@since(version = 0.1.0) +interface reversed-upper { + reverse-and-uppercase: func(s: string) -> string; +} + +world revup { + // + // NOTE, the import below translates to: + // :/@ + // + import example:string-reverse/reverse@0.1.0; + + export reversed-upper; +} +``` + +This time, the `world` named `revup` that we are building *relies* on the interface `reverse` in the package `string-reverse` from the namespace `example`. + +We can make use of *any* WebAssembly component that matches that interface, as long as we *compose* their functionality with the component that implements the `revup` world. + +The `revup` world `import`s (and makes use) of `reverse` in order to `export` (provide) the `reversed-upper` interface, which contains the `reverse-and-uppercase` function (in JS, `reverseAndUppercase`). + +> [!NOTE] +> Functionality is imported from the `interface`, *not* the `world`. `world`s can be included/used, but the syntax is slightly different for that. + +The JavaScript to make this work ([`string-reverse-upper.mjs` in `jco/examples`](https://github.com/bytecodealliance/jco/blob/main/examples/components/string-reverse-upper/string-reverse-upper.mjs)) looks like this: + +```js +/** + * This module is the JS implementation of the `revup` WIT world + */ + +/** + * The import here is *virtual*. It refers to the `import`ed `reverse` interface in component.wit. + * + * These types *do not resolve* when the first `string-reverse-upper` component is built, + * but the types are relevant for the resulting *composed* component. + */ +import { reverseString } from 'example:string-reverse/reverse@0.1.0'; + +/** + * The JavaScript export below represents the export of the `reversed-upper` interface, + * which which contains `revup` as it's primary exported function. + */ +export const reversedUpper = { + /** + * Represents the implementation of the `reverse-and-uppercase` function in the `reversed-upper` interface + * + * This function makes use of `reverse-string` which is *imported* from another WebAssembly binary. + */ + reverseAndUppercase() { + return reverseString(s).toLocaleUpperCase(); + }, +}; +``` + +We can build the component with `jco componentize`: + +```console +npx jco componentize \ + string-reverse-upper.mjs \ + --wit wit/ \ + --world-name revup \ + --out string-reverse-upper.incomplete.wasm \ + --disable all +``` + +While we've successfully built a WebAssembly component, unlike the other examples, ours is *not yet complete*. + +We can see that if we print the WIT of the generated component by running `jco wit`: + +```console +npx jco wit string-reverse-upper.incomplete.wasm +``` + +You should see output like the following: + +``` +package root:component; + +world root { + import example:string-reverse/reverse@0.1.0; + + export example:string-reverse-upper/reversed-upper@0.1.0; +} +``` + +This tells us that the component still has *unfulfilled `import`s* -- we *use* the `reverseString` function that's in `reverse` as if it exists, but it's not yet a real part of the WebAssembly component (hence we've named it `.incomplete.wasm`. + +To compose the two components (`string-reverse-upper/string-reverse-upper.incomplete.wasm` and `string-reverse/string-reverse.wasm` we built earlier), we'll need the [WebAssembly Composition tool (`wac`)][wac]. We can use `wac plug`: + +```console +wac plug \ + -o string-reverse-upper.wasm \ + --plug ../string-reverse/string-reverse.wasm \ + string-reverse-upper.incomplete.wasm +``` + +> [!NOTE] +> You can also run this step with `npm run compose`. + +A new component `string-reverse-upper.wasm` should now be present, which is a "complete" component -- we can check the output of `jco wit` to ensure that all the imports are satisfied: + +```wit +package root:component; + +world root { + export example:string-reverse-upper/reversed-upper@0.1.0; +} +``` + +It's as-if we never imported any functionality at all -- the functionality present in `string-reverse.wasm` has been *merged into* `string-reverse-upper.wasm`, and it now simply `export`s the advanced functionality. + +We can run this completed component with in any WebAssembly-capable native JavaScript environment by using a the transpiled result: + +```console +npx jco transpile string-reverse-upper.wasm -o dist/transpiled +``` + +> [!NOTE] +> In the example project, you can run `npm run transpile` instead, which will also change the extension on `dist/transpiled/string-reverse-upper.js` to `.mjs` + +You should see output like the following: + +``` + Transpiled JS Component Files: + + - dist/transpiled/interfaces/example-string-reverse-upper-reversed-upper.d.ts 0.12 KiB + - dist/transpiled/string-reverse-upper.core.wasm 10.1 MiB + - dist/transpiled/string-reverse-upper.core2.wasm 10.1 MiB + - dist/transpiled/string-reverse-upper.d.ts 0.19 KiB + - dist/transpiled/string-reverse-upper.js 6.13 KiB +``` + +> [!TIP] +> Notice that there are *two* core WebAssembly files? That's because two core WebAssembly modules were involved +> in creating the ultimate functionality we needed. + +To run the transpiled component, we can write code like the following: + +```mjs +/** + * If this import listed below is missing, please run + * + * ``` + * npm run build && npm run compose && npm run transpile` + * ``` + */ +import { reversedUpper } from "./dist/transpiled/string-reverse-upper.mjs"; + +const result = reversedUpper.reverseAndUppercase("!dlroW olleH"); + +console.log(`reverseAndUppercase('!dlroW olleH') = ${result}`); +``` + +> [!NOTE] +> In the [`jco` example project](https://github.com/bytecodealliance/jco/tree/main/examples/components/string-reverse-upper), you can run `npm run transpiled-js` + +You should see output like the following: + +``` +reverseAndUppercase('!dlroW olleH') = HELLO WORLD! +``` + +[wac]: https://github.com/bytecodealliance/wac +[jco-examples-string-reverse-upper]: https://github.com/bytecodealliance/jco/tree/main/examples/components/string-reverse-upper + +[!TIP]: # +[!NOTE]: # +[!WARNING]: # diff --git a/component-model/src/language-support/python.md b/component-model/src/language-support/python.md index b9aed72..eacffc6 100644 --- a/component-model/src/language-support/python.md +++ b/component-model/src/language-support/python.md @@ -1,30 +1,61 @@ # Python Tooling -### Building a Component with `componentize-py` +## Building a Component with `componentize-py` -[`componentize-py`](https://github.com/dicej/componentize-py) is a tool that converts a Python +[`componentize-py`](https://github.com/bytecodealliance/componentize-py) is a tool that converts a Python application to a WebAssembly component. -Create a Python program that implements the `add` function in the [`example` -world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). Note that it imports the bindings that will be created by -`componentize-py`: +First, install [Python 3.10 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install `componentize-py`: ```sh -$ cat<> guest.py -import example +pip install componentize-py +``` -class Example(example.Example): - def add(x: int, y: int) -> int: - return x + y -EOT +Next, create or download the WIT world you would like to target. For this example we will use an [`adder` +world][adder-wit] with an `add` function (e.g. `wit/component.wit`): + +```wit +package docs:adder@0.1.0; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world adder { + export add; +} ``` -[Install `componentize-py`](https://github.com/dicej/componentize-py#installing-from-pypi) and -generate a component from `guest.py`. +If you want to generate bindings produced for the WIT world (for an IDE or typechecker), you can generate them using the `bindings` subcommand. Specify the path to the WIT interface with the world you are targeting: ```sh -$ pip install componentize-py -$ componentize-py -d /path/to/examples/example-host/add.wit -w example componentize guest -o add.wasm +$ componentize-py --wit-path wit/component/wit --world adder bindings . +``` + +> [!NOTE] +> You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. + +Bindings were created in an `adder` package which contains an `Add` protocol with an `add` method that we can implement. + +To implement this interface, put the following code in a file called `app.py`: + +```py +import adder + +class Add(adder.Adder): + def add(self, x: int, y: int) -> int: + return x + y +``` + +We now can compile our application to a Wasm component using the `componentize` subcommand: + +```console +componentize-py \ + --wit-path wit/component.wit \ + --world adder \ + componentize \ + app \ + -o add.wasm Component built successfully ``` @@ -36,42 +67,78 @@ $ cargo run --release -- 1 2 ../path/to/add.wasm 1 + 2 = 3 ``` -### Running components from Python Applications +See [`componentize-py`'s examples](https://github.com/bytecodealliance/componentize-py/tree/main/examples) to try out build HTTP, CLI, and TCP components from Python applications. + +### Building a Component that Exports an Interface + +The [sample `add.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit) exports a function. However, you'll often prefer to export an interface, either to comply with an existing specification or to capture a set of functions and types that tend to go together. Let's expand our example world to export an interface rather than directly export the function. + +```wit +// add-interface.wit +package example:component; + +interface add { + add: func(x: u32, y: u32) -> u32; +} + +world example { + export add; +} +``` + +If you peek at the bindings, you'll notice that we now implement a class for the `add` interface rather than for the `example` world. This is a consistent pattern. As you export more interfaces from your world, you implement more classes. Our add example gets the slight update of: + +```py +# app.py +import example + +class Add(example.Example): + def add(self, a: int, b: int) -> int: + return a + b +``` + +Once again, compile an application to a Wasm component using the `componentize` subcommand: -Wasm components can also be invoked from Python applications. This walks through the tooling needed -to call the `app.wasm` component from the previous section from a Python application. First, install -`wasmtime-py`, being sure to use a version [this PR has -merged](https://github.com/bytecodealliance/wasmtime-py/pull/171) or working off that branch. +```sh +$ componentize-py --wit-path add-interface.wit --world example componentize app -o add.wasm +Component built successfully +``` + +## Running components from Python Applications + +Wasm components can also be invoked from Python applications. This section walks through using tooling +to call the [pre-built `app.wasm` component][add-wasm] in the examples. -> Note: be sure to use at least Python 3.11 +> `wasmtime-py` is only able to run components built with `componentize-py` when the `--stub-wasi` option is used at build time. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), and `componentize-py` by default generates components which use resources from the `wasi:cli` world. See [this example](https://github.com/bytecodealliance/componentize-py/tree/main/examples/sandbox) of using the `--stub-wasi` option to generate a `wasmtime-py`-compatible component. + +First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py): ```sh -$ git clone https://github.com/dicej/wasmtime-py -$ (cd wasmtime-py && python ci/download-wasmtime.py && python ci/build-rust.py && pip install .) +$ pip install wasmtime ``` -Now, generate the bindings to be able to call the component from a Python host application. +First, generate the bindings to be able to call the component from a Python host application. ```sh +# Get an add component that does not import the WASI CLI world +$ wget https://github.com/bytecodealliance/component-docs/raw/main/component-model/examples/example-host/add.wasm $ python3 -m wasmtime.bindgen add.wasm --out-dir add ``` -The generated package `add` has all of the requisite exports/imports for the component and is -annotated with types to assist with type-checking and self-documentation as much as possible. - -Now, create a Python program to run the component. Note that imports for WASI preview 2 are -explicitly set to null. This is because when creating a component from a Python module, -`componentize-py` pulls in extra WASI Preview 2 imports, even if they are not used by the component. -Currently, language toolchains are likely to pull in more than a component declares in WAT. +The generated package `add` has all of the requisite exports/imports for the +component and is annotated with types to assist with type-checking and +self-documentation as much as possible. Inside the package is a `Root` class +with an `add` function that calls the component's exported `add` function. We +can now write a Python program that calls `add`: ```py -from add import Root, RootImports +from add import Root from wasmtime import Store def main(): store = Store() - component = Root(store, RootImports(poll=None, monotonic_clock=None, wall_clock=None, streams=None, filesystem=None, random=None, environment=None, preopens=None, exit=None, stdin=None, stdout=None, stderr=None)) - print("1 + 2 = ", component.add(store, 1, 2)) + component = Root(store) + print("1 + 2 =", component.add(store, 1, 2)) if __name__ == '__main__': main() @@ -83,3 +150,9 @@ Run the Python host program: $ python3 host.py 1 + 2 = 3 ``` + +[add-wasm]: https://github.com/bytecodealliance/component-docs/blob/main/component-model/examples/example-host/add.wasm + +[adder-wit]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit + +[!NOTE]: # diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 73f7e42..ceecc82 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -1,124 +1,136 @@ # Components in Rust -Rust has first-class support for the component model via [the `cargo component` tool](https://github.com/bytecodealliance/cargo-component). It is a `cargo` subcommand for -creating WebAssembly components using Rust as the component's implementation language. +Rust has first-class support for the component model via the [`cargo-component` tool][cargo-component]. +We will be using the `cargo component` subcommand to create WebAssembly components using Rust as +the component's implementation language. -## Installing `cargo component` +> [!NOTE] +> You can find more details about `cargo-component` on [crates.io](https://crates.io/crates/cargo-component). -To install `cargo component`, run: +## 1. Setup +Install [`cargo-component`][cargo-component-install]: ```sh -cargo install cargo-component +cargo install --locked cargo-component +``` +Install [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools#installation): +```sh +cargo install --locked wasm-tools +``` +Install [`wasmtime`](https://github.com/bytecodealliance/wasmtime#installation): +```sh +curl https://wasmtime.dev/install.sh -sSf | bash ``` -> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). - -## Building a Component with `cargo component` +## 2. Scaffolding a Component -Create a Rust program that implements the `add` function in the [`example` -world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). Note that it imports the bindings that will be created by -`cargo-component`. First scaffold a project: +We will create a component in Rust that implements the `add` function exported +by the [`adder` world][docs-adder] world in the `docs:adder` +[package](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#package-names). +First, we will create a new WebAssembly component package called `add`: ```sh -$ cargo component new add --reactor && cd add +cargo component new add --lib && cd add ``` -Update `wit/world.wit` to match `add.wit` and modify the component package reference to change the -package name to `example`. The `component` section of `Cargo.toml` should look like the following: +## 3. Adding the WIT world -```toml -[package.metadata.component] -package = "component:example" +We now need to change our generated `wit/world.wit` to match `docs:adder`: +```wit +{{#include ../../examples/tutorial/wit/adder/world.wit}} ``` -`cargo-component` will generate bindings for the world specified in a package's `Cargo.toml`. In particular, it will create a `Guest` trait that a component should implement. Since our `example` world has no interfaces, the trait lives directly under the bindings module. Implement the `Guest` trait in `add/src/lib.rs` such that it satisfied the `example` world, adding an `add` function. It should look similar to the following: - -```rs -cargo_component_bindings::generate!(); -use bindings::Guest; - -struct Component; +The `package.metadata.component` section of our `Cargo.toml` should be changed +to the following: -impl Guest for Component { - fn add(x: i32, y: i32) -> i32 { - x + y - } -} +```toml +[package.metadata.component] +package = "docs:adder" ``` -Now, build the component, being sure to optimize with a release build. +## 4. Generating bindings + +Now that we've updated our `world.wit` and `Cargo.toml`, we can re-generate +bindings with the command below: ```sh -$ cargo component build --release +cargo component bindings ``` -You can use `wasm-tools component wit` to output the WIT package of the component: +`cargo-component` will generate bindings for our +world and create a `Guest` trait that a component should +implement. -```sh -$ wasm-tools component wit add/target/wasm32-wasi/release/add.wasm -package root:component; +## 5. Implementing the `Guest` trait -world root { - export add: func(x: s32, y: s32) -> s32; -} +Implement the `Guest` trait in `src/lib.rs`, using the scaffolded code. Your code should look something like the following: + +```rs +{{#include ../../examples/tutorial/adder/src/lib.rs}} ``` -### Running a Component from Rust Applications +## 6. Building a Component -To verify that our component works, lets run it from a Rust application that knows how to import a -component of the [`example` world](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit). - -The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate -Rust bindings, bring in WASI worlds, and execute the component. +Now, let's build our component, being sure to optimize with a release build: ```sh -$ cd examples/add-host -$ cargo run --release -- 1 2 ../add/target/wasm32-wasi/release/add.wasm -1 + 2 = 3 +cargo component build --release ``` -See [the language guide](../language-support.md#building-a-component-with-cargo-component). +> [!WARNING] +> Building with `--release` removes all debug-related information from the resulting `.wasm` file. +> +> When prototyping or testing locally, you might want to avoid `--release` to +> obtain useful backtraces in case of errors (for example, with +> [`wasmtime::WasmBacktraceDetails::Enable`](https://docs.rs/wasmtime/latest/wasmtime/enum.WasmBacktraceDetails.html#variant.Enable)). +> Note: the resulting `.wasm` file will be considerably larger (likely 4MB+). -## Exporting an interface with `cargo component` +You can use `wasm-tools` to output the WIT package of the component: + +```sh +wasm-tools component wit target/wasm32-wasip1/release/add.wasm +``` -The [sample `add.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit) exports a function. However, to use your component from another component, it must export an interface. This results in slightly fiddlier bindings. For example, to implement the following world: +The command above should produce the output below: ```wit -package docs:adder@0.1.0; +package root:component; -interface add { - add: func(a: u32, b: u32) -> u32; +world root { + export docs:adder/add@0.1.0; } - -world adder { - export add; +package docs:adder@0.1.0 { + interface add { + add: func(x: u32, y: u32) -> u32; + } } ``` -you would write the following Rust code: -```rust -cargo_component_bindings::generate!(); +### Running a Component -// Separating out the interface puts it in a sub-module -use bindings::exports::docs::adder::add::Guest; +To verify that our component works, lets run it from a Rust application that knows how to run a +component targeting the [`adder` world](#adding-the-wit-world). -struct Component; +The application uses [`wasmtime`](https://github.com/bytecodealliance/wasmtime) crates to generate +Rust bindings, bring in WASI worlds, and execute the component. -impl Guest for Component { - fn add(a: u32, b: u32) -> u32 { - a + b - } -} +```console +$ cd examples/example-host +$ cargo run --release -- 1 2 ../add/target/wasm32-wasip1/release/adder.wasm +1 + 2 = 3 ``` -## Importing an interface with `cargo component` +## Importing an interface -The world file (`wit/world.wit`) generated for you by `cargo component new --reactor` doesn't specify any imports. +The world file (`wit/world.wit`) we generated doesn't specify any imports. +If your component consumes other components, you can edit the `world.wit` file to import their interfaces. -> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. +> [!NOTE] +> This section is about importing custom WIT interfaces from library components. +> By default, `cargo-component` imports any required [WASI interfaces](https://wasi.dev/interfaces) +> for us without needing to explicitly declare them. -If your component consumes other components, you can edit the `world.wit` file to import their interfaces. For example, suppose you have created and built an adder component as explained in the [exporting an interface section](#exporting-an-interface-with-cargo-component) and want to use that component in a calculator component. Here is a partial example world for a calculator that imports the add interface: @@ -147,7 +159,10 @@ Because the `docs:adder` package is in a different project, we must first tell ` "docs:adder" = { path = "../adder/wit" } # directory containing the WIT package ``` -Note that the path is to the adder project's WIT _directory_, not to the `world.wit` file. A WIT package may be spread across multiple files in the same directory; `cargo component` will look at all the files. +> [!NOTE] +> The path for `docs:adder` is relative to the `wit` _directory_, not to the `world.wit` file. +> +> A WIT package may be spread across multiple files in the same directory; `cargo component` will search them all. ### Calling the import from Rust @@ -155,12 +170,12 @@ Now the declaration of `add` in the adder's WIT file is visible to the `calculat ```rust // src/lib.rs -cargo_component_bindings::generate!(); +mod bindings; use bindings::exports::docs::calculator::calculate::Guest; // Bring the imported add function into scope -use bindings::docs::adder::add::add; +use bindings::docs::calculator::add::add; struct Component; @@ -181,7 +196,7 @@ When you build this using `cargo component build`, the `add` interface remains i # Do a release build to prune unused imports (e.g. WASI) $ cargo component build --release -$ wasm-tools component wit ./target/wasm32-wasi/release/calculator.wasm +$ wasm-tools component wit ./target/wasm32-wasip1/release/calculator.wasm package root:component; world root { @@ -191,11 +206,12 @@ world root { } ``` -As the import is unfulfilled, the `calculator.wasm` component could not run by itself in its current form. To fulfil the `add` import, so that the calculator can run, you would need to [compose the `calculator.wasm` and `adder.wasm` files into a single, self-contained component](../creating-and-consuming/composing.md). +As the import is unfulfilled, the `calculator.wasm` component could not run by itself in its current form. To fulfill the `add` import, so that +only `calculate` is exported, you would need to [compose the `calculator.wasm` with some `adder.wasm` into a single, self-contained component](../creating-and-consuming/composing.md). ## Creating a command component with `cargo component` -A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime` (or other `wasm:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with a `main` function, instead of a library crate (`lib`) package. +A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime` (or other `wasi:cli` hosts). In Rust terms, it's the equivalent of an application (`bin`) package with a `main` function, instead of a library crate (`lib`) package. To create a command with cargo component, run: @@ -203,9 +219,9 @@ To create a command with cargo component, run: cargo component new ``` -Unlike library components, this does _not_ have the `--reactor` flag. You will see that the created project is different too: +Unlike library components, this does _not_ have the `--lib` flag. You will see that the created project is different too: -- It doesn't contain a `.wit` file. `cargo component build` will automatically export the `wasm:cli/run` interface for Rust `bin` packages, and hook it up to `main`. +- It doesn't contain a `.wit` file. `cargo component build` will automatically export the `wasi:cli/run` interface for Rust `bin` packages, and hook it up to `main`. - Because there's no `.wit` file, `Cargo.toml` doesn't contain a `package.metadata.component.target` section. - The Rust file is called `main.rs` instead of `lib.rs`, and contains a `main` function instead of an interface implementation. @@ -215,9 +231,9 @@ You can write Rust in this project, just as you normally would, including import To run your command component: -``` +```sh cargo component build -wasmtime run --wasm component-model ./target/wasm32-wasi/debug/.wasm +wasmtime run ./target/wasm32-wasip1/debug/.wasm ``` > **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. @@ -228,52 +244,318 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co 1. Add a `wit/world.wit` to your project, and write a WIT world that imports the interface(s) you want to use. For example: -```wit -package docs:app; + ```wit + package docs:app; -world app { - import docs:calculator/calculate@0.1.0; -} -``` + world app { + import docs:calculator/calculate@0.1.0; + } + ``` -> `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. + > `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. 2. Edit `Cargo.toml` to tell `cargo component` about the new WIT file: -```toml -[package.metadata.component.target] -path = "wit" -``` + ```toml + [package.metadata.component.target] + path = "wit" + ``` -(This entry is created automatically for library components but not for command components.) + (This entry is created automatically for library components but not for command components.) 3. Edit `Cargo.toml` to tell `cargo component` where to find external package WITs: -```toml -[package.metadata.component.target.dependencies] -"docs:calculator" = { path = "../calculator/wit" } -"docs:adder" = { path = "../adder/wit" } -``` + ```toml + [package.metadata.component.target.dependencies] + "docs:calculator" = { path = "../calculator/wit" } + "docs:adder" = { path = "../adder/wit" } + ``` -> If the external package refers to other packages, you need to provide the paths to them as well. + > If the external package refers to other packages, you need to provide the paths to them as well. 4. Use the imported interface in your Rust code: -```rust -use bindings::docs::calculator::calculate::eval_expression; + ```rust + use bindings::docs::calculator::calculate::eval_expression; -fn main() { - let result = eval_expression("1 + 1"); - println!("1 + 1 = {result}"); - std::thread::sleep(Duration::from_millis(10)); -} -``` + fn main() { + let result = eval_expression("1 + 1"); + println!("1 + 1 = {result}"); + } + ``` 5. [Compose the command component with the `.wasm` components that implement the imports.](../creating-and-consuming/composing.md) 6. Run the composed component: -```sh -$ wasmtime run --wasm component-model ./my-composed-command.wasm -1 + 1 = 579 # might need to go back and do some work on the calculator implementation + ```console + $ wasmtime run ./my-composed-command.wasm + 1 + 1 = 579 # might need to go back and do some work on the calculator implementation + ``` + +## Using user-defined types + +[User-defined types](../design/wit.md#user-defined-types) map to Rust types as follows. + +| WIT type | Rust binding | +|------------|--------------| +| `record` | `struct` with public fields corresponding to the record fields | +| `variant` | `enum` with cases corresponding to the variant cases | +| `enum` | `enum` with cases corresponding to the enum cases, with no data attached | +| `resource` | [See below](#using-resources) | +| `flags` | Opaque type supporting bit flag operations, with constants for flag values | + +For example, consider the following WIT: + +```wit +interface types { + enum operation { + add, + sub, + mul, + div + } + + record expression { + left: u32, + operation: operation, + right: u32 + } + + eval: func(expr: expression) -> u32; +} ``` + +When exported from a component, this could be implemented as: + +```rust +impl Guest for Implementation { + fn eval(expr: Expression) -> u32 { + // Record fields become public fields on a struct + let (l, r) = (expr.left, expr.right); + match expr.operation { + // Enum becomes an enum with only unit cases + Operation::Add => l + r, + Operation::Sub => l - r, + Operation::Mul => l * r, + Operation::Div => l / r, + } + } +} +``` + +## Using resources + +[Resources](../design/wit.md#resources) are handles to entities that live outside the component, for example in a host, or in a different component. + +### Example + +In this section, our example resource will be a [Reverse Polish Notation (RPN)](https://en.wikipedia.org/wiki/Reverse_Polish_notation) calculator. (Engineers of a certain vintage will remember this from handheld calculators of the 1970s.) A RPN calculator is a stateful entity: a consumer pushes operands and operations onto a stack maintained within the calculator, then evaluates the stack to produce a value. The resource in WIT looks like this: + +```wit +package docs:rpn@0.1.0; + +interface types { + enum operation { + add, + sub, + mul, + div + } + + resource engine { + constructor(); + push-operand: func(operand: u32); + push-operation: func(operation: operation); + execute: func() -> u32; + } +} + +world calculator { + export types; +} +``` + +### Implementing and exporting a resource in a component + +To implement the calculator using `cargo component`: + +1. Create a library component as shown in previous sections, with the WIT given above. + +2. Define a Rust `struct` to represent the calculator state: + + ```rust + use std::cell::RefCell; + + struct CalcEngine { + stack: RefCell>, + } + ``` + + > Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. + +3. The generated bindings (`bindings.rs`) for an exported resource include a trait named `GuestX`, where `X` is the resource name. (You may need to run `cargo component build` to regenerate the bindings after updating the WIT.) For the calculator `engine` resource, the trait is `GuestEngine`. Implement this trait on the `struct` from step 2: + + ```rust + use bindings::exports::docs::rpn::types::{GuestEngine, Operation}; + + impl GuestEngine for CalcEngine { + fn new() -> Self { + CalcEngine { + stack: RefCell::new(vec![]) + } + } + + fn push_operand(&self, operand: u32) { + self.stack.borrow_mut().push(operand); + } + + fn push_operation(&self, operation: Operation) { + let mut stack = self.stack.borrow_mut(); + let right = stack.pop().unwrap(); // TODO: error handling! + let left = stack.pop().unwrap(); + let result = match operation { + Operation::Add => left + right, + Operation::Sub => left - right, + Operation::Mul => left * right, + Operation::Div => left / right, + }; + stack.push(result); + } + + fn execute(&self) -> u32 { + self.stack.borrow_mut().pop().unwrap() // TODO: error handling! + } + } + ``` + +4. We now have a working calculator type which implements the `engine` contract, but we must still connect that type to the `engine` resource type. This is done by implementing the generated `Guest` trait. For this WIT, the `Guest` trait contains nothing except an associated type. You can use an empty `struct` to implement the `Guest` trait on. Set the associated type for the resource - in our case, `Engine` - to the type which implements the resource trait - in our case, the `CalcEngine` `struct` which implements `GuestEngine`. Then use the `export!` macro to export the mapping: + + ```rust + struct Implementation; + impl Guest for Implementation { + type Engine = CalcEngine; + } + + bindings::export!(Implementation with_types_in bindings); + ``` + +This completes the implementation of the calculator `engine` resource. Run `cargo component build` to create a component `.wasm` file. + +### Importing and consuming a resource in a component + +To use the calculator engine in another component, that component must import the resource. + +1. Create a command component as shown in previous sections. + +2. Add a `wit/world.wit` to your project, and write a WIT world that imports the RPN calculator types: + + ```wit + package docs:rpn-cmd; + + world app { + import docs:rpn/types@0.1.0; + } + ``` + +3. Edit `Cargo.toml` to tell `cargo component` about the new WIT file and the external RPN package file: + + ```toml + [package.metadata.component] + package = "docs:rpn-cmd" + + [package.metadata.component.target] + path = "wit" + + [package.metadata.component.target.dependencies] + "docs:rpn" = { path = "../wit" } # or wherever your resource WIT is + ``` + +4. The resource now appears in the generated bindings as a `struct`, with appropriate associated functions. Use these to construct a test app: + + ```rust + #[allow(warnings)] + mod bindings; + use bindings::docs::rpn::types::{Engine, Operation}; + + fn main() { + let calc = Engine::new(); + calc.push_operand(1); + calc.push_operand(2); + calc.push_operation(Operation::Add); + let sum = calc.execute(); + println!("{sum}"); + } + ``` + +You can now build the command component and [compose it with the `.wasm` component that implements the resource.](../creating-and-consuming/composing.md). You can then run the composed command with `wasmtime run`. + +### Implementing and exporting a resource implementation in a host + +If you are hosting a Wasm runtime, you can export a resource from your host for guests to consume. Hosting a runtime is outside the scope of this book, so we will give only a broad outline here. This is specific to the Wasmtime runtime; other runtimes may express things differently. + +1. Use `wasmtime::component::bindgen!` to specify the WIT you are a host for: + + ```rust + wasmtime::component::bindgen!({ + path: "../wit" + }); + ``` + +2. Tell `bindgen!` how you will represent the resource in the host via the `with` field. This can be any Rust type. For example, the RPN engine could be represented by a `CalcEngine` struct: + + ```rust + wasmtime::component::bindgen!({ + path: "../wit", + with: { + "docs:rpn/types/engine": CalcEngine, + } + }); + ``` + + > If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. + +3. If the representation type isn't a built-in type, define it: + + ```rust + struct CalcEngine { /* ... */ } + ``` + +4. As a host, you will already be implementing a `Host` trait. You will now need to implement a `HostX` trait (where `X` is the resource name) _on the same type_ as the `Host` trait: + + ```rust + impl docs::rpn::types::HostEngine for MyHost { + fn new(&mut self) -> wasmtime::component::Resource { /* ... */ } + fn push_operand(&mut self, self_: wasmtime::component::Resource) { /* ... */ } + // etc. + } + ``` + + > **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. + +5. Add a `wasmtime::component::ResourceTable` to the host: + + ```rust + struct MyHost { + calcs: wasmtime::component::ResourceTable, + } + ``` + +6. In your resource method implementations, use this table to store and access instances of the resource representation: + + ```rust + impl docs::rpn::types::HostEngine for MyHost { + fn new(&mut self) -> wasmtime::component::Resource { + self.calcs.push(CalcEngine::new()).unwrap() // TODO: error handling + } + fn push_operand(&mut self, self_: wasmtime::component::Resource) { + let calc_engine = self.calcs.get(&self_).unwrap(); + // calc_engine is a CalcEngine - call its functions + } + // etc. + } + ``` + +[cargo-component]: https://github.com/bytecodealliance/cargo-component +[cargo-component-install]: https://github.com/bytecodealliance/cargo-component#install +[docs-adder]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit diff --git a/component-model/src/reference/useful-links.md b/component-model/src/reference/useful-links.md new file mode 100644 index 0000000..e7b63c4 --- /dev/null +++ b/component-model/src/reference/useful-links.md @@ -0,0 +1,17 @@ +# Useful links + +The following references are helpful in understanding the Component Model and related ecosystem/projects. + +- [WebAssembly Composition tool (`wac`)][wac] +- [WebAssembly package tools (notably `wkg`)][wkg] +- [WASI Preview 2][wasi-p2] +- [Component Model internals][wasm-cm-repo] + - [Component Model AST][ast-explainer] + - [Canonical ABI][canonical-abi] + +[wasm-cm-repo]: https://github.com/WebAssembly/component-model +[wasi-p2]: https://github.com/WebAssembly/WASI/tree/main/wasip2 +[ast-explainer]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md +[canonical-abi]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md +[wac]: https://github.com/bytecodealliance/wac +[wkg]: https://github.com/bytecodealliance/wasm-pkg-tools diff --git a/component-model/src/runtimes/wasmtime.md b/component-model/src/runtimes/wasmtime.md index 6386013..d0a3b47 100644 --- a/component-model/src/runtimes/wasmtime.md +++ b/component-model/src/runtimes/wasmtime.md @@ -1,14 +1,16 @@ # Wasmtime -[Wasmtime](https://github.com/bytecodealliance/wasmtime/) is the reference implementation of the Component Model. It supports running components that implement the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit) and serving components the implement the [`wasi:http/proxy` world](https://github.com/WebAssembly/wasi-http/blob/main/wit/proxy.wit). +[Wasmtime](https://github.com/bytecodealliance/wasmtime/) is the reference implementation of the Component Model. It supports running components that implement the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit) and serving components that implement the [`wasi:http/proxy` world](https://github.com/WebAssembly/wasi-http/blob/main/wit/proxy.wit). ## Running command components with Wasmtime -To run a command component with wasmtime, execute: +To run a command component with Wasmtime, execute: ```sh -wasmtime run --wasm component-model +wasmtime run ``` +> If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. + By default, Wasmtime denies the component access to all system resources. For example, the component cannot access the file system or environment variables. See the [Wasmtime guide](https://docs.wasmtime.dev/) for information on granting access, and for other Wasmtime features. ## Running HTTP components with Wasmtime diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index ef796a4..c4f3542 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -2,141 +2,179 @@ If you like to learn by doing, this tutorial will walk through how to build, compose, and run components through a calculator example. Calculators can conduct many operations: add, subtract, -multiply, and so on. In this example, each operation will be a component, that will be composed with +multiply, and so on. + +In this example, each operation will be a component, that will be composed with an `eval-expression` component that will evaluate the expression using the expected operator. With one operation per component, this calculator is exaggeratedly granular to show how independent logic -of an application can be contained in a component. In production, components will likely have a -larger scope than a simple mathematical operation. +of an application can be contained in a component. -Our eventual solution will involve three components: one for the calculator engine, one for the -addition operation, and one for the command-line interface. Once we have built these as separate -Wasm components, we will compose them into a single runnable component, and test it using the -`wasmtime` CLI. +In production, components will likely have a larger scope than a simple mathematical operation. -## The calculator interface +Our eventual solution will involve three components: -For tutorial purposes, we are going to define all our interfaces in one WIT package (in fact, one -`.wit` file). This file defines: +1. A calculator engine, +2. An addition operation +3. A command-line interface. -* An interface for the calculator itself. We'll use this later to carry out calculations. It - contains an evaluate function, and an enum that delineates the operations that can be involved in - a calculation. In this tutorial, the only operation is `add`. -* Interfaces for the various operations the calculator might need to carry out as part of a - calculation. For the tutorial, again, the only interface we define is for the "add" operation. -* A world describing the calculator component. This world exports the calculator interface, meaning - that other components can call it to perform calculations. It imports the operation interfaces - (such as "add"), meaning it relies on other components to perform those operations. -* A world describing each operator component. Again, there's just the "adder" world right now, and - this exports the "add" interface, meaning that components such as the calculator can call it when - they need to add numbers. -* A world describing the "primary" app component, which imports the "calculate" interface. This is - the component will take in command line arguments and pass them to the "eval-expression" function - of the calculator component. +Once we have built these as separate Wasm components, we will compose them into a single runnable +component, and test it using the [`wasmtime` CLI][wasmtime]. -```wit -// calculator.wit -package docs:calculator@0.1.0; +[wasmtime]: https://wasmtime.dev/ + +## The calculator interface -interface calculate { - enum op { - add, - } - eval-expression: func(op: op, x: u32, y: u32) -> u32; -} +For tutorial purposes, we are going to put our "calculator engine" and "addition operation" interfaces into two separate WIT packages, each containing one WIT file. -interface add { - add: func(a: u32, b: u32) -> u32; -} +This setup may seem excessive, but it illustrates a real-world use case where components come +from different authors and packages. -world adder { - export add; -} +These files can be found in the component book repository in the [`examples/tutorial/wit` directory](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit) under `wit/adder/world.wit` and `wit/calculator/world.wit`: -world calculator { - export calculate; - import add; -} + ```wit + // wit/adder/world.wit + package docs:adder@0.1.0; -world app { - import calculate; -} + interface add { + add: func(x: u32, y: u32) -> u32; + } + world adder { + export add; + } ``` +```wit + // wit/calculator/world.wit + package docs:calculator@0.1.0; + + interface calculate { + enum op { + add, + } + eval-expression: func(op: op, x: u32, y: u32) -> u32; + } + + world calculator { + export calculate; + import docs:adder/add@0.1.0; + } + + world app { + import calculate; + } + ``` + +These files define: +* A world `adder` that exports the `add` interface. Again, components such as the calculator can call it when + they need to add numbers. +* A world `calculator` describing the calculator component. This world exports the calculator interface, meaning + that other components can call it to perform calculations. It imports the operation interfaces + (such as `add`), meaning it relies on other components to perform those operations. +* An interface `calculate` that contains an evaluate function and an enum that delineates + the operations that can be involved in a calculation. In this tutorial, the only operation is `add`. +* A world `app` describing the "primary" app component, which imports the `calculate` interface. + This component will take in command line arguments and pass them to the `eval-expression` function + of the calculator component. + ## Create an `add` component Reference the [language guide](language-support.md) and [authoring components documentation](creating-and-consuming/authoring.md) to create a component that implements the -`adder` world of `calculator.wit`. For reference, see the completed +`adder` world of `adder/wit/world.wit`. + +For reference, see the completed [example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/adder/). ## Create a `calculator` component Reference the [language guide](language-support.md) and [authoring components documentation](creating-and-consuming/authoring.md) to create a component that implements the -`calculator` world of `calculator.wit`. For reference, see the completed -[example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/calculator/). The component should import the `add` function from the -`adder` world and call it if the `op` enum matches `add`. +`calculator` world of `wit/calculator/world.wit`. + +For reference, see the completed +[example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/calculator/). -## Crate a `command` component +Once complete, the component should import the `add` function from the `adder` world and call it if the `op` enum matches `add`. + +## Create a `command` component A _command_ is a component with a specific export that allows it to be executed directly by -`wasmtime` (or other `wasm:cli` hosts). The host expects it to export the [`wasi:cli/run` +`wasmtime` (or other `wasi:cli` hosts). + +The WebAssembly host expects it to export the [`wasi:cli/run` interface](https://github.com/WebAssembly/wasi-cli/blob/main/wit/run.wit), which is the equivalent -of the `main` function to WASI. `cargo-component` will automatically resolve a Rust `bin` package +of the [`main` function][wiki-entrypoint] to WASI. + +[`cargo-component`][cargo-component] will automatically resolve a Rust `bin` package with a `main` function to a component with `wasi:cli/run` exported. Scaffold a new Wasm application with a `command` component: -```sh +```console cargo component new command --command ``` This component will implement the [`app`](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/calculator.wit) world, which -imports the `calculate` interface. In `Cargo.toml`, point `cargo-component` to the WIT file and -specify that it should pull in bindings for the `app` world: +imports the `calculate` interface. + +In `Cargo.toml`, point `cargo-component` to the WIT file and specify that it should pull in bindings +for the `app` world from the path to `calculator.wit`: ```toml [package.metadata.component.target] -path = "../path/to/calculator.wit" +path = "../wit/calculator/world.wit" world = "app" ``` +Since the calculator world imports the `add` interface, the command component needs to pull in the `adder` WIT as a dependency, as well. +```toml +[package.metadata.component.target.dependencies] +"docs:adder" = { path = "../wit/adder" } +``` Now, implement a command line application that: -1. takes in three arguments: two operands and the name of an operator ("1 2 add") -2. parses the operator name and ensures it is supported in the `op` enum -3. calls the `calculate` interface's `eval_expression`, passing in the arguments. +1. Takes in three arguments: two operands and the name of an operator ("1 2 add") +2. Parses the operator name and ensures it is supported in the `op` enum +3. Calls the `calculate` interface's `eval_expression`, passing in the arguments. For reference, see a completed [example](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/command/). +[wiki-entrypoint]: https://en.wikipedia.org/wiki/Entry_point +[cargo-component]: https://crates.io/crates/cargo-component + ## Composing the calculator Now, we are ready to bring our components together into one runnable calculator component, using -`wasm-tools`. We will first compose the calculator component with the add component to satisfy it's -imports. We then compose that resolved calculator component with the command component to satisfy -its `calculate` imports. The result is a command component that has all its imports satisfied and -exports the `wasi:cli/run` function, which can be executed by `wasmtime`. +`wac`. + +We will: + +1. Compose the calculator component with the add component to satisfy the calculator component's `adder` import +2. Compose that resolved calculator component once more with the command component to satisfy the command component's `calculate` import. + +The result is a fully-formed command component that has all its imports satisfied and has a single +export (the `wasi:cli/run` interface), which can be executed by [`wasmtime`][wasmtime]. ```sh -wasm-tools compose calculator.wasm -d adder.wasm -o calculator.wasm -wasm-tools compose command.wasm -d composed.wasm -o command.wasm +wac plug calculator.wasm --plug adder.wasm -o composed.wasm +wac plug command.wasm --plug composed.wasm -o final.wasm ``` -> If you'd prefer to take a more visual approach to composing components, see the [documentation on -> composing components with -> wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). +> If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). ## Running the calculator -Now it all adds up! Run the command component with the `wasmtime` CLI, ensuring you are using a -[`v14.0.0 or greater release](https://github.com/bytecodealliance/wasmtime/releases), as earlier releases of -the `wasmtime` command line do not include component model support. +Now it all adds up! Run the final component with the `wasmtime` CLI, ensuring you are using a +[recent release][wasmtime-releases] (`v14.0.0` or greater), as earlier releases of +the `wasmtime` CLI do not include component model support. -```sh -wasmtime run --wasm component-model command.wasm 1 2 add +``` +wasmtime run final.wasm 1 2 add 1 + 2 = 3 ``` +[wasmtime-releases]: https://github.com/bytecodealliance/wasmtime/releases + ## To infinity and beyond! To expand the exercise to add more components, modify `calculator.wit` to add another operator world diff --git a/component-model/theme/head.hbs b/component-model/theme/head.hbs new file mode 100644 index 0000000..14bb3d5 --- /dev/null +++ b/component-model/theme/head.hbs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/justfile b/justfile new file mode 100644 index 0000000..baa84b1 --- /dev/null +++ b/justfile @@ -0,0 +1,35 @@ +just := env_var_or_default("JUST", "just") +just_dir := env_var_or_default("JUST_DIR", justfile_directory()) + +python := env_var_or_default("PYTHON", "python3") +cargo := env_var_or_default("CARGO", "cargo") +mdbook := env_var_or_default("MDBOOK", "mdbook") + +publish_domain := env_var_or_default("PUBLISH_DOMAIN", "component-model.bytecodealliance.org") + +scripts_dir := env_var_or_default("SCRIPTS_DIR", "scripts") + +sitemap_output_path := env_var_or_default("SITEMAP_OUTPUT_PATH", absolute_path("./component-model/book/html/sitemap.xml")) +book_output_dir := env_var_or_default("BOOK_OUTPUT_DIR", "./component-model/book/html") + +@_default: + {{just}} --list + +# Print the directory the book is/would be output to +[group('meta')] +@print-book-dir: + echo -n {{book_output_dir}} + +# Build the book +[group('build')] +@build-book: + {{mdbook}} build component-model + +# Build the sitemap +[group('build')] +@build-sitemap: + {{python}} {{scripts_dir}}/generate_sitemap.py --domain "{{publish_domain}}" --higher-priority "design" --output-path {{sitemap_output_path}} + if [ ! -f "{{book_output_dir}}/index.html" ]; then \ + echo "[error] index.html @ [{{book_output_dir}}] is missing. Build or path misconfigured"; \ + exit 1; \ + fi diff --git a/scripts/generate_sitemap.py b/scripts/generate_sitemap.py new file mode 100644 index 0000000..b490e61 --- /dev/null +++ b/scripts/generate_sitemap.py @@ -0,0 +1,72 @@ +import os +from urllib.parse import urljoin +from datetime import datetime +from pathlib import Path + +import argparse + +def parse_summary(summary_file_path): + """Parse URLs from the SUMMARY.md file.""" + with open(summary_file_path, "r") as file: + for line in file: + if "](" in line: + url = line.split("](")[1].split(")")[0] + # Add .html extension if not the root URL + if url.endswith(".md"): + url = url[:-3] + ".html" + yield url + +def determine_priority(url_path, higher_priority_section): + """Determine the priority based on the URL path and specified higher priority section.""" + if url_path.count("/") <= 1: # Pages directly under the base URL + return "1.0" + elif higher_priority_section and url_path.startswith(f"./{higher_priority_section}"): # Pages in the specified higher priority section + return "0.8" + else: + return "0.5" # All other pages + +def generate_sitemap(domain, output_path, summary_file_path, higher_priority_section): + """Generate a sitemap XML file from SUMMARY.md structure.""" + domain = "https://" + domain + urls = parse_summary(summary_file_path) # Add base URL to the list of URLs + urls = [""] + list(urls) + + sitemap = '\n' + sitemap += '\n' + + for url in urls: + full_url = urljoin(domain, url) + priority = determine_priority(url, higher_priority_section) + + sitemap += " \n" + sitemap += f" {full_url}\n" + sitemap += " weekly\n" + sitemap += f" {priority}\n" + sitemap += " \n" + + sitemap += "" + + # Write the sitemap to the specified output path + with open(output_path, "w") as file: + file.write(sitemap) + +DEFAULT_SUMMARY_MD_PATH = (Path(__file__).parent / "../component-model/src/SUMMARY.md").resolve() +DEFAULT_SITEMAP_XML_PATH = (Path(__file__).parent / "../component-model/book/html/sitemap.sml").resolve() + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate a sitemap for mdBook") + parser.add_argument("-d", "--domain", required=True, help="Domain for the mdBook site (e.g., 'component-model.bytecodealliance.org')") + parser.add_argument("-o", "--output-path", default=DEFAULT_SITEMAP_XML_PATH, help="Output path for the sitemap file") + parser.add_argument("-s", "--summary-md-path", default=DEFAULT_SUMMARY_MD_PATH, help="Path to SUMMARY.md") + parser.add_argument("-p", "--higher-priority", help="Subsection path (e.g., 'design') to assign a higher priority of 0.8") + args = parser.parse_args() + + summary_file_path = Path(args.summary_md_path).resolve() + if not summary_file_path.exists(): + raise FileNotFoundError(f"failed to find summary file [{summary_file_path}]") + + output_path = Path(args.output_path).resolve() + if not output_path.parent.exists(): + raise FileNotFoundError(f"failed to find output dir [{output_path.parent}]") + + generate_sitemap(args.domain, output_path, summary_file_path, args.higher_priority)