[
  {
    "path": ".actrc",
    "content": "-P ubuntu-24.04=catthehacker/ubuntu:act-24.04\n"
  },
  {
    "path": ".bazelrc",
    "content": "# Force Bazel to use --target=wasm32-wasip1\nbuild --platforms=@rules_rust//rust/platform:wasi\n"
  },
  {
    "path": ".bazelversion",
    "content": "8.5.1\n"
  },
  {
    "path": ".bcr/metadata.template.json",
    "content": "{\n  \"homepage\": \"https://github.com/proxy-wasm/proxy-wasm-rust-sdk\",\n  \"maintainers\": [\n    {\n      \"github\": \"PiotrSikora\",\n      \"github_user_id\": 190297,\n      \"name\": \"Piotr Sikora\"\n    }\n  ],\n  \"repository\": [\n    \"github:proxy-wasm/proxy-wasm-rust-sdk\"\n  ],\n  \"versions\": [],\n  \"yanked_versions\": {}\n}\n"
  },
  {
    "path": ".bcr/presubmit.yml",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nmatrix:\n  platform:\n    - debian11\n    - ubuntu2004\n    - ubuntu2004_arm64\n    - macos\n    - macos_arm64\n  bazel: [7.x, 8.x, 9.x]\n\ntasks:\n  verify_targets:\n    name: Verify build targets\n    platform: ${{ platform }}\n    bazel: ${{ bazel }}\n    build_targets:\n      - \"@proxy-wasm-rust-sdk//:proxy_wasm\"\n"
  },
  {
    "path": ".bcr/source.template.json",
    "content": "{\n  \"integrity\": \"\",\n  \"strip_prefix\": \"proxy-wasm-rust-sdk-{VERSION}\",\n  \"url\": \"https://github.com/{OWNER}/{REPO}/archive/refs/tags/v{VERSION}.tar.gz\"\n}\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nversion: 2\nupdates:\n  - package-ecosystem: bazel\n    directory: /\n    schedule:\n      interval: weekly\n\n  - package-ecosystem: cargo\n    directories:\n      - /\n      - examples/envoy_filter_metadata\n      - examples/grpc_auth_random\n      - examples/hello_world\n      - examples/http_auth_random\n      - examples/http_body\n      - examples/http_config\n      - examples/http_headers\n    schedule:\n      interval: weekly\n\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: weekly\n"
  },
  {
    "path": ".github/workflows/publish-to-bcr.yml",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nname: Publish to BCR\n\non:\n  # Automatically trigger when a version tag is pushed.\n  push:\n    tags:\n      - \"v*.*.*\"\n\n  # Allow manual dispatch from the GitHub UI for retries.\n  workflow_dispatch:\n    inputs:\n      tag_name:\n        description: \"Git tag to publish (e.g. v0.2.5)\"\n        required: true\n        type: string\n\njobs:\n  publish:\n    uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.1.0\n    with:\n      attest: false\n      open_pull_request: false\n      registry_fork: PiotrSikora/bazel-central-registry\n      tag_name: ${{ inputs.tag_name || github.ref_name }}\n    permissions:\n      attestations: write\n      contents: write\n      id-token: write\n    secrets:\n      publish_token: ${{ secrets.BCR_PUBLISH_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/rust.yml",
    "content": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nname: Rust\n\non:\n\n  pull_request:\n    branches:\n    - main\n\n  push:\n    branches:\n    - main\n\n  schedule:\n    - cron: '0 0 * * *'\n\njobs:\n\n  licenses:\n    runs-on: ubuntu-24.04\n\n    steps:\n    - uses: actions/checkout@v6\n    - uses: actions/setup-go@v6\n      with:\n        go-version: '^1.24'\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/go/pkg/mod\n        key: licenses-${{ hashFiles('.github/workflows/rust.yml') }}\n\n    - name: Install dependencies\n      run: |\n        go install github.com/google/addlicense@v1.2.0\n        export PATH=$PATH:$(go env GOPATH)/bin\n\n    - name: Check licenses\n      run: |\n        addlicense -check -ignore \"bazel/cargo/remote/**\" .\n\n  bazel:\n    runs-on: ubuntu-24.04\n\n    steps:\n    - uses: actions/checkout@v6\n    - uses: actions/setup-go@v6\n      with:\n        go-version: '^1.24'\n\n    - name: Cache\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cache/bazel\n          ~/.cache/bazelisk\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/go/pkg/mod\n        key: bazel-${{ hashFiles('.github/workflows/rust.yml', 'BUILD', 'WORKSPACE', '.bazelrc', '.bazelversion', 'bazel/cargo/Cargo.Bazel.lock', 'bazel/dependencies.bzl', 'bazel/repositories.bzl') }}\n\n    - name: Install dependencies\n      run: |\n        go install github.com/bazelbuild/bazelisk@v1.28.1\n        go install github.com/bazelbuild/buildtools/buildifier@v0.0.0-20260121081817-bbf01ec6cb49\n        export PATH=$PATH:$(go env GOPATH)/bin\n\n    - name: Build (wasm32-unknown-unknown)\n      run: bazelisk --noworkspace_rc build --noenable_bzlmod --enable_workspace --platforms=@rules_rust//rust/platform:wasm //...\n\n    - name: Build (wasm32-unknown-unknown/bzlmod)\n      run: bazelisk --noworkspace_rc build --enable_bzlmod --noenable_workspace --platforms=@rules_rust//rust/platform:wasm //...\n\n    - name: Build (wasm32-wasip1)\n      run: bazelisk --noworkspace_rc build --noenable_bzlmod --enable_workspace --platforms=@rules_rust//rust/platform:wasi //...\n\n    - name: Build (wasm32-wasip1/bzlmod)\n      run: bazelisk --noworkspace_rc build --enable_bzlmod --noenable_workspace --platforms=@rules_rust//rust/platform:wasi //...\n\n    - name: Format (buildifier)\n      run: |\n        buildifier -mode=check -r .\n\n    - name: Format (rules_rust)\n      run: |\n        bazelisk --noworkspace_rc run --noenable_bzlmod --enable_workspace //bazel/cargo:crates_vendor\n        git diff --exit-code\n\n    - name: Format (MODULE.bazel.lock)\n      run: bazelisk mod deps --lockfile_mode=error\n\n  msrv:\n    runs-on: ubuntu-24.04\n\n    env:\n      RUSTFLAGS: -D warnings\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n          **/target\n        key: msrv-${{ hashFiles('Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y --default-toolchain 1.68.0\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Update Rust\n      run: |\n        rustup toolchain install 1.68.0 --component clippy --component rustfmt\n        rustup default 1.68.0\n        rustup target add wasm32-unknown-unknown\n        rustup target add wasm32-wasi\n\n    - name: Build (wasm32-unknown-unknown)\n      run: cargo build --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Clippy (wasm32-unknown-unknown)\n      run: cargo clippy --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Build (wasm32-wasi)\n      run: cargo build --release --all-targets --target=wasm32-wasi\n\n    - name: Clippy (wasm32-wasi)\n      run: cargo clippy --release --all-targets --target=wasm32-wasi\n\n    - name: Test\n      run: cargo test\n\n    # Re-enable once our MSRV is Rust v1.71+.\n    # - name: Test (no leaks)\n    #  run: cargo test --features mockalloc\n\n    - name: Format (rustfmt)\n      run: cargo fmt -- --check\n\n    - name: Format (manifest)\n      run: cargo verify-project\n\n    - name: Package (docs)\n      run: cargo doc --no-deps --target=wasm32-unknown-unknown\n\n    - name: Package (publish)\n      run: cargo publish --dry-run --target=wasm32-unknown-unknown\n\n  stable:\n    runs-on: ubuntu-24.04\n\n    env:\n      RUSTFLAGS: -D warnings\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n          **/target\n        key: stable-${{ hashFiles('Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y --default-toolchain stable\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Update Rust\n      run: |\n        rustup toolchain install stable --component clippy --component rustfmt\n        rustup target add wasm32-unknown-unknown\n        rustup target add wasm32-wasip1\n\n    - name: Build (wasm32-unknown-unknown)\n      run: cargo build --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Clippy (wasm32-unknown-unknown)\n      run: cargo clippy --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Build (wasm32-wasip1)\n      run: cargo build --release --all-targets --target=wasm32-wasip1\n\n    - name: Clippy (wasm32-wasip1)\n      run: cargo clippy --release --all-targets --target=wasm32-wasip1\n\n    - name: Test\n      run: cargo test\n\n    - name: Test (no leaks)\n      run: cargo test --features mockalloc\n\n    - name: Format (rustfmt)\n      run: cargo fmt -- --check\n\n    - name: Format (manifest)\n      run: cargo verify-project\n\n    - name: Package (docs)\n      run: cargo doc --no-deps --target=wasm32-unknown-unknown\n\n    - name: Package (publish)\n      run: cargo publish --dry-run --target=wasm32-unknown-unknown\n\n  nightly:\n    runs-on: ubuntu-24.04\n\n    env:\n      RUSTFLAGS: -D warnings\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n          **/target\n        key: nightly-${{ hashFiles('Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y --default-toolchain nightly\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Update Rust\n      run: |\n        rustup toolchain install nightly --component clippy --component rustfmt\n        rustup default nightly\n        rustup target add wasm32-unknown-unknown\n        rustup target add wasm32-wasip1\n\n    - name: Build (wasm32-unknown-unknown)\n      run: cargo build --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Clippy (wasm32-unknown-unknown)\n      run: cargo clippy --release --all-targets --target=wasm32-unknown-unknown\n\n    - name: Build (wasm32-wasip1)\n      run: cargo build --release --all-targets --target=wasm32-wasip1\n\n    - name: Clippy (wasm32-wasip1)\n      run: cargo clippy --release --all-targets --target=wasm32-wasip1\n\n    - name: Test\n      run: cargo test\n\n    - name: Test (no leaks)\n      run: cargo test --features mockalloc\n\n    - name: Bench\n      run: cargo bench\n\n    - name: Format (rustfmt)\n      run: cargo fmt -- --check\n\n    - name: Format (manifest)\n      run: cargo verify-project\n\n    - name: Package (docs)\n      run: cargo doc --no-deps --target=wasm32-unknown-unknown\n\n    - name: Package (publish)\n      run: cargo publish --dry-run --target=wasm32-unknown-unknown\n\n  outdated:\n    runs-on: ubuntu-24.04\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n        key: outdated-${{ hashFiles('.github/workflows/rust.yml', 'Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Install dependencies\n      run: |\n        cargo install cargo-outdated --version 0.17.0\n\n    - name: Run cargo outdated (main)\n      run: |\n        cargo outdated --root-deps-only --exit-code 1\n\n    - name: Run cargo outdated (examples)\n      run: |\n        for example in $(find examples -name Cargo.toml); do \\\n          cd $(dirname $GITHUB_WORKSPACE/$example); \\\n          cargo outdated --root-deps-only --exit-code 1; \\\n        done\n\n  audit:\n    runs-on: ubuntu-24.04\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n        key: audit-${{ hashFiles('.github/workflows/rust.yml', 'Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Install dependencies\n      run: |\n        cargo install cargo-audit --version 0.22.0\n\n    - name: Run cargo audit (main)\n      run: |\n        cp -p bazel/cargo/Cargo.Bazel.lock Cargo.lock\n        cargo audit\n\n    - name: Run cargo audit (examples)\n      run: |\n        for example in $(find examples -name Cargo.toml); do \\\n          cd $(dirname $GITHUB_WORKSPACE/$example); \\\n          cargo audit; \\\n        done\n\n  examples:\n    runs-on: ubuntu-24.04\n\n    strategy:\n      matrix:\n        example:\n        - 'hello_world'\n        - 'http_auth_random'\n        - 'http_body'\n        - 'http_config'\n        - 'http_headers'\n        - 'grpc_auth_random'\n        - 'envoy_filter_metadata'\n\n    defaults:\n      run:\n        working-directory: ./examples/${{ matrix.example }}\n\n    env:\n      RUSTFLAGS: -D warnings\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n          **/target\n        key: example-${{ matrix.example }}-${{ hashFiles('Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Update Rust\n      run: |\n        rustup toolchain install stable --component clippy --component rustfmt\n        rustup target add wasm32-wasip1\n\n    - name: Build (wasm32-wasip1)\n      run: cargo build --release --target=wasm32-wasip1\n\n    - name: Clippy (wasm32-wasip1)\n      run: cargo clippy --release --target=wasm32-wasip1\n\n    - name: Format (rustfmt)\n      run: cargo fmt -- --check\n\n    - name: Format (manifest)\n      run: cargo verify-project\n\n    - name: Validate Envoy config\n      run: |\n        docker run --rm \\\n          -v $(pwd)/envoy.yaml:/envoy.yaml \\\n          -v $(pwd)/target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins \\\n          envoyproxy/envoy:v1.34-latest \\\n          --mode validate \\\n          -c envoy.yaml\n\n  reactors:\n    runs-on: ubuntu-24.04\n\n    strategy:\n      matrix:\n        example:\n        - 'hello_world'\n        - 'http_auth_random'\n        - 'http_body'\n        - 'http_config'\n        - 'http_headers'\n        - 'grpc_auth_random'\n        - 'envoy_filter_metadata'\n\n    defaults:\n      run:\n        working-directory: ./examples/${{ matrix.example }}\n\n    env:\n      RUSTFLAGS: -D warnings -Z wasi-exec-model=reactor\n\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Cache\n      if: ${{ env.ACT }}\n      uses: actions/cache@v5\n      with:\n        path: |\n          ~/.cargo/.crates.toml\n          ~/.cargo/.crates2.json\n          ~/.cargo/advisory-db\n          ~/.cargo/bin\n          ~/.cargo/registry\n          ~/.rustup\n          **/target\n        key: reactor-${{ matrix.example }}-${{ hashFiles('Cargo.toml') }}\n\n    - name: Install Rustup\n      if: ${{ env.ACT }}\n      run: |\n        curl -OL https://static.rust-lang.org/rustup/rustup-init.sh\n        chmod +x ./rustup-init.sh\n        ./rustup-init.sh -y --default-toolchain nightly\n        rm rustup-init.sh\n        echo \"$HOME/.cargo/bin\" >> $GITHUB_PATH\n\n    - name: Update Rust\n      run: |\n        rustup toolchain install nightly --component clippy --component rustfmt\n        rustup default nightly\n        rustup target add wasm32-wasip1\n\n    - name: Change crate type from library to binary\n      run: |\n        grep -v '^\\[lib\\]' Cargo.toml > Cargo.tmp\n        grep -v '^crate-type' Cargo.tmp > Cargo.toml\n        mv src/lib.rs src/main.rs\n\n    - name: Build (wasm32-wasip1)\n      run: cargo build --release --target=wasm32-wasip1\n\n    - name: Clippy (wasm32-wasip1)\n      run: cargo clippy --release --target=wasm32-wasip1\n\n    - name: Format (rustfmt)\n      run: cargo fmt -- --check\n\n    - name: Format (manifest)\n      run: cargo verify-project\n\n    - name: Rename .wasm to match expected filename\n      run: |\n        cd target/wasm32-wasip1/release\n        for file in $(ls -1 *.wasm); do \\\n          mv $file $(echo $file | sed 's/-/_/g'); \\\n        done\n\n    - name: Validate Envoy config\n      run: |\n        docker run --rm \\\n          -v $(pwd)/envoy.yaml:/envoy.yaml \\\n          -v $(pwd)/target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins \\\n          envoyproxy/envoy:v1.34-latest \\\n          --mode validate \\\n          -c envoy.yaml\n"
  },
  {
    "path": ".gitignore",
    "content": "/bazel-*\ntarget\nCargo.lock\n"
  },
  {
    "path": "BUILD",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_build_script\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\", \"rust_shared_library\")\n\nexports_files([\n    \"Cargo.toml\",\n])\n\ncargo_build_script(\n    name = \"proxy_wasm_build_script\",\n    srcs = [\"build.rs\"],\n    edition = \"2018\",\n    tags = [\"manual\"],\n    visibility = [\"//visibility:private\"],\n)\n\nrust_library(\n    name = \"proxy_wasm\",\n    srcs = glob([\"src/*.rs\"]),\n    edition = \"2018\",\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \":proxy_wasm_build_script\",\n        \"//bazel/cargo/remote:hashbrown\",\n        \"//bazel/cargo/remote:log\",\n    ],\n)\n\nrust_shared_library(\n    name = \"http_auth_random\",\n    srcs = [\"examples/http_auth_random/src/lib.rs\"],\n    edition = \"2018\",\n    rustc_flags = [\"-Cstrip=debuginfo\"],\n    visibility = [\"//visibility:private\"],\n    deps = [\n        \":proxy_wasm\",\n        \"//bazel/cargo/remote:log\",\n    ],\n)\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).\n\n## [0.2.4] - 2025-10-01\n\n### Fixed\n\n- Fixed a memory leak in `get_map` and `get_map_bytes` hostcalls.\n  This issue has been introduced in [0.2.3].\n  Thanks [@JaatadiaMulesoft](https://github.com/JaatadiaMulesoft)!\n\n## [0.2.3] - 2025-06-04\n\n### Changed\n\n- An empty value (`Some(\"\")` or `Some([])`) is now returned when retrieving\n  value of a HTTP header or trailer with an empty value. This is consistent\n  with the representation when retrieving a full HTTP header or trailer map.\n  Previously, a \"no value\" (`None`) was being returned, which made an empty\n  value indistinguishable from a non-existent HTTP header or trailer.\n  Thanks [@prembhaskal](https://github.com/prembhaskal)!\n\n### Added\n\n- Added support for foreign function callbacks.\n  Thanks [@casimiro](https://github.com/casimiro)!\n\n- Added convenience functions to remove headers and trailers.\n  Thanks [@itsLucario](https://github.com/itsLucario)!\n\n- Added convenience function to remove shared data.\n\n## [0.2.2] - 2024-07-21\n\n### Fixed\n\n- Fixed support for nested gRPC callouts.\n  Thanks [@andytesti](https://github.com/andytesti)!\n\n- Fixed panic on unknown `token_id` in `on_grpc_receive_initial_metadata`\n  and `on_grpc_receive_trailing_metadata`.\n  Thanks [@erikness-doordash](https://github.com/erikness-doordash)!\n\n- Fixed panic on unexpected failures in `get_property`.\n  Thanks [@alexsnaps](https://github.com/alexsnaps)!\n\n- Fixed panic on unexpected failures in `call_foreign_function`.\n  Reported by [@geNAZt](https://github.com/geNAZt).\n\n### Added\n\n- Added support for sending error responses with gRPC status codes.\n  Thanks [@juanmolle](https://github.com/juanmolle)!\n\n## [0.2.1] - 2022-11-22\n\n### Fixed\n\n- Fixed panic on unknown `token_id` in `on_grpc_close`.\n  Thanks [@Protryon](https://github.com/Protryon)!\n\n### Changed\n\n- Changed MSRV to v1.61.0.\n\n### Removed\n\n- Removed `wee-alloc` feature, because that crate is no longer maintained\n  and it leaks memory.\n\n## [0.2.0] - 2022-04-08\n\n### Fixed\n\n- Fixed performance degradation with `wasm32-wasi` target in Rust v1.56.0\n  or newer by adding `proxy_wasm::main` macro that should be used instead\n  of custom `_start`, `_initialize` and/or `main` exports.\n\n### Changed\n\n- Updated ABI to Proxy-Wasm ABI v0.2.1.\n\n### Added\n\n- Added support for calling foreign functions.\n  Thanks [@Gsantomaggio](https://github.com/Gsantomaggio)!\n\n## [0.1.4] - 2021-07-01\n\n### Added\n\n- Added support for gRPC callouts.\n  Thanks [@Shikugawa](https://github.com/Shikugawa)!\n\n## [0.1.3] - 2020-12-04\n\n### Fixed\n\n- Fixed support for nested HTTP callouts.\n  Thanks [@SvetlinZarev](https://github.com/SvetlinZarev)!\n\n### Changed\n\n- Changed `wee-alloc` to an optional feature.\n  Thanks [@yuval-k](https://github.com/yuval-k)!\n\n### Added\n\n- Added support for building for `wasm32-wasi` target.\n- Added support for metrics.\n- Added support for `RootContext` to create child contexts for streams.\n  Thanks [@dgn](https://github.com/dgn)!\n- Added support for setting network buffers.\n\n## [0.1.2] - 2020-08-05\n\n### Changed\n\n- Updated `MapType` values to match updated Proxy-Wasm ABI v0.1.0.\n  Thanks [@yskopets](https://github.com/yskopets)!\n\n## [0.1.1] - 2020-08-05\n\n### Added\n\n- Added support for building with Bazel.\n- Added support for setting HTTP bodies.\n  Thanks [@gbrail](https://github.com/gbrail)!\n\n## [0.1.0] - 2020-02-29\n\n### Added\n\n- Initial release.\n\n\n[0.2.4]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.2.3...v0.2.4\n[0.2.3]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.2.2...v0.2.3\n[0.2.2]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.2.1...v0.2.2\n[0.2.1]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.2.0...v0.2.1\n[0.2.0]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.1.4...v0.2.0\n[0.1.4]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.1.3...v0.1.4\n[0.1.3]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.1.2...v0.1.3\n[0.1.2]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.1.1...v0.1.2\n[0.1.1]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/compare/v0.1.0...v0.1.1\n[0.1.0]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/releases/tag/v0.1.0\n"
  },
  {
    "path": "CODEOWNERS",
    "content": "* @PiotrSikora\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Contribute\n\nWe'd love to accept your patches and contributions to this project. There are\njust a few small guidelines you need to follow.\n\n## Contributor License Agreement\n\nContributions to this project must be accompanied by a Contributor License\nAgreement. You (or your employer) retain the copyright to your contribution;\nthis simply gives us permission to use and redistribute your contributions as\npart of the project. Head over to <https://cla.developers.google.com/> to see\nyour current agreements on file or to sign a new one.\n\nYou generally only need to submit a CLA once, so if you've already submitted one\n(even if it was for a different project), you probably don't need to do it\nagain.\n\n## Code reviews\n\nAll submissions, including submissions by project members, require review. We\nuse GitHub pull requests for this purpose. Consult\n[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more\ninformation on using pull requests.\n\n## Community Guidelines\n\nThis project follows [Google's Open Source Community\nGuidelines](https://opensource.google/conduct/).\n"
  },
  {
    "path": "Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\nname = \"proxy-wasm\"\nversion = \"0.2.5-dev\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\nrust-version = \"1.68\"\ndescription = \"WebAssembly for Proxies\"\nreadme = \"README.md\"\nlicense = \"Apache-2.0\"\nrepository = \"https://github.com/proxy-wasm/proxy-wasm-rust-sdk\"\nedition = \"2018\"\nbuild = \"build.rs\"\n\n[dependencies]\nhashbrown = \"0.16\"\nlog = \"0.4\"\nmockalloc = { version = \"0.1\", optional = true }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n\n[profile.test]\ninherits = \"release\"\ndebug = true\n\n[profile.bench]\ninherits = \"release\"\ndebug = true\n"
  },
  {
    "path": "DEVELOPMENT.md",
    "content": "# Development\n\n## Testing\n\nGitHub Actions can be executed locally using the [`act`] tool.\n\nAll tests can be executed using:\n\n    act\n\nIndividual tests can be executed using `-j` and `--matrix` parameters, e.g.:\n\n    act -j bazel\n    act -j stable\n    act -j nightly\n    act -j examples --matrix example:http_auth_random\n\nBy default, all jobs are cached in `~/.cache/actcache`. This can be disabled\nusing the `--no-cache-server` parameter.\n\n## Updating Bazel dependencies\n\nWhen adding or updating Cargo dependencies, the existing Bazel `BUILD` files\nmust be regenerated using the [`bazelisk`] tool:\n\n```sh\nbazelisk run --noenable_bzlmod --enable_workspace //bazel/cargo:crates_vendor -- --repin all\n```\n\n\n[`act`]: https://github.com/nektos/act\n[`bazelisk`]: https://github.com/bazelbuild/bazelisk\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MODULE.bazel",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nmodule(\n    name = \"proxy-wasm-rust-sdk\",\n    version = \"0.2.5-dev\",\n    repo_name = \"proxy_wasm_rust_sdk\",\n)\n\n# Regular dependencies (sorted alphabetically).\nbazel_dep(name = \"bazel_features\", version = \"1.38.0\")\nbazel_dep(name = \"bazel_skylib\", version = \"1.8.2\")\nbazel_dep(name = \"rules_cc\", version = \"0.2.14\")\nbazel_dep(name = \"rules_rust\", version = \"0.68.1\")\n\n# Configure Rust toolchain.\nrust = use_extension(\"@rules_rust//rust:extensions.bzl\", \"rust\")\nrust.toolchain(\n    edition = \"2018\",\n    versions = [\"1.91.1\"],\n)\nuse_repo(rust, \"rust_toolchains\")\n\nregister_toolchains(\n    \"@rust_toolchains//:all\",\n    # Dummy C/C++ toolchains for Wasm targets.\n    \"@rules_rust//rust/private/dummy_cc_toolchain:dummy_cc_wasm32_toolchain\",\n    \"@rules_rust//rust/private/dummy_cc_toolchain:dummy_cc_wasm64_toolchain\",\n)\n\n# Cargo dependencies.\ncrates_deps = use_extension(\"//bazel:extensions.bzl\", \"crates_deps\")\nuse_repo(\n    crates_deps,\n    \"crates_vendor\",\n    \"crates_vendor__hashbrown-0.16.0\",\n    \"crates_vendor__log-0.4.27\",\n)\n"
  },
  {
    "path": "README.md",
    "content": "# WebAssembly for Proxies (Rust SDK)\n\n[![Build Status][build-badge]][build-link]\n[![Crate][crate-badge]][crate-link]\n[![Documentation][docs-badge]][docs-link]\n[![Apache 2.0 License][license-badge]][license-link]\n\n[build-badge]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/workflows/Rust/badge.svg?branch=main\n[build-link]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/actions?query=workflow%3ARust+branch%3Amain\n[crate-badge]: https://img.shields.io/crates/v/proxy-wasm.svg\n[crate-link]: https://crates.io/crates/proxy-wasm\n[docs-badge]: https://docs.rs/proxy-wasm/badge.svg\n[docs-link]: https://docs.rs/proxy-wasm\n[license-badge]: https://img.shields.io/github/license/proxy-wasm/proxy-wasm-rust-sdk\n[license-link]: https://github.com/proxy-wasm/proxy-wasm-rust-sdk/blob/main/LICENSE\n\n## Examples\n\n- [Hello World](./examples/hello_world/)\n- [HTTP Auth (random)](./examples/http_auth_random/)\n- [HTTP Headers](./examples/http_headers/)\n- [HTTP Response body](./examples/http_body/)\n- [HTTP Configuration](./examples/http_config/)\n- [gRPC Auth (random)](./examples/grpc_auth_random/)\n- [Envoy filter metadata](./examples/envoy_filter_metadata/)\n\n## Articles & blog posts from the community\n\n- [Extending Envoy with WASM and Rust](https://antweiss.com/blog/extending-envoy-with-wasm-and-rust/)\n- [Writing Envoy filters in Rust with WebAssembly](https://content.red-badger.com/resources/extending-istio-with-rust-and-webassembly)\n\n## Contributing changes\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) and [DEVELOPMENT.md](./DEVELOPMENT.md) files.\n"
  },
  {
    "path": "WORKSPACE",
    "content": "workspace(name = \"proxy_wasm_rust_sdk\")\n\nload(\"@proxy_wasm_rust_sdk//bazel:repositories.bzl\", \"proxy_wasm_rust_sdk_repositories\")\n\nproxy_wasm_rust_sdk_repositories()\n\nload(\"@proxy_wasm_rust_sdk//bazel:dependencies_bazel.bzl\", \"proxy_wasm_rust_sdk_dependencies_bazel\")\n\nproxy_wasm_rust_sdk_dependencies_bazel()\n\nload(\"@proxy_wasm_rust_sdk//bazel:dependencies_compat.bzl\", \"proxy_wasm_rust_sdk_dependencies_compat\")\n\nproxy_wasm_rust_sdk_dependencies_compat()\n\nload(\"@proxy_wasm_rust_sdk//bazel:dependencies_crates.bzl\", \"proxy_wasm_rust_sdk_dependencies_crates\")\n\nproxy_wasm_rust_sdk_dependencies_crates()\n"
  },
  {
    "path": "WORKSPACE.bzlmod",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "bazel/BUILD",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n"
  },
  {
    "path": "bazel/cargo/BUILD",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_rust//crate_universe:defs.bzl\", \"crates_vendor\")\n\nexports_files([\n    \"Cargo.Bazel.lock\",\n])\n\ncrates_vendor(\n    name = \"crates_vendor\",\n    cargo_lockfile = \"//bazel/cargo:Cargo.Bazel.lock\",\n    manifests = [\"//:Cargo.toml\"],\n    mode = \"remote\",\n    tags = [\"manual\"],\n    vendor_path = \"//bazel/cargo/remote\",\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.allocator-api2-0.2.21.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n    name = \"cargo_toml_env_vars\",\n    src = \"Cargo.toml\",\n)\n\nrust_library(\n    name = \"allocator_api2\",\n    srcs = glob(\n        include = [\"**/*.rs\"],\n        allow_empty = True,\n    ),\n    compile_data = glob(\n        include = [\"**\"],\n        allow_empty = True,\n        exclude = [\n            \"**/* *\",\n            \".tmp_git_root/**/*\",\n            \"BUILD\",\n            \"BUILD.bazel\",\n            \"WORKSPACE\",\n            \"WORKSPACE.bazel\",\n        ],\n    ),\n    crate_features = [\n        \"alloc\",\n    ],\n    crate_root = \"src/lib.rs\",\n    edition = \"2018\",\n    rustc_env_files = [\n        \":cargo_toml_env_vars\",\n    ],\n    rustc_flags = [\n        \"--cap-lints=allow\",\n    ],\n    tags = [\n        \"cargo-bazel\",\n        \"crate-name=allocator-api2\",\n        \"manual\",\n        \"noclippy\",\n        \"norustfmt\",\n    ],\n    target_compatible_with = select({\n        \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios-sim\": [],\n        \"@rules_rust//rust/platform:aarch64-linux-android\": [],\n        \"@rules_rust//rust/platform:aarch64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-uefi\": [],\n        \"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:armv7-linux-androideabi\": [],\n        \"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:i686-apple-darwin\": [],\n        \"@rules_rust//rust/platform:i686-linux-android\": [],\n        \"@rules_rust//rust/platform:i686-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:i686-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:i686-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:s390x-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:thumbv7em-none-eabi\": [],\n        \"@rules_rust//rust/platform:thumbv8m.main-none-eabi\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-emscripten\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1-threads\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip2\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-ios\": [],\n        \"@rules_rust//rust/platform:x86_64-linux-android\": [],\n        \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-none\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-uefi\": [],\n        \"//conditions:default\": [\"@platforms//:incompatible\"],\n    }),\n    version = \"0.2.21\",\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files(\n    [\n        \"cargo-bazel.json\",\n        \"crates.bzl\",\n        \"defs.bzl\",\n    ] + glob(\n        include = [\"*.bazel\"],\n        allow_empty = True,\n    ),\n)\n\nfilegroup(\n    name = \"srcs\",\n    srcs = glob(\n        include = [\n            \"*.bazel\",\n            \"*.bzl\",\n        ],\n        allow_empty = True,\n    ),\n)\n\n# Workspace Member Dependencies\nalias(\n    name = \"hashbrown-0.16.0\",\n    actual = \"@crates_vendor__hashbrown-0.16.0//:hashbrown\",\n    tags = [\"manual\"],\n)\n\nalias(\n    name = \"hashbrown\",\n    actual = \"@crates_vendor__hashbrown-0.16.0//:hashbrown\",\n    tags = [\"manual\"],\n)\n\nalias(\n    name = \"log-0.4.27\",\n    actual = \"@crates_vendor__log-0.4.27//:log\",\n    tags = [\"manual\"],\n)\n\nalias(\n    name = \"log\",\n    actual = \"@crates_vendor__log-0.4.27//:log\",\n    tags = [\"manual\"],\n)\n\nalias(\n    name = \"proxy-wasm-0.2.5-dev\",\n    actual = \"@crates_vendor__proxy-wasm-0.2.5-dev//:proxy_wasm\",\n    tags = [\"manual\"],\n)\n\nalias(\n    name = \"proxy-wasm\",\n    actual = \"@crates_vendor__proxy-wasm-0.2.5-dev//:proxy_wasm\",\n    tags = [\"manual\"],\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.equivalent-1.0.2.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n    name = \"cargo_toml_env_vars\",\n    src = \"Cargo.toml\",\n)\n\nrust_library(\n    name = \"equivalent\",\n    srcs = glob(\n        include = [\"**/*.rs\"],\n        allow_empty = True,\n    ),\n    compile_data = glob(\n        include = [\"**\"],\n        allow_empty = True,\n        exclude = [\n            \"**/* *\",\n            \".tmp_git_root/**/*\",\n            \"BUILD\",\n            \"BUILD.bazel\",\n            \"WORKSPACE\",\n            \"WORKSPACE.bazel\",\n        ],\n    ),\n    crate_root = \"src/lib.rs\",\n    edition = \"2015\",\n    rustc_env_files = [\n        \":cargo_toml_env_vars\",\n    ],\n    rustc_flags = [\n        \"--cap-lints=allow\",\n    ],\n    tags = [\n        \"cargo-bazel\",\n        \"crate-name=equivalent\",\n        \"manual\",\n        \"noclippy\",\n        \"norustfmt\",\n    ],\n    target_compatible_with = select({\n        \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios-sim\": [],\n        \"@rules_rust//rust/platform:aarch64-linux-android\": [],\n        \"@rules_rust//rust/platform:aarch64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-uefi\": [],\n        \"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:armv7-linux-androideabi\": [],\n        \"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:i686-apple-darwin\": [],\n        \"@rules_rust//rust/platform:i686-linux-android\": [],\n        \"@rules_rust//rust/platform:i686-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:i686-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:i686-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:s390x-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:thumbv7em-none-eabi\": [],\n        \"@rules_rust//rust/platform:thumbv8m.main-none-eabi\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-emscripten\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1-threads\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip2\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-ios\": [],\n        \"@rules_rust//rust/platform:x86_64-linux-android\": [],\n        \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-none\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-uefi\": [],\n        \"//conditions:default\": [\"@platforms//:incompatible\"],\n    }),\n    version = \"1.0.2\",\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.foldhash-0.2.0.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n    name = \"cargo_toml_env_vars\",\n    src = \"Cargo.toml\",\n)\n\nrust_library(\n    name = \"foldhash\",\n    srcs = glob(\n        include = [\"**/*.rs\"],\n        allow_empty = True,\n    ),\n    compile_data = glob(\n        include = [\"**\"],\n        allow_empty = True,\n        exclude = [\n            \"**/* *\",\n            \".tmp_git_root/**/*\",\n            \"BUILD\",\n            \"BUILD.bazel\",\n            \"WORKSPACE\",\n            \"WORKSPACE.bazel\",\n        ],\n    ),\n    crate_root = \"src/lib.rs\",\n    edition = \"2021\",\n    rustc_env_files = [\n        \":cargo_toml_env_vars\",\n    ],\n    rustc_flags = [\n        \"--cap-lints=allow\",\n    ],\n    tags = [\n        \"cargo-bazel\",\n        \"crate-name=foldhash\",\n        \"manual\",\n        \"noclippy\",\n        \"norustfmt\",\n    ],\n    target_compatible_with = select({\n        \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios-sim\": [],\n        \"@rules_rust//rust/platform:aarch64-linux-android\": [],\n        \"@rules_rust//rust/platform:aarch64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-uefi\": [],\n        \"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:armv7-linux-androideabi\": [],\n        \"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:i686-apple-darwin\": [],\n        \"@rules_rust//rust/platform:i686-linux-android\": [],\n        \"@rules_rust//rust/platform:i686-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:i686-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:i686-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:s390x-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:thumbv7em-none-eabi\": [],\n        \"@rules_rust//rust/platform:thumbv8m.main-none-eabi\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-emscripten\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1-threads\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip2\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-ios\": [],\n        \"@rules_rust//rust/platform:x86_64-linux-android\": [],\n        \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-none\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-uefi\": [],\n        \"//conditions:default\": [\"@platforms//:incompatible\"],\n    }),\n    version = \"0.2.0\",\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.hashbrown-0.16.0.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n    name = \"cargo_toml_env_vars\",\n    src = \"Cargo.toml\",\n)\n\nrust_library(\n    name = \"hashbrown\",\n    srcs = glob(\n        include = [\"**/*.rs\"],\n        allow_empty = True,\n    ),\n    compile_data = glob(\n        include = [\"**\"],\n        allow_empty = True,\n        exclude = [\n            \"**/* *\",\n            \".tmp_git_root/**/*\",\n            \"BUILD\",\n            \"BUILD.bazel\",\n            \"WORKSPACE\",\n            \"WORKSPACE.bazel\",\n        ],\n    ),\n    crate_features = [\n        \"allocator-api2\",\n        \"default\",\n        \"default-hasher\",\n        \"equivalent\",\n        \"inline-more\",\n        \"raw-entry\",\n    ],\n    crate_root = \"src/lib.rs\",\n    edition = \"2021\",\n    rustc_env_files = [\n        \":cargo_toml_env_vars\",\n    ],\n    rustc_flags = [\n        \"--cap-lints=allow\",\n    ],\n    tags = [\n        \"cargo-bazel\",\n        \"crate-name=hashbrown\",\n        \"manual\",\n        \"noclippy\",\n        \"norustfmt\",\n    ],\n    target_compatible_with = select({\n        \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios-sim\": [],\n        \"@rules_rust//rust/platform:aarch64-linux-android\": [],\n        \"@rules_rust//rust/platform:aarch64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-uefi\": [],\n        \"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:armv7-linux-androideabi\": [],\n        \"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:i686-apple-darwin\": [],\n        \"@rules_rust//rust/platform:i686-linux-android\": [],\n        \"@rules_rust//rust/platform:i686-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:i686-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:i686-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:s390x-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:thumbv7em-none-eabi\": [],\n        \"@rules_rust//rust/platform:thumbv8m.main-none-eabi\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-emscripten\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1-threads\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip2\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-ios\": [],\n        \"@rules_rust//rust/platform:x86_64-linux-android\": [],\n        \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-none\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-uefi\": [],\n        \"//conditions:default\": [\"@platforms//:incompatible\"],\n    }),\n    version = \"0.16.0\",\n    deps = [\n        \"@crates_vendor__allocator-api2-0.2.21//:allocator_api2\",\n        \"@crates_vendor__equivalent-1.0.2//:equivalent\",\n        \"@crates_vendor__foldhash-0.2.0//:foldhash\",\n    ],\n)\n"
  },
  {
    "path": "bazel/cargo/remote/BUILD.log-0.4.27.bazel",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n    name = \"cargo_toml_env_vars\",\n    src = \"Cargo.toml\",\n)\n\nrust_library(\n    name = \"log\",\n    srcs = glob(\n        include = [\"**/*.rs\"],\n        allow_empty = True,\n    ),\n    compile_data = glob(\n        include = [\"**\"],\n        allow_empty = True,\n        exclude = [\n            \"**/* *\",\n            \".tmp_git_root/**/*\",\n            \"BUILD\",\n            \"BUILD.bazel\",\n            \"WORKSPACE\",\n            \"WORKSPACE.bazel\",\n        ],\n    ),\n    crate_root = \"src/lib.rs\",\n    edition = \"2021\",\n    rustc_env_files = [\n        \":cargo_toml_env_vars\",\n    ],\n    rustc_flags = [\n        \"--cap-lints=allow\",\n    ],\n    tags = [\n        \"cargo-bazel\",\n        \"crate-name=log\",\n        \"manual\",\n        \"noclippy\",\n        \"norustfmt\",\n    ],\n    target_compatible_with = select({\n        \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios\": [],\n        \"@rules_rust//rust/platform:aarch64-apple-ios-sim\": [],\n        \"@rules_rust//rust/platform:aarch64-linux-android\": [],\n        \"@rules_rust//rust/platform:aarch64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\": [],\n        \"@rules_rust//rust/platform:aarch64-unknown-uefi\": [],\n        \"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:armv7-linux-androideabi\": [],\n        \"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\": [],\n        \"@rules_rust//rust/platform:i686-apple-darwin\": [],\n        \"@rules_rust//rust/platform:i686-linux-android\": [],\n        \"@rules_rust//rust/platform:i686-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:i686-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:i686-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\": [],\n        \"@rules_rust//rust/platform:s390x-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:thumbv7em-none-eabi\": [],\n        \"@rules_rust//rust/platform:thumbv8m.main-none-eabi\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-emscripten\": [],\n        \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip1-threads\": [],\n        \"@rules_rust//rust/platform:wasm32-wasip2\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-darwin\": [],\n        \"@rules_rust//rust/platform:x86_64-apple-ios\": [],\n        \"@rules_rust//rust/platform:x86_64-linux-android\": [],\n        \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-freebsd\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-fuchsia\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-none\": [],\n        \"@rules_rust//rust/platform:x86_64-unknown-uefi\": [],\n        \"//conditions:default\": [\"@platforms//:incompatible\"],\n    }),\n    version = \"0.4.27\",\n)\n"
  },
  {
    "path": "bazel/cargo/remote/alias_rules.bzl",
    "content": "\"\"\"Alias that transitions its target to `compilation_mode=opt`.  Use `transition_alias=\"opt\"` to enable.\"\"\"\n\nload(\"@rules_cc//cc:defs.bzl\", \"CcInfo\")\nload(\"@rules_rust//rust:rust_common.bzl\", \"COMMON_PROVIDERS\")\n\ndef _transition_alias_impl(ctx):\n    # `ctx.attr.actual` is a list of 1 item due to the transition\n    providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS]\n    if CcInfo in ctx.attr.actual[0]:\n        providers.append(ctx.attr.actual[0][CcInfo])\n    return providers\n\ndef _change_compilation_mode(compilation_mode):\n    def _change_compilation_mode_impl(_settings, _attr):\n        return {\n            \"//command_line_option:compilation_mode\": compilation_mode,\n        }\n\n    return transition(\n        implementation = _change_compilation_mode_impl,\n        inputs = [],\n        outputs = [\n            \"//command_line_option:compilation_mode\",\n        ],\n    )\n\ndef _transition_alias_rule(compilation_mode):\n    return rule(\n        implementation = _transition_alias_impl,\n        provides = COMMON_PROVIDERS,\n        attrs = {\n            \"actual\": attr.label(\n                mandatory = True,\n                doc = \"`rust_library()` target to transition to `compilation_mode=opt`.\",\n                providers = COMMON_PROVIDERS,\n                cfg = _change_compilation_mode(compilation_mode),\n            ),\n            \"_allowlist_function_transition\": attr.label(\n                default = \"@bazel_tools//tools/allowlists/function_transition_allowlist\",\n            ),\n        },\n        doc = \"Transitions a Rust library crate to the `compilation_mode=opt`.\",\n    )\n\ntransition_alias_dbg = _transition_alias_rule(\"dbg\")\ntransition_alias_fastbuild = _transition_alias_rule(\"fastbuild\")\ntransition_alias_opt = _transition_alias_rule(\"opt\")\n"
  },
  {
    "path": "bazel/cargo/remote/crates.bzl",
    "content": "###############################################################################\n# @generated\n# This file is auto-generated by the cargo-bazel tool.\n#\n# DO NOT MODIFY: Local changes may be replaced in future executions.\n###############################################################################\n\"\"\"Rules for defining repositories for remote `crates_vendor` repositories\"\"\"\n\nload(\"@bazel_tools//tools/build_defs/repo:utils.bzl\", \"maybe\")\n\n# buildifier: disable=bzl-visibility\nload(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:defs.bzl\", _crate_repositories = \"crate_repositories\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:crates_vendor.bzl\", \"crates_vendor_remote_repository\")\n\ndef crate_repositories():\n    \"\"\"Generates repositories for vendored crates.\n\n    Returns:\n      A list of repos visible to the module through the module extension.\n    \"\"\"\n    maybe(\n        crates_vendor_remote_repository,\n        name = \"crates_vendor\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.bazel\"),\n        defs_module = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:defs.bzl\"),\n    )\n\n    direct_deps = [struct(repo = \"crates_vendor\", is_dev_dep = False)]\n    direct_deps.extend(_crate_repositories())\n    return direct_deps\n"
  },
  {
    "path": "bazel/cargo/remote/defs.bzl",
    "content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To\n# regenerate this file, run the following:\n#\n#     bazel run @//bazel/cargo:crates_vendor\n###############################################################################\n\"\"\"\n# `crates_repository` API\n\n- [aliases](#aliases)\n- [crate_deps](#crate_deps)\n- [all_crate_deps](#all_crate_deps)\n- [crate_repositories](#crate_repositories)\n\n\"\"\"\n\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\nload(\"@bazel_tools//tools/build_defs/repo:utils.bzl\", \"maybe\")\n\n###############################################################################\n# MACROS API\n###############################################################################\n\n# An identifier that represent common dependencies (unconditional).\n_COMMON_CONDITION = \"\"\n\ndef _flatten_dependency_maps(all_dependency_maps):\n    \"\"\"Flatten a list of dependency maps into one dictionary.\n\n    Dependency maps have the following structure:\n\n    ```python\n    DEPENDENCIES_MAP = {\n        # The first key in the map is a Bazel package\n        # name of the workspace this file is defined in.\n        \"workspace_member_package\": {\n\n            # Not all dependencies are supported for all platforms.\n            # the condition key is the condition required to be true\n            # on the host platform.\n            \"condition\": {\n\n                # An alias to a crate target.     # The label of the crate target the\n                # Aliases are only crate names.   # package name refers to.\n                \"package_name\":                   \"@full//:label\",\n            }\n        }\n    }\n    ```\n\n    Args:\n        all_dependency_maps (list): A list of dicts as described above\n\n    Returns:\n        dict: A dictionary as described above\n    \"\"\"\n    dependencies = {}\n\n    for workspace_deps_map in all_dependency_maps:\n        for pkg_name, conditional_deps_map in workspace_deps_map.items():\n            if pkg_name not in dependencies:\n                non_frozen_map = dict()\n                for key, values in conditional_deps_map.items():\n                    non_frozen_map.update({key: dict(values.items())})\n                dependencies.setdefault(pkg_name, non_frozen_map)\n                continue\n\n            for condition, deps_map in conditional_deps_map.items():\n                # If the condition has not been recorded, do so and continue\n                if condition not in dependencies[pkg_name]:\n                    dependencies[pkg_name].setdefault(condition, dict(deps_map.items()))\n                    continue\n\n                # Alert on any miss-matched dependencies\n                inconsistent_entries = []\n                for crate_name, crate_label in deps_map.items():\n                    existing = dependencies[pkg_name][condition].get(crate_name)\n                    if existing and existing != crate_label:\n                        inconsistent_entries.append((crate_name, existing, crate_label))\n                    dependencies[pkg_name][condition].update({crate_name: crate_label})\n\n    return dependencies\n\ndef crate_deps(deps, package_name = None):\n    \"\"\"Finds the fully qualified label of the requested crates for the package where this macro is called.\n\n    Args:\n        deps (list): The desired list of crate targets.\n        package_name (str, optional): The package name of the set of dependencies to look up.\n            Defaults to `native.package_name()`.\n\n    Returns:\n        list: A list of labels to generated rust targets (str)\n    \"\"\"\n\n    if not deps:\n        return []\n\n    if package_name == None:\n        package_name = native.package_name()\n\n    # Join both sets of dependencies\n    dependencies = _flatten_dependency_maps([\n        _NORMAL_DEPENDENCIES,\n        _NORMAL_DEV_DEPENDENCIES,\n        _PROC_MACRO_DEPENDENCIES,\n        _PROC_MACRO_DEV_DEPENDENCIES,\n        _BUILD_DEPENDENCIES,\n        _BUILD_PROC_MACRO_DEPENDENCIES,\n    ]).pop(package_name, {})\n\n    # Combine all conditional packages so we can easily index over a flat list\n    # TODO: Perhaps this should actually return select statements and maintain\n    # the conditionals of the dependencies\n    flat_deps = {}\n    for deps_set in dependencies.values():\n        for crate_name, crate_label in deps_set.items():\n            flat_deps.update({crate_name: crate_label})\n\n    missing_crates = []\n    crate_targets = []\n    for crate_target in deps:\n        if crate_target not in flat_deps:\n            missing_crates.append(crate_target)\n        else:\n            crate_targets.append(flat_deps[crate_target])\n\n    if missing_crates:\n        fail(\"Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`\".format(\n            missing_crates,\n            package_name,\n            dependencies,\n        ))\n\n    return crate_targets\n\ndef all_crate_deps(\n        normal = False,\n        normal_dev = False,\n        proc_macro = False,\n        proc_macro_dev = False,\n        build = False,\n        build_proc_macro = False,\n        package_name = None):\n    \"\"\"Finds the fully qualified label of all requested direct crate dependencies \\\n    for the package where this macro is called.\n\n    If no parameters are set, all normal dependencies are returned. Setting any one flag will\n    otherwise impact the contents of the returned list.\n\n    Args:\n        normal (bool, optional): If True, normal dependencies are included in the\n            output list.\n        normal_dev (bool, optional): If True, normal dev dependencies will be\n            included in the output list..\n        proc_macro (bool, optional): If True, proc_macro dependencies are included\n            in the output list.\n        proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n            included in the output list.\n        build (bool, optional): If True, build dependencies are included\n            in the output list.\n        build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n            included in the output list.\n        package_name (str, optional): The package name of the set of dependencies to look up.\n            Defaults to `native.package_name()` when unset.\n\n    Returns:\n        list: A list of labels to generated rust targets (str)\n    \"\"\"\n\n    if package_name == None:\n        package_name = native.package_name()\n\n    # Determine the relevant maps to use\n    all_dependency_maps = []\n    if normal:\n        all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n    if normal_dev:\n        all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES)\n    if proc_macro:\n        all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)\n    if proc_macro_dev:\n        all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES)\n    if build:\n        all_dependency_maps.append(_BUILD_DEPENDENCIES)\n    if build_proc_macro:\n        all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES)\n\n    # Default to always using normal dependencies\n    if not all_dependency_maps:\n        all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n\n    dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None)\n\n    if not dependencies:\n        if dependencies == None:\n            fail(\"Tried to get all_crate_deps for package \" + package_name + \" but that package had no Cargo.toml file\")\n        else:\n            return []\n\n    crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values())\n    for condition, deps in dependencies.items():\n        crate_deps += selects.with_or({\n            tuple(_CONDITIONS[condition]): deps.values(),\n            \"//conditions:default\": [],\n        })\n\n    return crate_deps\n\ndef aliases(\n        normal = False,\n        normal_dev = False,\n        proc_macro = False,\n        proc_macro_dev = False,\n        build = False,\n        build_proc_macro = False,\n        package_name = None):\n    \"\"\"Produces a map of Crate alias names to their original label\n\n    If no dependency kinds are specified, `normal` and `proc_macro` are used by default.\n    Setting any one flag will otherwise determine the contents of the returned dict.\n\n    Args:\n        normal (bool, optional): If True, normal dependencies are included in the\n            output list.\n        normal_dev (bool, optional): If True, normal dev dependencies will be\n            included in the output list..\n        proc_macro (bool, optional): If True, proc_macro dependencies are included\n            in the output list.\n        proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n            included in the output list.\n        build (bool, optional): If True, build dependencies are included\n            in the output list.\n        build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n            included in the output list.\n        package_name (str, optional): The package name of the set of dependencies to look up.\n            Defaults to `native.package_name()` when unset.\n\n    Returns:\n        dict: The aliases of all associated packages\n    \"\"\"\n    if package_name == None:\n        package_name = native.package_name()\n\n    # Determine the relevant maps to use\n    all_aliases_maps = []\n    if normal:\n        all_aliases_maps.append(_NORMAL_ALIASES)\n    if normal_dev:\n        all_aliases_maps.append(_NORMAL_DEV_ALIASES)\n    if proc_macro:\n        all_aliases_maps.append(_PROC_MACRO_ALIASES)\n    if proc_macro_dev:\n        all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES)\n    if build:\n        all_aliases_maps.append(_BUILD_ALIASES)\n    if build_proc_macro:\n        all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES)\n\n    # Default to always using normal aliases\n    if not all_aliases_maps:\n        all_aliases_maps.append(_NORMAL_ALIASES)\n        all_aliases_maps.append(_PROC_MACRO_ALIASES)\n\n    aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None)\n\n    if not aliases:\n        return dict()\n\n    common_items = aliases.pop(_COMMON_CONDITION, {}).items()\n\n    # If there are only common items in the dictionary, immediately return them\n    if not len(aliases.keys()) == 1:\n        return dict(common_items)\n\n    # Build a single select statement where each conditional has accounted for the\n    # common set of aliases.\n    crate_aliases = {\"//conditions:default\": dict(common_items)}\n    for condition, deps in aliases.items():\n        condition_triples = _CONDITIONS[condition]\n        for triple in condition_triples:\n            if triple in crate_aliases:\n                crate_aliases[triple].update(deps)\n            else:\n                crate_aliases.update({triple: dict(deps.items() + common_items)})\n\n    return select(crate_aliases)\n\n###############################################################################\n# WORKSPACE MEMBER DEPS AND ALIASES\n###############################################################################\n\n_NORMAL_DEPENDENCIES = {\n    \"\": {\n        _COMMON_CONDITION: {\n            \"hashbrown\": Label(\"@crates_vendor//:hashbrown-0.16.0\"),\n            \"log\": Label(\"@crates_vendor//:log-0.4.27\"),\n        },\n    },\n}\n\n_NORMAL_ALIASES = {\n    \"\": {\n        _COMMON_CONDITION: {\n        },\n    },\n}\n\n_NORMAL_DEV_DEPENDENCIES = {\n    \"\": {\n    },\n}\n\n_NORMAL_DEV_ALIASES = {\n    \"\": {\n    },\n}\n\n_PROC_MACRO_DEPENDENCIES = {\n    \"\": {\n    },\n}\n\n_PROC_MACRO_ALIASES = {\n    \"\": {\n    },\n}\n\n_PROC_MACRO_DEV_DEPENDENCIES = {\n    \"\": {\n    },\n}\n\n_PROC_MACRO_DEV_ALIASES = {\n    \"\": {\n    },\n}\n\n_BUILD_DEPENDENCIES = {\n    \"\": {\n    },\n}\n\n_BUILD_ALIASES = {\n    \"\": {\n    },\n}\n\n_BUILD_PROC_MACRO_DEPENDENCIES = {\n    \"\": {\n    },\n}\n\n_BUILD_PROC_MACRO_ALIASES = {\n    \"\": {\n    },\n}\n\n_CONDITIONS = {\n    \"aarch64-apple-darwin\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n    \"aarch64-apple-ios\": [\"@rules_rust//rust/platform:aarch64-apple-ios\"],\n    \"aarch64-apple-ios-sim\": [\"@rules_rust//rust/platform:aarch64-apple-ios-sim\"],\n    \"aarch64-linux-android\": [\"@rules_rust//rust/platform:aarch64-linux-android\"],\n    \"aarch64-pc-windows-msvc\": [\"@rules_rust//rust/platform:aarch64-pc-windows-msvc\"],\n    \"aarch64-unknown-fuchsia\": [\"@rules_rust//rust/platform:aarch64-unknown-fuchsia\"],\n    \"aarch64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n    \"aarch64-unknown-nixos-gnu\": [\"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu\"],\n    \"aarch64-unknown-nto-qnx710\": [\"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710\"],\n    \"aarch64-unknown-uefi\": [\"@rules_rust//rust/platform:aarch64-unknown-uefi\"],\n    \"arm-unknown-linux-gnueabi\": [\"@rules_rust//rust/platform:arm-unknown-linux-gnueabi\"],\n    \"armv7-linux-androideabi\": [\"@rules_rust//rust/platform:armv7-linux-androideabi\"],\n    \"armv7-unknown-linux-gnueabi\": [\"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi\"],\n    \"i686-apple-darwin\": [\"@rules_rust//rust/platform:i686-apple-darwin\"],\n    \"i686-linux-android\": [\"@rules_rust//rust/platform:i686-linux-android\"],\n    \"i686-pc-windows-msvc\": [\"@rules_rust//rust/platform:i686-pc-windows-msvc\"],\n    \"i686-unknown-freebsd\": [\"@rules_rust//rust/platform:i686-unknown-freebsd\"],\n    \"i686-unknown-linux-gnu\": [\"@rules_rust//rust/platform:i686-unknown-linux-gnu\"],\n    \"powerpc-unknown-linux-gnu\": [\"@rules_rust//rust/platform:powerpc-unknown-linux-gnu\"],\n    \"riscv32imc-unknown-none-elf\": [\"@rules_rust//rust/platform:riscv32imc-unknown-none-elf\"],\n    \"riscv64gc-unknown-linux-gnu\": [\"@rules_rust//rust/platform:riscv64gc-unknown-linux-gnu\"],\n    \"riscv64gc-unknown-none-elf\": [\"@rules_rust//rust/platform:riscv64gc-unknown-none-elf\"],\n    \"s390x-unknown-linux-gnu\": [\"@rules_rust//rust/platform:s390x-unknown-linux-gnu\"],\n    \"thumbv7em-none-eabi\": [\"@rules_rust//rust/platform:thumbv7em-none-eabi\"],\n    \"thumbv8m.main-none-eabi\": [\"@rules_rust//rust/platform:thumbv8m.main-none-eabi\"],\n    \"wasm32-unknown-emscripten\": [\"@rules_rust//rust/platform:wasm32-unknown-emscripten\"],\n    \"wasm32-unknown-unknown\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n    \"wasm32-wasip1\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n    \"wasm32-wasip1-threads\": [\"@rules_rust//rust/platform:wasm32-wasip1-threads\"],\n    \"wasm32-wasip2\": [\"@rules_rust//rust/platform:wasm32-wasip2\"],\n    \"x86_64-apple-darwin\": [\"@rules_rust//rust/platform:x86_64-apple-darwin\"],\n    \"x86_64-apple-ios\": [\"@rules_rust//rust/platform:x86_64-apple-ios\"],\n    \"x86_64-linux-android\": [\"@rules_rust//rust/platform:x86_64-linux-android\"],\n    \"x86_64-pc-windows-msvc\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n    \"x86_64-unknown-freebsd\": [\"@rules_rust//rust/platform:x86_64-unknown-freebsd\"],\n    \"x86_64-unknown-fuchsia\": [\"@rules_rust//rust/platform:x86_64-unknown-fuchsia\"],\n    \"x86_64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\"],\n    \"x86_64-unknown-nixos-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n    \"x86_64-unknown-none\": [\"@rules_rust//rust/platform:x86_64-unknown-none\"],\n    \"x86_64-unknown-uefi\": [\"@rules_rust//rust/platform:x86_64-unknown-uefi\"],\n}\n\n###############################################################################\n\ndef crate_repositories():\n    \"\"\"A macro for defining repositories for all generated crates.\n\n    Returns:\n      A list of repos visible to the module through the module extension.\n    \"\"\"\n    maybe(\n        http_archive,\n        name = \"crates_vendor__allocator-api2-0.2.21\",\n        sha256 = \"683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923\",\n        type = \"tar.gz\",\n        urls = [\"https://static.crates.io/crates/allocator-api2/0.2.21/download\"],\n        strip_prefix = \"allocator-api2-0.2.21\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.allocator-api2-0.2.21.bazel\"),\n    )\n\n    maybe(\n        http_archive,\n        name = \"crates_vendor__equivalent-1.0.2\",\n        sha256 = \"877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f\",\n        type = \"tar.gz\",\n        urls = [\"https://static.crates.io/crates/equivalent/1.0.2/download\"],\n        strip_prefix = \"equivalent-1.0.2\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.equivalent-1.0.2.bazel\"),\n    )\n\n    maybe(\n        http_archive,\n        name = \"crates_vendor__foldhash-0.2.0\",\n        sha256 = \"77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb\",\n        type = \"tar.gz\",\n        urls = [\"https://static.crates.io/crates/foldhash/0.2.0/download\"],\n        strip_prefix = \"foldhash-0.2.0\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.foldhash-0.2.0.bazel\"),\n    )\n\n    maybe(\n        http_archive,\n        name = \"crates_vendor__hashbrown-0.16.0\",\n        sha256 = \"5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d\",\n        type = \"tar.gz\",\n        urls = [\"https://static.crates.io/crates/hashbrown/0.16.0/download\"],\n        strip_prefix = \"hashbrown-0.16.0\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.hashbrown-0.16.0.bazel\"),\n    )\n\n    maybe(\n        http_archive,\n        name = \"crates_vendor__log-0.4.27\",\n        sha256 = \"13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94\",\n        type = \"tar.gz\",\n        urls = [\"https://static.crates.io/crates/log/0.4.27/download\"],\n        strip_prefix = \"log-0.4.27\",\n        build_file = Label(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:BUILD.log-0.4.27.bazel\"),\n    )\n\n    return [\n        struct(repo = \"crates_vendor__hashbrown-0.16.0\", is_dev_dep = False),\n        struct(repo = \"crates_vendor__log-0.4.27\", is_dev_dep = False),\n    ]\n"
  },
  {
    "path": "bazel/dependencies_bazel.bzl",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@bazel_features//:deps.bzl\", \"bazel_features_deps\")\n\ndef proxy_wasm_rust_sdk_dependencies_bazel():\n    bazel_features_deps()\n"
  },
  {
    "path": "bazel/dependencies_compat.bzl",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@rules_cc//cc:extensions.bzl\", \"compatibility_proxy_repo\")\n\ndef proxy_wasm_rust_sdk_dependencies_compat():\n    compatibility_proxy_repo()\n"
  },
  {
    "path": "bazel/dependencies_crates.bzl",
    "content": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:defs.bzl\", \"crate_repositories\")\nload(\"@rules_rust//crate_universe:repositories.bzl\", \"crate_universe_dependencies\")\nload(\"@rules_rust//rust:repositories.bzl\", \"rust_repositories\")\n\ndef proxy_wasm_rust_sdk_dependencies_crates():\n    rust_repositories(versions = [\"1.91.1\"])\n    crate_universe_dependencies()\n    crate_repositories()\n"
  },
  {
    "path": "bazel/extensions.bzl",
    "content": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@bazel_features//:features.bzl\", \"bazel_features\")\nload(\"@proxy_wasm_rust_sdk//bazel/cargo/remote:crates.bzl\", \"crate_repositories\")\n\ndef _crates_deps_impl(module_ctx):\n    deps = []\n    for repo in crate_repositories():\n        if not repo.is_dev_dep:\n            deps.append(repo.repo)\n\n    return module_ctx.extension_metadata(\n        reproducible = bazel_features.external_deps.extension_metadata_has_reproducible,\n        root_module_direct_deps = deps,\n        root_module_direct_dev_deps = [],\n    )\n\ncrates_deps = module_extension(\n    doc = \"Dependencies for the Proxy-Wasm Rust SDK.\",\n    implementation = _crates_deps_impl,\n)\n"
  },
  {
    "path": "bazel/repositories.bzl",
    "content": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\nload(\"@bazel_tools//tools/build_defs/repo:utils.bzl\", \"maybe\")\n\ndef proxy_wasm_rust_sdk_repositories():\n    maybe(\n        http_archive,\n        name = \"bazel_features\",\n        sha256 = \"07271d0f6b12633777b69020c4cb1eb67b1939c0cf84bb3944dc85cc250c0c01\",\n        url = \"https://github.com/bazel-contrib/bazel_features/releases/download/v1.38.0/bazel_features-v1.38.0.tar.gz\",\n        strip_prefix = \"bazel_features-1.38.0\",\n    )\n\n    maybe(\n        http_archive,\n        name = \"rules_cc\",\n        sha256 = \"a2fdfde2ab9b2176bd6a33afca14458039023edb1dd2e73e6823810809df4027\",\n        url = \"https://github.com/bazelbuild/rules_cc/releases/download/0.2.14/rules_cc-0.2.14.tar.gz\",\n        strip_prefix = \"rules_cc-0.2.14\",\n    )\n\n    maybe(\n        http_archive,\n        name = \"rules_rust\",\n        integrity = \"sha256-yKqAbPYGZnmsI0YyQe6ArWkiZdrQRl9RERy74wuJA1I=\",\n        url = \"https://github.com/bazelbuild/rules_rust/releases/download/0.68.1/rules_rust-0.68.1.tar.gz\",\n    )\n\n    maybe(\n        http_archive,\n        name = \"bazel_skylib\",\n        sha256 = \"6e78f0e57de26801f6f564fa7c4a48dc8b36873e416257a92bbb0937eeac8446\",\n        url = \"https://github.com/bazelbuild/bazel-skylib/releases/download/1.8.2/bazel-skylib-1.8.2.tar.gz\",\n    )\n"
  },
  {
    "path": "build.rs",
    "content": "// Copyright 2022 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nfn main() {\n    println!(\"cargo:rerun-if-changed=build.rs\");\n    println!(\"cargo:rerun-if-env-changed=RUSTFLAGS\");\n    println!(\"cargo:rustc-check-cfg=cfg(nightly)\");\n    println!(\"cargo:rustc-check-cfg=cfg(wasi_exec_model_reactor)\");\n\n    if let Some(toolchain) = std::env::var_os(\"RUSTUP_TOOLCHAIN\") {\n        if toolchain.to_string_lossy().contains(\"nightly\") {\n            println!(\"cargo:rustc-cfg=nightly\");\n        }\n    }\n\n    if let Some(target_os) = std::env::var_os(\"CARGO_CFG_TARGET_OS\") {\n        if target_os != \"wasi\" {\n            return;\n        }\n    }\n\n    if let Some(rustflags) = std::env::var_os(\"CARGO_ENCODED_RUSTFLAGS\") {\n        for flag in rustflags.to_string_lossy().split('\\x1f') {\n            if flag.ends_with(\"wasi-exec-model=reactor\") {\n                println!(\"cargo:rustc-cfg=wasi_exec_model_reactor\");\n                return;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/envoy_filter_metadata/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-envoy-filter-metadata\"\nversion = \"0.0.1\"\nauthors = [\"Martijn Swaagma <martijn@swaagman.online>\"]\ndescription = \"Proxy-Wasm plugin example: Envoy filter metadata\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/envoy_filter_metadata/README.md",
    "content": "## Proxy-Wasm plugin example: Envoy metadata\n\nProxy-Wasm plugin that demonstrates reading metadata set by other Envoy filters.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\nSend a HTTP request to `localhost:10000` that will return the configured response.\n\n```sh\n$ curl localhost:10000\nWelcome, set the `x-custom-metadata` header to change the response!\n```\n\nSend a HTTP request to `localhost:10000` with a `x-custom-metadata` header value to get\nthe uppercased value in the response.\n\nThe response will also contain a response header `uppercased-metadata: SOME-VALUE`.\n\n```sh\n$ curl localhost:10000 -H \"x-custom-metadata: some-value\"\nCustom response with Envoy metadata: \"SOME-VALUE\"\n```\n"
  },
  {
    "path": "examples/envoy_filter_metadata/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/envoy_filter_metadata/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/\"\n                        direct_response:\n                          status: 200\n                          body:\n                            inline_string: \"Welcome, set the `x-custom-metadata` header to change the response!\\n\"\n              http_filters:\n                # Set uppercase metadata in Lua filter\n                - name: envoy.filters.http.lua\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua\n                    default_source_code:\n                      inline_string: |\n                        function envoy_on_request(request_handle)\n                          local headers = request_handle:headers()\n                          local data = headers:get(\"x-custom-metadata\")\n\n                          if data then\n                            request_handle:streamInfo():dynamicMetadata():set(\"envoy.filters.http.lua\", \"uppercased-custom-metadata\", string.upper(data))\n                          end\n\n                          request_handle:logInfo(\"Metadata set by lua filter\")\n                        end\n                # Read it from a WASM filter\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"envoy_metadata_filter\"\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_envoy_filter_metadata.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n"
  },
  {
    "path": "examples/envoy_filter_metadata/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(MetadataHttp {}) });\n}}\n\nstruct MetadataHttp {}\n\nimpl Context for MetadataHttp {}\n\nimpl HttpContext for MetadataHttp {\n    fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {\n        // Read data set by the lua filter\n        match self.get_property(vec![\n            \"metadata\",\n            \"filter_metadata\",\n            \"envoy.filters.http.lua\",\n            \"uppercased-custom-metadata\",\n        ]) {\n            Some(metadata) => match String::from_utf8(metadata) {\n                Ok(data) => {\n                    self.send_http_response(\n                        200,\n                        vec![(\"Powered-By\", \"proxy-wasm\"), (\"uppercased-metadata\", &data)],\n                        Some(format!(\"Custom response with Envoy metadata: {data:?}\\n\").as_bytes()),\n                    );\n                    Action::Pause\n                }\n                _ => Action::Continue,\n            },\n            _ => Action::Continue,\n        }\n    }\n}\n"
  },
  {
    "path": "examples/grpc_auth_random/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-grpc-auth-random\"\nversion = \"0.0.1\"\ndescription = \"Proxy-Wasm plugin example: gRPC auth (random)\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nlog = \"0.4\"\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/grpc_auth_random/README.md",
    "content": "## Proxy-Wasm plugin example: gRPC auth (random)\n\nProxy-Wasm plugin that grants access based on a result of gRPC callout.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\n#### Access granted.\n\nSend gRPC request to `localhost:10000` service `hello.HelloService`:\n\n```sh\n$ grpcurl -d '{\"greeting\": \"Rust\"}' -plaintext localhost:10000 hello.HelloService/SayHello\n{\n  \"reply\": \"hello Rust\"\n}\n```\n\nExpected Envoy logs:\n\n```console\n[...] wasm log grpc_auth_random: Access granted.\n```\n\n#### Access forbidden.\n\nSend gRPC request to `localhost:10000` service `hello.HelloService`:\n\n```sh\n$ grpcurl -d '{\"greeting\": \"Rust\"}' -plaintext localhost:10000 hello.HelloService/SayHello\nERROR:\n  Code: Aborted\n  Message: Aborted by Proxy-Wasm!\n```\n\nExpected Envoy logs:\n\n```console\n[...] wasm log grpc_auth_random: Access forbidden.\n```\n"
  },
  {
    "path": "examples/grpc_auth_random/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\n    depends_on:\n      - grpcbin\n  grpcbin:\n    image: kong/grpcbin\n    hostname: grpcbin\n    ports:\n      - \"9000:9000\"\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/grpc_auth_random/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/\"\n                        route:\n                          cluster: grpcbin\n              http_filters:\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"grpc_auth_random\"\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_grpc_auth_random.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n  clusters:\n    - name: grpcbin\n      connect_timeout: 5s\n      type: STRICT_DNS\n      lb_policy: ROUND_ROBIN\n      http2_protocol_options: {}\n      load_assignment:\n        cluster_name: grpcbin\n        endpoints:\n          - lb_endpoints:\n              - endpoint:\n                  address:\n                    socket_address:\n                      address: grpcbin\n                      port_value: 9000\n"
  },
  {
    "path": "examples/grpc_auth_random/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse log::info;\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\nuse std::time::Duration;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(GrpcAuthRandom) });\n}}\n\nstruct GrpcAuthRandom;\n\nimpl HttpContext for GrpcAuthRandom {\n    fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {\n        match self.get_http_request_header(\"content-type\") {\n            Some(value) if value.starts_with(\"application/grpc\") => {}\n            _ => {\n                // Reject non-gRPC clients.\n                self.send_http_response(\n                    503,\n                    vec![(\"Powered-By\", \"proxy-wasm\")],\n                    Some(b\"Service accessible only to gRPC clients.\\n\"),\n                );\n                return Action::Pause;\n            }\n        }\n\n        match self.get_http_request_header(\":path\") {\n            Some(value) if value.starts_with(\"/grpc.reflection\") => {\n                // Always allow gRPC calls to the reflection API.\n                Action::Continue\n            }\n            _ => {\n                // Allow other gRPC calls based on the result of grpcbin.GRPCBin/RandomError.\n                self.dispatch_grpc_call(\n                    \"grpcbin\",\n                    \"grpcbin.GRPCBin\",\n                    \"RandomError\",\n                    vec![],\n                    None,\n                    Duration::from_secs(1),\n                )\n                .unwrap();\n                Action::Pause\n            }\n        }\n    }\n\n    fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {\n        self.set_http_response_header(\"Powered-By\", Some(\"proxy-wasm\"));\n        Action::Continue\n    }\n}\n\nimpl Context for GrpcAuthRandom {\n    fn on_grpc_call_response(&mut self, _: u32, status_code: u32, _: usize) {\n        #[allow(unknown_lints, clippy::manual_is_multiple_of)]\n        if status_code % 2 == 0 {\n            info!(\"Access granted.\");\n            self.resume_http_request();\n        } else {\n            info!(\"Access forbidden.\");\n            self.send_grpc_response(\n                GrpcStatusCode::Aborted,\n                Some(\"Aborted by Proxy-Wasm!\"),\n                vec![(\"Powered-By\", b\"proxy-wasm\")],\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "examples/hello_world/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-hello-world\"\nversion = \"0.0.1\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\ndescription = \"Proxy-Wasm plugin example: Hello World\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\ncfg-if = \"1.0\"\nchrono = { version = \"0.4\", default-features = false, features = [\"clock\", \"std\"] }\nlog = \"0.4\"\nproxy-wasm = { path = \"../../\" }\n\n[target.'cfg(not(all(target_arch = \"wasm32\", target_os = \"unknown\")))'.dependencies]\ngetrandom = \"0.4\"\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/hello_world/README.md",
    "content": "## Proxy-Wasm plugin example: Hello World\n\nProxy-Wasm background service plugin that logs time and random numbers.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\nExpected Envoy logs (new line generated every 5s):\n\n```console\n[...] wasm log: Hello, World!\n[...] wasm log: It's 2022-11-22 03:39:17.849616 UTC, your lucky number is 41.\n[...] wasm log: It's 2022-11-22 03:39:22.846531 UTC, your lucky number is 28.\n[...] wasm log: It's 2022-11-22 03:39:27.847489 UTC, your lucky number is 102.\n[...] wasm log: It's 2022-11-22 03:39:32.848443 UTC, your lucky number is 250.\n```\n"
  },
  {
    "path": "examples/hello_world/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/hello_world/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nbootstrap_extensions:\n  - name: envoy.bootstrap.wasm\n    typed_config:\n      \"@type\": type.googleapis.com/envoy.extensions.wasm.v3.WasmService\n      singleton: true\n      config:\n        name: \"hello_world\"\n        vm_config:\n          runtime: \"envoy.wasm.runtime.v8\"\n          code:\n            local:\n              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_hello_world.wasm\"\n"
  },
  {
    "path": "examples/hello_world/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse cfg_if::cfg_if;\nuse chrono::{DateTime, Utc};\nuse log::info;\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\nuse std::time::Duration;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HelloWorld) });\n}}\n\nstruct HelloWorld;\n\nimpl Context for HelloWorld {}\n\nimpl RootContext for HelloWorld {\n    fn on_vm_start(&mut self, _: usize) -> bool {\n        info!(\"Hello, World!\");\n        self.set_tick_period(Duration::from_secs(5));\n        true\n    }\n\n    fn on_tick(&mut self) {\n        cfg_if! {\n            if #[cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))] {\n                let now: DateTime<Utc> = self.get_current_time().into();\n                info!(\"It's {}, there is no lucky number.\", now);\n\n            } else {\n                let now: DateTime<Utc> = Utc::now();\n                let mut buf = [0u8; 1];\n                getrandom::fill(&mut buf).unwrap();\n                info!(\"It's {}, your lucky number is {}.\", now, buf[0]);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/http_auth_random/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-http-auth-random\"\nversion = \"0.0.1\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\ndescription = \"Proxy-Wasm plugin example: HTTP auth (random)\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nlog = \"0.4\"\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/http_auth_random/README.md",
    "content": "## Proxy-Wasm plugin example: HTTP auth (random)\n\nProxy-Wasm plugin that grants access based on a result of HTTP callout.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\n#### Access granted.\n\nSend HTTP request to `localhost:10000/headers`:\n\n```sh\n$ curl localhost:10000/headers\n{\n  \"headers\": {\n    \"Accept\": \"*/*\", \n    \"Host\": \"localhost\", \n    \"User-Agent\": \"curl/7.81.0\", \n    \"X-Amzn-Trace-Id\": \"Root=1-637c4767-6e31776a0b407a0219b5b570\", \n    \"X-Envoy-Expected-Rq-Timeout-Ms\": \"15000\"\n  }\n}\n```\n\nExpected Envoy logs:\n\n```console\n[...] wasm log http_auth_random: Access granted.\n```\n\n#### Access forbidden.\n\nSend HTTP request to `localhost:10000/headers`:\n\n```sh\n$ curl localhost:10000/headers\nAccess forbidden.\n```\n\nExpected Envoy logs:\n\n```console\n[...] wasm log http_auth_random: Access forbidden.\n```\n"
  },
  {
    "path": "examples/http_auth_random/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\n    depends_on:\n      - httpbin\n  httpbin:\n    image: mccutchen/go-httpbin\n    hostname: httpbin\n    ports:\n      - \"8080:8080\"\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/http_auth_random/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/\"\n                        route:\n                          cluster: httpbin\n              http_filters:\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"http_auth_random\"\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_http_auth_random.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n  clusters:\n    - name: httpbin\n      connect_timeout: 5s\n      type: STRICT_DNS\n      lb_policy: ROUND_ROBIN\n      load_assignment:\n        cluster_name: httpbin\n        endpoints:\n          - lb_endpoints:\n              - endpoint:\n                  address:\n                    socket_address:\n                      address: httpbin\n                      port_value: 8080\n"
  },
  {
    "path": "examples/http_auth_random/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse log::info;\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\nuse std::time::Duration;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(HttpAuthRandom) });\n}}\n\nstruct HttpAuthRandom;\n\nimpl HttpContext for HttpAuthRandom {\n    fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {\n        self.dispatch_http_call(\n            \"httpbin\",\n            vec![\n                (\":method\", \"GET\"),\n                (\":path\", \"/bytes/1\"),\n                (\":authority\", \"httpbin.org\"),\n            ],\n            None,\n            vec![],\n            Duration::from_secs(1),\n        )\n        .unwrap();\n        Action::Pause\n    }\n\n    fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {\n        self.set_http_response_header(\"Powered-By\", Some(\"proxy-wasm\"));\n        Action::Continue\n    }\n}\n\nimpl Context for HttpAuthRandom {\n    fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) {\n        if let Some(body) = self.get_http_call_response_body(0, body_size) {\n            #[allow(unknown_lints, clippy::manual_is_multiple_of)]\n            if !body.is_empty() && body[0] % 2 == 0 {\n                info!(\"Access granted.\");\n                self.resume_http_request();\n                return;\n            }\n        }\n        info!(\"Access forbidden.\");\n        self.send_http_response(\n            403,\n            vec![(\"Powered-By\", \"proxy-wasm\")],\n            Some(b\"Access forbidden.\\n\"),\n        );\n    }\n}\n"
  },
  {
    "path": "examples/http_body/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-http-body\"\nversion = \"0.0.1\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\ndescription = \"Proxy-Wasm plugin example: HTTP body\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/http_body/README.md",
    "content": "## Proxy-Wasm plugin example: HTTP body\n\nProxy-Wasm plugin that redacts sensitive HTTP responses.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\n#### Response without secrets.\n\nSend HTTP request to `localhost:10000/hello`:\n\n```sh\n$ curl localhost:10000/hello\nEveryone may read this message.\n```\n\n#### Response with (redacted) secrets.\n\nSend HTTP request to `localhost:10000/secret`:\n\n```sh\n$ curl localhost:10000/secret\nOriginal message body (50 bytes) redacted.\n```\n"
  },
  {
    "path": "examples/http_body/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/http_body/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/secret\"\n                        direct_response:\n                          status: 200\n                          body:\n                            inline_string: \"This secret message should not be read by anyone.\\n\"\n                      - match:\n                          prefix: \"/\"\n                        direct_response:\n                          status: 200\n                          body:\n                            inline_string: \"Everyone may read this message.\\n\"\n              http_filters:\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"http_body\"\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_http_body.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n"
  },
  {
    "path": "examples/http_body/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HttpBodyRoot) });\n}}\n\nstruct HttpBodyRoot;\n\nimpl Context for HttpBodyRoot {}\n\nimpl RootContext for HttpBodyRoot {\n    fn get_type(&self) -> Option<ContextType> {\n        Some(ContextType::HttpContext)\n    }\n\n    fn create_http_context(&self, _: u32) -> Option<Box<dyn HttpContext>> {\n        Some(Box::new(HttpBody))\n    }\n}\n\nstruct HttpBody;\n\nimpl Context for HttpBody {}\n\nimpl HttpContext for HttpBody {\n    fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {\n        // If there is a Content-Length header and we change the length of\n        // the body later, then clients will break. So remove it.\n        // We must do this here, because once we exit this function we\n        // can no longer modify the response headers.\n        self.set_http_response_header(\"content-length\", None);\n        Action::Continue\n    }\n\n    fn on_http_response_body(&mut self, body_size: usize, end_of_stream: bool) -> Action {\n        if !end_of_stream {\n            // Wait -- we'll be called again when the complete body is buffered\n            // at the host side.\n            return Action::Pause;\n        }\n\n        // Replace the message body if it contains the text \"secret\".\n        // Since we returned \"Pause\" previuously, this will return the whole body.\n        if let Some(body_bytes) = self.get_http_response_body(0, body_size) {\n            let body_str = String::from_utf8(body_bytes).unwrap();\n            if body_str.contains(\"secret\") {\n                let new_body = format!(\"Original message body ({body_size} bytes) redacted.\\n\");\n                self.set_http_response_body(0, body_size, &new_body.into_bytes());\n            }\n        }\n        Action::Continue\n    }\n}\n"
  },
  {
    "path": "examples/http_config/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-http-config\"\nversion = \"0.0.1\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\ndescription = \"Proxy-Wasm plugin example: HTTP config\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/http_config/README.md",
    "content": "## Proxy-Wasm plugin example: HTTP config\n\nProxy-Wasm plugin that injects HTTP response header with a value from Envoy config.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\nSend HTTP request to `localhost:10000/hello`:\n\n```sh\n$ curl -I localhost:10000/hello\nHTTP/1.1 200 OK\ncontent-length: 40\ncontent-type: text/plain\ncustom-header: The secret to life is meaningless unless you discover it yourself\ndate: Tue, 22 Nov 2022 04:09:05 GMT\nserver: envoy\n```\n"
  },
  {
    "path": "examples/http_config/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/http_config/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/\"\n                        direct_response:\n                          status: 200\n                          body:\n                            inline_string: \"Inspect the HTTP header: custom-header.\\n\"\n              http_filters:\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"http_config\"\n                        configuration:\n                          \"@type\": \"type.googleapis.com/google.protobuf.StringValue\"\n                          value: The secret to life is meaningless unless you discover it yourself\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_http_config.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n"
  },
  {
    "path": "examples/http_config/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> {\n        Box::new(HttpConfigHeaderRoot {\n            header_content: String::new(),\n        })\n    });\n}}\n\nstruct HttpConfigHeader {\n    header_content: String,\n}\n\nimpl Context for HttpConfigHeader {}\n\nimpl HttpContext for HttpConfigHeader {\n    fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {\n        self.add_http_response_header(\"custom-header\", self.header_content.as_str());\n        Action::Continue\n    }\n}\n\nstruct HttpConfigHeaderRoot {\n    header_content: String,\n}\n\nimpl Context for HttpConfigHeaderRoot {}\n\nimpl RootContext for HttpConfigHeaderRoot {\n    fn on_configure(&mut self, _: usize) -> bool {\n        if let Some(config_bytes) = self.get_plugin_configuration() {\n            self.header_content = String::from_utf8(config_bytes).unwrap()\n        }\n        true\n    }\n\n    fn create_http_context(&self, _: u32) -> Option<Box<dyn HttpContext>> {\n        Some(Box::new(HttpConfigHeader {\n            header_content: self.header_content.clone(),\n        }))\n    }\n\n    fn get_type(&self) -> Option<ContextType> {\n        Some(ContextType::HttpContext)\n    }\n}\n"
  },
  {
    "path": "examples/http_headers/Cargo.toml",
    "content": "# Copyright 2026 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n[package]\npublish = false\nname = \"proxy-wasm-example-http-headers\"\nversion = \"0.0.1\"\nauthors = [\"Piotr Sikora <piotrsikora@google.com>\"]\ndescription = \"Proxy-Wasm plugin example: HTTP headers\"\nlicense = \"Apache-2.0\"\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nlog = \"0.4\"\nproxy-wasm = { path = \"../../\" }\n\n[profile.release]\nlto = true\nopt-level = 3\ncodegen-units = 1\npanic = \"abort\"\nstrip = \"debuginfo\"\n"
  },
  {
    "path": "examples/http_headers/README.md",
    "content": "## Proxy-Wasm plugin example: HTTP headers\n\nProxy-Wasm plugin that logs HTTP request/response headers.\n\n### Building\n\n```sh\n$ cargo build --target wasm32-wasip1 --release\n```\n\n### Using in Envoy\n\nThis example can be run with [`docker compose`](https://docs.docker.com/compose/install/)\nand has a matching Envoy configuration.\n\n```sh\n$ docker compose up\n```\n\nSend HTTP request to `localhost:10000/hello`:\n\n```sh\n$ curl localhost:10000/hello\nHello, World!\n```\n\nExpected Envoy logs:\n\n```console\n[...] wasm log http_headers: #2 -> :authority: localhost:10000\n[...] wasm log http_headers: #2 -> :path: /hello\n[...] wasm log http_headers: #2 -> :method: GET\n[...] wasm log http_headers: #2 -> :scheme: http\n[...] wasm log http_headers: #2 -> user-agent: curl/7.81.0\n[...] wasm log http_headers: #2 -> accept: */*\n[...] wasm log http_headers: #2 -> x-forwarded-proto: http\n[...] wasm log http_headers: #2 -> x-request-id: 3ed6eb3b-ddce-4fdc-8862-ddb8f168d406\n[...] wasm log http_headers: #2 <- :status: 200\n[...] wasm log http_headers: #2 <- hello: World\n[...] wasm log http_headers: #2 <- powered-by: proxy-wasm\n[...] wasm log http_headers: #2 <- content-length: 14\n[...] wasm log http_headers: #2 <- content-type: text/plain\n[...] wasm log http_headers: #2 completed.\n```\n"
  },
  {
    "path": "examples/http_headers/docker-compose.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nservices:\n  envoy:\n    image: envoyproxy/envoy:v1.34-latest\n    hostname: envoy\n    ports:\n      - \"10000:10000\"\n    volumes:\n      - ./envoy.yaml:/etc/envoy/envoy.yaml\n      - ./target/wasm32-wasip1/release:/etc/envoy/proxy-wasm-plugins\n    networks:\n      - envoymesh\nnetworks:\n  envoymesh: {}\n"
  },
  {
    "path": "examples/http_headers/envoy.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nstatic_resources:\n  listeners:\n    address:\n      socket_address:\n        address: 0.0.0.0\n        port_value: 10000\n    filter_chains:\n      - filters:\n          - name: envoy.filters.network.http_connection_manager\n            typed_config:\n              \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n              stat_prefix: ingress_http\n              codec_type: AUTO\n              route_config:\n                name: local_routes\n                virtual_hosts:\n                  - name: local_service\n                    domains:\n                      - \"*\"\n                    routes:\n                      - match:\n                          prefix: \"/\"\n                        direct_response:\n                          status: 200\n                          body:\n                            inline_string: \"Request /hello and be welcomed!\\n\"\n              http_filters:\n                - name: envoy.filters.http.wasm\n                  typed_config:\n                    \"@type\": type.googleapis.com/udpa.type.v1.TypedStruct\n                    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm\n                    value:\n                      config:\n                        name: \"http_headers\"\n                        vm_config:\n                          runtime: \"envoy.wasm.runtime.v8\"\n                          code:\n                            local:\n                              filename: \"/etc/envoy/proxy-wasm-plugins/proxy_wasm_example_http_headers.wasm\"\n                - name: envoy.filters.http.router\n                  typed_config:\n                    \"@type\": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n"
  },
  {
    "path": "examples/http_headers/src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse log::info;\nuse proxy_wasm::traits::*;\nuse proxy_wasm::types::*;\n\nproxy_wasm::main! {{\n    proxy_wasm::set_log_level(LogLevel::Trace);\n    proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HttpHeadersRoot) });\n}}\n\nstruct HttpHeadersRoot;\n\nimpl Context for HttpHeadersRoot {}\n\nimpl RootContext for HttpHeadersRoot {\n    fn get_type(&self) -> Option<ContextType> {\n        Some(ContextType::HttpContext)\n    }\n\n    fn create_http_context(&self, context_id: u32) -> Option<Box<dyn HttpContext>> {\n        Some(Box::new(HttpHeaders { context_id }))\n    }\n}\n\nstruct HttpHeaders {\n    context_id: u32,\n}\n\nimpl Context for HttpHeaders {}\n\nimpl HttpContext for HttpHeaders {\n    fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {\n        for (name, value) in &self.get_http_request_headers() {\n            info!(\"#{} -> {}: {}\", self.context_id, name, value);\n        }\n\n        match self.get_http_request_header(\":path\") {\n            Some(path) if path == \"/hello\" => {\n                self.send_http_response(\n                    200,\n                    vec![(\"Hello\", \"World\"), (\"Powered-By\", \"proxy-wasm\")],\n                    Some(b\"Hello, World!\\n\"),\n                );\n                Action::Pause\n            }\n            _ => Action::Continue,\n        }\n    }\n\n    fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {\n        for (name, value) in &self.get_http_response_headers() {\n            info!(\"#{} <- {}: {}\", self.context_id, name, value);\n        }\n        Action::Continue\n    }\n\n    fn on_log(&mut self) {\n        info!(\"#{} completed.\", self.context_id);\n    }\n}\n"
  },
  {
    "path": "src/allocator.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse std::mem::MaybeUninit;\n\n#[cfg_attr(\n    all(target_arch = \"wasm32\", target_os = \"unknown\"),\n    export_name = \"malloc\"\n)]\n#[cfg_attr(not(all(target_arch = \"wasm32\", target_os = \"unknown\")), no_mangle)]\npub extern \"C\" fn proxy_on_memory_allocate(size: usize) -> *mut u8 {\n    let mut vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(size);\n    unsafe {\n        vec.set_len(size);\n    }\n    let slice = vec.into_boxed_slice();\n    Box::into_raw(slice) as *mut u8\n}\n"
  },
  {
    "path": "src/dispatcher.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse crate::hostcalls;\nuse crate::traits::*;\nuse crate::types::*;\nuse hashbrown::HashMap;\nuse log::trace;\nuse std::cell::{Cell, RefCell};\n\nthread_local! {\nstatic DISPATCHER: Dispatcher = Dispatcher::new();\n}\n\npub(crate) fn set_root_context(callback: NewRootContext) {\n    DISPATCHER.with(|dispatcher| dispatcher.set_root_context(callback));\n}\n\npub(crate) fn set_stream_context(callback: NewStreamContext) {\n    DISPATCHER.with(|dispatcher| dispatcher.set_stream_context(callback));\n}\n\npub(crate) fn set_http_context(callback: NewHttpContext) {\n    DISPATCHER.with(|dispatcher| dispatcher.set_http_context(callback));\n}\n\npub(crate) fn register_callout(token_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.register_callout(token_id));\n}\n\npub(crate) fn register_grpc_callout(token_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.register_grpc_callout(token_id));\n}\n\npub(crate) fn register_grpc_stream(token_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.register_grpc_stream(token_id));\n}\n\nstruct NoopRoot;\n\nimpl Context for NoopRoot {}\nimpl RootContext for NoopRoot {}\n\nstruct Dispatcher {\n    new_root: Cell<Option<NewRootContext>>,\n    roots: RefCell<HashMap<u32, Box<dyn RootContext>>>,\n    new_stream: Cell<Option<NewStreamContext>>,\n    streams: RefCell<HashMap<u32, Box<dyn StreamContext>>>,\n    new_http_stream: Cell<Option<NewHttpContext>>,\n    http_streams: RefCell<HashMap<u32, Box<dyn HttpContext>>>,\n    active_id: Cell<u32>,\n    callouts: RefCell<HashMap<u32, u32>>,\n    grpc_callouts: RefCell<HashMap<u32, u32>>,\n    grpc_streams: RefCell<HashMap<u32, u32>>,\n}\n\nimpl Dispatcher {\n    fn new() -> Dispatcher {\n        Dispatcher {\n            new_root: Cell::new(None),\n            roots: RefCell::new(HashMap::new()),\n            new_stream: Cell::new(None),\n            streams: RefCell::new(HashMap::new()),\n            new_http_stream: Cell::new(None),\n            http_streams: RefCell::new(HashMap::new()),\n            active_id: Cell::new(0),\n            callouts: RefCell::new(HashMap::new()),\n            grpc_callouts: RefCell::new(HashMap::new()),\n            grpc_streams: RefCell::new(HashMap::new()),\n        }\n    }\n\n    fn set_root_context(&self, callback: NewRootContext) {\n        self.new_root.set(Some(callback));\n    }\n\n    fn set_stream_context(&self, callback: NewStreamContext) {\n        self.new_stream.set(Some(callback));\n    }\n\n    fn set_http_context(&self, callback: NewHttpContext) {\n        self.new_http_stream.set(Some(callback));\n    }\n\n    fn register_callout(&self, token_id: u32) {\n        if self\n            .callouts\n            .borrow_mut()\n            .insert(token_id, self.active_id.get())\n            .is_some()\n        {\n            panic!(\"duplicate token_id\")\n        }\n    }\n\n    fn register_grpc_stream(&self, token_id: u32) {\n        if self\n            .grpc_streams\n            .borrow_mut()\n            .insert(token_id, self.active_id.get())\n            .is_some()\n        {\n            panic!(\"duplicate token_id\")\n        }\n    }\n\n    fn register_grpc_callout(&self, token_id: u32) {\n        if self\n            .grpc_callouts\n            .borrow_mut()\n            .insert(token_id, self.active_id.get())\n            .is_some()\n        {\n            panic!(\"duplicate token_id\")\n        }\n    }\n\n    fn create_root_context(&self, context_id: u32) {\n        let new_context = match self.new_root.get() {\n            Some(f) => f(context_id),\n            None => Box::new(NoopRoot),\n        };\n        if self\n            .roots\n            .borrow_mut()\n            .insert(context_id, new_context)\n            .is_some()\n        {\n            panic!(\"duplicate context_id\")\n        }\n    }\n\n    fn create_stream_context(&self, context_id: u32, root_context_id: u32) {\n        let new_context = match self.roots.borrow().get(&root_context_id) {\n            Some(root_context) => match self.new_stream.get() {\n                Some(f) => f(context_id, root_context_id),\n                None => match root_context.create_stream_context(context_id) {\n                    Some(stream_context) => stream_context,\n                    None => panic!(\"create_stream_context returned None\"),\n                },\n            },\n            None => panic!(\"invalid root_context_id\"),\n        };\n        if self\n            .streams\n            .borrow_mut()\n            .insert(context_id, new_context)\n            .is_some()\n        {\n            panic!(\"duplicate context_id\")\n        }\n    }\n\n    fn create_http_context(&self, context_id: u32, root_context_id: u32) {\n        let new_context = match self.roots.borrow().get(&root_context_id) {\n            Some(root_context) => match self.new_http_stream.get() {\n                Some(f) => f(context_id, root_context_id),\n                None => match root_context.create_http_context(context_id) {\n                    Some(stream_context) => stream_context,\n                    None => panic!(\"create_http_context returned None\"),\n                },\n            },\n            None => panic!(\"invalid root_context_id\"),\n        };\n        if self\n            .http_streams\n            .borrow_mut()\n            .insert(context_id, new_context)\n            .is_some()\n        {\n            panic!(\"duplicate context_id\")\n        }\n    }\n\n    fn on_create_context(&self, context_id: u32, root_context_id: u32) {\n        if root_context_id == 0 {\n            self.create_root_context(context_id);\n        } else if self.new_http_stream.get().is_some() {\n            self.create_http_context(context_id, root_context_id);\n        } else if self.new_stream.get().is_some() {\n            self.create_stream_context(context_id, root_context_id);\n        } else if let Some(root_context) = self.roots.borrow().get(&root_context_id) {\n            match root_context.get_type() {\n                Some(ContextType::HttpContext) => {\n                    self.create_http_context(context_id, root_context_id)\n                }\n                Some(ContextType::StreamContext) => {\n                    self.create_stream_context(context_id, root_context_id)\n                }\n                None => panic!(\"missing ContextType on root_context\"),\n            }\n        } else {\n            panic!(\"invalid root_context_id and missing constructors\");\n        }\n    }\n\n    fn on_done(&self, context_id: u32) -> bool {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_done()\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_done()\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_done()\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_log(&self, context_id: u32) {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_log()\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_log()\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_log()\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_delete(&self, context_id: u32) {\n        if !(self.http_streams.borrow_mut().remove(&context_id).is_some()\n            || self.streams.borrow_mut().remove(&context_id).is_some()\n            || self.roots.borrow_mut().remove(&context_id).is_some())\n        {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_vm_start(&self, context_id: u32, vm_configuration_size: usize) -> bool {\n        if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_vm_start(vm_configuration_size)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_configure(&self, context_id: u32, plugin_configuration_size: usize) -> bool {\n        if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_configure(plugin_configuration_size)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_tick(&self, context_id: u32) {\n        if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_tick()\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_queue_ready(&self, context_id: u32, queue_id: u32) {\n        if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            root.on_queue_ready(queue_id)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_new_connection(&self, context_id: u32) -> Action {\n        if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_new_connection()\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_downstream_data(&self, context_id: u32, data_size: usize, end_of_stream: bool) -> Action {\n        if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_downstream_data(data_size, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_downstream_close(&self, context_id: u32, peer_type: PeerType) {\n        if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_downstream_close(peer_type)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_upstream_data(&self, context_id: u32, data_size: usize, end_of_stream: bool) -> Action {\n        if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_upstream_data(data_size, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_upstream_close(&self, context_id: u32, peer_type: PeerType) {\n        if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            stream.on_upstream_close(peer_type)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_request_headers(\n        &self,\n        context_id: u32,\n        num_headers: usize,\n        end_of_stream: bool,\n    ) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_request_headers(num_headers, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_request_body(\n        &self,\n        context_id: u32,\n        body_size: usize,\n        end_of_stream: bool,\n    ) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_request_body(body_size, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_request_trailers(&self, context_id: u32, num_trailers: usize) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_request_trailers(num_trailers)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_response_headers(\n        &self,\n        context_id: u32,\n        num_headers: usize,\n        end_of_stream: bool,\n    ) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_response_headers(num_headers, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_response_body(\n        &self,\n        context_id: u32,\n        body_size: usize,\n        end_of_stream: bool,\n    ) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_response_body(body_size, end_of_stream)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_response_trailers(&self, context_id: u32, num_trailers: usize) -> Action {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            http_stream.on_http_response_trailers(num_trailers)\n        } else {\n            panic!(\"invalid context_id\")\n        }\n    }\n\n    fn on_http_call_response(\n        &self,\n        token_id: u32,\n        num_headers: usize,\n        body_size: usize,\n        num_trailers: usize,\n    ) {\n        let context_id = self\n            .callouts\n            .borrow_mut()\n            .remove(&token_id)\n            .expect(\"invalid token_id\");\n\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            http_stream.on_http_call_response(token_id, num_headers, body_size, num_trailers)\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            stream.on_http_call_response(token_id, num_headers, body_size, num_trailers)\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            root.on_http_call_response(token_id, num_headers, body_size, num_trailers)\n        }\n    }\n\n    fn on_grpc_receive_initial_metadata(&self, token_id: u32, headers: u32) {\n        let context_id = match self.grpc_streams.borrow_mut().get(&token_id) {\n            Some(id) => *id,\n            None => {\n                // TODO: change back to a panic once underlying issue is fixed.\n                trace!(\"on_grpc_receive_initial_metadata: invalid token_id\");\n                return;\n            }\n        };\n\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            http_stream.on_grpc_stream_initial_metadata(token_id, headers);\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            stream.on_grpc_stream_initial_metadata(token_id, headers);\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            root.on_grpc_stream_initial_metadata(token_id, headers);\n        }\n    }\n\n    fn on_grpc_receive(&self, token_id: u32, response_size: usize) {\n        let context_id = self.grpc_callouts.borrow_mut().remove(&token_id);\n        if let Some(context_id) = context_id {\n            if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                http_stream.on_grpc_call_response(token_id, 0, response_size);\n            } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                stream.on_grpc_call_response(token_id, 0, response_size);\n            } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                root.on_grpc_call_response(token_id, 0, response_size);\n            }\n        } else {\n            let context_id = self.grpc_streams.borrow().get(&token_id).cloned();\n            if let Some(context_id) = context_id {\n                if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    http_stream.on_grpc_stream_message(token_id, response_size);\n                } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    stream.on_grpc_stream_message(token_id, response_size);\n                } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    root.on_grpc_stream_message(token_id, response_size);\n                }\n            } else {\n                // TODO: change back to a panic once underlying issue is fixed.\n                trace!(\"on_grpc_receive_initial_metadata: invalid token_id\");\n            }\n        }\n    }\n\n    fn on_grpc_receive_trailing_metadata(&self, token_id: u32, trailers: u32) {\n        let context_id = match self.grpc_streams.borrow_mut().get(&token_id) {\n            Some(id) => *id,\n            None => {\n                // TODO: change back to a panic once underlying issue is fixed.\n                trace!(\"on_grpc_receive_trailing_metadata: invalid token_id\");\n                return;\n            }\n        };\n\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            http_stream.on_grpc_stream_trailing_metadata(token_id, trailers);\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            stream.on_grpc_stream_trailing_metadata(token_id, trailers);\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            root.on_grpc_stream_trailing_metadata(token_id, trailers);\n        }\n    }\n\n    fn on_grpc_close(&self, token_id: u32, status_code: u32) {\n        let context_id = self.grpc_callouts.borrow_mut().remove(&token_id);\n        if let Some(context_id) = context_id {\n            if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                http_stream.on_grpc_call_response(token_id, status_code, 0);\n            } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                stream.on_grpc_call_response(token_id, status_code, 0);\n            } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n                self.active_id.set(context_id);\n                hostcalls::set_effective_context(context_id).unwrap();\n                root.on_grpc_call_response(token_id, status_code, 0);\n            }\n        } else {\n            let context_id = self.grpc_streams.borrow_mut().remove(&token_id);\n            if let Some(context_id) = context_id {\n                if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    http_stream.on_grpc_stream_close(token_id, status_code)\n                } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    stream.on_grpc_stream_close(token_id, status_code)\n                } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n                    self.active_id.set(context_id);\n                    hostcalls::set_effective_context(context_id).unwrap();\n                    root.on_grpc_stream_close(token_id, status_code)\n                }\n            } else {\n                // TODO: change back to a panic once underlying issue is fixed.\n                trace!(\"on_grpc_close: invalid token_id, a non-connected stream has closed\");\n            }\n        }\n    }\n\n    fn on_foreign_function(&self, context_id: u32, function_id: u32, arugments_size: usize) {\n        if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            http_stream.on_foreign_function(function_id, arugments_size)\n        } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            stream.on_foreign_function(function_id, arugments_size)\n        } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) {\n            self.active_id.set(context_id);\n            hostcalls::set_effective_context(context_id).unwrap();\n            root.on_foreign_function(function_id, arugments_size)\n        }\n    }\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_context_create(context_id: u32, root_context_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_create_context(context_id, root_context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_done(context_id: u32) -> bool {\n    DISPATCHER.with(|dispatcher| dispatcher.on_done(context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_log(context_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_log(context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_delete(context_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_delete(context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_vm_start(context_id: u32, vm_configuration_size: usize) -> bool {\n    DISPATCHER.with(|dispatcher| dispatcher.on_vm_start(context_id, vm_configuration_size))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_configure(context_id: u32, plugin_configuration_size: usize) -> bool {\n    DISPATCHER.with(|dispatcher| dispatcher.on_configure(context_id, plugin_configuration_size))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_tick(context_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_tick(context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_queue_ready(context_id: u32, queue_id: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_queue_ready(context_id, queue_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_new_connection(context_id: u32) -> Action {\n    DISPATCHER.with(|dispatcher| dispatcher.on_new_connection(context_id))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_downstream_data(\n    context_id: u32,\n    data_size: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER\n        .with(|dispatcher| dispatcher.on_downstream_data(context_id, data_size, end_of_stream))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_downstream_connection_close(context_id: u32, peer_type: PeerType) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_downstream_close(context_id, peer_type))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_upstream_data(\n    context_id: u32,\n    data_size: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER.with(|dispatcher| dispatcher.on_upstream_data(context_id, data_size, end_of_stream))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_upstream_connection_close(context_id: u32, peer_type: PeerType) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_upstream_close(context_id, peer_type))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_request_headers(\n    context_id: u32,\n    num_headers: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER.with(|dispatcher| {\n        dispatcher.on_http_request_headers(context_id, num_headers, end_of_stream)\n    })\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_request_body(\n    context_id: u32,\n    body_size: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER\n        .with(|dispatcher| dispatcher.on_http_request_body(context_id, body_size, end_of_stream))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_request_trailers(context_id: u32, num_trailers: usize) -> Action {\n    DISPATCHER.with(|dispatcher| dispatcher.on_http_request_trailers(context_id, num_trailers))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_response_headers(\n    context_id: u32,\n    num_headers: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER.with(|dispatcher| {\n        dispatcher.on_http_response_headers(context_id, num_headers, end_of_stream)\n    })\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_response_body(\n    context_id: u32,\n    body_size: usize,\n    end_of_stream: bool,\n) -> Action {\n    DISPATCHER\n        .with(|dispatcher| dispatcher.on_http_response_body(context_id, body_size, end_of_stream))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_response_trailers(context_id: u32, num_trailers: usize) -> Action {\n    DISPATCHER.with(|dispatcher| dispatcher.on_http_response_trailers(context_id, num_trailers))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_http_call_response(\n    _context_id: u32,\n    token_id: u32,\n    num_headers: usize,\n    body_size: usize,\n    num_trailers: usize,\n) {\n    DISPATCHER.with(|dispatcher| {\n        dispatcher.on_http_call_response(token_id, num_headers, body_size, num_trailers)\n    })\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_grpc_receive_initial_metadata(\n    _context_id: u32,\n    token_id: u32,\n    headers: u32,\n) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_grpc_receive_initial_metadata(token_id, headers))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_grpc_receive(_context_id: u32, token_id: u32, response_size: usize) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_grpc_receive(token_id, response_size))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_grpc_receive_trailing_metadata(\n    _context_id: u32,\n    token_id: u32,\n    trailers: u32,\n) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_grpc_receive_trailing_metadata(token_id, trailers))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_grpc_close(_context_id: u32, token_id: u32, status_code: u32) {\n    DISPATCHER.with(|dispatcher| dispatcher.on_grpc_close(token_id, status_code))\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_on_foreign_function(\n    context_id: u32,\n    function_id: u32,\n    arguments_size: usize,\n) {\n    DISPATCHER\n        .with(|dispatcher| dispatcher.on_foreign_function(context_id, function_id, arguments_size))\n}\n"
  },
  {
    "path": "src/hostcalls.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse crate::dispatcher;\nuse crate::types::*;\nuse std::ptr::{null, null_mut};\nuse std::time::{Duration, SystemTime, UNIX_EPOCH};\n\nextern \"C\" {\n    fn proxy_log(level: LogLevel, message_data: *const u8, message_size: usize) -> Status;\n}\n\npub fn log(level: LogLevel, message: &str) -> Result<(), Status> {\n    unsafe {\n        match proxy_log(level, message.as_ptr(), message.len()) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_log_level(return_level: *mut LogLevel) -> Status;\n}\n\npub fn get_log_level() -> Result<LogLevel, Status> {\n    let mut return_level: LogLevel = LogLevel::Trace;\n    unsafe {\n        match proxy_get_log_level(&mut return_level) {\n            Status::Ok => Ok(return_level),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_current_time_nanoseconds(return_time: *mut u64) -> Status;\n}\n\npub fn get_current_time() -> Result<SystemTime, Status> {\n    let mut return_time: u64 = 0;\n    unsafe {\n        match proxy_get_current_time_nanoseconds(&mut return_time) {\n            Status::Ok => Ok(UNIX_EPOCH + Duration::from_nanos(return_time)),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_tick_period_milliseconds(period: u32) -> Status;\n}\n\npub fn set_tick_period(period: Duration) -> Result<(), Status> {\n    unsafe {\n        match proxy_set_tick_period_milliseconds(period.as_millis() as u32) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_buffer_bytes(\n        buffer_type: BufferType,\n        start: usize,\n        max_size: usize,\n        return_buffer_data: *mut *mut u8,\n        return_buffer_size: *mut usize,\n    ) -> Status;\n}\n\npub fn get_buffer(\n    buffer_type: BufferType,\n    start: usize,\n    max_size: usize,\n) -> Result<Option<Bytes>, Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_get_buffer_bytes(\n            buffer_type,\n            start,\n            max_size,\n            &mut return_data,\n            &mut return_size,\n        ) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(Vec::from_raw_parts(\n                        return_data,\n                        return_size,\n                        return_size,\n                    )))\n                } else {\n                    Ok(None)\n                }\n            }\n            Status::NotFound => Ok(None),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_buffer_bytes(\n        buffer_type: BufferType,\n        start: usize,\n        size: usize,\n        buffer_data: *const u8,\n        buffer_size: usize,\n    ) -> Status;\n}\n\npub fn set_buffer(\n    buffer_type: BufferType,\n    start: usize,\n    size: usize,\n    value: &[u8],\n) -> Result<(), Status> {\n    unsafe {\n        match proxy_set_buffer_bytes(buffer_type, start, size, value.as_ptr(), value.len()) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\n#[cfg(not(all(test, feature = \"mockalloc\")))]\nextern \"C\" {\n    fn proxy_get_header_map_pairs(\n        map_type: MapType,\n        return_map_data: *mut *mut u8,\n        return_map_size: *mut usize,\n    ) -> Status;\n}\n\n#[cfg(all(test, feature = \"mockalloc\"))]\nfn proxy_get_header_map_pairs(\n    map_type: MapType,\n    return_map_data: *mut *mut u8,\n    return_map_size: *mut usize,\n) -> Status {\n    mocks::proxy_get_header_map_pairs(map_type, return_map_data, return_map_size)\n}\n\npub fn get_map(map_type: MapType) -> Result<Vec<(String, String)>, Status> {\n    unsafe {\n        let mut return_data: *mut u8 = null_mut();\n        let mut return_size: usize = 0;\n        match proxy_get_header_map_pairs(map_type, &mut return_data, &mut return_size) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    let serialized_map = Vec::from_raw_parts(return_data, return_size, return_size);\n                    Ok(utils::deserialize_map(&serialized_map))\n                } else {\n                    Ok(Vec::new())\n                }\n            }\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn get_map_bytes(map_type: MapType) -> Result<Vec<(String, Bytes)>, Status> {\n    unsafe {\n        let mut return_data: *mut u8 = null_mut();\n        let mut return_size: usize = 0;\n        match proxy_get_header_map_pairs(map_type, &mut return_data, &mut return_size) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    let serialized_map = Vec::from_raw_parts(return_data, return_size, return_size);\n                    Ok(utils::deserialize_map_bytes(&serialized_map))\n                } else {\n                    Ok(Vec::new())\n                }\n            }\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_header_map_pairs(\n        map_type: MapType,\n        map_data: *const u8,\n        map_size: usize,\n    ) -> Status;\n}\n\npub fn set_map(map_type: MapType, map: Vec<(&str, &str)>) -> Result<(), Status> {\n    let serialized_map = utils::serialize_map(&map);\n    unsafe {\n        match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn set_map_bytes(map_type: MapType, map: Vec<(&str, &[u8])>) -> Result<(), Status> {\n    let serialized_map = utils::serialize_map_bytes(&map);\n    unsafe {\n        match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_header_map_value(\n        map_type: MapType,\n        key_data: *const u8,\n        key_size: usize,\n        return_value_data: *mut *mut u8,\n        return_value_size: *mut usize,\n    ) -> Status;\n}\n\npub fn get_map_value(map_type: MapType, key: &str) -> Result<Option<String>, Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_get_header_map_value(\n            map_type,\n            key.as_ptr(),\n            key.len(),\n            &mut return_data,\n            &mut return_size,\n        ) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(\n                        String::from_utf8(Vec::from_raw_parts(\n                            return_data,\n                            return_size,\n                            return_size,\n                        ))\n                        .unwrap(),\n                    ))\n                } else {\n                    Ok(Some(String::new()))\n                }\n            }\n            Status::NotFound => Ok(None),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn get_map_value_bytes(map_type: MapType, key: &str) -> Result<Option<Bytes>, Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_get_header_map_value(\n            map_type,\n            key.as_ptr(),\n            key.len(),\n            &mut return_data,\n            &mut return_size,\n        ) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(Vec::from_raw_parts(\n                        return_data,\n                        return_size,\n                        return_size,\n                    )))\n                } else {\n                    Ok(Some(Vec::new()))\n                }\n            }\n            Status::NotFound => Ok(None),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_remove_header_map_value(\n        map_type: MapType,\n        key_data: *const u8,\n        key_size: usize,\n    ) -> Status;\n}\n\npub fn remove_map_value(map_type: MapType, key: &str) -> Result<(), Status> {\n    unsafe {\n        match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_replace_header_map_value(\n        map_type: MapType,\n        key_data: *const u8,\n        key_size: usize,\n        value_data: *const u8,\n        value_size: usize,\n    ) -> Status;\n}\n\npub fn set_map_value(map_type: MapType, key: &str, value: Option<&str>) -> Result<(), Status> {\n    unsafe {\n        if let Some(value) = value {\n            match proxy_replace_header_map_value(\n                map_type,\n                key.as_ptr(),\n                key.len(),\n                value.as_ptr(),\n                value.len(),\n            ) {\n                Status::Ok => Ok(()),\n                status => panic!(\"unexpected status: {}\", status as u32),\n            }\n        } else {\n            match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {\n                Status::Ok => Ok(()),\n                status => panic!(\"unexpected status: {}\", status as u32),\n            }\n        }\n    }\n}\n\npub fn set_map_value_bytes(\n    map_type: MapType,\n    key: &str,\n    value: Option<&[u8]>,\n) -> Result<(), Status> {\n    unsafe {\n        if let Some(value) = value {\n            match proxy_replace_header_map_value(\n                map_type,\n                key.as_ptr(),\n                key.len(),\n                value.as_ptr(),\n                value.len(),\n            ) {\n                Status::Ok => Ok(()),\n                status => panic!(\"unexpected status: {}\", status as u32),\n            }\n        } else {\n            match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) {\n                Status::Ok => Ok(()),\n                status => panic!(\"unexpected status: {}\", status as u32),\n            }\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_add_header_map_value(\n        map_type: MapType,\n        key_data: *const u8,\n        key_size: usize,\n        value_data: *const u8,\n        value_size: usize,\n    ) -> Status;\n}\n\npub fn add_map_value(map_type: MapType, key: &str, value: &str) -> Result<(), Status> {\n    unsafe {\n        match proxy_add_header_map_value(\n            map_type,\n            key.as_ptr(),\n            key.len(),\n            value.as_ptr(),\n            value.len(),\n        ) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn add_map_value_bytes(map_type: MapType, key: &str, value: &[u8]) -> Result<(), Status> {\n    unsafe {\n        match proxy_add_header_map_value(\n            map_type,\n            key.as_ptr(),\n            key.len(),\n            value.as_ptr(),\n            value.len(),\n        ) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_property(\n        path_data: *const u8,\n        path_size: usize,\n        return_value_data: *mut *mut u8,\n        return_value_size: *mut usize,\n    ) -> Status;\n}\n\npub fn get_property(path: Vec<&str>) -> Result<Option<Bytes>, Status> {\n    let serialized_path = utils::serialize_property_path(path);\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_get_property(\n            serialized_path.as_ptr(),\n            serialized_path.len(),\n            &mut return_data,\n            &mut return_size,\n        ) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(Vec::from_raw_parts(\n                        return_data,\n                        return_size,\n                        return_size,\n                    )))\n                } else {\n                    Ok(None)\n                }\n            }\n            Status::NotFound => Ok(None),\n            Status::SerializationFailure => Err(Status::SerializationFailure),\n            Status::InternalFailure => Err(Status::InternalFailure),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_property(\n        path_data: *const u8,\n        path_size: usize,\n        value_data: *const u8,\n        value_size: usize,\n    ) -> Status;\n}\n\npub fn set_property(path: Vec<&str>, value: Option<&[u8]>) -> Result<(), Status> {\n    let serialized_path = utils::serialize_property_path(path);\n    unsafe {\n        match proxy_set_property(\n            serialized_path.as_ptr(),\n            serialized_path.len(),\n            value.map_or(null(), |value| value.as_ptr()),\n            value.map_or(0, |value| value.len()),\n        ) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_shared_data(\n        key_data: *const u8,\n        key_size: usize,\n        return_value_data: *mut *mut u8,\n        return_value_size: *mut usize,\n        return_cas: *mut u32,\n    ) -> Status;\n}\n\npub fn get_shared_data(key: &str) -> Result<(Option<Bytes>, Option<u32>), Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    let mut return_cas: u32 = 0;\n    unsafe {\n        match proxy_get_shared_data(\n            key.as_ptr(),\n            key.len(),\n            &mut return_data,\n            &mut return_size,\n            &mut return_cas,\n        ) {\n            Status::Ok => {\n                let cas = match return_cas {\n                    0 => None,\n                    cas => Some(cas),\n                };\n                if !return_data.is_null() {\n                    Ok((\n                        Some(Vec::from_raw_parts(return_data, return_size, return_size)),\n                        cas,\n                    ))\n                } else {\n                    Ok((None, cas))\n                }\n            }\n            Status::NotFound => Ok((None, None)),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_shared_data(\n        key_data: *const u8,\n        key_size: usize,\n        value_data: *const u8,\n        value_size: usize,\n        cas: u32,\n    ) -> Status;\n}\n\npub fn set_shared_data(key: &str, value: Option<&[u8]>, cas: Option<u32>) -> Result<(), Status> {\n    unsafe {\n        match proxy_set_shared_data(\n            key.as_ptr(),\n            key.len(),\n            value.map_or(null(), |value| value.as_ptr()),\n            value.map_or(0, |value| value.len()),\n            cas.unwrap_or(0),\n        ) {\n            Status::Ok => Ok(()),\n            Status::CasMismatch => Err(Status::CasMismatch),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_register_shared_queue(\n        name_data: *const u8,\n        name_size: usize,\n        return_id: *mut u32,\n    ) -> Status;\n}\n\npub fn register_shared_queue(name: &str) -> Result<u32, Status> {\n    unsafe {\n        let mut return_id: u32 = 0;\n        match proxy_register_shared_queue(name.as_ptr(), name.len(), &mut return_id) {\n            Status::Ok => Ok(return_id),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_resolve_shared_queue(\n        vm_id_data: *const u8,\n        vm_id_size: usize,\n        name_data: *const u8,\n        name_size: usize,\n        return_id: *mut u32,\n    ) -> Status;\n}\n\npub fn resolve_shared_queue(vm_id: &str, name: &str) -> Result<Option<u32>, Status> {\n    let mut return_id: u32 = 0;\n    unsafe {\n        match proxy_resolve_shared_queue(\n            vm_id.as_ptr(),\n            vm_id.len(),\n            name.as_ptr(),\n            name.len(),\n            &mut return_id,\n        ) {\n            Status::Ok => Ok(Some(return_id)),\n            Status::NotFound => Ok(None),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_dequeue_shared_queue(\n        queue_id: u32,\n        return_value_data: *mut *mut u8,\n        return_value_size: *mut usize,\n    ) -> Status;\n}\n\npub fn dequeue_shared_queue(queue_id: u32) -> Result<Option<Bytes>, Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_dequeue_shared_queue(queue_id, &mut return_data, &mut return_size) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(Vec::from_raw_parts(\n                        return_data,\n                        return_size,\n                        return_size,\n                    )))\n                } else {\n                    Ok(None)\n                }\n            }\n            Status::Empty => Ok(None),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_enqueue_shared_queue(\n        queue_id: u32,\n        value_data: *const u8,\n        value_size: usize,\n    ) -> Status;\n}\n\npub fn enqueue_shared_queue(queue_id: u32, value: Option<&[u8]>) -> Result<(), Status> {\n    unsafe {\n        match proxy_enqueue_shared_queue(\n            queue_id,\n            value.map_or(null(), |value| value.as_ptr()),\n            value.map_or(0, |value| value.len()),\n        ) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_continue_stream(stream_type: StreamType) -> Status;\n}\n\npub fn resume_downstream() -> Result<(), Status> {\n    unsafe {\n        match proxy_continue_stream(StreamType::Downstream) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn resume_upstream() -> Result<(), Status> {\n    unsafe {\n        match proxy_continue_stream(StreamType::Upstream) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn resume_http_request() -> Result<(), Status> {\n    unsafe {\n        match proxy_continue_stream(StreamType::HttpRequest) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn resume_http_response() -> Result<(), Status> {\n    unsafe {\n        match proxy_continue_stream(StreamType::HttpResponse) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_close_stream(stream_type: StreamType) -> Status;\n}\n\npub fn close_downstream() -> Result<(), Status> {\n    unsafe {\n        match proxy_close_stream(StreamType::Downstream) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\npub fn close_upstream() -> Result<(), Status> {\n    unsafe {\n        match proxy_close_stream(StreamType::Upstream) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn reset_http_request() -> Result<(), Status> {\n    unsafe {\n        match proxy_close_stream(StreamType::HttpRequest) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn reset_http_response() -> Result<(), Status> {\n    unsafe {\n        match proxy_close_stream(StreamType::HttpResponse) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_send_local_response(\n        status_code: u32,\n        status_code_details_data: *const u8,\n        status_code_details_size: usize,\n        body_data: *const u8,\n        body_size: usize,\n        headers_data: *const u8,\n        headers_size: usize,\n        grpc_status: i32,\n    ) -> Status;\n}\n\npub fn send_http_response(\n    status_code: u32,\n    headers: Vec<(&str, &str)>,\n    body: Option<&[u8]>,\n) -> Result<(), Status> {\n    let serialized_headers = utils::serialize_map(&headers);\n    unsafe {\n        match proxy_send_local_response(\n            status_code,\n            null(),\n            0,\n            body.map_or(null(), |body| body.as_ptr()),\n            body.map_or(0, |body| body.len()),\n            serialized_headers.as_ptr(),\n            serialized_headers.len(),\n            -1,\n        ) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn send_grpc_response(\n    grpc_status: GrpcStatusCode,\n    grpc_status_message: Option<&str>,\n    custom_metadata: Vec<(&str, &[u8])>,\n) -> Result<(), Status> {\n    let serialized_custom_metadata = utils::serialize_map_bytes(&custom_metadata);\n    unsafe {\n        match proxy_send_local_response(\n            200,\n            null(),\n            0,\n            grpc_status_message.map_or(null(), |grpc_status_message| grpc_status_message.as_ptr()),\n            grpc_status_message.map_or(0, |grpc_status_message| grpc_status_message.len()),\n            serialized_custom_metadata.as_ptr(),\n            serialized_custom_metadata.len(),\n            grpc_status as i32,\n        ) {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_http_call(\n        upstream_data: *const u8,\n        upstream_size: usize,\n        headers_data: *const u8,\n        headers_size: usize,\n        body_data: *const u8,\n        body_size: usize,\n        trailers_data: *const u8,\n        trailers_size: usize,\n        timeout: u32,\n        return_token: *mut u32,\n    ) -> Status;\n}\n\npub fn dispatch_http_call(\n    upstream: &str,\n    headers: Vec<(&str, &str)>,\n    body: Option<&[u8]>,\n    trailers: Vec<(&str, &str)>,\n    timeout: Duration,\n) -> Result<u32, Status> {\n    let serialized_headers = utils::serialize_map(&headers);\n    let serialized_trailers = utils::serialize_map(&trailers);\n    let mut return_token: u32 = 0;\n    unsafe {\n        match proxy_http_call(\n            upstream.as_ptr(),\n            upstream.len(),\n            serialized_headers.as_ptr(),\n            serialized_headers.len(),\n            body.map_or(null(), |body| body.as_ptr()),\n            body.map_or(0, |body| body.len()),\n            serialized_trailers.as_ptr(),\n            serialized_trailers.len(),\n            timeout.as_millis() as u32,\n            &mut return_token,\n        ) {\n            Status::Ok => {\n                dispatcher::register_callout(return_token);\n                Ok(return_token)\n            }\n            Status::BadArgument => Err(Status::BadArgument),\n            Status::InternalFailure => Err(Status::InternalFailure),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_grpc_call(\n        upstream_data: *const u8,\n        upstream_size: usize,\n        service_name_data: *const u8,\n        service_name_size: usize,\n        method_name_data: *const u8,\n        method_name_size: usize,\n        initial_metadata_data: *const u8,\n        initial_metadata_size: usize,\n        message_data_data: *const u8,\n        message_data_size: usize,\n        timeout: u32,\n        return_callout_id: *mut u32,\n    ) -> Status;\n}\n\npub fn dispatch_grpc_call(\n    upstream_name: &str,\n    service_name: &str,\n    method_name: &str,\n    initial_metadata: Vec<(&str, &[u8])>,\n    message: Option<&[u8]>,\n    timeout: Duration,\n) -> Result<u32, Status> {\n    let mut return_callout_id = 0;\n    let serialized_initial_metadata = utils::serialize_map_bytes(&initial_metadata);\n    unsafe {\n        match proxy_grpc_call(\n            upstream_name.as_ptr(),\n            upstream_name.len(),\n            service_name.as_ptr(),\n            service_name.len(),\n            method_name.as_ptr(),\n            method_name.len(),\n            serialized_initial_metadata.as_ptr(),\n            serialized_initial_metadata.len(),\n            message.map_or(null(), |message| message.as_ptr()),\n            message.map_or(0, |message| message.len()),\n            timeout.as_millis() as u32,\n            &mut return_callout_id,\n        ) {\n            Status::Ok => {\n                dispatcher::register_grpc_callout(return_callout_id);\n                Ok(return_callout_id)\n            }\n            Status::ParseFailure => Err(Status::ParseFailure),\n            Status::InternalFailure => Err(Status::InternalFailure),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_grpc_stream(\n        upstream_data: *const u8,\n        upstream_size: usize,\n        service_name_data: *const u8,\n        service_name_size: usize,\n        method_name_data: *const u8,\n        method_name_size: usize,\n        initial_metadata_data: *const u8,\n        initial_metadata_size: usize,\n        return_stream_id: *mut u32,\n    ) -> Status;\n}\n\npub fn open_grpc_stream(\n    upstream_name: &str,\n    service_name: &str,\n    method_name: &str,\n    initial_metadata: Vec<(&str, &[u8])>,\n) -> Result<u32, Status> {\n    let mut return_stream_id = 0;\n    let serialized_initial_metadata = utils::serialize_map_bytes(&initial_metadata);\n    unsafe {\n        match proxy_grpc_stream(\n            upstream_name.as_ptr(),\n            upstream_name.len(),\n            service_name.as_ptr(),\n            service_name.len(),\n            method_name.as_ptr(),\n            method_name.len(),\n            serialized_initial_metadata.as_ptr(),\n            serialized_initial_metadata.len(),\n            &mut return_stream_id,\n        ) {\n            Status::Ok => {\n                dispatcher::register_grpc_stream(return_stream_id);\n                Ok(return_stream_id)\n            }\n            Status::ParseFailure => Err(Status::ParseFailure),\n            Status::InternalFailure => Err(Status::InternalFailure),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_grpc_send(\n        token: u32,\n        message_ptr: *const u8,\n        message_len: usize,\n        end_stream: bool,\n    ) -> Status;\n}\n\npub fn send_grpc_stream_message(\n    token: u32,\n    message: Option<&[u8]>,\n    end_stream: bool,\n) -> Result<(), Status> {\n    unsafe {\n        match proxy_grpc_send(\n            token,\n            message.map_or(null(), |message| message.as_ptr()),\n            message.map_or(0, |message| message.len()),\n            end_stream,\n        ) {\n            Status::Ok => Ok(()),\n            Status::BadArgument => Err(Status::BadArgument),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_grpc_cancel(token_id: u32) -> Status;\n}\n\npub fn cancel_grpc_call(token_id: u32) -> Result<(), Status> {\n    unsafe {\n        match proxy_grpc_cancel(token_id) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\npub fn cancel_grpc_stream(token_id: u32) -> Result<(), Status> {\n    unsafe {\n        match proxy_grpc_cancel(token_id) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_grpc_close(token_id: u32) -> Status;\n}\n\npub fn close_grpc_stream(token_id: u32) -> Result<(), Status> {\n    unsafe {\n        match proxy_grpc_close(token_id) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_status(\n        return_code: *mut u32,\n        return_message_data: *mut *mut u8,\n        return_message_size: *mut usize,\n    ) -> Status;\n}\n\npub fn get_grpc_status() -> Result<(u32, Option<String>), Status> {\n    let mut return_code: u32 = 0;\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_get_status(&mut return_code, &mut return_data, &mut return_size) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok((\n                        return_code,\n                        Some(\n                            String::from_utf8(Vec::from_raw_parts(\n                                return_data,\n                                return_size,\n                                return_size,\n                            ))\n                            .unwrap(),\n                        ),\n                    ))\n                } else {\n                    Ok((return_code, None))\n                }\n            }\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_set_effective_context(context_id: u32) -> Status;\n}\n\npub fn set_effective_context(context_id: u32) -> Result<(), Status> {\n    unsafe {\n        match proxy_set_effective_context(context_id) {\n            Status::Ok => Ok(()),\n            Status::BadArgument => Err(Status::BadArgument),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_call_foreign_function(\n        function_name_data: *const u8,\n        function_name_size: usize,\n        arguments_data: *const u8,\n        arguments_size: usize,\n        results_data: *mut *mut u8,\n        results_size: *mut usize,\n    ) -> Status;\n}\n\npub fn call_foreign_function(\n    function_name: &str,\n    arguments: Option<&[u8]>,\n) -> Result<Option<Bytes>, Status> {\n    let mut return_data: *mut u8 = null_mut();\n    let mut return_size: usize = 0;\n    unsafe {\n        match proxy_call_foreign_function(\n            function_name.as_ptr(),\n            function_name.len(),\n            arguments.map_or(null(), |arguments| arguments.as_ptr()),\n            arguments.map_or(0, |arguments| arguments.len()),\n            &mut return_data,\n            &mut return_size,\n        ) {\n            Status::Ok => {\n                if !return_data.is_null() {\n                    Ok(Some(Vec::from_raw_parts(\n                        return_data,\n                        return_size,\n                        return_size,\n                    )))\n                } else {\n                    Ok(None)\n                }\n            }\n            Status::NotFound => Err(Status::NotFound),\n            Status::BadArgument => Err(Status::BadArgument),\n            Status::SerializationFailure => Err(Status::SerializationFailure),\n            Status::InternalFailure => Err(Status::InternalFailure),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_done() -> Status;\n}\n\npub fn done() -> Result<(), Status> {\n    unsafe {\n        match proxy_done() {\n            Status::Ok => Ok(()),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_define_metric(\n        metric_type: MetricType,\n        name_data: *const u8,\n        name_size: usize,\n        return_id: *mut u32,\n    ) -> Status;\n}\n\npub fn define_metric(metric_type: MetricType, name: &str) -> Result<u32, Status> {\n    let mut return_id: u32 = 0;\n    unsafe {\n        match proxy_define_metric(metric_type, name.as_ptr(), name.len(), &mut return_id) {\n            Status::Ok => Ok(return_id),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_get_metric(metric_id: u32, return_value: *mut u64) -> Status;\n}\n\npub fn get_metric(metric_id: u32) -> Result<u64, Status> {\n    let mut return_value: u64 = 0;\n    unsafe {\n        match proxy_get_metric(metric_id, &mut return_value) {\n            Status::Ok => Ok(return_value),\n            Status::NotFound => Err(Status::NotFound),\n            Status::BadArgument => Err(Status::BadArgument),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_record_metric(metric_id: u32, value: u64) -> Status;\n}\n\npub fn record_metric(metric_id: u32, value: u64) -> Result<(), Status> {\n    unsafe {\n        match proxy_record_metric(metric_id, value) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\nextern \"C\" {\n    fn proxy_increment_metric(metric_id: u32, offset: i64) -> Status;\n}\n\npub fn increment_metric(metric_id: u32, offset: i64) -> Result<(), Status> {\n    unsafe {\n        match proxy_increment_metric(metric_id, offset) {\n            Status::Ok => Ok(()),\n            Status::NotFound => Err(Status::NotFound),\n            Status::BadArgument => Err(Status::BadArgument),\n            status => panic!(\"unexpected status: {}\", status as u32),\n        }\n    }\n}\n\n#[cfg(all(test, feature = \"mockalloc\"))]\nmod mocks {\n    use crate::hostcalls::utils::tests::SERIALIZED_MAP;\n    use crate::types::*;\n    use std::alloc::{alloc, Layout};\n\n    pub fn proxy_get_header_map_pairs(\n        _map_type: MapType,\n        return_map_data: *mut *mut u8,\n        return_map_size: *mut usize,\n    ) -> Status {\n        let layout = Layout::array::<u8>(SERIALIZED_MAP.len()).unwrap();\n        unsafe {\n            *return_map_data = alloc(layout);\n            *return_map_size = SERIALIZED_MAP.len();\n            std::ptr::copy(\n                SERIALIZED_MAP.as_ptr(),\n                *return_map_data,\n                SERIALIZED_MAP.len(),\n            );\n        }\n        Status::Ok\n    }\n}\n\n#[cfg(all(test, feature = \"mockalloc\"))]\nmod tests {\n    use crate::types::*;\n    use mockalloc::Mockalloc;\n    use std::alloc::System;\n\n    #[global_allocator]\n    static ALLOCATOR: Mockalloc<System> = Mockalloc(System);\n\n    #[mockalloc::test]\n    fn test_get_map_no_leaks() {\n        let result = super::get_map(MapType::HttpRequestHeaders);\n        assert!(result.is_ok());\n    }\n\n    #[mockalloc::test]\n    fn test_get_map_bytes_no_leaks() {\n        let result = super::get_map_bytes(MapType::HttpRequestHeaders);\n        assert!(result.is_ok());\n    }\n}\n\nmod utils {\n    use crate::types::Bytes;\n    use std::convert::TryFrom;\n\n    pub(super) fn serialize_property_path(path: Vec<&str>) -> Bytes {\n        if path.is_empty() {\n            return Vec::new();\n        }\n        let mut size: usize = 0;\n        for part in &path {\n            size += part.len() + 1;\n        }\n        let mut bytes: Bytes = Vec::with_capacity(size);\n        for part in &path {\n            bytes.extend_from_slice(part.as_bytes());\n            bytes.push(0);\n        }\n        bytes.pop();\n        bytes\n    }\n\n    pub(super) fn serialize_map(map: &[(&str, &str)]) -> Bytes {\n        let mut size: usize = 4;\n        for (name, value) in map {\n            size += name.len() + value.len() + 10;\n        }\n        let mut bytes: Bytes = Vec::with_capacity(size);\n        bytes.extend_from_slice(&(map.len() as u32).to_le_bytes());\n        for (name, value) in map {\n            bytes.extend_from_slice(&(name.len() as u32).to_le_bytes());\n            bytes.extend_from_slice(&(value.len() as u32).to_le_bytes());\n        }\n        for (name, value) in map {\n            bytes.extend_from_slice(name.as_bytes());\n            bytes.push(0);\n            bytes.extend_from_slice(value.as_bytes());\n            bytes.push(0);\n        }\n        bytes\n    }\n\n    pub(super) fn serialize_map_bytes(map: &[(&str, &[u8])]) -> Bytes {\n        let mut size: usize = 4;\n        for (name, value) in map {\n            size += name.len() + value.len() + 10;\n        }\n        let mut bytes: Bytes = Vec::with_capacity(size);\n        bytes.extend_from_slice(&(map.len() as u32).to_le_bytes());\n        for (name, value) in map {\n            bytes.extend_from_slice(&(name.len() as u32).to_le_bytes());\n            bytes.extend_from_slice(&(value.len() as u32).to_le_bytes());\n        }\n        for (name, value) in map {\n            bytes.extend_from_slice(name.as_bytes());\n            bytes.push(0);\n            bytes.extend_from_slice(value);\n            bytes.push(0);\n        }\n        bytes\n    }\n\n    pub(super) fn deserialize_map(bytes: &[u8]) -> Vec<(String, String)> {\n        if bytes.is_empty() {\n            return Vec::new();\n        }\n        let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[0..4]).unwrap()) as usize;\n        let mut map = Vec::with_capacity(size);\n        let mut p = 4 + size * 8;\n        for n in 0..size {\n            let s = 4 + n * 8;\n            let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s..s + 4]).unwrap()) as usize;\n            let key = bytes[p..p + size].to_vec();\n            p += size + 1;\n            let size =\n                u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s + 4..s + 8]).unwrap()) as usize;\n            let value = bytes[p..p + size].to_vec();\n            p += size + 1;\n            map.push((\n                String::from_utf8(key).unwrap(),\n                String::from_utf8(value).unwrap(),\n            ));\n        }\n        map\n    }\n\n    pub(super) fn deserialize_map_bytes(bytes: &[u8]) -> Vec<(String, Bytes)> {\n        if bytes.is_empty() {\n            return Vec::new();\n        }\n        let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[0..4]).unwrap()) as usize;\n        let mut map = Vec::with_capacity(size);\n        let mut p = 4 + size * 8;\n        for n in 0..size {\n            let s = 4 + n * 8;\n            let size = u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s..s + 4]).unwrap()) as usize;\n            let key = bytes[p..p + size].to_vec();\n            p += size + 1;\n            let size =\n                u32::from_le_bytes(<[u8; 4]>::try_from(&bytes[s + 4..s + 8]).unwrap()) as usize;\n            let value = bytes[p..p + size].to_vec();\n            p += size + 1;\n            map.push((String::from_utf8(key).unwrap(), value));\n        }\n        map\n    }\n\n    #[cfg(test)]\n    pub(super) mod tests {\n        use super::*;\n\n        #[cfg(nightly)]\n        use test::Bencher;\n\n        static MAP: &[(&str, &str)] = &[\n            (\":method\", \"GET\"),\n            (\":path\", \"/bytes/1\"),\n            (\":authority\", \"httpbin.org\"),\n            (\"Powered-By\", \"proxy-wasm\"),\n        ];\n\n        #[rustfmt::skip]\n        pub(in crate::hostcalls) static SERIALIZED_MAP: &[u8] = &[\n            // num entries\n            4, 0, 0, 0,\n            // len (\":method\", \"GET\")\n            7, 0, 0, 0, 3, 0, 0, 0,\n            // len (\":path\", \"/bytes/1\")\n            5, 0, 0, 0, 8, 0, 0, 0,\n            // len (\":authority\", \"httpbin.org\")\n            10, 0, 0, 0, 11, 0, 0, 0,\n            // len (\"Powered-By\", \"proxy-wasm\")\n            10, 0, 0, 0, 10, 0, 0, 0,\n            // \":method\"\n            58, 109, 101, 116, 104, 111, 100, 0,\n            // \"GET\"\n            71, 69, 84, 0,\n            // \":path\"\n            58, 112, 97, 116, 104, 0,\n            // \"/bytes/1\"\n            47, 98, 121, 116, 101, 115, 47, 49, 0,\n            // \":authority\"\n            58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 0,\n            // \"httpbin.org\"\n            104, 116, 116, 112, 98, 105, 110, 46, 111, 114, 103, 0,\n            // \"Powered-By\"\n            80, 111, 119, 101, 114, 101, 100, 45, 66, 121, 0,\n            // \"proxy-wasm\"\n            112, 114, 111, 120, 121, 45, 119, 97, 115, 109, 0,\n        ];\n\n        #[test]\n        fn test_serialize_map_empty() {\n            let serialized_map = serialize_map(&[]);\n            assert_eq!(serialized_map, [0, 0, 0, 0]);\n        }\n\n        #[test]\n        fn test_serialize_map_empty_bytes() {\n            let serialized_map = serialize_map_bytes(&[]);\n            assert_eq!(serialized_map, [0, 0, 0, 0]);\n        }\n\n        #[test]\n        fn test_deserialize_map_empty() {\n            let map = deserialize_map(&[]);\n            assert_eq!(map, []);\n            let map = deserialize_map(&[0, 0, 0, 0]);\n            assert_eq!(map, []);\n        }\n\n        #[test]\n        fn test_deserialize_map_empty_bytes() {\n            let map = deserialize_map_bytes(&[]);\n            assert_eq!(map, []);\n            let map = deserialize_map_bytes(&[0, 0, 0, 0]);\n            assert_eq!(map, []);\n        }\n\n        #[test]\n        fn test_serialize_map() {\n            let serialized_map = serialize_map(MAP);\n            assert_eq!(serialized_map, SERIALIZED_MAP);\n        }\n\n        #[test]\n        fn test_serialize_map_bytes() {\n            let map: Vec<(&str, &[u8])> = MAP.iter().map(|x| (x.0, x.1.as_bytes())).collect();\n            let serialized_map = serialize_map_bytes(&map);\n            assert_eq!(serialized_map, SERIALIZED_MAP);\n        }\n\n        #[test]\n        fn test_deserialize_map() {\n            let map = deserialize_map(SERIALIZED_MAP);\n            assert_eq!(map.len(), MAP.len());\n            for (got, expected) in map.into_iter().zip(MAP) {\n                assert_eq!(got.0, expected.0);\n                assert_eq!(got.1, expected.1);\n            }\n        }\n\n        #[test]\n        fn test_deserialize_map_bytes() {\n            let map = deserialize_map_bytes(SERIALIZED_MAP);\n            assert_eq!(map.len(), MAP.len());\n            for (got, expected) in map.into_iter().zip(MAP) {\n                assert_eq!(got.0, expected.0);\n                assert_eq!(got.1, expected.1.as_bytes());\n            }\n        }\n\n        #[test]\n        fn test_deserialize_map_roundtrip() {\n            let map = deserialize_map(SERIALIZED_MAP);\n            // TODO(v0.3): fix arguments, so that maps can be reused without conversion.\n            let map_refs: Vec<(&str, &str)> =\n                map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();\n            let serialized_map = serialize_map(&map_refs);\n            assert_eq!(serialized_map, SERIALIZED_MAP);\n        }\n\n        #[test]\n        fn test_deserialize_map_roundtrip_bytes() {\n            let map = deserialize_map_bytes(SERIALIZED_MAP);\n            // TODO(v0.3): fix arguments, so that maps can be reused without conversion.\n            let map_refs: Vec<(&str, &[u8])> =\n                map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();\n            let serialized_map = serialize_map_bytes(&map_refs);\n            assert_eq!(serialized_map, SERIALIZED_MAP);\n        }\n\n        #[test]\n        fn test_deserialize_map_all_chars() {\n            // 0x00-0x7f are valid single-byte UTF-8 characters.\n            for i in 0..0x7f {\n                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];\n                let map = deserialize_map(&serialized_src);\n                // TODO(v0.3): fix arguments, so that maps can be reused without conversion.\n                let map_refs: Vec<(&str, &str)> =\n                    map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();\n                let serialized_map = serialize_map(&map_refs);\n                assert_eq!(serialized_map, serialized_src);\n            }\n            // 0x80-0xff are invalid single-byte UTF-8 characters.\n            for i in 0x80..0xff {\n                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];\n                std::panic::set_hook(Box::new(|_| {}));\n                let result = std::panic::catch_unwind(|| {\n                    deserialize_map(&serialized_src);\n                });\n                assert!(result.is_err());\n            }\n        }\n\n        #[test]\n        fn test_deserialize_map_all_chars_bytes() {\n            // All 256 single-byte characters are allowed when emitting bytes.\n            for i in 0..0xff {\n                let serialized_src = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 99, 0, i, 0];\n                let map = deserialize_map_bytes(&serialized_src);\n                // TODO(v0.3): fix arguments, so that maps can be reused without conversion.\n                let map_refs: Vec<(&str, &[u8])> =\n                    map.iter().map(|x| (x.0.as_ref(), x.1.as_ref())).collect();\n                let serialized_map = serialize_map_bytes(&map_refs);\n                assert_eq!(serialized_map, serialized_src);\n            }\n        }\n\n        #[cfg(nightly)]\n        #[bench]\n        fn bench_serialize_map(b: &mut Bencher) {\n            let map = MAP.to_vec();\n            b.iter(|| {\n                serialize_map(test::black_box(&map));\n            });\n        }\n\n        #[cfg(nightly)]\n        #[bench]\n        fn bench_serialize_map_bytes(b: &mut Bencher) {\n            let map: Vec<(&str, &[u8])> = MAP.iter().map(|x| (x.0, x.1.as_bytes())).collect();\n            b.iter(|| {\n                serialize_map_bytes(test::black_box(&map));\n            });\n        }\n\n        #[cfg(nightly)]\n        #[bench]\n        fn bench_deserialize_map(b: &mut Bencher) {\n            let serialized_map = SERIALIZED_MAP.to_vec();\n            b.iter(|| {\n                deserialize_map(test::black_box(&serialized_map));\n            });\n        }\n\n        #[cfg(nightly)]\n        #[bench]\n        fn bench_deserialize_map_bytes(b: &mut Bencher) {\n            let serialized_map = SERIALIZED_MAP.to_vec();\n            b.iter(|| {\n                deserialize_map_bytes(test::black_box(&serialized_map));\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#![cfg_attr(all(test, nightly), feature(test))]\n\n#[cfg(all(test, nightly))]\nextern crate test;\n\npub mod hostcalls;\npub mod traits;\npub mod types;\n\nmod allocator;\nmod dispatcher;\nmod logger;\n\n// For crate-type=\"cdylib\".\n#[cfg(not(wasi_exec_model_reactor))]\n#[macro_export]\nmacro_rules! main {\n    ($code:block) => {\n        #[cfg(target_os = \"wasi\")]\n        extern \"C\" {\n            fn __wasm_call_ctors();\n        }\n\n        #[no_mangle]\n        pub extern \"C\" fn _initialize() {\n            #[cfg(target_os = \"wasi\")]\n            unsafe {\n                __wasm_call_ctors();\n            }\n\n            $code;\n        }\n    };\n}\n\n// For crate-type=\"bin\" with RUSTFLAGS=\"-Z wasi-exec-model=reactor\".\n#[cfg(wasi_exec_model_reactor)]\n#[macro_export]\nmacro_rules! main {\n    ($code:block) => {\n        pub fn main() -> Result<(), Box<dyn std::error::Error>> {\n            $code;\n            Ok(())\n        }\n    };\n}\n\npub fn set_log_level(level: types::LogLevel) {\n    logger::set_log_level(level);\n}\n\npub fn set_root_context(callback: types::NewRootContext) {\n    dispatcher::set_root_context(callback);\n}\n\npub fn set_stream_context(callback: types::NewStreamContext) {\n    dispatcher::set_stream_context(callback);\n}\n\npub fn set_http_context(callback: types::NewHttpContext) {\n    dispatcher::set_http_context(callback);\n}\n\n#[no_mangle]\npub extern \"C\" fn proxy_abi_version_0_2_1() {}\n"
  },
  {
    "path": "src/logger.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse crate::hostcalls;\nuse crate::types::LogLevel;\nuse std::panic;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\nstruct Logger;\n\nstatic LOGGER: Logger = Logger;\nstatic INITIALIZED: AtomicBool = AtomicBool::new(false);\n\npub(crate) fn set_log_level(level: LogLevel) {\n    if !INITIALIZED.load(Ordering::Relaxed) {\n        log::set_logger(&LOGGER).unwrap();\n        panic::set_hook(Box::new(|panic_info| {\n            hostcalls::log(LogLevel::Critical, &panic_info.to_string()).unwrap();\n        }));\n        INITIALIZED.store(true, Ordering::Relaxed);\n    }\n    LOGGER.set_log_level(level);\n}\n\nimpl Logger {\n    pub fn set_log_level(&self, level: LogLevel) {\n        let filter = match level {\n            LogLevel::Trace => log::LevelFilter::Trace,\n            LogLevel::Debug => log::LevelFilter::Debug,\n            LogLevel::Info => log::LevelFilter::Info,\n            LogLevel::Warn => log::LevelFilter::Warn,\n            LogLevel::Error => log::LevelFilter::Error,\n            LogLevel::Critical => log::LevelFilter::Off,\n        };\n        log::set_max_level(filter);\n    }\n}\n\nimpl log::Log for Logger {\n    fn enabled(&self, metadata: &log::Metadata) -> bool {\n        metadata.level() <= log::max_level()\n    }\n\n    fn log(&self, record: &log::Record) {\n        if !self.enabled(record.metadata()) {\n            return;\n        }\n        let level = match record.level() {\n            log::Level::Trace => LogLevel::Trace,\n            log::Level::Debug => LogLevel::Debug,\n            log::Level::Info => LogLevel::Info,\n            log::Level::Warn => LogLevel::Warn,\n            log::Level::Error => LogLevel::Error,\n        };\n        let message = record.args().to_string();\n        hostcalls::log(level, &message).unwrap();\n    }\n\n    fn flush(&self) {}\n}\n"
  },
  {
    "path": "src/traits.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse crate::hostcalls;\nuse crate::types::*;\nuse std::time::{Duration, SystemTime};\n\npub trait Context {\n    fn get_current_time(&self) -> SystemTime {\n        hostcalls::get_current_time().unwrap()\n    }\n\n    fn get_property(&self, path: Vec<&str>) -> Option<Bytes> {\n        hostcalls::get_property(path).unwrap()\n    }\n\n    fn set_property(&self, path: Vec<&str>, value: Option<&[u8]>) {\n        hostcalls::set_property(path, value).unwrap()\n    }\n\n    fn get_shared_data(&self, key: &str) -> (Option<Bytes>, Option<u32>) {\n        hostcalls::get_shared_data(key).unwrap()\n    }\n\n    fn set_shared_data(\n        &self,\n        key: &str,\n        value: Option<&[u8]>,\n        cas: Option<u32>,\n    ) -> Result<(), Status> {\n        hostcalls::set_shared_data(key, value, cas)\n    }\n\n    fn remove_shared_data(&self, key: &str, cas: Option<u32>) -> Result<(), Status> {\n        hostcalls::set_shared_data(key, None, cas)\n    }\n\n    fn register_shared_queue(&self, name: &str) -> u32 {\n        hostcalls::register_shared_queue(name).unwrap()\n    }\n\n    fn resolve_shared_queue(&self, vm_id: &str, name: &str) -> Option<u32> {\n        hostcalls::resolve_shared_queue(vm_id, name).unwrap()\n    }\n\n    fn dequeue_shared_queue(&self, queue_id: u32) -> Result<Option<Bytes>, Status> {\n        hostcalls::dequeue_shared_queue(queue_id)\n    }\n\n    fn enqueue_shared_queue(&self, queue_id: u32, value: Option<&[u8]>) -> Result<(), Status> {\n        hostcalls::enqueue_shared_queue(queue_id, value)\n    }\n\n    fn dispatch_http_call(\n        &self,\n        upstream: &str,\n        headers: Vec<(&str, &str)>,\n        body: Option<&[u8]>,\n        trailers: Vec<(&str, &str)>,\n        timeout: Duration,\n    ) -> Result<u32, Status> {\n        hostcalls::dispatch_http_call(upstream, headers, body, trailers, timeout)\n    }\n\n    fn on_http_call_response(\n        &mut self,\n        _token_id: u32,\n        _num_headers: usize,\n        _body_size: usize,\n        _num_trailers: usize,\n    ) {\n    }\n\n    fn get_http_call_response_headers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpCallResponseHeaders).unwrap()\n    }\n\n    fn get_http_call_response_headers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpCallResponseHeaders).unwrap()\n    }\n\n    fn get_http_call_response_header(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpCallResponseHeaders, name).unwrap()\n    }\n\n    fn get_http_call_response_header_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpCallResponseHeaders, name).unwrap()\n    }\n\n    fn get_http_call_response_body(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::HttpCallResponseBody, start, max_size).unwrap()\n    }\n\n    fn get_http_call_response_trailers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpCallResponseTrailers).unwrap()\n    }\n\n    fn get_http_call_response_trailers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpCallResponseTrailers).unwrap()\n    }\n\n    fn get_http_call_response_trailer(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpCallResponseTrailers, name).unwrap()\n    }\n\n    fn get_http_call_response_trailer_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpCallResponseTrailers, name).unwrap()\n    }\n\n    fn dispatch_grpc_call(\n        &self,\n        upstream_name: &str,\n        service_name: &str,\n        method_name: &str,\n        initial_metadata: Vec<(&str, &[u8])>,\n        message: Option<&[u8]>,\n        timeout: Duration,\n    ) -> Result<u32, Status> {\n        hostcalls::dispatch_grpc_call(\n            upstream_name,\n            service_name,\n            method_name,\n            initial_metadata,\n            message,\n            timeout,\n        )\n    }\n\n    fn on_grpc_call_response(&mut self, _token_id: u32, _status_code: u32, _response_size: usize) {}\n\n    fn get_grpc_call_response_body(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::GrpcReceiveBuffer, start, max_size).unwrap()\n    }\n\n    fn cancel_grpc_call(&self, token_id: u32) {\n        hostcalls::cancel_grpc_call(token_id).unwrap()\n    }\n\n    fn open_grpc_stream(\n        &self,\n        cluster_name: &str,\n        service_name: &str,\n        method_name: &str,\n        initial_metadata: Vec<(&str, &[u8])>,\n    ) -> Result<u32, Status> {\n        hostcalls::open_grpc_stream(cluster_name, service_name, method_name, initial_metadata)\n    }\n\n    fn on_grpc_stream_initial_metadata(&mut self, _token_id: u32, _num_elements: u32) {}\n\n    fn get_grpc_stream_initial_metadata(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::GrpcReceiveInitialMetadata).unwrap()\n    }\n\n    fn get_grpc_stream_initial_metadata_value(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::GrpcReceiveInitialMetadata, name).unwrap()\n    }\n\n    fn send_grpc_stream_message(&self, token_id: u32, message: Option<&[u8]>, end_stream: bool) {\n        hostcalls::send_grpc_stream_message(token_id, message, end_stream).unwrap()\n    }\n\n    fn on_grpc_stream_message(&mut self, _token_id: u32, _message_size: usize) {}\n\n    fn get_grpc_stream_message(&mut self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::GrpcReceiveBuffer, start, max_size).unwrap()\n    }\n\n    fn on_grpc_stream_trailing_metadata(&mut self, _token_id: u32, _num_elements: u32) {}\n\n    fn get_grpc_stream_trailing_metadata(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::GrpcReceiveTrailingMetadata).unwrap()\n    }\n\n    fn get_grpc_stream_trailing_metadata_value(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::GrpcReceiveTrailingMetadata, name).unwrap()\n    }\n\n    fn cancel_grpc_stream(&self, token_id: u32) {\n        hostcalls::cancel_grpc_stream(token_id).unwrap()\n    }\n\n    fn close_grpc_stream(&self, token_id: u32) {\n        hostcalls::close_grpc_stream(token_id).unwrap()\n    }\n\n    fn on_grpc_stream_close(&mut self, _token_id: u32, _status_code: u32) {}\n\n    fn get_grpc_status(&self) -> (u32, Option<String>) {\n        hostcalls::get_grpc_status().unwrap()\n    }\n\n    fn on_foreign_function(&mut self, _function_id: u32, _arguments_size: usize) {}\n\n    fn call_foreign_function(\n        &self,\n        function_name: &str,\n        arguments: Option<&[u8]>,\n    ) -> Result<Option<Bytes>, Status> {\n        hostcalls::call_foreign_function(function_name, arguments)\n    }\n\n    fn on_done(&mut self) -> bool {\n        true\n    }\n\n    fn done(&self) {\n        hostcalls::done().unwrap()\n    }\n}\n\npub trait RootContext: Context {\n    fn on_vm_start(&mut self, _vm_configuration_size: usize) -> bool {\n        true\n    }\n\n    fn get_vm_configuration(&self) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::VmConfiguration, 0, usize::MAX).unwrap()\n    }\n\n    fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool {\n        true\n    }\n\n    fn get_plugin_configuration(&self) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::PluginConfiguration, 0, usize::MAX).unwrap()\n    }\n\n    fn set_tick_period(&self, period: Duration) {\n        hostcalls::set_tick_period(period).unwrap()\n    }\n\n    fn on_tick(&mut self) {}\n\n    fn on_queue_ready(&mut self, _queue_id: u32) {}\n\n    fn on_log(&mut self) {}\n\n    fn create_http_context(&self, _context_id: u32) -> Option<Box<dyn HttpContext>> {\n        None\n    }\n\n    fn create_stream_context(&self, _context_id: u32) -> Option<Box<dyn StreamContext>> {\n        None\n    }\n\n    fn get_type(&self) -> Option<ContextType> {\n        None\n    }\n}\n\npub trait StreamContext: Context {\n    fn on_new_connection(&mut self) -> Action {\n        Action::Continue\n    }\n\n    fn on_downstream_data(&mut self, _data_size: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_downstream_data(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::DownstreamData, start, max_size).unwrap()\n    }\n\n    fn set_downstream_data(&self, start: usize, size: usize, value: &[u8]) {\n        hostcalls::set_buffer(BufferType::DownstreamData, start, size, value).unwrap()\n    }\n\n    fn resume_downstream(&self) {\n        hostcalls::resume_downstream().unwrap()\n    }\n\n    fn close_downstream(&self) {\n        hostcalls::close_downstream().unwrap()\n    }\n\n    fn on_downstream_close(&mut self, _peer_type: PeerType) {}\n\n    fn on_upstream_data(&mut self, _data_size: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_upstream_data(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::UpstreamData, start, max_size).unwrap()\n    }\n\n    fn set_upstream_data(&self, start: usize, size: usize, value: &[u8]) {\n        hostcalls::set_buffer(BufferType::UpstreamData, start, size, value).unwrap()\n    }\n\n    fn resume_upstream(&self) {\n        hostcalls::resume_upstream().unwrap()\n    }\n\n    fn close_upstream(&self) {\n        hostcalls::close_upstream().unwrap()\n    }\n\n    fn on_upstream_close(&mut self, _peer_type: PeerType) {}\n\n    fn on_log(&mut self) {}\n}\n\npub trait HttpContext: Context {\n    fn on_http_request_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_request_headers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpRequestHeaders).unwrap()\n    }\n\n    fn get_http_request_headers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpRequestHeaders).unwrap()\n    }\n\n    fn set_http_request_headers(&self, headers: Vec<(&str, &str)>) {\n        hostcalls::set_map(MapType::HttpRequestHeaders, headers).unwrap()\n    }\n\n    fn set_http_request_headers_bytes(&self, headers: Vec<(&str, &[u8])>) {\n        hostcalls::set_map_bytes(MapType::HttpRequestHeaders, headers).unwrap()\n    }\n\n    fn get_http_request_header(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpRequestHeaders, name).unwrap()\n    }\n\n    fn get_http_request_header_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpRequestHeaders, name).unwrap()\n    }\n\n    fn set_http_request_header(&self, name: &str, value: Option<&str>) {\n        hostcalls::set_map_value(MapType::HttpRequestHeaders, name, value).unwrap()\n    }\n\n    fn set_http_request_header_bytes(&self, name: &str, value: Option<&[u8]>) {\n        hostcalls::set_map_value_bytes(MapType::HttpRequestHeaders, name, value).unwrap()\n    }\n\n    fn add_http_request_header(&self, name: &str, value: &str) {\n        hostcalls::add_map_value(MapType::HttpRequestHeaders, name, value).unwrap()\n    }\n\n    fn add_http_request_header_bytes(&self, name: &str, value: &[u8]) {\n        hostcalls::add_map_value_bytes(MapType::HttpRequestHeaders, name, value).unwrap()\n    }\n\n    fn remove_http_request_header(&self, name: &str) {\n        hostcalls::remove_map_value(MapType::HttpRequestHeaders, name).unwrap()\n    }\n\n    fn on_http_request_body(&mut self, _body_size: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_request_body(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::HttpRequestBody, start, max_size).unwrap()\n    }\n\n    fn set_http_request_body(&self, start: usize, size: usize, value: &[u8]) {\n        hostcalls::set_buffer(BufferType::HttpRequestBody, start, size, value).unwrap()\n    }\n\n    fn on_http_request_trailers(&mut self, _num_trailers: usize) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_request_trailers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpRequestTrailers).unwrap()\n    }\n\n    fn get_http_request_trailers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpRequestTrailers).unwrap()\n    }\n\n    fn set_http_request_trailers(&self, trailers: Vec<(&str, &str)>) {\n        hostcalls::set_map(MapType::HttpRequestTrailers, trailers).unwrap()\n    }\n\n    fn set_http_request_trailers_bytes(&self, trailers: Vec<(&str, &[u8])>) {\n        hostcalls::set_map_bytes(MapType::HttpRequestTrailers, trailers).unwrap()\n    }\n\n    fn get_http_request_trailer(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpRequestTrailers, name).unwrap()\n    }\n\n    fn get_http_request_trailer_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpRequestTrailers, name).unwrap()\n    }\n\n    fn set_http_request_trailer(&self, name: &str, value: Option<&str>) {\n        hostcalls::set_map_value(MapType::HttpRequestTrailers, name, value).unwrap()\n    }\n\n    fn set_http_request_trailer_bytes(&self, name: &str, value: Option<&[u8]>) {\n        hostcalls::set_map_value_bytes(MapType::HttpRequestTrailers, name, value).unwrap()\n    }\n\n    fn add_http_request_trailer(&self, name: &str, value: &str) {\n        hostcalls::add_map_value(MapType::HttpRequestTrailers, name, value).unwrap()\n    }\n\n    fn add_http_request_trailer_bytes(&self, name: &str, value: &[u8]) {\n        hostcalls::add_map_value_bytes(MapType::HttpRequestTrailers, name, value).unwrap()\n    }\n\n    fn remove_http_request_trailer(&self, name: &str) {\n        hostcalls::remove_map_value(MapType::HttpRequestTrailers, name).unwrap()\n    }\n\n    fn resume_http_request(&self) {\n        hostcalls::resume_http_request().unwrap()\n    }\n\n    fn reset_http_request(&self) {\n        hostcalls::reset_http_request().unwrap()\n    }\n\n    fn on_http_response_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_response_headers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpResponseHeaders).unwrap()\n    }\n\n    fn get_http_response_headers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpResponseHeaders).unwrap()\n    }\n\n    fn set_http_response_headers(&self, headers: Vec<(&str, &str)>) {\n        hostcalls::set_map(MapType::HttpResponseHeaders, headers).unwrap()\n    }\n\n    fn set_http_response_headers_bytes(&self, headers: Vec<(&str, &[u8])>) {\n        hostcalls::set_map_bytes(MapType::HttpResponseHeaders, headers).unwrap()\n    }\n\n    fn get_http_response_header(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpResponseHeaders, name).unwrap()\n    }\n\n    fn get_http_response_header_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpResponseHeaders, name).unwrap()\n    }\n\n    fn set_http_response_header(&self, name: &str, value: Option<&str>) {\n        hostcalls::set_map_value(MapType::HttpResponseHeaders, name, value).unwrap()\n    }\n\n    fn set_http_response_header_bytes(&self, name: &str, value: Option<&[u8]>) {\n        hostcalls::set_map_value_bytes(MapType::HttpResponseHeaders, name, value).unwrap()\n    }\n\n    fn add_http_response_header(&self, name: &str, value: &str) {\n        hostcalls::add_map_value(MapType::HttpResponseHeaders, name, value).unwrap()\n    }\n\n    fn add_http_response_header_bytes(&self, name: &str, value: &[u8]) {\n        hostcalls::add_map_value_bytes(MapType::HttpResponseHeaders, name, value).unwrap()\n    }\n\n    fn remove_http_response_header(&self, name: &str) {\n        hostcalls::remove_map_value(MapType::HttpResponseHeaders, name).unwrap()\n    }\n\n    fn on_http_response_body(&mut self, _body_size: usize, _end_of_stream: bool) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_response_body(&self, start: usize, max_size: usize) -> Option<Bytes> {\n        hostcalls::get_buffer(BufferType::HttpResponseBody, start, max_size).unwrap()\n    }\n\n    fn set_http_response_body(&self, start: usize, size: usize, value: &[u8]) {\n        hostcalls::set_buffer(BufferType::HttpResponseBody, start, size, value).unwrap()\n    }\n\n    fn on_http_response_trailers(&mut self, _num_trailers: usize) -> Action {\n        Action::Continue\n    }\n\n    fn get_http_response_trailers(&self) -> Vec<(String, String)> {\n        hostcalls::get_map(MapType::HttpResponseTrailers).unwrap()\n    }\n\n    fn get_http_response_trailers_bytes(&self) -> Vec<(String, Bytes)> {\n        hostcalls::get_map_bytes(MapType::HttpResponseTrailers).unwrap()\n    }\n\n    fn set_http_response_trailers(&self, trailers: Vec<(&str, &str)>) {\n        hostcalls::set_map(MapType::HttpResponseTrailers, trailers).unwrap()\n    }\n\n    fn set_http_response_trailers_bytes(&self, trailers: Vec<(&str, &[u8])>) {\n        hostcalls::set_map_bytes(MapType::HttpResponseTrailers, trailers).unwrap()\n    }\n\n    fn get_http_response_trailer(&self, name: &str) -> Option<String> {\n        hostcalls::get_map_value(MapType::HttpResponseTrailers, name).unwrap()\n    }\n\n    fn get_http_response_trailer_bytes(&self, name: &str) -> Option<Bytes> {\n        hostcalls::get_map_value_bytes(MapType::HttpResponseTrailers, name).unwrap()\n    }\n\n    fn set_http_response_trailer(&self, name: &str, value: Option<&str>) {\n        hostcalls::set_map_value(MapType::HttpResponseTrailers, name, value).unwrap()\n    }\n\n    fn set_http_response_trailer_bytes(&self, name: &str, value: Option<&[u8]>) {\n        hostcalls::set_map_value_bytes(MapType::HttpResponseTrailers, name, value).unwrap()\n    }\n\n    fn add_http_response_trailer(&self, name: &str, value: &str) {\n        hostcalls::add_map_value(MapType::HttpResponseTrailers, name, value).unwrap()\n    }\n\n    fn add_http_response_trailer_bytes(&self, name: &str, value: &[u8]) {\n        hostcalls::add_map_value_bytes(MapType::HttpResponseTrailers, name, value).unwrap()\n    }\n\n    fn remove_http_response_trailer(&self, name: &str) {\n        hostcalls::remove_map_value(MapType::HttpResponseTrailers, name).unwrap()\n    }\n\n    fn resume_http_response(&self) {\n        hostcalls::resume_http_response().unwrap()\n    }\n\n    fn reset_http_response(&self) {\n        hostcalls::reset_http_response().unwrap()\n    }\n\n    fn send_http_response(\n        &self,\n        status_code: u32,\n        headers: Vec<(&str, &str)>,\n        body: Option<&[u8]>,\n    ) {\n        hostcalls::send_http_response(status_code, headers, body).unwrap()\n    }\n\n    fn send_grpc_response(\n        &self,\n        grpc_status: GrpcStatusCode,\n        grpc_status_message: Option<&str>,\n        custom_metadata: Vec<(&str, &[u8])>,\n    ) {\n        hostcalls::send_grpc_response(grpc_status, grpc_status_message, custom_metadata).unwrap()\n    }\n\n    fn on_log(&mut self) {}\n}\n"
  },
  {
    "path": "src/types.rs",
    "content": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nuse crate::traits::*;\n\npub type NewRootContext = fn(context_id: u32) -> Box<dyn RootContext>;\npub type NewStreamContext = fn(context_id: u32, root_context_id: u32) -> Box<dyn StreamContext>;\npub type NewHttpContext = fn(context_id: u32, root_context_id: u32) -> Box<dyn HttpContext>;\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\npub enum LogLevel {\n    Trace = 0,\n    Debug = 1,\n    Info = 2,\n    Warn = 3,\n    Error = 4,\n    Critical = 5,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum Action {\n    Continue = 0,\n    Pause = 1,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum Status {\n    Ok = 0,\n    NotFound = 1,\n    BadArgument = 2,\n    SerializationFailure = 3,\n    ParseFailure = 4,\n    Empty = 7,\n    CasMismatch = 8,\n    InternalFailure = 10,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum ContextType {\n    HttpContext = 0,\n    StreamContext = 1,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum StreamType {\n    HttpRequest = 0,\n    HttpResponse = 1,\n    Downstream = 2,\n    Upstream = 3,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum BufferType {\n    HttpRequestBody = 0,\n    HttpResponseBody = 1,\n    DownstreamData = 2,\n    UpstreamData = 3,\n    HttpCallResponseBody = 4,\n    GrpcReceiveBuffer = 5,\n    VmConfiguration = 6,\n    PluginConfiguration = 7,\n    CallData = 8,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum MapType {\n    HttpRequestHeaders = 0,\n    HttpRequestTrailers = 1,\n    HttpResponseHeaders = 2,\n    HttpResponseTrailers = 3,\n    GrpcReceiveInitialMetadata = 4,\n    GrpcReceiveTrailingMetadata = 5,\n    HttpCallResponseHeaders = 6,\n    HttpCallResponseTrailers = 7,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum PeerType {\n    Unknown = 0,\n    Local = 1,\n    Remote = 2,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum MetricType {\n    Counter = 0,\n    Gauge = 1,\n    Histogram = 2,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\n#[non_exhaustive]\npub enum GrpcStatusCode {\n    Ok = 0,\n    Cancelled = 1,\n    Unknown = 2,\n    InvalidArgument = 3,\n    DeadlineExceeded = 4,\n    NotFound = 5,\n    AlreadyExists = 6,\n    PermissionDenied = 7,\n    ResourceExhausted = 8,\n    FailedPrecondition = 9,\n    Aborted = 10,\n    OutOfRange = 11,\n    Unimplemented = 12,\n    Internal = 13,\n    Unavailable = 14,\n    DataLoss = 15,\n    Unauthenticated = 16,\n}\n\npub type Bytes = Vec<u8>;\n"
  }
]