From a8312c0a90e3c161adcd77eb5f0fdd3020240480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonasz=20Ma=C5=82ecki?= Date: Wed, 7 Oct 2026 15:59:30 +0200 Subject: [PATCH 1/4] feat(examples): add hello-odin, an Odin ABI v2 guest The hello guest in Odin, an example only (#155): the c flavour's plumbing byte for byte (wit/, src/gen/, src/fnv1/, proto/, which the examples-share-the-scaffold-plumbing test now holds identical, and which the root Makefile's vendor-proto and gen-bindings regenerate there too), the generated nanopb structs declared again in Odin with their wasm32 layout held by #asserts, the codec and the c glue's wasi:http client called over Odin's foreign interface, and the bindings' exports_function_run defined in Odin. odin builds a freestanding wasm32 object, build.zig compiles the C half and links the core module through zig cc (not build-exe: Odin's runtime defines bzero with a return value, and wasm-ld's signature-mismatch warning fails build-exe), and guestfn build takes the project for a c one and wraps it with no adapter: a 71 KB component, compiled by the runtime in about 10 ms. Unit tests run natively with odin test over the C half compiled for the host; the xprin suite is the c example's. --- Makefile | 29 +- crates/guestfn/src/scaffold.rs | 14 +- examples/hello-odin/.gitignore | 5 + examples/hello-odin/Makefile | 40 + examples/hello-odin/README.md | 130 + examples/hello-odin/build.zig | 155 + examples/hello-odin/build.zig.zon | 22 + .../example/composition-egress.yaml | 28 + examples/hello-odin/example/composition.yaml | 24 + examples/hello-odin/example/fixtures/en | 1 + examples/hello-odin/example/functions.yaml | 12 + examples/hello-odin/example/policy.cedar | 9 + examples/hello-odin/example/wasmfn.local.yaml | 19 + examples/hello-odin/example/xprin.yaml | 37 + examples/hello-odin/example/xr.yaml | 5 + .../proto/google/protobuf/duration.options | 3 + .../proto/google/protobuf/duration.proto | 115 + .../proto/google/protobuf/struct.options | 3 + .../proto/google/protobuf/struct.proto | 111 + .../hello-odin/proto/run_function.options | 8 + examples/hello-odin/proto/run_function.proto | 441 ++ examples/hello-odin/src/fn_test.odin | 151 + examples/hello-odin/src/fnv1.odin | 280 + .../src/fnv1/google/protobuf/duration.pb.c | 12 + .../src/fnv1/google/protobuf/duration.pb.h | 118 + .../src/fnv1/google/protobuf/struct.pb.c | 31 + .../src/fnv1/google/protobuf/struct.pb.h | 178 + .../hello-odin/src/fnv1/run_function.pb.c | 100 + .../hello-odin/src/fnv1/run_function.pb.h | 1065 ++++ examples/hello-odin/src/gen/function.c | 5585 +++++++++++++++++ examples/hello-odin/src/gen/function.h | 1336 ++++ .../src/gen/function_component_type.o | Bin 0 -> 6664 bytes examples/hello-odin/src/main.odin | 132 + examples/hello-odin/src/structpb.odin | 110 + examples/hello-odin/src/wasmfn.c | 366 ++ examples/hello-odin/src/wasmfn.h | 51 + examples/hello-odin/src/wasmfn.odin | 359 ++ examples/hello-odin/wasmfn.yaml | 22 + examples/hello-odin/wit/deps/cli.wit | 235 + examples/hello-odin/wit/deps/clocks.wit | 164 + examples/hello-odin/wit/deps/filesystem.wit | 591 ++ examples/hello-odin/wit/deps/http.wit | 735 +++ examples/hello-odin/wit/deps/io.wit | 301 + examples/hello-odin/wit/deps/random.wit | 94 + examples/hello-odin/wit/deps/sockets.wit | 951 +++ examples/hello-odin/wit/world.wit | 25 + 46 files changed, 14190 insertions(+), 13 deletions(-) create mode 100644 examples/hello-odin/.gitignore create mode 100644 examples/hello-odin/Makefile create mode 100644 examples/hello-odin/README.md create mode 100644 examples/hello-odin/build.zig create mode 100644 examples/hello-odin/build.zig.zon create mode 100644 examples/hello-odin/example/composition-egress.yaml create mode 100644 examples/hello-odin/example/composition.yaml create mode 100644 examples/hello-odin/example/fixtures/en create mode 100644 examples/hello-odin/example/functions.yaml create mode 100644 examples/hello-odin/example/policy.cedar create mode 100644 examples/hello-odin/example/wasmfn.local.yaml create mode 100644 examples/hello-odin/example/xprin.yaml create mode 100644 examples/hello-odin/example/xr.yaml create mode 100644 examples/hello-odin/proto/google/protobuf/duration.options create mode 100644 examples/hello-odin/proto/google/protobuf/duration.proto create mode 100644 examples/hello-odin/proto/google/protobuf/struct.options create mode 100644 examples/hello-odin/proto/google/protobuf/struct.proto create mode 100644 examples/hello-odin/proto/run_function.options create mode 100644 examples/hello-odin/proto/run_function.proto create mode 100644 examples/hello-odin/src/fn_test.odin create mode 100644 examples/hello-odin/src/fnv1.odin create mode 100644 examples/hello-odin/src/fnv1/google/protobuf/duration.pb.c create mode 100644 examples/hello-odin/src/fnv1/google/protobuf/duration.pb.h create mode 100644 examples/hello-odin/src/fnv1/google/protobuf/struct.pb.c create mode 100644 examples/hello-odin/src/fnv1/google/protobuf/struct.pb.h create mode 100644 examples/hello-odin/src/fnv1/run_function.pb.c create mode 100644 examples/hello-odin/src/fnv1/run_function.pb.h create mode 100644 examples/hello-odin/src/gen/function.c create mode 100644 examples/hello-odin/src/gen/function.h create mode 100644 examples/hello-odin/src/gen/function_component_type.o create mode 100644 examples/hello-odin/src/main.odin create mode 100644 examples/hello-odin/src/structpb.odin create mode 100644 examples/hello-odin/src/wasmfn.c create mode 100644 examples/hello-odin/src/wasmfn.h create mode 100644 examples/hello-odin/src/wasmfn.odin create mode 100644 examples/hello-odin/wasmfn.yaml create mode 100644 examples/hello-odin/wit/deps/cli.wit create mode 100644 examples/hello-odin/wit/deps/clocks.wit create mode 100644 examples/hello-odin/wit/deps/filesystem.wit create mode 100644 examples/hello-odin/wit/deps/http.wit create mode 100644 examples/hello-odin/wit/deps/io.wit create mode 100644 examples/hello-odin/wit/deps/random.wit create mode 100644 examples/hello-odin/wit/deps/sockets.wit create mode 100644 examples/hello-odin/wit/world.wit diff --git a/Makefile b/Makefile index 76f77cf0..9715f5e5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Re-vendoring crossplane/crossplane's proto/fn/v1/run_function.proto (AGENTS.md # "Changing the scaffold"). Every tracked proto/run_function.proto - the files -# Renovate's version-header rule reads: five templates, five goldens, six +# Renovate's version-header rule reads: five templates, five goldens, seven # examples - is the upstream file byte for byte under a five-line header whose # first line names the release. A Renovate bump moves that version in every # header but can neither re-download the file nor regenerate the codecs checked @@ -10,10 +10,11 @@ # `make vendor-proto` takes the release from the headers (the rust template's); # `make vendor-proto VERSION=vX.Y.Z` vendors one Renovate has not proposed. # -# `make gen-bindings` is the same loop for the wit-bindgen bindings: the c -# and zig guests' C bindings (examples/hello-c/src/gen and -# examples/hello-zig/src/gen: one generator's output over one world, which -# the guestfn tests hold identical) and the go guest's Go bindings +# `make gen-bindings` is the same loop for the wit-bindgen bindings: the c, +# zig and odin guests' C bindings (examples/hello-c/src/gen, +# examples/hello-zig/src/gen and examples/hello-odin/src/gen: one generator's +# output over one world, which the guestfn tests hold identical) and the go +# guest's Go bindings # (examples/pdb-addon/internal/bindings, over its own world). It runs the # pinned wit-bindgen in each, mirrors each result into its template (the go # one with the module path templated as [[ .Module ]]) and refreshes the @@ -33,10 +34,10 @@ # protobuf runtime older than that stamp, so # PROTOC_VERSION must not pass the runtime the python template's # requirements.txt pins (team-tags's is the same file). NANOPB_VERSION is -# the nanopb release hello-c's build.zig.zon compiles and e2e.yml's codec -# drift check installs. WIT_BINDGEN_VERSION is the wit-bindgen-cli release -# that wrote hello-c's, hello-zig's and pdb-addon's checked-in bindings and -# e2e.yml's bindings drift checks install. +# the nanopb release hello-c's and hello-odin's build.zig.zon compile and +# e2e.yml's codec drift checks install. WIT_BINDGEN_VERSION is the +# wit-bindgen-cli release that wrote hello-c's, hello-zig's, hello-odin's and +# pdb-addon's checked-in bindings and e2e.yml's bindings drift checks install. PROTOC_VERSION := 35.1 NANOPB_VERSION := 0.4.9.1 WIT_BINDGEN_VERSION := 0.62.0 @@ -82,11 +83,14 @@ vendor-proto-fetch: ## Overwrite every copy with the upstream file at $(VERSION) # rust and rust-v2 have no checked-in codec (build.rs runs prost-build); the # zig, c, ts and python codecs are mirrored into their guestfn # templates, which examples_share_the_scaffold_plumbing holds identical to -# the examples. The ts and python codecs are copied file by file: a gen/ directory -# may hold a __pycache__ the templates must not embed. +# the examples (hello-odin regenerates the c codec over its own copy of the +# proto, and the same test holds it to the c template's). The ts and python +# codecs are copied file by file: a gen/ directory may hold a __pycache__ the +# templates must not embed. vendor-proto-codecs: tools ## Regenerate every checked-in guest codec with the pinned generators and mirror them into the templates $(WITH_TOOLS) $(MAKE) -C examples/hello-zig gen-proto $(WITH_TOOLS) $(MAKE) -C examples/hello-c gen-proto + $(WITH_TOOLS) $(MAKE) -C examples/hello-odin gen-proto $(WITH_TOOLS) $(MAKE) -C examples/team-tags gen-proto $(WITH_TOOLS) $(MAKE) -C examples/policy-gate gen-proto $(WITH_TOOLS) $(MAKE) -C examples/dashboard-bundle gen-proto @@ -109,9 +113,10 @@ vendor-proto-goldens: ## Refresh the guestfn scaffold goldens from the templates # is copied as it is. GO_MODULE := github.com/jonasz-lasut/function-wasm/examples/pdb-addon GO_BINDINGS := crates/guestfn/templates/go/internal/bindings -gen-bindings: tools ## Regenerate hello-c's, hello-zig's and pdb-addon's wit-bindgen bindings with the pinned wit-bindgen, mirror them into the c, zig and go templates and refresh the goldens +gen-bindings: tools ## Regenerate hello-c's, hello-zig's, hello-odin's and pdb-addon's wit-bindgen bindings with the pinned wit-bindgen, mirror the c, zig and go ones into their templates and refresh the goldens $(WITH_TOOLS) $(MAKE) -C examples/hello-c gen-bindings $(WITH_TOOLS) $(MAKE) -C examples/hello-zig gen-bindings + $(WITH_TOOLS) $(MAKE) -C examples/hello-odin gen-bindings $(WITH_TOOLS) $(MAKE) -C examples/pdb-addon gen-bindings rm -rf crates/guestfn/templates/c/src/gen && cp -R examples/hello-c/src/gen crates/guestfn/templates/c/src/gen rm -rf crates/guestfn/templates/zig/src/gen && cp -R examples/hello-zig/src/gen crates/guestfn/templates/zig/src/gen diff --git a/crates/guestfn/src/scaffold.rs b/crates/guestfn/src/scaffold.rs index 21ccb0a4..71c3bb1d 100644 --- a/crates/guestfn/src/scaffold.rs +++ b/crates/guestfn/src/scaffold.rs @@ -267,7 +267,7 @@ mod tests { /// README, the example manifests) is the example's own. #[test] fn examples_share_the_scaffold_plumbing() { - let examples: [(&str, &[&str], Options); 6] = [ + let examples: [(&str, &[&str], Options); 7] = [ ( "pdb-addon", &[ @@ -326,6 +326,18 @@ mod tests { ..Default::default() }, ), + // The Odin example has no scaffold of its own: it implements + // the world through the c flavour's bindings and codec, which + // it carries byte for byte; its glue and build are its own. + ( + "hello-odin", + &["proto/", "wit/", "src/fnv1/", "src/gen/"], + Options { + lang: LANG_C.into(), + name: "hello-odin".into(), + ..Default::default() + }, + ), ( "policy-gate", &["proto/", "src/gen/", "src/log.d.ts"], diff --git a/examples/hello-odin/.gitignore b/examples/hello-odin/.gitignore new file mode 100644 index 00000000..1f1808fd --- /dev/null +++ b/examples/hello-odin/.gitignore @@ -0,0 +1,5 @@ +.zig-cache/ +zig-out/ +zig-pkg/ +zig-prefix/ +*.wasm diff --git a/examples/hello-odin/Makefile b/examples/hello-odin/Makefile new file mode 100644 index 00000000..6cb1b7ad --- /dev/null +++ b/examples/hello-odin/Makefile @@ -0,0 +1,40 @@ +# The hello guest in Odin on ABI v2: needs odin (dev-2026-10) and zig (0.16) +# on PATH - odin compiles the guest to a wasm32 object, zig cc compiles the C +# half (build.zig fetches nanopb) and links the core module - and guestfn, +# which comes from this repository (cargo run) and wraps that core module into +# the component the runtime loads (no wasm-tools, no adapter download). +# wit-bindgen 0.62.0 is only needed to regenerate the checked-in bindings +# (make gen-bindings; the root Makefile's gen-bindings installs it pinned) +# and nanopb_generator (pip install nanopb) the checked-in codec (make +# gen-proto). Render needs the crossplane CLI and Docker, render-check also +# xprin. GUESTFN, FUNCTION_BIN (read by ../render.sh) and XPRIN can name +# prebuilt binaries instead, as CI does. +ROOT := $(abspath ../..) +GUESTFN ?= cargo run --manifest-path $(ROOT)/Cargo.toml --release -p guestfn -- + +.PHONY: build test lint gen-proto gen-bindings render render-check clean + +build: ## Compile the guest to fn.wasm (a component) + $(GUESTFN) build --dir $(CURDIR) + +test: ## Run the unit tests natively + zig build test + +lint: ## Vet the Odin sources for the wasm target and check build.zig's formatting + zig fmt --check build.zig + zig build lint + +gen-proto: ## Regenerate src/fnv1 from proto/ (needs nanopb_generator) + zig build gen-proto + +gen-bindings: ## Regenerate src/gen from wit/ (needs wit-bindgen 0.62.0) + zig build gen-bindings + +render: build ## Start the runtime serving this directory and crossplane render example/ + ../render.sh $(CURDIR) + +render-check: build ## Like render, but assert the output (used by CI) + ../render.sh $(CURDIR) --check + +clean: + rm -rf .zig-cache zig-out zig-pkg zig-prefix fn.wasm diff --git a/examples/hello-odin/README.md b/examples/hello-odin/README.md new file mode 100644 index 00000000..1d286902 --- /dev/null +++ b/examples/hello-odin/README.md @@ -0,0 +1,130 @@ +# hello-odin + +A [Crossplane](https://crossplane.io) composition function in +[Odin](https://odin-lang.org) on +[ABI v2](https://github.com/jonasz-lasut/function-wasm/blob/main/docs/abi-v2.md): +a WebAssembly component of about 70 KB, run by +[function-wasm](https://github.com/jonasz-lasut/function-wasm). The Odin +guest implements the world through the `c` flavour's wit-bindgen C +bindings, talks protobuf through nanopb over Odin's foreign interface, and +reaches the host's HTTP egress through the `c` flavour's own client. `odin` +compiles the guest to one wasm32 object, `zig cc` compiles the C half and +links the core module, and `guestfn build` wraps it into the component - no +wasi-sdk, no wasm-tools, no adapter download. There is no `guestfn init +--lang odin`: this example is the Odin path +([#155](https://github.com/jonasz-lasut/function-wasm/issues/155)). + +- `wit/world.wit` and `wit/deps/` are the `c` flavour's: the + `wasmfn:function` contract restated in a `local:guest` package with `run` + declared sync and `wasi:http/outgoing-handler@0.2.12` imported for the + greeting fetch. `src/gen` is wit-bindgen's C output over it (`function.h`, + `function.c`, `function_component_type.o`), byte for byte the `c` + flavour's, checked in; `make gen-bindings` regenerates it. +- `proto/` and `src/fnv1` are the vendored crossplane proto and the nanopb + codec the `c` flavour generates from it, byte for byte (`make gen-proto` + regenerates it); the plumbing test in this repository holds all four + directories identical to the `c` template. `src/fnv1.odin` declares the + generated structs again in Odin with the same layout, and holds every + size and offset it relies on with `#assert`s against what `zig cc` + computes for wasm32, so a drift fails the build. +- `src/main.odin` - `run_function` over the mirrored structs (edit this). + `src/structpb.odin` reads and builds `google.protobuf.Struct` values; + `src/wasmfn.odin` is the ABI glue: the world's `run` export + (`exports_function_run`, the one C function the bindings' run shim + expects; decode, run, encode; errors become fatal results), the typed + `log` import as a logger, `http_get_text` over the C client, and an Odin + allocator over wasi-libc's heap, the module's one heap, so what Odin + allocates may be handed to the canonical ABI and freed there. Only the + export and the imports are wasm-specific: natively the logger prints to + stderr and a test installs a fake host for HTTP. +- `src/wasmfn.c` is the `c` flavour's `wasi:http@0.2` client, kept as it is + with the parts the Odin side implements cut out (the export, the codec, + the log). +- `build.zig` runs `odin build src -target:freestanding_wasm32 + -build-mode:obj -no-entry-point`, compiles the C half with `zig cc` and + links the core module with `zig cc` (a wasip1 reactor that imports nothing + from `wasi_snapshot_preview1`, so `guestfn build` links no adapter). + Freestanding, because Odin's runtime then imports nothing; the libc its + allocations come from is the one the module links anyway. `core:fmt` + is deliberately not used: it brings reflection and type tables that + grow the module from 68 KB to 198 KB. +- `src/fn_test.odin` - the unit tests, run natively by `odin test` over the + C half compiled for the host (`zig build test`): the function with a fake + host, and one request through nanopb's decode, run and encode. + +Toolchain: Odin `dev-2026-10` (`brew install odin`, or the +[release](https://github.com/odin-lang/Odin/releases) for your platform on +PATH) and Zig 0.16. The Odin compile takes 0.2 s; a cold `guestfn build` +(the C half, the link, the wrap) about 7 s, a warm one 0.2 s; the runtime +compiles the component in about 10 ms. + +```shell +# Unit tests run natively; lint vets the Odin sources for the wasm target. +make test # zig build test (odin test over the host-compiled C half) +make lint # zig fmt --check build.zig, odin check -vet -strict-style + +# Compile to a component: zig build, then guestfn wraps zig-out/bin/fn.wasm. +make build # guestfn build (from this repository) → fn.wasm + +# What the runtime sees. +guestfn inspect fn.wasm # ABI v2, exports run, imports wasi:http@0.2.12 and log + +# Publish it as an OCI artifact; it prints the module block for the Composition. +guestfn push ghcr.io/example/hello-odin:v0.1.0 +``` + +Reference the module from a Composition step of function-wasm: + +```yaml +- step: hello-odin + functionRef: + name: function-wasm + input: + apiVersion: wasm.fn.crossplane.io/v1 + kind: Input + module: + type: OCI + oci: # printed by guestfn push + ref: ghcr.io/example/hello-odin:v0.1.0@sha256: + config: + greeting: hi +``` + +`example/` renders locally with the function-wasm runtime serving this +directory (`--module-dir`) under `example/policy.cedar` and the fixture +server `render.sh` starts; `make render-check` runs both xprin cases - the +configured greeting, and the greeting fetched through the host's egress under +`example/wasmfn.local.yaml`, a manifest that requires it: + +```shell +make render # crossplane render example/xr.yaml ... +make render-check # example/xprin.yaml (xprin on PATH, or XPRIN) +``` + +## What Odin needs on wasm + +- A foreign import whose name ends in `.o` (`foreign import bindings + "function.o"`) is, on a wasm target, a set of plain link-time symbols; a + bare name or `system:` makes them wasm imports of that module. Odin never + opens the file in an object build, so the name only labels where the + symbols come from (natively, for the tests, the same imports name the + objects `zig build test` compiles). A foreign variable (the nanopb message + descriptors) must sit in a library-less `foreign {}` block. +- `@(require, linkage = "strong")` on the export: nothing in Odin references + `exports_function_run`, and an `@(export)` would make it a wasm export of + its own beside the world's `run`. +- A `proc "c"` sets its own `context`; the default one's allocators are + replaced with the libc heap here. Struct returns by value follow clang's + wasm32 C ABI (a hidden pointer), so nanopb's `pb_istream_from_buffer` is + called as declared. +- Odin's runtime defines `memcpy`, `memset`, `memmove` and `bzero` strongly + on every wasm target; zig's libc ones are weak and lose, but its `bzero` + returns a value where libc's returns nothing, which `wasm-ld` words as a + signature-mismatch warning. `zig build-exe` turns the warning into a + failure, `zig cc` passes it through, which is why `build.zig` links with + `zig cc` and a cold build prints the warning once. +- A panic (a bounds check, a nil dereference) traps without a message: the + freestanding runtime has nowhere to write it. The host reports the trap as + the request's fatal result. +- No `_startup_runtime` runs: a global with a runtime initializer or an + `@(init)` procedure would stay uninitialised. This guest has none. diff --git a/examples/hello-odin/build.zig b/examples/hello-odin/build.zig new file mode 100644 index 00000000..bcc0e838 --- /dev/null +++ b/examples/hello-odin/build.zig @@ -0,0 +1,155 @@ +const std = @import("std"); + +// The Odin half of the guest: one package, compiled by odin to a wasm32 +// object the core module links. Every .odin file is an input of that step so +// the object is rebuilt when any of them changes. +const odin_sources = [_][]const u8{ "src/main.odin", "src/wasmfn.odin", "src/fnv1.odin", "src/structpb.odin" }; +// The C half: the wasi:http client of the c flavour's glue (src/wasmfn.c), +// the codec nanopb_generator wrote from proto/ (src/fnv1, the c flavour's +// byte for byte) and the bindings wit-bindgen c wrote from wit/ (src/gen, +// the c flavour's byte for byte): the run export shim, the log import, the +// wasi:http client interfaces and cabi_realloc. +const glue_sources = [_][]const u8{"src/wasmfn.c"}; +const codec_sources = [_][]const u8{ + "src/fnv1/run_function.pb.c", + "src/fnv1/google/protobuf/struct.pb.c", + "src/fnv1/google/protobuf/duration.pb.c", +}; +const binding_sources = [_][]const u8{"src/gen/function.c"}; +const nanopb_sources = [_][]const u8{ "pb_common.c", "pb_decode.c", "pb_encode.c" }; +// Every C file sees the same nanopb configuration as the c flavour: +// heap-allocated dynamic fields and 32-bit sizes - the layout src/fnv1.odin +// mirrors. The glue is held to -Werror; gnu11 for strdup. +const pb_flags = [_][]const u8{ "-DPB_ENABLE_MALLOC=1", "-DPB_FIELD_32BIT=1" }; +const glue_flags = pb_flags ++ [_][]const u8{ "-std=gnu11", "-Wall", "-Wextra", "-Werror" }; + +pub fn build(b: *std.Build) void { + const optimize = b.standardOptimizeOption(.{}); + const native = b.standardTargetOptions(.{}); + const nanopb = b.dependency("nanopb", .{}); + const includes = [_]std.Build.LazyPath{ b.path("src"), b.path("src/fnv1"), b.path("src/gen"), nanopb.path("") }; + + // odin build src: the Odin package as one freestanding wasm32 object. + // Freestanding, because the Odin runtime then imports nothing (no + // wasi_snapshot_preview1, so guestfn build links no adapter); the libc + // its allocations come from is the wasi-libc linked below. + // -no-entry-point: the world's run export is the entry. + const odin = b.addSystemCommand(&.{ "odin", "build", "src", "-target:freestanding_wasm32", "-build-mode:obj", "-no-entry-point", odinOptimize(optimize) }); + odin.setCwd(b.path("")); + for (odin_sources) |src| odin.addFileInput(b.path(src)); + const guest_object = odin.addPrefixedOutputFileArg("-out:", "guest.o"); + + // The C half, one object per file, through zig cc (clang). + var objects: std.ArrayList(std.Build.LazyPath) = .empty; + for (nanopb_sources) |src| objects.append(b.allocator, compileC(b, optimize, nanopb.path(src), &pb_flags, &includes)) catch @panic("OOM"); + for (codec_sources) |src| objects.append(b.allocator, compileC(b, optimize, b.path(src), &pb_flags, &includes)) catch @panic("OOM"); + for (glue_sources) |src| objects.append(b.allocator, compileC(b, optimize, b.path(src), &glue_flags, &includes)) catch @panic("OOM"); + for (binding_sources) |src| objects.append(b.allocator, compileC(b, optimize, b.path(src), &pb_flags, &includes)) catch @panic("OOM"); + + // The core module, zig-out/bin/fn.wasm: a wasip1 reactor whose exports + // are the canonical ABI's (run, cabi_post_run, cabi_realloc) and which + // carries the component-type custom section of the bindings' object file + // - the guest's world, encoded. guestfn build wraps it into the component + // the runtime loads; it imports nothing from wasi_snapshot_preview1 (the + // wasi-libc it links needs nothing from the host for malloc and strings), + // so no adapter is linked in. Linked by zig cc rather than zig's own + // build-exe step: Odin's runtime defines bzero (strongly, on every wasm + // target) with a return value where libc's has none, and wasm-ld words + // that as a signature-mismatch warning that build-exe turns into a + // failure; zig cc passes the warning through (Odin's definition wins over + // zig's weak one, nothing calls bzero). + const link = b.addSystemCommand(&.{ b.graph.zig_exe, "cc", "--target=wasm32-wasi", "-mexec-model=reactor", ccOptimize(optimize) }); + link.addFileArg(guest_object); + for (objects.items) |object| link.addFileArg(object); + link.addFileArg(b.path("src/gen/function_component_type.o")); + link.addArg("-o"); + const core = link.addOutputFileArg("fn.wasm"); + b.getInstallStep().dependOn(&b.addInstallBinFile(core, "fn.wasm").step); + + // zig build test: the unit tests, natively. The C half the tests need + // (nanopb and the codec; the bindings and the wasi:http client are + // wasi-only) is compiled for the host into objects under + // zig-out/lib/guestc, which src/fnv1.odin names for the Odin test build + // to link (objects rather than an archive: zig's archiver pads mach-o + // members in a way Apple's ld rejects), then odin test runs + // src/fn_test.odin, vetted like the wasm build. + const tests = b.addSystemCommand(&.{ "odin", "test", "src", "-vet", "-strict-style" }); + tests.setCwd(b.path("")); + _ = tests.addPrefixedOutputFileArg("-out:", "fn_test"); + tests.has_side_effects = true; + for (nanopb_sources) |src| tests.step.dependOn(nativeObject(b, native, optimize, nanopb.path(src), src, &includes)); + for (codec_sources) |src| tests.step.dependOn(nativeObject(b, native, optimize, b.path(src), src, &includes)); + b.step("test", "Run the unit tests natively").dependOn(&tests.step); + + // zig build lint: the Odin sources type-checked and vetted for the wasm + // target (the layout #asserts in src/fnv1.odin run here too). + const lint = b.step("lint", "Type-check and vet the Odin sources for the wasm target"); + const vet = b.addSystemCommand(&.{ "odin", "check", "src", "-target:freestanding_wasm32", "-no-entry-point", "-vet", "-strict-style" }); + vet.setCwd(b.path("")); + lint.dependOn(&vet.step); + + // Regenerate the fnv1 codec from the vendored proto: zig build gen-proto + // (needs nanopb_generator on PATH: pip install nanopb==0.4.9.1). + const gen = b.step("gen-proto", "generate the fnv1 codec from proto/ with nanopb_generator"); + const generator = b.addSystemCommand(&.{ + "nanopb_generator", + "-I", + "proto", + "-D", + "src/fnv1", + "proto/run_function.proto", + "proto/google/protobuf/struct.proto", + "proto/google/protobuf/duration.proto", + }); + generator.setCwd(b.path("")); + gen.dependOn(&generator.step); + + // Regenerate the world's bindings: zig build gen-bindings (needs + // wit-bindgen on PATH at the version the checked-in src/gen names in its + // header, wit-bindgen-cli 0.62.0). + const gen_bindings = b.step("gen-bindings", "generate src/gen from wit/ with wit-bindgen c"); + const bindgen = b.addSystemCommand(&.{ "wit-bindgen", "c", "wit", "--world", "function", "--out-dir", "src/gen" }); + bindgen.setCwd(b.path("")); + gen_bindings.dependOn(&bindgen.step); +} + +// compileC compiles one C file for wasm32-wasi into an object in the cache. +fn compileC(b: *std.Build, optimize: std.builtin.OptimizeMode, source: std.Build.LazyPath, flags: []const []const u8, includes: []const std.Build.LazyPath) std.Build.LazyPath { + const cc = b.addSystemCommand(&.{ b.graph.zig_exe, "cc", "--target=wasm32-wasi", ccOptimize(optimize), "-c" }); + cc.addArgs(flags); + for (includes) |dir| cc.addPrefixedDirectoryArg("-I", dir); + cc.addFileArg(source); + cc.addArg("-o"); + return cc.addOutputFileArg("out.o"); +} + +// nativeObject compiles one C file for the host and installs the object as +// zig-out/lib/guestc/.o, where src/fnv1.odin names it for the tests. +// Without UBSan: a Debug build of C under zig instruments it, and the Odin +// test build that links the objects carries no sanitizer runtime. +fn nativeObject(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, source: std.Build.LazyPath, path: []const u8, includes: []const std.Build.LazyPath) *std.Build.Step { + const mod = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true }); + for (includes) |dir| mod.addIncludePath(dir); + mod.addCSourceFile(.{ .file = source, .flags = &(pb_flags ++ [_][]const u8{"-fno-sanitize=undefined"}) }); + const stem = std.fs.path.stem(path); + const object = b.addObject(.{ .name = stem, .root_module = mod }); + return &b.addInstallFileWithDir(object.getEmittedBin(), .lib, b.fmt("guestc/{s}.o", .{stem})).step; +} + +// odinOptimize maps zig's optimize mode onto odin's -o flag. +fn odinOptimize(mode: std.builtin.OptimizeMode) []const u8 { + return switch (mode) { + .Debug => "-o:none", + .ReleaseSafe, .ReleaseFast => "-o:speed", + .ReleaseSmall => "-o:size", + }; +} + +// ccOptimize maps zig's optimize mode onto clang's -O flag. +fn ccOptimize(mode: std.builtin.OptimizeMode) []const u8 { + return switch (mode) { + .Debug => "-O0", + .ReleaseSafe, .ReleaseFast => "-O2", + .ReleaseSmall => "-Oz", + }; +} diff --git a/examples/hello-odin/build.zig.zon b/examples/hello-odin/build.zig.zon new file mode 100644 index 00000000..038c5b94 --- /dev/null +++ b/examples/hello-odin/build.zig.zon @@ -0,0 +1,22 @@ +.{ + .name = .hello_odin, + .version = "0.1.0", + .minimum_zig_version = "0.16.0", + .fingerprint = 0x8d5386f1d695af51, + .dependencies = .{ + // The protobuf codec: three C files, heap-allocating decode/encode + // (PB_ENABLE_MALLOC) over the structs nanopb_generator writes from the + // vendored proto (src/fnv1), which src/fnv1.odin mirrors. + .nanopb = .{ + .url = "https://github.com/nanopb/nanopb/archive/refs/tags/0.4.9.2.tar.gz", + .hash = "N-V-__8AAC4aKQDfYc_SoLQzYD5EUMZ2mN6f8qXQy--vmpFN", + }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + "proto", + "wit", + }, +} diff --git a/examples/hello-odin/example/composition-egress.yaml b/examples/hello-odin/example/composition-egress.yaml new file mode 100644 index 00000000..f7e6692f --- /dev/null +++ b/examples/hello-odin/example/composition-egress.yaml @@ -0,0 +1,28 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: hello-odin-egress +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XR + mode: Pipeline + pipeline: + - step: hello-odin + functionRef: + name: function-wasm + input: + apiVersion: wasm.fn.crossplane.io/v1 + kind: Input + module: + # The egress case: the same module under a manifest that requires GET + # on the fixture server (wasmfn.local.yaml), which the operator policy + # render.sh serves (policy.cedar) permits. The composition layer is + # default-permit for sandbox capabilities, so no compositionPolicy is + # needed; one could narrow the grant here. + type: Path + path: fn.wasm + manifestPath: example/wasmfn.local.yaml + config: + # The fixture server render.sh starts, serving example/fixtures/. + greetingUrl: http://127.0.0.1:9480/en diff --git a/examples/hello-odin/example/composition.yaml b/examples/hello-odin/example/composition.yaml new file mode 100644 index 00000000..c44d85b0 --- /dev/null +++ b/examples/hello-odin/example/composition.yaml @@ -0,0 +1,24 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: hello-odin +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XR + mode: Pipeline + pipeline: + - step: hello-odin + functionRef: + name: function-wasm + input: + apiVersion: wasm.fn.crossplane.io/v1 + kind: Input + module: + # For local rendering the runtime serves this directory (--module-dir). + # In a cluster use type: OCI and an oci reference pinned to the digest + # guestfn push prints. + type: Path + path: fn.wasm + config: + greeting: hi diff --git a/examples/hello-odin/example/fixtures/en b/examples/hello-odin/example/fixtures/en new file mode 100644 index 00000000..0ff4fb4d --- /dev/null +++ b/examples/hello-odin/example/fixtures/en @@ -0,0 +1 @@ +howdy diff --git a/examples/hello-odin/example/functions.yaml b/examples/hello-odin/example/functions.yaml new file mode 100644 index 00000000..6522095d --- /dev/null +++ b/examples/hello-odin/example/functions.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: pkg.crossplane.io/v1 +kind: Function +metadata: + name: function-wasm + annotations: + # Development runtime: run the function-wasm runtime locally, serving this + # directory, e.g. from a checkout of function-wasm: + # cargo run -p function-wasm -- --insecure --debug --module-dir= + render.crossplane.io/runtime: Development +spec: + package: ghcr.io/jonasz-lasut/function-wasm:v0.1.0 diff --git a/examples/hello-odin/example/policy.cedar b/examples/hello-odin/example/policy.cedar new file mode 100644 index 00000000..d62e63d9 --- /dev/null +++ b/examples/hello-odin/example/policy.cedar @@ -0,0 +1,9 @@ +// The operator grant policy of the local render (--sandbox-policy-file): the +// module may GET its greeting from the fixture server render.sh starts, and +// the runtime may dial loopback to reach it, which its egress block list +// refuses by default. In a cluster the operator grants the real host instead. +permit (principal, action == Action::"grantEgress", resource == HostPattern::"127.0.0.1") +when { context.method == "GET" }; + +permit (principal, action == Action::"dialAddress", resource) +when { context.ip.isLoopback() }; diff --git a/examples/hello-odin/example/wasmfn.local.yaml b/examples/hello-odin/example/wasmfn.local.yaml new file mode 100644 index 00000000..71e4200f --- /dev/null +++ b/examples/hello-odin/example/wasmfn.local.yaml @@ -0,0 +1,19 @@ +# The manifest the egress render case runs this module under +# (module.manifestPath in composition-egress.yaml): the published wasmfn.yaml +# plus an egress requirement for the fixture server render.sh starts on +# 127.0.0.1:9480, so the greeting is fetched through the host's egress. +abi: 2 +name: hello-odin +version: 0.1.0 +requires: + egress: + http: + - host: 127.0.0.1 + methods: [GET] +config: + schema: + type: object + properties: + greeting: {type: string} + greetingUrl: {type: string, format: uri} + additionalProperties: false diff --git a/examples/hello-odin/example/xprin.yaml b/examples/hello-odin/example/xprin.yaml new file mode 100644 index 00000000..eef805ee --- /dev/null +++ b/examples/hello-odin/example/xprin.yaml @@ -0,0 +1,37 @@ +# The example's render test (https://github.com/crossplane-contrib/xprin), +# run by `make render-check` against the runtime serving this directory with +# example/policy.cedar as the operator policy and example/fixtures/ on the +# fixture server. +tests: +- name: greeting + inputs: + xr: xr.yaml + composition: composition.yaml + functions: functions.yaml + assertions: + xprin: + - name: the module composes the greeting ConfigMap + type: Count + value: 2 + - name: the ConfigMap carries the configured greeting + type: FieldValue + resource: ConfigMap + field: data.greeting + operator: is + value: hi example-xr +- name: greeting fetched through the host's egress + inputs: + xr: xr.yaml + composition: composition-egress.yaml + functions: functions.yaml + assertions: + xprin: + - name: the module composes the greeting ConfigMap + type: Count + value: 2 + - name: the ConfigMap carries the greeting the fixture server answered + type: FieldValue + resource: ConfigMap + field: data.greeting + operator: is + value: howdy example-xr diff --git a/examples/hello-odin/example/xr.yaml b/examples/hello-odin/example/xr.yaml new file mode 100644 index 00000000..0dfd1e81 --- /dev/null +++ b/examples/hello-odin/example/xr.yaml @@ -0,0 +1,5 @@ +apiVersion: example.crossplane.io/v1 +kind: XR +metadata: + name: example-xr +spec: {} diff --git a/examples/hello-odin/proto/google/protobuf/duration.options b/examples/hello-odin/proto/google/protobuf/duration.options new file mode 100644 index 00000000..070e7dc0 --- /dev/null +++ b/examples/hello-odin/proto/google/protobuf/duration.options @@ -0,0 +1,3 @@ +# nanopb options, as for run_function.proto: dynamic-length fields on the heap, +# which also breaks the Value/Struct/ListValue recursion with pointers. +* fallback_type:FT_POINTER diff --git a/examples/hello-odin/proto/google/protobuf/duration.proto b/examples/hello-odin/proto/google/protobuf/duration.proto new file mode 100644 index 00000000..41f40c22 --- /dev/null +++ b/examples/hello-odin/proto/google/protobuf/duration.proto @@ -0,0 +1,115 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/durationpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DurationProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// # Examples +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (duration.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// Example 3: Compute Duration from datetime.timedelta in Python. +// +// td = datetime.timedelta(days=3, minutes=10) +// duration = Duration() +// duration.FromTimedelta(td) +// +// # JSON Mapping +// +// In JSON format, the Duration type is encoded as a string rather than an +// object, where the string ends in the suffix "s" (indicating seconds) and +// is preceded by the number of seconds, with nanoseconds expressed as +// fractional seconds. For example, 3 seconds with 0 nanoseconds should be +// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should +// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 +// microsecond should be expressed in JSON format as "3.000001s". +// +message Duration { + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. Note: these bounds are computed from: + // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/examples/hello-odin/proto/google/protobuf/struct.options b/examples/hello-odin/proto/google/protobuf/struct.options new file mode 100644 index 00000000..070e7dc0 --- /dev/null +++ b/examples/hello-odin/proto/google/protobuf/struct.options @@ -0,0 +1,3 @@ +# nanopb options, as for run_function.proto: dynamic-length fields on the heap, +# which also breaks the Value/Struct/ListValue recursion with pointers. +* fallback_type:FT_POINTER diff --git a/examples/hello-odin/proto/google/protobuf/struct.proto b/examples/hello-odin/proto/google/protobuf/struct.proto new file mode 100644 index 00000000..a03667da --- /dev/null +++ b/examples/hello-odin/proto/google/protobuf/struct.proto @@ -0,0 +1,111 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/structpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "StructProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; + +// Represents a JSON object. +// +// An unordered key-value map, intending to perfectly capture the semantics of a +// JSON object. This enables parsing any arbitrary JSON payload as a message +// field in ProtoJSON format. +// +// This follows RFC 8259 guidelines for interoperable JSON: notably this type +// cannot represent large Int64 values or `NaN`/`Infinity` numbers, +// since the JSON format generally does not support those values in its number +// type. +// +// If you do not intend to parse arbitrary JSON into your message, a custom +// typed message should be preferred instead of using this type. +message Struct { + // Unordered map of dynamically typed values. + map fields = 1; +} + +// Represents a JSON value. +// +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of these +// variants. Absence of any variant is an invalid state. +message Value { + // The kind of value. + oneof kind { + // Represents a JSON `null`. + NullValue null_value = 1; + + // Represents a JSON number. Must not be `NaN`, `Infinity` or + // `-Infinity`, since those are not supported in JSON. This also cannot + // represent large Int64 values, since JSON format generally does not + // support them in its number type. + double number_value = 2; + + // Represents a JSON string. + string string_value = 3; + + // Represents a JSON boolean (`true` or `false` literal in JSON). + bool bool_value = 4; + + // Represents a JSON object. + Struct struct_value = 5; + + // Represents a JSON array. + ListValue list_value = 6; + } +} + +// Represents a JSON `null`. +// +// `NullValue` is a sentinel, using an enum with only one value to represent +// the null value for the `Value` type union. +// +// A field of type `NullValue` with any value other than `0` is considered +// invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set +// as a JSON `null` regardless of the integer value, and so will round trip to +// a `0` value. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// Represents a JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/examples/hello-odin/proto/run_function.options b/examples/hello-odin/proto/run_function.options new file mode 100644 index 00000000..f9d72fa5 --- /dev/null +++ b/examples/hello-odin/proto/run_function.options @@ -0,0 +1,8 @@ +# nanopb options for run_function.proto (docs: nanopb "Generator options"). +# Strings, bytes, repeated fields and maps have no fixed bound in this +# contract, so they are heap allocated (fallback_type with PB_ENABLE_MALLOC); +# scalars and singular submessages stay inline in the generated structs. +* fallback_type:FT_POINTER +# Name the C types fnv1_RunFunctionRequest rather than +# apiextensions_fn_proto_v1_RunFunctionRequest. +*run_function.proto package:"fnv1" diff --git a/examples/hello-odin/proto/run_function.proto b/examples/hello-odin/proto/run_function.proto new file mode 100644 index 00000000..e23e990f --- /dev/null +++ b/examples/hello-odin/proto/run_function.proto @@ -0,0 +1,441 @@ +// Vendored from crossplane/crossplane v2.4.2. Apache-2.0. Renovate tracks that +// version; on a bump re-download +// https://github.com/crossplane/crossplane/blob/main/proto/fn/v1/run_function.proto +// into every copy, then regenerate the C codec with `zig build gen-proto` (needs nanopb_generator). + +/* + Copyright 2022 The Crossplane Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +syntax = "proto3"; + +// This package defines the RPC for both composition and operation functions. +// Only composition functions are part of the 'apiextensions' API group. In +// retrospect this package should've been crossplane.proto.fn.v1, but it's too +// late to change it now. + +//buf:lint:ignore PACKAGE_DIRECTORY_MATCH +package apiextensions.fn.proto.v1; + +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; + +option go_package = "github.com/crossplane/crossplane/v2/proto/fn/v1"; + +// A FunctionRunnerService is a function. +service FunctionRunnerService { + // RunFunction runs the function. + rpc RunFunction(RunFunctionRequest) returns (RunFunctionResponse) {} +} + +// A RunFunctionRequest requests that the function be run. +message RunFunctionRequest { + // Metadata pertaining to this request. + RequestMeta meta = 1; + + // The observed state prior to invocation of a function pipeline. State passed + // to each function is fresh as of the time the pipeline was invoked, not as + // of the time each function was invoked. + State observed = 2; + + // Desired state according to a function pipeline. The state passed to a + // particular function may have been accumulated by previous functions in the + // pipeline. + // + // Note that the desired state must be a partial object with only the fields + // that this function (and its predecessors in the pipeline) wants to have set + // in the object. Copying a non-partial observed state to desired is most + // likely not what you want to do. Leaving out fields that had been returned + // as desired before will result in them being deleted from the objects in the + // cluster. + State desired = 3; + + // Optional input specific to this function invocation. A JSON representation + // of the 'input' block of the relevant entry in a function pipeline. + optional google.protobuf.Struct input = 4; + + // Optional context. Crossplane may pass arbitrary contextual information to a + // function. A function may also return context in its RunFunctionResponse, + // and that context will be passed to subsequent functions. Crossplane + // discards all context returned by the last function in the pipeline. + optional google.protobuf.Struct context = 5; + + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.extra_resources field. If a + // function requested extra resources that did not exist, Crossplane sets + // the map key to an empty Resources message to indicate that it attempted to + // satisfy the request. This field is only populated when the function uses + // extra_resources in its requirements. + // + // Deprecated: Use required_resources instead. + map extra_resources = 6 [deprecated = true]; + + // Optional credentials that this function may use to communicate with an + // external system. + map credentials = 7; + + // Optional resources that the function specified in its requirements. Note + // that resources is a map to Resources, plural. The map key corresponds to + // the key in a RunFunctionResponse's requirements.resources field. If a + // function requested required resources that did not exist, Crossplane sets + // the map key to an empty Resources message to indicate that it attempted to + // satisfy the request. This field is only populated when the function uses + // resources in its requirements. + map required_resources = 8; + + // Optional schemas that the function specified in its requirements. The map + // key corresponds to the key in a RunFunctionResponse's requirements.schemas + // field. If a function requested a schema that could not be found, Crossplane + // sets the map key to an empty Schema message to indicate that it attempted + // to satisfy the request. + map required_schemas = 9; +} + +// Credentials that a function may use to communicate with an external system. +message Credentials { + // Source of the credentials. + oneof source { + // Credential data loaded by Crossplane, for example from a Secret. + CredentialData credential_data = 1; + } +} + +// CredentialData loaded by Crossplane, for example from a Secret. +message CredentialData { + map data = 1; +} + +// Resources represents the state of several Crossplane resources. +message Resources { + repeated Resource items = 1; +} + +// A RunFunctionResponse contains the result of a function run. +message RunFunctionResponse { + // Metadata pertaining to this response. + ResponseMeta meta = 1; + + // Desired state according to a function pipeline. functions may add desired + // state, and may mutate or delete any part of the desired state they are + // concerned with. A function must pass through any part of the desired state + // that it is not concerned with. + // + // Note that the desired state must be a partial object with only the fields + // that this function (and its predecessors in the pipeline) wants to have set + // in the object. Copying a non-partial observed state to desired is most + // likely not what you want to do. Leaving out fields that had been returned + // as desired before will result in them being deleted from the objects in the + // cluster. + State desired = 2; + + // Results of the function run. Results are used for observability purposes. + repeated Result results = 3; + + // Optional context to be passed to the next function in the pipeline as part + // of the RunFunctionRequest. Dropped on the last function in the pipeline. + optional google.protobuf.Struct context = 4; + + // Requirements that must be satisfied for this function to run successfully. + Requirements requirements = 5; + + // Status conditions to be applied to the XR. Conditions may also optionally + // be applied to the XR's associated claim. + // + // Conditions are only used for composition. They're ignored by Operations. + repeated Condition conditions = 6; + + // Optional output specific to this function invocation. + // + // Only Operations use function output. XRs will discard any function output. + optional google.protobuf.Struct output = 7; +} + +// RequestMeta contains metadata pertaining to a RunFunctionRequest. +message RequestMeta { + // An opaque string identifying a request. Requests with identical tags will + // be otherwise identical. + string tag = 1; + + // Capabilities supported by this version of Crossplane. Functions may use + // this to determine whether Crossplane will honor certain fields in their + // response, or populate certain fields in their request. + repeated Capability capabilities = 2; +} + +// Capability indicates that Crossplane supports a particular feature. +// Functions can check for capabilities to determine whether Crossplane will +// honor a particular request or response field. +enum Capability { + CAPABILITY_UNSPECIFIED = 0; + + // Crossplane sends capabilities in RequestMeta. If this capability is + // present, the function knows that if another capability is absent, it's + // because Crossplane doesn't support it (not because Crossplane predates + // capability advertisement). Added in Crossplane v2.2. + CAPABILITY_CAPABILITIES = 1; + + // Crossplane supports the requirements.resources field. Functions can return + // resource requirements and Crossplane will fetch the requested resources and + // return them in required_resources. Added in Crossplane v1.15. + CAPABILITY_REQUIRED_RESOURCES = 2; + + // Crossplane supports the credentials field. Functions can receive + // credentials from secrets specified in the Composition. Added in Crossplane + // v1.16. + CAPABILITY_CREDENTIALS = 3; + + // Crossplane supports the conditions field. Functions can return status + // conditions to be applied to the XR and optionally its claim. Added in + // Crossplane v1.17. + CAPABILITY_CONDITIONS = 4; + + // Crossplane supports the requirements.schemas field. Functions can request + // OpenAPI schemas and Crossplane will return them in required_schemas. Added + // in Crossplane v2.2. + CAPABILITY_REQUIRED_SCHEMAS = 5; +} + +// Requirements that must be satisfied for a function to run successfully. +message Requirements { + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + // + // Deprecated: Use resources instead. + map extra_resources = 1 [deprecated = true]; + + // Resources that this function requires. The map key uniquely identifies the + // group of resources. + map resources = 2; + + // Schemas that this function requires. The map key uniquely identifies the + // schema request. + map schemas = 3; +} + +// SchemaSelector identifies a resource kind whose OpenAPI schema is requested. +message SchemaSelector { + // API version of the resource kind, e.g. "example.org/v1". + string api_version = 1; + + // Kind of resource, e.g. "MyResource". + string kind = 2; +} + +// Schema represents the OpenAPI schema for a resource kind. +message Schema { + // The OpenAPI v3 schema of the resource kind as unstructured JSON. + // For CRDs this is the spec.versions[].schema.openAPIV3Schema field. + // Empty if Crossplane could not find a schema for the requested kind. + optional google.protobuf.Struct openapi_v3 = 1; +} + +// ResourceSelector selects a group of resources, either by name or by label. +message ResourceSelector { + // API version of resources to select. + string api_version = 1; + + // Kind of resources to select. + string kind = 2; + + // Resources to match. + oneof match { + // Match the resource with this name. + string match_name = 3; + + // Match all resources with these labels. + MatchLabels match_labels = 4; + } + + // Match resources in this namespace. Omit namespace to match cluster scoped + // resources, or to match namespaced resources by labels across all + // namespaces. + optional string namespace = 5; +} + +// MatchLabels defines a set of labels to match resources against. +message MatchLabels { + map labels = 1; +} + +// ResponseMeta contains metadata pertaining to a RunFunctionResponse. +message ResponseMeta { + // An opaque string identifying the content of the request. Must match the + // meta.tag of the corresponding RunFunctionRequest. + string tag = 1; + + // Time-to-live of this response. Crossplane will call the function again when + // the TTL expires. Crossplane may cache the response to avoid calling the + // function again until the TTL expires. + optional google.protobuf.Duration ttl = 2; +} + +// State of the XR (XR) and any resources. +message State { + // The state of the XR (XR). + Resource composite = 1; + + // The state of any other resources. In composition functions these are the + // composed resources. In operation functions they're arbitrary resources that + // the operation wants to create or update. + map resources = 2; +} + +// A Resource represents the state of a Kubernetes resource. +message Resource { + // The JSON representation of the resource. + // + // * Crossplane will set this field in a RunFunctionRequest to the entire + // observed state of a resource - including its metadata, spec, and status. + // + // * A function should set this field in a RunFunctionRequest to communicate + // the desired state of the resource. + // + // * A function may only specify the desired status of a XR - not its metadata + // or spec. A function should not return desired metadata or spec for a XR. + // This will be ignored. + // + // * A function may not specify the desired status of any other resource - + // e.g. composed resources. It may only specify their metadata and spec. + // Status will be ignored. + google.protobuf.Struct resource = 1; + + // The resource's connection details. + // + // * Crossplane will set this field in a RunFunctionRequest to communicate the + // the observed connection details of a composite or composed resource. + // + // * A function should set this field in a RunFunctionResponse to indicate the + // desired connection details of legacy XRs. For modern XRs, this will be ignored. + // + // * A function should not set this field in a RunFunctionResponse to indicate + // the desired connection details of a composed resource. This will be + // ignored. + // + // Connection details are only used for composition. They're ignored by + // Operations. + map connection_details = 2; + + // Ready indicates whether the resource should be considered ready. + // + // * Crossplane will never set this field in a RunFunctionRequest. + // + // * A function should set this field to READY_TRUE in a RunFunctionResponse + // to indicate that a desired resource is ready. + // + // * A function should set this field to READY_TRUE in a RunFunctionResponse + // to indicate that a desired XR is ready. This overwrites the standard + // readiness detection that determines the ready state of the composite by the + // ready state of the composed resources. + // + // Ready is only used for composition. It's ignored by Operations. + Ready ready = 3; +} + +// Ready indicates whether a resource should be considered ready. +enum Ready { + READY_UNSPECIFIED = 0; + + // True means the resource has been observed to be ready. + READY_TRUE = 1; + + // False means the resource has not been observed to be ready. + READY_FALSE = 2; +} + +// A Result of running a function. +message Result { + // Severity of this result. + Severity severity = 1; + + // Human-readable details about the result. + string message = 2; + + // Optional PascalCase, machine-readable reason for this result. If omitted, + // the value will be ComposeResources. + optional string reason = 3; + + // The resources this result targets. + optional Target target = 4; +} + +// Severity of function results. +enum Severity { + SEVERITY_UNSPECIFIED = 0; + + // Fatal results are fatal; subsequent functions may run, but the function + // pipeline run will be considered a failure and the first fatal result will + // be returned as an error. + SEVERITY_FATAL = 1; + + // Warning results are non-fatal; the entire pipeline will run to completion + // but warning events and debug logs associated with the XR or Operation will + // be emitted. + SEVERITY_WARNING = 2; + + // Normal results are emitted as normal events and debug logs associated with + // the XR or operation. + SEVERITY_NORMAL = 3; +} + +// Target of function results and conditions. +enum Target { + // If the target is unspecified, the result targets the XR. + TARGET_UNSPECIFIED = 0; + + // Target the XR. Results that target the XR should include detailed, advanced + // information. + TARGET_COMPOSITE = 1; + + // Target the XR and the claim. Results that target the XR and the claim + // should include only end-user friendly information. + TARGET_COMPOSITE_AND_CLAIM = 2; +} + +// Status condition to be applied to the XR. Condition may also optionally be +// applied to the XR's associated claim. For detailed information on proper +// usage of status conditions, please see +// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties. +message Condition { + // Type of condition in PascalCase. + string type = 1; + + // Status of the condition. + Status status = 2; + + // Reason contains a programmatic identifier indicating the reason for the + // condition's last transition. Producers of specific condition types may + // define expected values and meanings for this field, and whether the values + // are considered a guaranteed API. The value should be a PascalCase string. + // This field may not be empty. + string reason = 3; + + // Message is a human readable message indicating details about the + // transition. This may be an empty string. + optional string message = 4; + + // The resources this condition targets. + optional Target target = 5; +} + +enum Status { + STATUS_CONDITION_UNSPECIFIED = 0; + + STATUS_CONDITION_UNKNOWN = 1; + + STATUS_CONDITION_TRUE = 2; + + STATUS_CONDITION_FALSE = 3; +} diff --git a/examples/hello-odin/src/fn_test.odin b/examples/hello-odin/src/fn_test.odin new file mode 100644 index 00000000..25563e6d --- /dev/null +++ b/examples/hello-odin/src/fn_test.odin @@ -0,0 +1,151 @@ +// Unit tests of the guest, run natively by odin test (zig build test) over +// the C half built as a static library: the function over the mirrored +// structs with a fake host for HTTP, and one trip through nanopb's decode, +// run and encode, which holds the native layout to the codec's the way the +// #asserts in fnv1.odin hold the wasm32 one. +#+build !freestanding +package guest + +import "core:c" +import "core:mem/virtual" +import "core:testing" + +// The guest allocates and never frees (a fresh wasm instance per request +// drops it); each test runs it in an arena of its own. + +@(test) +default_greeting :: proc(t: ^testing.T) { + arena: virtual.Arena + defer virtual.arena_destroy(&arena) + context.allocator = virtual.arena_allocator(&arena) + + req := request("my-xr", nil) + rsp: Run_Function_Response + testing.expect_value(t, run_function(&req, &rsp), "") + testing.expect_value(t, greeting_of(&rsp), "hello my-xr") + testing.expect_value(t, string(rsp.results[0].message), "greeted my-xr") + testing.expect_value(t, string(rsp.conditions[0].type), "FunctionSuccess") +} + +@(test) +configured_greeting_keeps_desired :: proc(t: ^testing.T) { + arena: virtual.Arena + defer virtual.arena_destroy(&arena) + context.allocator = virtual.arena_allocator(&arena) + + config: Struct + struct_set(&config, "greeting", string_value("hi")) + req := request("my-xr", &config) + req.has_desired = true + state_add_resource(&req.desired, "other", Struct{}) + rsp: Run_Function_Response + testing.expect_value(t, run_function(&req, &rsp), "") + testing.expect_value(t, greeting_of(&rsp), "hi my-xr") + testing.expect_value(t, rsp.desired.resources_count, 2) +} + +@(test) +bad_config_is_a_fatal :: proc(t: ^testing.T) { + arena: virtual.Arena + defer virtual.arena_destroy(&arena) + context.allocator = virtual.arena_allocator(&arena) + + config: Struct + struct_set(&config, "greeting", number_value(7)) + req := request("my-xr", &config) + rsp: Run_Function_Response + testing.expect_value(t, run_function(&req, &rsp), "cannot read config: greeting must be a string") +} + +@(test) +greeting_from_url_through_the_host :: proc(t: ^testing.T) { + arena: virtual.Arena + defer virtual.arena_destroy(&arena) + context.allocator = virtual.arena_allocator(&arena) + + test_host = proc(url: string) -> (text: string, err: string) { + if url == "https://greetings.example.com/en" { + return "howdy", "" + } + return "", "sandbox.egress: no rule admits host \"evil.example.com\"" + } + defer test_host = nil + + ok_config: Struct + struct_set(&ok_config, "greetingUrl", string_value("https://greetings.example.com/en")) + ok_req := request("my-xr", &ok_config) + ok_rsp: Run_Function_Response + testing.expect_value(t, run_function(&ok_req, &ok_rsp), "") + testing.expect_value(t, greeting_of(&ok_rsp), "howdy my-xr") + + bad_config: Struct + struct_set(&bad_config, "greetingUrl", string_value("https://evil.example.com/en")) + bad_req := request("my-xr", &bad_config) + bad_rsp: Run_Function_Response + testing.expect_value( + t, + run_function(&bad_req, &bad_rsp), + "cannot fetch greeting: sandbox.egress: no rule admits host \"evil.example.com\"", + ) +} + +// The whole guest half on the wire: a request encoded by the codec, handled +// (decode, run, encode), its response decoded again - what the host does to +// the module, over the native layout of the mirrored structs. +@(test) +request_through_the_codec :: proc(t: ^testing.T) { + arena: virtual.Arena + defer virtual.arena_destroy(&arena) + context.allocator = virtual.arena_allocator(&arena) + + config: Struct + struct_set(&config, "greeting", string_value("hey")) + req := request("my-xr", &config) + size: c.size_t + testing.expect(t, pb_get_encoded_size(&size, &Run_Function_Request_msg, &req)) + wire := make([]u8, size) + os := pb_ostream_from_buffer(raw_data(wire), size) + testing.expect(t, pb_encode(&os, &Run_Function_Request_msg, &req)) + + out, ok := handle(wire[:os.bytes_written]) + testing.expect(t, ok) + + rsp: Run_Function_Response + is := pb_istream_from_buffer(raw_data(out), c.size_t(len(out))) + testing.expect(t, pb_decode(&is, &Run_Function_Response_msg, &rsp)) + testing.expect_value(t, string(rsp.meta.tag), "hello") + testing.expect_value(t, rsp.meta.ttl.seconds, 60) + testing.expect_value(t, greeting_of(&rsp), "hey my-xr") + testing.expect_value(t, rsp.results[0].severity, Severity.NORMAL) +} + +// request is a RunFunctionRequest tagged "hello", observing a composite +// named name, with config as the Input's config block when given. +request :: proc(name: string, config: ^Struct) -> Run_Function_Request { + req: Run_Function_Request + req.has_meta = true + req.meta.tag = "hello" + metadata: Struct + struct_set(&metadata, "name", string_value(name)) + resource: Struct + struct_set(&resource, "apiVersion", string_value("example.org/v1")) + struct_set(&resource, "kind", string_value("XR")) + struct_set(&resource, "metadata", struct_value(metadata)) + req.has_observed = true + req.observed.has_composite = true + req.observed.composite.has_resource = true + req.observed.composite.resource = resource + if config != nil { + req.has_input = true + struct_set(&req.input, "config", struct_value(config^)) + } + return req +} + +// greeting_of is data.greeting of the last desired resource. +greeting_of :: proc(rsp: ^Run_Function_Response) -> string { + n := rsp.desired.resources_count + cm := &rsp.desired.resources[n - 1].value.resource + s, _ := value_string(struct_lookup(cm, "data", "greeting")) + return s +} diff --git a/examples/hello-odin/src/fnv1.odin b/examples/hello-odin/src/fnv1.odin new file mode 100644 index 00000000..e42483fd --- /dev/null +++ b/examples/hello-odin/src/fnv1.odin @@ -0,0 +1,280 @@ +// The codec: nanopb through the FFI. The structs nanopb_generator wrote into +// src/fnv1 (run_function.pb.h, struct.pb.h, duration.pb.h, the c flavour's +// byte for byte, with its options: every dynamic field a heap pointer plus a +// 32-bit count, singular submessages inline behind a has_ flag) are declared +// again here with the same layout, so pb_decode fills them and pb_encode +// reads them through the C descriptors. Odin lays a struct out as C does +// (declaration order, natural alignment), and the #asserts at the end hold +// every size and offset the guest relies on to what zig cc computes for +// wasm32: a drift fails the build, never the run. +package guest + +import "core:c" + +pb_size_t :: u32 + +// ─── google.protobuf ──────────────────────────────────────────────────────── + +Null_Value :: c.int + +Struct :: struct { + fields_count: pb_size_t, + fields: [^]Struct_Fields_Entry, +} + +List_Value :: struct { + values_count: pb_size_t, + values: [^]Value, +} + +Value :: struct { + which_kind: pb_size_t, + kind: struct #raw_union { + null_value: Null_Value, + number_value: f64, + string_value: cstring, + bool_value: bool, + struct_value: Struct, + list_value: List_Value, + }, +} + +Struct_Fields_Entry :: struct { + key: cstring, + has_value: bool, + value: Value, +} + +// The oneof tags of Value.kind (google_protobuf_Value_*_tag). +VALUE_NULL_TAG :: 1 +VALUE_NUMBER_TAG :: 2 +VALUE_STRING_TAG :: 3 +VALUE_BOOL_TAG :: 4 +VALUE_STRUCT_TAG :: 5 +VALUE_LIST_TAG :: 6 + +Duration :: struct { + seconds: i64, + nanos: i32, +} + +// ─── apiextensions.fn.proto.v1 ────────────────────────────────────────────── + +Capability :: c.int + +Ready :: enum c.int { + UNSPECIFIED = 0, + TRUE = 1, + FALSE = 2, +} + +Severity :: enum c.int { + UNSPECIFIED = 0, + FATAL = 1, + WARNING = 2, + NORMAL = 3, +} + +Target :: enum c.int { + UNSPECIFIED = 0, + COMPOSITE = 1, + COMPOSITE_AND_CLAIM = 2, +} + +Status :: enum c.int { + UNSPECIFIED = 0, + UNKNOWN = 1, + TRUE = 2, + FALSE = 3, +} + +Request_Meta :: struct { + tag: cstring, + capabilities_count: pb_size_t, + capabilities: [^]Capability, +} + +Resource :: struct { + has_resource: bool, + resource: Struct, + connection_details_count: pb_size_t, + connection_details: rawptr, // [^]Resource_Connection_Details_Entry, unused here + ready: Ready, +} + +State :: struct { + has_composite: bool, + composite: Resource, + resources_count: pb_size_t, + resources: [^]State_Resources_Entry, +} + +State_Resources_Entry :: struct { + key: cstring, + has_value: bool, + value: Resource, +} + +Run_Function_Request :: struct { + has_meta: bool, + meta: Request_Meta, + has_observed: bool, + observed: State, + has_desired: bool, + desired: State, + has_input: bool, + input: Struct, + has_context: bool, + ctx: Struct, // context in the proto; a keyword here + extra_resources_count: pb_size_t, + extra_resources: rawptr, + credentials_count: pb_size_t, + credentials: rawptr, + required_resources_count: pb_size_t, + required_resources: rawptr, + required_schemas_count: pb_size_t, + required_schemas: rawptr, +} + +Response_Meta :: struct { + tag: cstring, + has_ttl: bool, + ttl: Duration, +} + +Requirements :: struct { + extra_resources_count: pb_size_t, + extra_resources: rawptr, + resources_count: pb_size_t, + resources: rawptr, + schemas_count: pb_size_t, + schemas: rawptr, +} + +Result :: struct { + severity: Severity, + message: cstring, + reason: cstring, + has_target: bool, + target: Target, +} + +Condition :: struct { + type: cstring, + status: Status, + reason: cstring, + message: cstring, + has_target: bool, + target: Target, +} + +Run_Function_Response :: struct { + has_meta: bool, + meta: Response_Meta, + has_desired: bool, + desired: State, + results_count: pb_size_t, + results: [^]Result, + has_context: bool, + ctx: Struct, + has_requirements: bool, + requirements: Requirements, + conditions_count: pb_size_t, + conditions: [^]Condition, + has_output: bool, + output: Struct, +} + +// ─── nanopb ───────────────────────────────────────────────────────────────── + +// pb_istream_t and pb_ostream_t (pb_decode.h, pb_encode.h) with errmsg on +// (PB_NO_ERRMSG unset), filled by pb_istream_from_buffer and +// pb_ostream_from_buffer: a struct returned by value, which Odin lowers on +// wasm32 the way clang does (through a hidden pointer), so the C API is called +// as declared. +Istream :: struct { + callback: rawptr, + state: rawptr, + bytes_left: c.size_t, + errmsg: cstring, +} + +Ostream :: struct { + callback: rawptr, + state: rawptr, + max_size: c.size_t, + bytes_written: c.size_t, + errmsg: cstring, +} + +// pb_msgdesc_t, opaque: only ever named by address. +Msg_Desc :: struct { + opaque: u32, +} + +when ODIN_ARCH == .wasm32 { + // A foreign import whose name ends in .o is, on a wasm target, a set of + // plain link-time symbols (no wasm import module), and Odin never opens + // the file: these are the symbols zig links from nanopb and the + // generated codec. + foreign import nanopb "nanopb.o" +} else { + // Natively (the unit tests): the same C half as the objects build.zig + // compiles for zig build test, named relative to this file. + foreign import nanopb { + "../zig-out/lib/guestc/pb_common.o", + "../zig-out/lib/guestc/pb_decode.o", + "../zig-out/lib/guestc/pb_encode.o", + "../zig-out/lib/guestc/run_function.pb.o", + "../zig-out/lib/guestc/struct.pb.o", + "../zig-out/lib/guestc/duration.pb.o", + } +} + +@(default_calling_convention = "c") +foreign nanopb { + pb_istream_from_buffer :: proc(buf: [^]u8, msglen: c.size_t) -> Istream --- + pb_decode :: proc(stream: ^Istream, fields: ^Msg_Desc, dest_struct: rawptr) -> bool --- + pb_ostream_from_buffer :: proc(buf: [^]u8, bufsize: c.size_t) -> Ostream --- + pb_encode :: proc(stream: ^Ostream, fields: ^Msg_Desc, src_struct: rawptr) -> bool --- + pb_get_encoded_size :: proc(size: ^c.size_t, fields: ^Msg_Desc, src_struct: rawptr) -> bool --- +} + +// The message descriptors (src/fnv1/run_function.pb.c). A foreign variable +// on a wasm target must come from a library-less foreign block: it is then a +// plain external symbol, like the procedures above. +foreign { + @(link_name = "fnv1_RunFunctionRequest_msg") + Run_Function_Request_msg: Msg_Desc + @(link_name = "fnv1_RunFunctionResponse_msg") + Run_Function_Response_msg: Msg_Desc +} + +// ─── the layout, held to the C compiler's ─────────────────────────────────── + +// The wasm32 sizes and offsets (what zig cc computes for the C structs with +// this nanopb configuration); the native layout is held by the codec round +// trip in fn_test.odin. +when ODIN_ARCH == .wasm32 { +#assert(size_of(Struct) == 8) +#assert(size_of(List_Value) == 8) +#assert(size_of(Value) == 16 && offset_of(Value, kind) == 8) +#assert(size_of(Struct_Fields_Entry) == 24 && offset_of(Struct_Fields_Entry, value) == 8) +#assert(size_of(Duration) == 16) +#assert(size_of(Request_Meta) == 12) +#assert(size_of(Resource) == 24 && offset_of(Resource, resource) == 4 && offset_of(Resource, connection_details_count) == 12 && offset_of(Resource, ready) == 20) +#assert(size_of(State) == 36 && offset_of(State, composite) == 4 && offset_of(State, resources_count) == 28 && offset_of(State, resources) == 32) +#assert(size_of(State_Resources_Entry) == 32 && offset_of(State_Resources_Entry, value) == 8) +#assert(size_of(Run_Function_Request) == 152) +#assert(offset_of(Run_Function_Request, meta) == 4 && offset_of(Run_Function_Request, observed) == 20 && offset_of(Run_Function_Request, desired) == 60) +#assert(offset_of(Run_Function_Request, input) == 100 && offset_of(Run_Function_Request, ctx) == 112 && offset_of(Run_Function_Request, extra_resources_count) == 120) +#assert(size_of(Response_Meta) == 24 && offset_of(Response_Meta, ttl) == 8) +#assert(size_of(Requirements) == 24) +#assert(size_of(Result) == 20 && offset_of(Result, target) == 16) +#assert(size_of(Condition) == 24 && offset_of(Condition, target) == 20) +#assert(size_of(Run_Function_Response) == 144) +#assert(offset_of(Run_Function_Response, meta) == 8 && offset_of(Run_Function_Response, desired) == 36 && offset_of(Run_Function_Response, results_count) == 72 && offset_of(Run_Function_Response, results) == 76) +#assert(offset_of(Run_Function_Response, ctx) == 84 && offset_of(Run_Function_Response, requirements) == 96 && offset_of(Run_Function_Response, conditions_count) == 120 && offset_of(Run_Function_Response, conditions) == 124 && offset_of(Run_Function_Response, output) == 132) +#assert(size_of(Istream) == 16 && offset_of(Istream, bytes_left) == 8 && offset_of(Istream, errmsg) == 12) +#assert(size_of(Ostream) == 20 && offset_of(Ostream, max_size) == 8 && offset_of(Ostream, bytes_written) == 12 && offset_of(Ostream, errmsg) == 16) +} diff --git a/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.c b/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.c new file mode 100644 index 00000000..7e55acfe --- /dev/null +++ b/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.9.1 */ + +#include "google/protobuf/duration.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(google_protobuf_Duration, google_protobuf_Duration, AUTO) + + + diff --git a/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.h b/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.h new file mode 100644 index 00000000..1ff047db --- /dev/null +++ b/examples/hello-odin/src/fnv1/google/protobuf/duration.pb.h @@ -0,0 +1,118 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.9.1 */ + +#ifndef PB_GOOGLE_PROTOBUF_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED +#define PB_GOOGLE_PROTOBUF_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* A Duration represents a signed, fixed-length span of time represented + as a count of seconds and fractions of seconds at nanosecond + resolution. It is independent of any calendar and concepts like "day" + or "month". It is related to Timestamp in that the difference between + two Timestamp values is a Duration and it can be added or subtracted + from a Timestamp. Range is approximately +-10,000 years. + + # Examples + + Example 1: Compute Duration from two Timestamps in pseudo code. + + Timestamp start = ...; + Timestamp end = ...; + Duration duration = ...; + + duration.seconds = end.seconds - start.seconds; + duration.nanos = end.nanos - start.nanos; + + if (duration.seconds < 0 && duration.nanos > 0) { + duration.seconds += 1; + duration.nanos -= 1000000000; + } else if (duration.seconds > 0 && duration.nanos < 0) { + duration.seconds -= 1; + duration.nanos += 1000000000; + } + + Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + + Timestamp start = ...; + Duration duration = ...; + Timestamp end = ...; + + end.seconds = start.seconds + duration.seconds; + end.nanos = start.nanos + duration.nanos; + + if (end.nanos < 0) { + end.seconds -= 1; + end.nanos += 1000000000; + } else if (end.nanos >= 1000000000) { + end.seconds += 1; + end.nanos -= 1000000000; + } + + Example 3: Compute Duration from datetime.timedelta in Python. + + td = datetime.timedelta(days=3, minutes=10) + duration = Duration() + duration.FromTimedelta(td) + + # JSON Mapping + + In JSON format, the Duration type is encoded as a string rather than an + object, where the string ends in the suffix "s" (indicating seconds) and + is preceded by the number of seconds, with nanoseconds expressed as + fractional seconds. For example, 3 seconds with 0 nanoseconds should be + encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + microsecond should be expressed in JSON format as "3.000001s". */ +typedef struct _google_protobuf_Duration { + /* Signed seconds of the span of time. Must be from -315,576,000,000 + to +315,576,000,000 inclusive. Note: these bounds are computed from: + 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years */ + int64_t seconds; + /* Signed fractions of a second at nanosecond resolution of the span + of time. Durations less than one second are represented with a 0 + `seconds` field and a positive or negative `nanos` field. For durations + of one second or more, a non-zero value for the `nanos` field must be + of the same sign as the `seconds` field. Must be from -999,999,999 + to +999,999,999 inclusive. */ + int32_t nanos; +} google_protobuf_Duration; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define google_protobuf_Duration_init_default {0, 0} +#define google_protobuf_Duration_init_zero {0, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_protobuf_Duration_seconds_tag 1 +#define google_protobuf_Duration_nanos_tag 2 + +/* Struct field encoding specification for nanopb */ +#define google_protobuf_Duration_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT64, seconds, 1) \ +X(a, STATIC, SINGULAR, INT32, nanos, 2) +#define google_protobuf_Duration_CALLBACK NULL +#define google_protobuf_Duration_DEFAULT NULL + +extern const pb_msgdesc_t google_protobuf_Duration_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define google_protobuf_Duration_fields &google_protobuf_Duration_msg + +/* Maximum encoded size of messages (where known) */ +#define GOOGLE_PROTOBUF_GOOGLE_PROTOBUF_DURATION_PB_H_MAX_SIZE google_protobuf_Duration_size +#define google_protobuf_Duration_size 22 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.c b/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.c new file mode 100644 index 00000000..8426d98f --- /dev/null +++ b/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.c @@ -0,0 +1,31 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.9.1 */ + +#include "google/protobuf/struct.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(google_protobuf_Struct, google_protobuf_Struct, AUTO) + + +PB_BIND(google_protobuf_Struct_FieldsEntry, google_protobuf_Struct_FieldsEntry, AUTO) + + +PB_BIND(google_protobuf_Value, google_protobuf_Value, AUTO) + + +PB_BIND(google_protobuf_ListValue, google_protobuf_ListValue, AUTO) + + + + + +#ifndef PB_CONVERT_DOUBLE_FLOAT +/* On some platforms (such as AVR), double is really float. + * To be able to encode/decode double on these platforms, you need. + * to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line. + */ +PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) +#endif + diff --git a/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.h b/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.h new file mode 100644 index 00000000..241fe8c2 --- /dev/null +++ b/examples/hello-odin/src/fnv1/google/protobuf/struct.pb.h @@ -0,0 +1,178 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.9.1 */ + +#ifndef PB_GOOGLE_PROTOBUF_GOOGLE_PROTOBUF_STRUCT_PB_H_INCLUDED +#define PB_GOOGLE_PROTOBUF_GOOGLE_PROTOBUF_STRUCT_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +/* Represents a JSON `null`. + + `NullValue` is a sentinel, using an enum with only one value to represent + the null value for the `Value` type union. + + A field of type `NullValue` with any value other than `0` is considered + invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set + as a JSON `null` regardless of the integer value, and so will round trip to + a `0` value. */ +typedef enum _google_protobuf_NullValue { + /* Null value. */ + google_protobuf_NullValue_NULL_VALUE = 0 +} google_protobuf_NullValue; + +/* Struct definitions */ +/* Represents a JSON object. + + An unordered key-value map, intending to perfectly capture the semantics of a + JSON object. This enables parsing any arbitrary JSON payload as a message + field in ProtoJSON format. + + This follows RFC 8259 guidelines for interoperable JSON: notably this type + cannot represent large Int64 values or `NaN`/`Infinity` numbers, + since the JSON format generally does not support those values in its number + type. + + If you do not intend to parse arbitrary JSON into your message, a custom + typed message should be preferred instead of using this type. */ +typedef struct _google_protobuf_Struct { + /* Unordered map of dynamically typed values. */ + pb_size_t fields_count; + struct _google_protobuf_Struct_FieldsEntry *fields; +} google_protobuf_Struct; + +/* Represents a JSON array. */ +typedef struct _google_protobuf_ListValue { + /* Repeated field of dynamically typed values. */ + pb_size_t values_count; + struct _google_protobuf_Value *values; +} google_protobuf_ListValue; + +/* Represents a JSON value. + + `Value` represents a dynamically typed value which can be either + null, a number, a string, a boolean, a recursive struct value, or a + list of values. A producer of value is expected to set one of these + variants. Absence of any variant is an invalid state. */ +typedef struct _google_protobuf_Value { + pb_size_t which_kind; + union { + /* Represents a JSON `null`. */ + google_protobuf_NullValue null_value; + /* Represents a JSON number. Must not be `NaN`, `Infinity` or + `-Infinity`, since those are not supported in JSON. This also cannot + represent large Int64 values, since JSON format generally does not + support them in its number type. */ + double number_value; + /* Represents a JSON string. */ + char *string_value; + /* Represents a JSON boolean (`true` or `false` literal in JSON). */ + bool bool_value; + /* Represents a JSON object. */ + google_protobuf_Struct struct_value; + /* Represents a JSON array. */ + google_protobuf_ListValue list_value; + } kind; +} google_protobuf_Value; + +typedef struct _google_protobuf_Struct_FieldsEntry { + char *key; + bool has_value; + google_protobuf_Value value; +} google_protobuf_Struct_FieldsEntry; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper constants for enums */ +#define _google_protobuf_NullValue_MIN google_protobuf_NullValue_NULL_VALUE +#define _google_protobuf_NullValue_MAX google_protobuf_NullValue_NULL_VALUE +#define _google_protobuf_NullValue_ARRAYSIZE ((google_protobuf_NullValue)(google_protobuf_NullValue_NULL_VALUE+1)) + + + +#define google_protobuf_Value_kind_null_value_ENUMTYPE google_protobuf_NullValue + + + +/* Initializer values for message structs */ +#define google_protobuf_Struct_init_default {0, NULL} +#define google_protobuf_Struct_FieldsEntry_init_default {NULL, false, google_protobuf_Value_init_default} +#define google_protobuf_Value_init_default {0, {_google_protobuf_NullValue_MIN}} +#define google_protobuf_ListValue_init_default {0, NULL} +#define google_protobuf_Struct_init_zero {0, NULL} +#define google_protobuf_Struct_FieldsEntry_init_zero {NULL, false, google_protobuf_Value_init_zero} +#define google_protobuf_Value_init_zero {0, {_google_protobuf_NullValue_MIN}} +#define google_protobuf_ListValue_init_zero {0, NULL} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_protobuf_Struct_fields_tag 1 +#define google_protobuf_ListValue_values_tag 1 +#define google_protobuf_Value_null_value_tag 1 +#define google_protobuf_Value_number_value_tag 2 +#define google_protobuf_Value_string_value_tag 3 +#define google_protobuf_Value_bool_value_tag 4 +#define google_protobuf_Value_struct_value_tag 5 +#define google_protobuf_Value_list_value_tag 6 +#define google_protobuf_Struct_FieldsEntry_key_tag 1 +#define google_protobuf_Struct_FieldsEntry_value_tag 2 + +/* Struct field encoding specification for nanopb */ +#define google_protobuf_Struct_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, fields, 1) +#define google_protobuf_Struct_CALLBACK NULL +#define google_protobuf_Struct_DEFAULT NULL +#define google_protobuf_Struct_fields_MSGTYPE google_protobuf_Struct_FieldsEntry + +#define google_protobuf_Struct_FieldsEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define google_protobuf_Struct_FieldsEntry_CALLBACK NULL +#define google_protobuf_Struct_FieldsEntry_DEFAULT NULL +#define google_protobuf_Struct_FieldsEntry_value_MSGTYPE google_protobuf_Value + +#define google_protobuf_Value_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, UENUM, (kind,null_value,kind.null_value), 1) \ +X(a, STATIC, ONEOF, DOUBLE, (kind,number_value,kind.number_value), 2) \ +X(a, POINTER, ONEOF, STRING, (kind,string_value,kind.string_value), 3) \ +X(a, STATIC, ONEOF, BOOL, (kind,bool_value,kind.bool_value), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (kind,struct_value,kind.struct_value), 5) \ +X(a, STATIC, ONEOF, MESSAGE, (kind,list_value,kind.list_value), 6) +#define google_protobuf_Value_CALLBACK NULL +#define google_protobuf_Value_DEFAULT NULL +#define google_protobuf_Value_kind_struct_value_MSGTYPE google_protobuf_Struct +#define google_protobuf_Value_kind_list_value_MSGTYPE google_protobuf_ListValue + +#define google_protobuf_ListValue_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, values, 1) +#define google_protobuf_ListValue_CALLBACK NULL +#define google_protobuf_ListValue_DEFAULT NULL +#define google_protobuf_ListValue_values_MSGTYPE google_protobuf_Value + +extern const pb_msgdesc_t google_protobuf_Struct_msg; +extern const pb_msgdesc_t google_protobuf_Struct_FieldsEntry_msg; +extern const pb_msgdesc_t google_protobuf_Value_msg; +extern const pb_msgdesc_t google_protobuf_ListValue_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define google_protobuf_Struct_fields &google_protobuf_Struct_msg +#define google_protobuf_Struct_FieldsEntry_fields &google_protobuf_Struct_FieldsEntry_msg +#define google_protobuf_Value_fields &google_protobuf_Value_msg +#define google_protobuf_ListValue_fields &google_protobuf_ListValue_msg + +/* Maximum encoded size of messages (where known) */ +/* google_protobuf_Struct_size depends on runtime parameters */ +/* google_protobuf_Struct_FieldsEntry_size depends on runtime parameters */ +/* google_protobuf_Value_size depends on runtime parameters */ +/* google_protobuf_ListValue_size depends on runtime parameters */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/examples/hello-odin/src/fnv1/run_function.pb.c b/examples/hello-odin/src/fnv1/run_function.pb.c new file mode 100644 index 00000000..a3db037d --- /dev/null +++ b/examples/hello-odin/src/fnv1/run_function.pb.c @@ -0,0 +1,100 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.9.1 */ + +#include "run_function.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(fnv1_RunFunctionRequest, fnv1_RunFunctionRequest, 2) + + +PB_BIND(fnv1_RunFunctionRequest_ExtraResourcesEntry, fnv1_RunFunctionRequest_ExtraResourcesEntry, AUTO) + + +PB_BIND(fnv1_RunFunctionRequest_CredentialsEntry, fnv1_RunFunctionRequest_CredentialsEntry, AUTO) + + +PB_BIND(fnv1_RunFunctionRequest_RequiredResourcesEntry, fnv1_RunFunctionRequest_RequiredResourcesEntry, AUTO) + + +PB_BIND(fnv1_RunFunctionRequest_RequiredSchemasEntry, fnv1_RunFunctionRequest_RequiredSchemasEntry, AUTO) + + +PB_BIND(fnv1_Credentials, fnv1_Credentials, AUTO) + + +PB_BIND(fnv1_CredentialData, fnv1_CredentialData, AUTO) + + +PB_BIND(fnv1_CredentialData_DataEntry, fnv1_CredentialData_DataEntry, AUTO) + + +PB_BIND(fnv1_Resources, fnv1_Resources, AUTO) + + +PB_BIND(fnv1_RunFunctionResponse, fnv1_RunFunctionResponse, AUTO) + + +PB_BIND(fnv1_RequestMeta, fnv1_RequestMeta, AUTO) + + +PB_BIND(fnv1_Requirements, fnv1_Requirements, AUTO) + + +PB_BIND(fnv1_Requirements_ExtraResourcesEntry, fnv1_Requirements_ExtraResourcesEntry, AUTO) + + +PB_BIND(fnv1_Requirements_ResourcesEntry, fnv1_Requirements_ResourcesEntry, AUTO) + + +PB_BIND(fnv1_Requirements_SchemasEntry, fnv1_Requirements_SchemasEntry, AUTO) + + +PB_BIND(fnv1_SchemaSelector, fnv1_SchemaSelector, AUTO) + + +PB_BIND(fnv1_Schema, fnv1_Schema, AUTO) + + +PB_BIND(fnv1_ResourceSelector, fnv1_ResourceSelector, AUTO) + + +PB_BIND(fnv1_MatchLabels, fnv1_MatchLabels, AUTO) + + +PB_BIND(fnv1_MatchLabels_LabelsEntry, fnv1_MatchLabels_LabelsEntry, AUTO) + + +PB_BIND(fnv1_ResponseMeta, fnv1_ResponseMeta, AUTO) + + +PB_BIND(fnv1_State, fnv1_State, AUTO) + + +PB_BIND(fnv1_State_ResourcesEntry, fnv1_State_ResourcesEntry, AUTO) + + +PB_BIND(fnv1_Resource, fnv1_Resource, AUTO) + + +PB_BIND(fnv1_Resource_ConnectionDetailsEntry, fnv1_Resource_ConnectionDetailsEntry, AUTO) + + +PB_BIND(fnv1_Result, fnv1_Result, AUTO) + + +PB_BIND(fnv1_Condition, fnv1_Condition, AUTO) + + + + + + + + + + + + + diff --git a/examples/hello-odin/src/fnv1/run_function.pb.h b/examples/hello-odin/src/fnv1/run_function.pb.h new file mode 100644 index 00000000..d62efa4f --- /dev/null +++ b/examples/hello-odin/src/fnv1/run_function.pb.h @@ -0,0 +1,1065 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.9.1 */ + +#ifndef PB_APIEXTENSIONS_FN_PROTO_V1_RUN_FUNCTION_PB_H_INCLUDED +#define PB_APIEXTENSIONS_FN_PROTO_V1_RUN_FUNCTION_PB_H_INCLUDED +#include +#include "google/protobuf/duration.pb.h" +#include "google/protobuf/struct.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +/* Capability indicates that Crossplane supports a particular feature. + Functions can check for capabilities to determine whether Crossplane will + honor a particular request or response field. */ +typedef enum _fnv1_Capability { + fnv1_Capability_CAPABILITY_UNSPECIFIED = 0, + /* Crossplane sends capabilities in RequestMeta. If this capability is + present, the function knows that if another capability is absent, it's + because Crossplane doesn't support it (not because Crossplane predates + capability advertisement). Added in Crossplane v2.2. */ + fnv1_Capability_CAPABILITY_CAPABILITIES = 1, + /* Crossplane supports the requirements.resources field. Functions can return + resource requirements and Crossplane will fetch the requested resources and + return them in required_resources. Added in Crossplane v1.15. */ + fnv1_Capability_CAPABILITY_REQUIRED_RESOURCES = 2, + /* Crossplane supports the credentials field. Functions can receive + credentials from secrets specified in the Composition. Added in Crossplane + v1.16. */ + fnv1_Capability_CAPABILITY_CREDENTIALS = 3, + /* Crossplane supports the conditions field. Functions can return status + conditions to be applied to the XR and optionally its claim. Added in + Crossplane v1.17. */ + fnv1_Capability_CAPABILITY_CONDITIONS = 4, + /* Crossplane supports the requirements.schemas field. Functions can request + OpenAPI schemas and Crossplane will return them in required_schemas. Added + in Crossplane v2.2. */ + fnv1_Capability_CAPABILITY_REQUIRED_SCHEMAS = 5 +} fnv1_Capability; + +/* Ready indicates whether a resource should be considered ready. */ +typedef enum _fnv1_Ready { + fnv1_Ready_READY_UNSPECIFIED = 0, + /* True means the resource has been observed to be ready. */ + fnv1_Ready_READY_TRUE = 1, + /* False means the resource has not been observed to be ready. */ + fnv1_Ready_READY_FALSE = 2 +} fnv1_Ready; + +/* Severity of function results. */ +typedef enum _fnv1_Severity { + fnv1_Severity_SEVERITY_UNSPECIFIED = 0, + /* Fatal results are fatal; subsequent functions may run, but the function + pipeline run will be considered a failure and the first fatal result will + be returned as an error. */ + fnv1_Severity_SEVERITY_FATAL = 1, + /* Warning results are non-fatal; the entire pipeline will run to completion + but warning events and debug logs associated with the XR or Operation will + be emitted. */ + fnv1_Severity_SEVERITY_WARNING = 2, + /* Normal results are emitted as normal events and debug logs associated with + the XR or operation. */ + fnv1_Severity_SEVERITY_NORMAL = 3 +} fnv1_Severity; + +/* Target of function results and conditions. */ +typedef enum _fnv1_Target { + /* If the target is unspecified, the result targets the XR. */ + fnv1_Target_TARGET_UNSPECIFIED = 0, + /* Target the XR. Results that target the XR should include detailed, advanced + information. */ + fnv1_Target_TARGET_COMPOSITE = 1, + /* Target the XR and the claim. Results that target the XR and the claim + should include only end-user friendly information. */ + fnv1_Target_TARGET_COMPOSITE_AND_CLAIM = 2 +} fnv1_Target; + +typedef enum _fnv1_Status { + fnv1_Status_STATUS_CONDITION_UNSPECIFIED = 0, + fnv1_Status_STATUS_CONDITION_UNKNOWN = 1, + fnv1_Status_STATUS_CONDITION_TRUE = 2, + fnv1_Status_STATUS_CONDITION_FALSE = 3 +} fnv1_Status; + +/* Struct definitions */ +/* CredentialData loaded by Crossplane, for example from a Secret. */ +typedef struct _fnv1_CredentialData { + pb_size_t data_count; + struct _fnv1_CredentialData_DataEntry *data; +} fnv1_CredentialData; + +/* Credentials that a function may use to communicate with an external system. */ +typedef struct _fnv1_Credentials { + pb_size_t which_source; + union { + /* Credential data loaded by Crossplane, for example from a Secret. */ + fnv1_CredentialData credential_data; + } source; +} fnv1_Credentials; + +typedef struct _fnv1_RunFunctionRequest_CredentialsEntry { + char *key; + bool has_value; + fnv1_Credentials value; +} fnv1_RunFunctionRequest_CredentialsEntry; + +typedef struct _fnv1_CredentialData_DataEntry { + char *key; + pb_bytes_array_t *value; +} fnv1_CredentialData_DataEntry; + +/* Resources represents the state of several Crossplane resources. */ +typedef struct _fnv1_Resources { + pb_size_t items_count; + struct _fnv1_Resource *items; +} fnv1_Resources; + +typedef struct _fnv1_RunFunctionRequest_ExtraResourcesEntry { + char *key; + bool has_value; + fnv1_Resources value; +} fnv1_RunFunctionRequest_ExtraResourcesEntry; + +typedef struct _fnv1_RunFunctionRequest_RequiredResourcesEntry { + char *key; + bool has_value; + fnv1_Resources value; +} fnv1_RunFunctionRequest_RequiredResourcesEntry; + +/* RequestMeta contains metadata pertaining to a RunFunctionRequest. */ +typedef struct _fnv1_RequestMeta { + /* An opaque string identifying a request. Requests with identical tags will + be otherwise identical. */ + char *tag; + /* Capabilities supported by this version of Crossplane. Functions may use + this to determine whether Crossplane will honor certain fields in their + response, or populate certain fields in their request. */ + pb_size_t capabilities_count; + fnv1_Capability *capabilities; +} fnv1_RequestMeta; + +/* Requirements that must be satisfied for a function to run successfully. */ +typedef struct _fnv1_Requirements { + /* Resources that this function requires. The map key uniquely identifies the + group of resources. + + Deprecated: Use resources instead. */ + pb_size_t extra_resources_count; + struct _fnv1_Requirements_ExtraResourcesEntry *extra_resources; + /* Resources that this function requires. The map key uniquely identifies the + group of resources. */ + pb_size_t resources_count; + struct _fnv1_Requirements_ResourcesEntry *resources; + /* Schemas that this function requires. The map key uniquely identifies the + schema request. */ + pb_size_t schemas_count; + struct _fnv1_Requirements_SchemasEntry *schemas; +} fnv1_Requirements; + +/* SchemaSelector identifies a resource kind whose OpenAPI schema is requested. */ +typedef struct _fnv1_SchemaSelector { + /* API version of the resource kind, e.g. "example.org/v1". */ + char *api_version; + /* Kind of resource, e.g. "MyResource". */ + char *kind; +} fnv1_SchemaSelector; + +typedef struct _fnv1_Requirements_SchemasEntry { + char *key; + bool has_value; + fnv1_SchemaSelector value; +} fnv1_Requirements_SchemasEntry; + +/* Schema represents the OpenAPI schema for a resource kind. */ +typedef struct _fnv1_Schema { + /* The OpenAPI v3 schema of the resource kind as unstructured JSON. + For CRDs this is the spec.versions[].schema.openAPIV3Schema field. + Empty if Crossplane could not find a schema for the requested kind. */ + bool has_openapi_v3; + google_protobuf_Struct openapi_v3; +} fnv1_Schema; + +typedef struct _fnv1_RunFunctionRequest_RequiredSchemasEntry { + char *key; + bool has_value; + fnv1_Schema value; +} fnv1_RunFunctionRequest_RequiredSchemasEntry; + +/* MatchLabels defines a set of labels to match resources against. */ +typedef struct _fnv1_MatchLabels { + pb_size_t labels_count; + struct _fnv1_MatchLabels_LabelsEntry *labels; +} fnv1_MatchLabels; + +/* ResourceSelector selects a group of resources, either by name or by label. */ +typedef struct _fnv1_ResourceSelector { + /* API version of resources to select. */ + char *api_version; + /* Kind of resources to select. */ + char *kind; + pb_size_t which_match; + union { + /* Match the resource with this name. */ + char *match_name; + /* Match all resources with these labels. */ + fnv1_MatchLabels match_labels; + } match; + /* Match resources in this namespace. Omit namespace to match cluster scoped + resources, or to match namespaced resources by labels across all + namespaces. */ + char *namespace; +} fnv1_ResourceSelector; + +typedef struct _fnv1_Requirements_ExtraResourcesEntry { + char *key; + bool has_value; + fnv1_ResourceSelector value; +} fnv1_Requirements_ExtraResourcesEntry; + +typedef struct _fnv1_Requirements_ResourcesEntry { + char *key; + bool has_value; + fnv1_ResourceSelector value; +} fnv1_Requirements_ResourcesEntry; + +typedef struct _fnv1_MatchLabels_LabelsEntry { + char *key; + char *value; +} fnv1_MatchLabels_LabelsEntry; + +/* ResponseMeta contains metadata pertaining to a RunFunctionResponse. */ +typedef struct _fnv1_ResponseMeta { + /* An opaque string identifying the content of the request. Must match the + meta.tag of the corresponding RunFunctionRequest. */ + char *tag; + /* Time-to-live of this response. Crossplane will call the function again when + the TTL expires. Crossplane may cache the response to avoid calling the + function again until the TTL expires. */ + bool has_ttl; + google_protobuf_Duration ttl; +} fnv1_ResponseMeta; + +/* A Resource represents the state of a Kubernetes resource. */ +typedef struct _fnv1_Resource { + /* The JSON representation of the resource. + + * Crossplane will set this field in a RunFunctionRequest to the entire + observed state of a resource - including its metadata, spec, and status. + + * A function should set this field in a RunFunctionRequest to communicate + the desired state of the resource. + + * A function may only specify the desired status of a XR - not its metadata + or spec. A function should not return desired metadata or spec for a XR. + This will be ignored. + + * A function may not specify the desired status of any other resource - + e.g. composed resources. It may only specify their metadata and spec. + Status will be ignored. */ + bool has_resource; + google_protobuf_Struct resource; + /* The resource's connection details. + + * Crossplane will set this field in a RunFunctionRequest to communicate the + the observed connection details of a composite or composed resource. + + * A function should set this field in a RunFunctionResponse to indicate the + desired connection details of legacy XRs. For modern XRs, this will be ignored. + + * A function should not set this field in a RunFunctionResponse to indicate + the desired connection details of a composed resource. This will be + ignored. + + Connection details are only used for composition. They're ignored by + Operations. */ + pb_size_t connection_details_count; + struct _fnv1_Resource_ConnectionDetailsEntry *connection_details; + /* Ready indicates whether the resource should be considered ready. + + * Crossplane will never set this field in a RunFunctionRequest. + + * A function should set this field to READY_TRUE in a RunFunctionResponse + to indicate that a desired resource is ready. + + * A function should set this field to READY_TRUE in a RunFunctionResponse + to indicate that a desired XR is ready. This overwrites the standard + readiness detection that determines the ready state of the composite by the + ready state of the composed resources. + + Ready is only used for composition. It's ignored by Operations. */ + fnv1_Ready ready; +} fnv1_Resource; + +/* State of the XR (XR) and any resources. */ +typedef struct _fnv1_State { + /* The state of the XR (XR). */ + bool has_composite; + fnv1_Resource composite; + /* The state of any other resources. In composition functions these are the + composed resources. In operation functions they're arbitrary resources that + the operation wants to create or update. */ + pb_size_t resources_count; + struct _fnv1_State_ResourcesEntry *resources; +} fnv1_State; + +/* A RunFunctionRequest requests that the function be run. */ +typedef struct _fnv1_RunFunctionRequest { + /* Metadata pertaining to this request. */ + bool has_meta; + fnv1_RequestMeta meta; + /* The observed state prior to invocation of a function pipeline. State passed + to each function is fresh as of the time the pipeline was invoked, not as + of the time each function was invoked. */ + bool has_observed; + fnv1_State observed; + /* Desired state according to a function pipeline. The state passed to a + particular function may have been accumulated by previous functions in the + pipeline. + + Note that the desired state must be a partial object with only the fields + that this function (and its predecessors in the pipeline) wants to have set + in the object. Copying a non-partial observed state to desired is most + likely not what you want to do. Leaving out fields that had been returned + as desired before will result in them being deleted from the objects in the + cluster. */ + bool has_desired; + fnv1_State desired; + /* Optional input specific to this function invocation. A JSON representation + of the 'input' block of the relevant entry in a function pipeline. */ + bool has_input; + google_protobuf_Struct input; + /* Optional context. Crossplane may pass arbitrary contextual information to a + function. A function may also return context in its RunFunctionResponse, + and that context will be passed to subsequent functions. Crossplane + discards all context returned by the last function in the pipeline. */ + bool has_context; + google_protobuf_Struct context; + /* Optional resources that the function specified in its requirements. Note + that resources is a map to Resources, plural. The map key corresponds to + the key in a RunFunctionResponse's requirements.extra_resources field. If a + function requested extra resources that did not exist, Crossplane sets + the map key to an empty Resources message to indicate that it attempted to + satisfy the request. This field is only populated when the function uses + extra_resources in its requirements. + + Deprecated: Use required_resources instead. */ + pb_size_t extra_resources_count; + struct _fnv1_RunFunctionRequest_ExtraResourcesEntry *extra_resources; + /* Optional credentials that this function may use to communicate with an + external system. */ + pb_size_t credentials_count; + struct _fnv1_RunFunctionRequest_CredentialsEntry *credentials; + /* Optional resources that the function specified in its requirements. Note + that resources is a map to Resources, plural. The map key corresponds to + the key in a RunFunctionResponse's requirements.resources field. If a + function requested required resources that did not exist, Crossplane sets + the map key to an empty Resources message to indicate that it attempted to + satisfy the request. This field is only populated when the function uses + resources in its requirements. */ + pb_size_t required_resources_count; + struct _fnv1_RunFunctionRequest_RequiredResourcesEntry *required_resources; + /* Optional schemas that the function specified in its requirements. The map + key corresponds to the key in a RunFunctionResponse's requirements.schemas + field. If a function requested a schema that could not be found, Crossplane + sets the map key to an empty Schema message to indicate that it attempted + to satisfy the request. */ + pb_size_t required_schemas_count; + struct _fnv1_RunFunctionRequest_RequiredSchemasEntry *required_schemas; +} fnv1_RunFunctionRequest; + +/* A RunFunctionResponse contains the result of a function run. */ +typedef struct _fnv1_RunFunctionResponse { + /* Metadata pertaining to this response. */ + bool has_meta; + fnv1_ResponseMeta meta; + /* Desired state according to a function pipeline. functions may add desired + state, and may mutate or delete any part of the desired state they are + concerned with. A function must pass through any part of the desired state + that it is not concerned with. + + Note that the desired state must be a partial object with only the fields + that this function (and its predecessors in the pipeline) wants to have set + in the object. Copying a non-partial observed state to desired is most + likely not what you want to do. Leaving out fields that had been returned + as desired before will result in them being deleted from the objects in the + cluster. */ + bool has_desired; + fnv1_State desired; + /* Results of the function run. Results are used for observability purposes. */ + pb_size_t results_count; + struct _fnv1_Result *results; + /* Optional context to be passed to the next function in the pipeline as part + of the RunFunctionRequest. Dropped on the last function in the pipeline. */ + bool has_context; + google_protobuf_Struct context; + /* Requirements that must be satisfied for this function to run successfully. */ + bool has_requirements; + fnv1_Requirements requirements; + /* Status conditions to be applied to the XR. Conditions may also optionally + be applied to the XR's associated claim. + + Conditions are only used for composition. They're ignored by Operations. */ + pb_size_t conditions_count; + struct _fnv1_Condition *conditions; + /* Optional output specific to this function invocation. + + Only Operations use function output. XRs will discard any function output. */ + bool has_output; + google_protobuf_Struct output; +} fnv1_RunFunctionResponse; + +typedef struct _fnv1_State_ResourcesEntry { + char *key; + bool has_value; + fnv1_Resource value; +} fnv1_State_ResourcesEntry; + +typedef struct _fnv1_Resource_ConnectionDetailsEntry { + char *key; + pb_bytes_array_t *value; +} fnv1_Resource_ConnectionDetailsEntry; + +/* A Result of running a function. */ +typedef struct _fnv1_Result { + /* Severity of this result. */ + fnv1_Severity severity; + /* Human-readable details about the result. */ + char *message; + /* Optional PascalCase, machine-readable reason for this result. If omitted, + the value will be ComposeResources. */ + char *reason; + /* The resources this result targets. */ + bool has_target; + fnv1_Target target; +} fnv1_Result; + +/* Status condition to be applied to the XR. Condition may also optionally be + applied to the XR's associated claim. For detailed information on proper + usage of status conditions, please see + https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties. */ +typedef struct _fnv1_Condition { + /* Type of condition in PascalCase. */ + char *type; + /* Status of the condition. */ + fnv1_Status status; + /* Reason contains a programmatic identifier indicating the reason for the + condition's last transition. Producers of specific condition types may + define expected values and meanings for this field, and whether the values + are considered a guaranteed API. The value should be a PascalCase string. + This field may not be empty. */ + char *reason; + /* Message is a human readable message indicating details about the + transition. This may be an empty string. */ + char *message; + /* The resources this condition targets. */ + bool has_target; + fnv1_Target target; +} fnv1_Condition; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper constants for enums */ +#define _fnv1_Capability_MIN fnv1_Capability_CAPABILITY_UNSPECIFIED +#define _fnv1_Capability_MAX fnv1_Capability_CAPABILITY_REQUIRED_SCHEMAS +#define _fnv1_Capability_ARRAYSIZE ((fnv1_Capability)(fnv1_Capability_CAPABILITY_REQUIRED_SCHEMAS+1)) + +#define _fnv1_Ready_MIN fnv1_Ready_READY_UNSPECIFIED +#define _fnv1_Ready_MAX fnv1_Ready_READY_FALSE +#define _fnv1_Ready_ARRAYSIZE ((fnv1_Ready)(fnv1_Ready_READY_FALSE+1)) + +#define _fnv1_Severity_MIN fnv1_Severity_SEVERITY_UNSPECIFIED +#define _fnv1_Severity_MAX fnv1_Severity_SEVERITY_NORMAL +#define _fnv1_Severity_ARRAYSIZE ((fnv1_Severity)(fnv1_Severity_SEVERITY_NORMAL+1)) + +#define _fnv1_Target_MIN fnv1_Target_TARGET_UNSPECIFIED +#define _fnv1_Target_MAX fnv1_Target_TARGET_COMPOSITE_AND_CLAIM +#define _fnv1_Target_ARRAYSIZE ((fnv1_Target)(fnv1_Target_TARGET_COMPOSITE_AND_CLAIM+1)) + +#define _fnv1_Status_MIN fnv1_Status_STATUS_CONDITION_UNSPECIFIED +#define _fnv1_Status_MAX fnv1_Status_STATUS_CONDITION_FALSE +#define _fnv1_Status_ARRAYSIZE ((fnv1_Status)(fnv1_Status_STATUS_CONDITION_FALSE+1)) + + + + + + + + + + + +#define fnv1_RequestMeta_capabilities_ENUMTYPE fnv1_Capability + + + + + + + + + + + + + +#define fnv1_Resource_ready_ENUMTYPE fnv1_Ready + + +#define fnv1_Result_severity_ENUMTYPE fnv1_Severity +#define fnv1_Result_target_ENUMTYPE fnv1_Target + +#define fnv1_Condition_status_ENUMTYPE fnv1_Status +#define fnv1_Condition_target_ENUMTYPE fnv1_Target + + +/* Initializer values for message structs */ +#define fnv1_RunFunctionRequest_init_default {false, fnv1_RequestMeta_init_default, false, fnv1_State_init_default, false, fnv1_State_init_default, false, google_protobuf_Struct_init_default, false, google_protobuf_Struct_init_default, 0, NULL, 0, NULL, 0, NULL, 0, NULL} +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_init_default {NULL, false, fnv1_Resources_init_default} +#define fnv1_RunFunctionRequest_CredentialsEntry_init_default {NULL, false, fnv1_Credentials_init_default} +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_init_default {NULL, false, fnv1_Resources_init_default} +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_init_default {NULL, false, fnv1_Schema_init_default} +#define fnv1_Credentials_init_default {0, {fnv1_CredentialData_init_default}} +#define fnv1_CredentialData_init_default {0, NULL} +#define fnv1_CredentialData_DataEntry_init_default {NULL, NULL} +#define fnv1_Resources_init_default {0, NULL} +#define fnv1_RunFunctionResponse_init_default {false, fnv1_ResponseMeta_init_default, false, fnv1_State_init_default, 0, NULL, false, google_protobuf_Struct_init_default, false, fnv1_Requirements_init_default, 0, NULL, false, google_protobuf_Struct_init_default} +#define fnv1_RequestMeta_init_default {NULL, 0, NULL} +#define fnv1_Requirements_init_default {0, NULL, 0, NULL, 0, NULL} +#define fnv1_Requirements_ExtraResourcesEntry_init_default {NULL, false, fnv1_ResourceSelector_init_default} +#define fnv1_Requirements_ResourcesEntry_init_default {NULL, false, fnv1_ResourceSelector_init_default} +#define fnv1_Requirements_SchemasEntry_init_default {NULL, false, fnv1_SchemaSelector_init_default} +#define fnv1_SchemaSelector_init_default {NULL, NULL} +#define fnv1_Schema_init_default {false, google_protobuf_Struct_init_default} +#define fnv1_ResourceSelector_init_default {NULL, NULL, 0, {NULL}, NULL} +#define fnv1_MatchLabels_init_default {0, NULL} +#define fnv1_MatchLabels_LabelsEntry_init_default {NULL, NULL} +#define fnv1_ResponseMeta_init_default {NULL, false, google_protobuf_Duration_init_default} +#define fnv1_State_init_default {false, fnv1_Resource_init_default, 0, NULL} +#define fnv1_State_ResourcesEntry_init_default {NULL, false, fnv1_Resource_init_default} +#define fnv1_Resource_init_default {false, google_protobuf_Struct_init_default, 0, NULL, _fnv1_Ready_MIN} +#define fnv1_Resource_ConnectionDetailsEntry_init_default {NULL, NULL} +#define fnv1_Result_init_default {_fnv1_Severity_MIN, NULL, NULL, false, _fnv1_Target_MIN} +#define fnv1_Condition_init_default {NULL, _fnv1_Status_MIN, NULL, NULL, false, _fnv1_Target_MIN} +#define fnv1_RunFunctionRequest_init_zero {false, fnv1_RequestMeta_init_zero, false, fnv1_State_init_zero, false, fnv1_State_init_zero, false, google_protobuf_Struct_init_zero, false, google_protobuf_Struct_init_zero, 0, NULL, 0, NULL, 0, NULL, 0, NULL} +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_init_zero {NULL, false, fnv1_Resources_init_zero} +#define fnv1_RunFunctionRequest_CredentialsEntry_init_zero {NULL, false, fnv1_Credentials_init_zero} +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_init_zero {NULL, false, fnv1_Resources_init_zero} +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_init_zero {NULL, false, fnv1_Schema_init_zero} +#define fnv1_Credentials_init_zero {0, {fnv1_CredentialData_init_zero}} +#define fnv1_CredentialData_init_zero {0, NULL} +#define fnv1_CredentialData_DataEntry_init_zero {NULL, NULL} +#define fnv1_Resources_init_zero {0, NULL} +#define fnv1_RunFunctionResponse_init_zero {false, fnv1_ResponseMeta_init_zero, false, fnv1_State_init_zero, 0, NULL, false, google_protobuf_Struct_init_zero, false, fnv1_Requirements_init_zero, 0, NULL, false, google_protobuf_Struct_init_zero} +#define fnv1_RequestMeta_init_zero {NULL, 0, NULL} +#define fnv1_Requirements_init_zero {0, NULL, 0, NULL, 0, NULL} +#define fnv1_Requirements_ExtraResourcesEntry_init_zero {NULL, false, fnv1_ResourceSelector_init_zero} +#define fnv1_Requirements_ResourcesEntry_init_zero {NULL, false, fnv1_ResourceSelector_init_zero} +#define fnv1_Requirements_SchemasEntry_init_zero {NULL, false, fnv1_SchemaSelector_init_zero} +#define fnv1_SchemaSelector_init_zero {NULL, NULL} +#define fnv1_Schema_init_zero {false, google_protobuf_Struct_init_zero} +#define fnv1_ResourceSelector_init_zero {NULL, NULL, 0, {NULL}, NULL} +#define fnv1_MatchLabels_init_zero {0, NULL} +#define fnv1_MatchLabels_LabelsEntry_init_zero {NULL, NULL} +#define fnv1_ResponseMeta_init_zero {NULL, false, google_protobuf_Duration_init_zero} +#define fnv1_State_init_zero {false, fnv1_Resource_init_zero, 0, NULL} +#define fnv1_State_ResourcesEntry_init_zero {NULL, false, fnv1_Resource_init_zero} +#define fnv1_Resource_init_zero {false, google_protobuf_Struct_init_zero, 0, NULL, _fnv1_Ready_MIN} +#define fnv1_Resource_ConnectionDetailsEntry_init_zero {NULL, NULL} +#define fnv1_Result_init_zero {_fnv1_Severity_MIN, NULL, NULL, false, _fnv1_Target_MIN} +#define fnv1_Condition_init_zero {NULL, _fnv1_Status_MIN, NULL, NULL, false, _fnv1_Target_MIN} + +/* Field tags (for use in manual encoding/decoding) */ +#define fnv1_CredentialData_data_tag 1 +#define fnv1_Credentials_credential_data_tag 1 +#define fnv1_RunFunctionRequest_CredentialsEntry_key_tag 1 +#define fnv1_RunFunctionRequest_CredentialsEntry_value_tag 2 +#define fnv1_CredentialData_DataEntry_key_tag 1 +#define fnv1_CredentialData_DataEntry_value_tag 2 +#define fnv1_Resources_items_tag 1 +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_key_tag 1 +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_value_tag 2 +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_key_tag 1 +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_value_tag 2 +#define fnv1_RequestMeta_tag_tag 1 +#define fnv1_RequestMeta_capabilities_tag 2 +#define fnv1_Requirements_extra_resources_tag 1 +#define fnv1_Requirements_resources_tag 2 +#define fnv1_Requirements_schemas_tag 3 +#define fnv1_SchemaSelector_api_version_tag 1 +#define fnv1_SchemaSelector_kind_tag 2 +#define fnv1_Requirements_SchemasEntry_key_tag 1 +#define fnv1_Requirements_SchemasEntry_value_tag 2 +#define fnv1_Schema_openapi_v3_tag 1 +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_key_tag 1 +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_value_tag 2 +#define fnv1_MatchLabels_labels_tag 1 +#define fnv1_ResourceSelector_api_version_tag 1 +#define fnv1_ResourceSelector_kind_tag 2 +#define fnv1_ResourceSelector_match_name_tag 3 +#define fnv1_ResourceSelector_match_labels_tag 4 +#define fnv1_ResourceSelector_namespace_tag 5 +#define fnv1_Requirements_ExtraResourcesEntry_key_tag 1 +#define fnv1_Requirements_ExtraResourcesEntry_value_tag 2 +#define fnv1_Requirements_ResourcesEntry_key_tag 1 +#define fnv1_Requirements_ResourcesEntry_value_tag 2 +#define fnv1_MatchLabels_LabelsEntry_key_tag 1 +#define fnv1_MatchLabels_LabelsEntry_value_tag 2 +#define fnv1_ResponseMeta_tag_tag 1 +#define fnv1_ResponseMeta_ttl_tag 2 +#define fnv1_Resource_resource_tag 1 +#define fnv1_Resource_connection_details_tag 2 +#define fnv1_Resource_ready_tag 3 +#define fnv1_State_composite_tag 1 +#define fnv1_State_resources_tag 2 +#define fnv1_RunFunctionRequest_meta_tag 1 +#define fnv1_RunFunctionRequest_observed_tag 2 +#define fnv1_RunFunctionRequest_desired_tag 3 +#define fnv1_RunFunctionRequest_input_tag 4 +#define fnv1_RunFunctionRequest_context_tag 5 +#define fnv1_RunFunctionRequest_extra_resources_tag 6 +#define fnv1_RunFunctionRequest_credentials_tag 7 +#define fnv1_RunFunctionRequest_required_resources_tag 8 +#define fnv1_RunFunctionRequest_required_schemas_tag 9 +#define fnv1_RunFunctionResponse_meta_tag 1 +#define fnv1_RunFunctionResponse_desired_tag 2 +#define fnv1_RunFunctionResponse_results_tag 3 +#define fnv1_RunFunctionResponse_context_tag 4 +#define fnv1_RunFunctionResponse_requirements_tag 5 +#define fnv1_RunFunctionResponse_conditions_tag 6 +#define fnv1_RunFunctionResponse_output_tag 7 +#define fnv1_State_ResourcesEntry_key_tag 1 +#define fnv1_State_ResourcesEntry_value_tag 2 +#define fnv1_Resource_ConnectionDetailsEntry_key_tag 1 +#define fnv1_Resource_ConnectionDetailsEntry_value_tag 2 +#define fnv1_Result_severity_tag 1 +#define fnv1_Result_message_tag 2 +#define fnv1_Result_reason_tag 3 +#define fnv1_Result_target_tag 4 +#define fnv1_Condition_type_tag 1 +#define fnv1_Condition_status_tag 2 +#define fnv1_Condition_reason_tag 3 +#define fnv1_Condition_message_tag 4 +#define fnv1_Condition_target_tag 5 + +/* Struct field encoding specification for nanopb */ +#define fnv1_RunFunctionRequest_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, meta, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, observed, 2) \ +X(a, STATIC, OPTIONAL, MESSAGE, desired, 3) \ +X(a, STATIC, OPTIONAL, MESSAGE, input, 4) \ +X(a, STATIC, OPTIONAL, MESSAGE, context, 5) \ +X(a, POINTER, REPEATED, MESSAGE, extra_resources, 6) \ +X(a, POINTER, REPEATED, MESSAGE, credentials, 7) \ +X(a, POINTER, REPEATED, MESSAGE, required_resources, 8) \ +X(a, POINTER, REPEATED, MESSAGE, required_schemas, 9) +#define fnv1_RunFunctionRequest_CALLBACK NULL +#define fnv1_RunFunctionRequest_DEFAULT NULL +#define fnv1_RunFunctionRequest_meta_MSGTYPE fnv1_RequestMeta +#define fnv1_RunFunctionRequest_observed_MSGTYPE fnv1_State +#define fnv1_RunFunctionRequest_desired_MSGTYPE fnv1_State +#define fnv1_RunFunctionRequest_input_MSGTYPE google_protobuf_Struct +#define fnv1_RunFunctionRequest_context_MSGTYPE google_protobuf_Struct +#define fnv1_RunFunctionRequest_extra_resources_MSGTYPE fnv1_RunFunctionRequest_ExtraResourcesEntry +#define fnv1_RunFunctionRequest_credentials_MSGTYPE fnv1_RunFunctionRequest_CredentialsEntry +#define fnv1_RunFunctionRequest_required_resources_MSGTYPE fnv1_RunFunctionRequest_RequiredResourcesEntry +#define fnv1_RunFunctionRequest_required_schemas_MSGTYPE fnv1_RunFunctionRequest_RequiredSchemasEntry + +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_CALLBACK NULL +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_DEFAULT NULL +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_value_MSGTYPE fnv1_Resources + +#define fnv1_RunFunctionRequest_CredentialsEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_RunFunctionRequest_CredentialsEntry_CALLBACK NULL +#define fnv1_RunFunctionRequest_CredentialsEntry_DEFAULT NULL +#define fnv1_RunFunctionRequest_CredentialsEntry_value_MSGTYPE fnv1_Credentials + +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_CALLBACK NULL +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_DEFAULT NULL +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_value_MSGTYPE fnv1_Resources + +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_CALLBACK NULL +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_DEFAULT NULL +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_value_MSGTYPE fnv1_Schema + +#define fnv1_Credentials_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (source,credential_data,source.credential_data), 1) +#define fnv1_Credentials_CALLBACK NULL +#define fnv1_Credentials_DEFAULT NULL +#define fnv1_Credentials_source_credential_data_MSGTYPE fnv1_CredentialData + +#define fnv1_CredentialData_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, data, 1) +#define fnv1_CredentialData_CALLBACK NULL +#define fnv1_CredentialData_DEFAULT NULL +#define fnv1_CredentialData_data_MSGTYPE fnv1_CredentialData_DataEntry + +#define fnv1_CredentialData_DataEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, POINTER, SINGULAR, BYTES, value, 2) +#define fnv1_CredentialData_DataEntry_CALLBACK NULL +#define fnv1_CredentialData_DataEntry_DEFAULT NULL + +#define fnv1_Resources_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, items, 1) +#define fnv1_Resources_CALLBACK NULL +#define fnv1_Resources_DEFAULT NULL +#define fnv1_Resources_items_MSGTYPE fnv1_Resource + +#define fnv1_RunFunctionResponse_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, meta, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, desired, 2) \ +X(a, POINTER, REPEATED, MESSAGE, results, 3) \ +X(a, STATIC, OPTIONAL, MESSAGE, context, 4) \ +X(a, STATIC, OPTIONAL, MESSAGE, requirements, 5) \ +X(a, POINTER, REPEATED, MESSAGE, conditions, 6) \ +X(a, STATIC, OPTIONAL, MESSAGE, output, 7) +#define fnv1_RunFunctionResponse_CALLBACK NULL +#define fnv1_RunFunctionResponse_DEFAULT NULL +#define fnv1_RunFunctionResponse_meta_MSGTYPE fnv1_ResponseMeta +#define fnv1_RunFunctionResponse_desired_MSGTYPE fnv1_State +#define fnv1_RunFunctionResponse_results_MSGTYPE fnv1_Result +#define fnv1_RunFunctionResponse_context_MSGTYPE google_protobuf_Struct +#define fnv1_RunFunctionResponse_requirements_MSGTYPE fnv1_Requirements +#define fnv1_RunFunctionResponse_conditions_MSGTYPE fnv1_Condition +#define fnv1_RunFunctionResponse_output_MSGTYPE google_protobuf_Struct + +#define fnv1_RequestMeta_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, tag, 1) \ +X(a, POINTER, REPEATED, UENUM, capabilities, 2) +#define fnv1_RequestMeta_CALLBACK NULL +#define fnv1_RequestMeta_DEFAULT NULL + +#define fnv1_Requirements_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, extra_resources, 1) \ +X(a, POINTER, REPEATED, MESSAGE, resources, 2) \ +X(a, POINTER, REPEATED, MESSAGE, schemas, 3) +#define fnv1_Requirements_CALLBACK NULL +#define fnv1_Requirements_DEFAULT NULL +#define fnv1_Requirements_extra_resources_MSGTYPE fnv1_Requirements_ExtraResourcesEntry +#define fnv1_Requirements_resources_MSGTYPE fnv1_Requirements_ResourcesEntry +#define fnv1_Requirements_schemas_MSGTYPE fnv1_Requirements_SchemasEntry + +#define fnv1_Requirements_ExtraResourcesEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_Requirements_ExtraResourcesEntry_CALLBACK NULL +#define fnv1_Requirements_ExtraResourcesEntry_DEFAULT NULL +#define fnv1_Requirements_ExtraResourcesEntry_value_MSGTYPE fnv1_ResourceSelector + +#define fnv1_Requirements_ResourcesEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_Requirements_ResourcesEntry_CALLBACK NULL +#define fnv1_Requirements_ResourcesEntry_DEFAULT NULL +#define fnv1_Requirements_ResourcesEntry_value_MSGTYPE fnv1_ResourceSelector + +#define fnv1_Requirements_SchemasEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_Requirements_SchemasEntry_CALLBACK NULL +#define fnv1_Requirements_SchemasEntry_DEFAULT NULL +#define fnv1_Requirements_SchemasEntry_value_MSGTYPE fnv1_SchemaSelector + +#define fnv1_SchemaSelector_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, api_version, 1) \ +X(a, POINTER, SINGULAR, STRING, kind, 2) +#define fnv1_SchemaSelector_CALLBACK NULL +#define fnv1_SchemaSelector_DEFAULT NULL + +#define fnv1_Schema_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, openapi_v3, 1) +#define fnv1_Schema_CALLBACK NULL +#define fnv1_Schema_DEFAULT NULL +#define fnv1_Schema_openapi_v3_MSGTYPE google_protobuf_Struct + +#define fnv1_ResourceSelector_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, api_version, 1) \ +X(a, POINTER, SINGULAR, STRING, kind, 2) \ +X(a, POINTER, ONEOF, STRING, (match,match_name,match.match_name), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (match,match_labels,match.match_labels), 4) \ +X(a, POINTER, OPTIONAL, STRING, namespace, 5) +#define fnv1_ResourceSelector_CALLBACK NULL +#define fnv1_ResourceSelector_DEFAULT NULL +#define fnv1_ResourceSelector_match_match_labels_MSGTYPE fnv1_MatchLabels + +#define fnv1_MatchLabels_FIELDLIST(X, a) \ +X(a, POINTER, REPEATED, MESSAGE, labels, 1) +#define fnv1_MatchLabels_CALLBACK NULL +#define fnv1_MatchLabels_DEFAULT NULL +#define fnv1_MatchLabels_labels_MSGTYPE fnv1_MatchLabels_LabelsEntry + +#define fnv1_MatchLabels_LabelsEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, POINTER, SINGULAR, STRING, value, 2) +#define fnv1_MatchLabels_LabelsEntry_CALLBACK NULL +#define fnv1_MatchLabels_LabelsEntry_DEFAULT NULL + +#define fnv1_ResponseMeta_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, tag, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, ttl, 2) +#define fnv1_ResponseMeta_CALLBACK NULL +#define fnv1_ResponseMeta_DEFAULT NULL +#define fnv1_ResponseMeta_ttl_MSGTYPE google_protobuf_Duration + +#define fnv1_State_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, composite, 1) \ +X(a, POINTER, REPEATED, MESSAGE, resources, 2) +#define fnv1_State_CALLBACK NULL +#define fnv1_State_DEFAULT NULL +#define fnv1_State_composite_MSGTYPE fnv1_Resource +#define fnv1_State_resources_MSGTYPE fnv1_State_ResourcesEntry + +#define fnv1_State_ResourcesEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, value, 2) +#define fnv1_State_ResourcesEntry_CALLBACK NULL +#define fnv1_State_ResourcesEntry_DEFAULT NULL +#define fnv1_State_ResourcesEntry_value_MSGTYPE fnv1_Resource + +#define fnv1_Resource_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, resource, 1) \ +X(a, POINTER, REPEATED, MESSAGE, connection_details, 2) \ +X(a, STATIC, SINGULAR, UENUM, ready, 3) +#define fnv1_Resource_CALLBACK NULL +#define fnv1_Resource_DEFAULT NULL +#define fnv1_Resource_resource_MSGTYPE google_protobuf_Struct +#define fnv1_Resource_connection_details_MSGTYPE fnv1_Resource_ConnectionDetailsEntry + +#define fnv1_Resource_ConnectionDetailsEntry_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, key, 1) \ +X(a, POINTER, SINGULAR, BYTES, value, 2) +#define fnv1_Resource_ConnectionDetailsEntry_CALLBACK NULL +#define fnv1_Resource_ConnectionDetailsEntry_DEFAULT NULL + +#define fnv1_Result_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, severity, 1) \ +X(a, POINTER, SINGULAR, STRING, message, 2) \ +X(a, POINTER, OPTIONAL, STRING, reason, 3) \ +X(a, STATIC, OPTIONAL, UENUM, target, 4) +#define fnv1_Result_CALLBACK NULL +#define fnv1_Result_DEFAULT NULL + +#define fnv1_Condition_FIELDLIST(X, a) \ +X(a, POINTER, SINGULAR, STRING, type, 1) \ +X(a, STATIC, SINGULAR, UENUM, status, 2) \ +X(a, POINTER, SINGULAR, STRING, reason, 3) \ +X(a, POINTER, OPTIONAL, STRING, message, 4) \ +X(a, STATIC, OPTIONAL, UENUM, target, 5) +#define fnv1_Condition_CALLBACK NULL +#define fnv1_Condition_DEFAULT NULL + +extern const pb_msgdesc_t fnv1_RunFunctionRequest_msg; +extern const pb_msgdesc_t fnv1_RunFunctionRequest_ExtraResourcesEntry_msg; +extern const pb_msgdesc_t fnv1_RunFunctionRequest_CredentialsEntry_msg; +extern const pb_msgdesc_t fnv1_RunFunctionRequest_RequiredResourcesEntry_msg; +extern const pb_msgdesc_t fnv1_RunFunctionRequest_RequiredSchemasEntry_msg; +extern const pb_msgdesc_t fnv1_Credentials_msg; +extern const pb_msgdesc_t fnv1_CredentialData_msg; +extern const pb_msgdesc_t fnv1_CredentialData_DataEntry_msg; +extern const pb_msgdesc_t fnv1_Resources_msg; +extern const pb_msgdesc_t fnv1_RunFunctionResponse_msg; +extern const pb_msgdesc_t fnv1_RequestMeta_msg; +extern const pb_msgdesc_t fnv1_Requirements_msg; +extern const pb_msgdesc_t fnv1_Requirements_ExtraResourcesEntry_msg; +extern const pb_msgdesc_t fnv1_Requirements_ResourcesEntry_msg; +extern const pb_msgdesc_t fnv1_Requirements_SchemasEntry_msg; +extern const pb_msgdesc_t fnv1_SchemaSelector_msg; +extern const pb_msgdesc_t fnv1_Schema_msg; +extern const pb_msgdesc_t fnv1_ResourceSelector_msg; +extern const pb_msgdesc_t fnv1_MatchLabels_msg; +extern const pb_msgdesc_t fnv1_MatchLabels_LabelsEntry_msg; +extern const pb_msgdesc_t fnv1_ResponseMeta_msg; +extern const pb_msgdesc_t fnv1_State_msg; +extern const pb_msgdesc_t fnv1_State_ResourcesEntry_msg; +extern const pb_msgdesc_t fnv1_Resource_msg; +extern const pb_msgdesc_t fnv1_Resource_ConnectionDetailsEntry_msg; +extern const pb_msgdesc_t fnv1_Result_msg; +extern const pb_msgdesc_t fnv1_Condition_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define fnv1_RunFunctionRequest_fields &fnv1_RunFunctionRequest_msg +#define fnv1_RunFunctionRequest_ExtraResourcesEntry_fields &fnv1_RunFunctionRequest_ExtraResourcesEntry_msg +#define fnv1_RunFunctionRequest_CredentialsEntry_fields &fnv1_RunFunctionRequest_CredentialsEntry_msg +#define fnv1_RunFunctionRequest_RequiredResourcesEntry_fields &fnv1_RunFunctionRequest_RequiredResourcesEntry_msg +#define fnv1_RunFunctionRequest_RequiredSchemasEntry_fields &fnv1_RunFunctionRequest_RequiredSchemasEntry_msg +#define fnv1_Credentials_fields &fnv1_Credentials_msg +#define fnv1_CredentialData_fields &fnv1_CredentialData_msg +#define fnv1_CredentialData_DataEntry_fields &fnv1_CredentialData_DataEntry_msg +#define fnv1_Resources_fields &fnv1_Resources_msg +#define fnv1_RunFunctionResponse_fields &fnv1_RunFunctionResponse_msg +#define fnv1_RequestMeta_fields &fnv1_RequestMeta_msg +#define fnv1_Requirements_fields &fnv1_Requirements_msg +#define fnv1_Requirements_ExtraResourcesEntry_fields &fnv1_Requirements_ExtraResourcesEntry_msg +#define fnv1_Requirements_ResourcesEntry_fields &fnv1_Requirements_ResourcesEntry_msg +#define fnv1_Requirements_SchemasEntry_fields &fnv1_Requirements_SchemasEntry_msg +#define fnv1_SchemaSelector_fields &fnv1_SchemaSelector_msg +#define fnv1_Schema_fields &fnv1_Schema_msg +#define fnv1_ResourceSelector_fields &fnv1_ResourceSelector_msg +#define fnv1_MatchLabels_fields &fnv1_MatchLabels_msg +#define fnv1_MatchLabels_LabelsEntry_fields &fnv1_MatchLabels_LabelsEntry_msg +#define fnv1_ResponseMeta_fields &fnv1_ResponseMeta_msg +#define fnv1_State_fields &fnv1_State_msg +#define fnv1_State_ResourcesEntry_fields &fnv1_State_ResourcesEntry_msg +#define fnv1_Resource_fields &fnv1_Resource_msg +#define fnv1_Resource_ConnectionDetailsEntry_fields &fnv1_Resource_ConnectionDetailsEntry_msg +#define fnv1_Result_fields &fnv1_Result_msg +#define fnv1_Condition_fields &fnv1_Condition_msg + +/* Maximum encoded size of messages (where known) */ +/* fnv1_RunFunctionRequest_size depends on runtime parameters */ +/* fnv1_RunFunctionRequest_ExtraResourcesEntry_size depends on runtime parameters */ +/* fnv1_RunFunctionRequest_CredentialsEntry_size depends on runtime parameters */ +/* fnv1_RunFunctionRequest_RequiredResourcesEntry_size depends on runtime parameters */ +/* fnv1_RunFunctionRequest_RequiredSchemasEntry_size depends on runtime parameters */ +/* fnv1_Credentials_size depends on runtime parameters */ +/* fnv1_CredentialData_size depends on runtime parameters */ +/* fnv1_CredentialData_DataEntry_size depends on runtime parameters */ +/* fnv1_Resources_size depends on runtime parameters */ +/* fnv1_RunFunctionResponse_size depends on runtime parameters */ +/* fnv1_RequestMeta_size depends on runtime parameters */ +/* fnv1_Requirements_size depends on runtime parameters */ +/* fnv1_Requirements_ExtraResourcesEntry_size depends on runtime parameters */ +/* fnv1_Requirements_ResourcesEntry_size depends on runtime parameters */ +/* fnv1_Requirements_SchemasEntry_size depends on runtime parameters */ +/* fnv1_SchemaSelector_size depends on runtime parameters */ +/* fnv1_ResourceSelector_size depends on runtime parameters */ +/* fnv1_MatchLabels_size depends on runtime parameters */ +/* fnv1_MatchLabels_LabelsEntry_size depends on runtime parameters */ +/* fnv1_ResponseMeta_size depends on runtime parameters */ +/* fnv1_State_size depends on runtime parameters */ +/* fnv1_State_ResourcesEntry_size depends on runtime parameters */ +/* fnv1_Resource_size depends on runtime parameters */ +/* fnv1_Resource_ConnectionDetailsEntry_size depends on runtime parameters */ +/* fnv1_Result_size depends on runtime parameters */ +/* fnv1_Condition_size depends on runtime parameters */ +#if defined(google_protobuf_Struct_size) +#define APIEXTENSIONS_FN_PROTO_V1_RUN_FUNCTION_PB_H_MAX_SIZE fnv1_Schema_size +#define fnv1_Schema_size (6 + google_protobuf_Struct_size) +#endif + +/* Mapping from canonical names (mangle_names or overridden package name) */ +#define apiextensions_fn_proto_v1_Capability fnv1_Capability +#define apiextensions_fn_proto_v1_Ready fnv1_Ready +#define apiextensions_fn_proto_v1_Severity fnv1_Severity +#define apiextensions_fn_proto_v1_Target fnv1_Target +#define apiextensions_fn_proto_v1_Status fnv1_Status +#define apiextensions_fn_proto_v1_RunFunctionRequest fnv1_RunFunctionRequest +#define apiextensions_fn_proto_v1_RunFunctionRequest_ExtraResourcesEntry fnv1_RunFunctionRequest_ExtraResourcesEntry +#define apiextensions_fn_proto_v1_RunFunctionRequest_CredentialsEntry fnv1_RunFunctionRequest_CredentialsEntry +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredResourcesEntry fnv1_RunFunctionRequest_RequiredResourcesEntry +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredSchemasEntry fnv1_RunFunctionRequest_RequiredSchemasEntry +#define apiextensions_fn_proto_v1_Credentials fnv1_Credentials +#define apiextensions_fn_proto_v1_CredentialData fnv1_CredentialData +#define apiextensions_fn_proto_v1_CredentialData_DataEntry fnv1_CredentialData_DataEntry +#define apiextensions_fn_proto_v1_Resources fnv1_Resources +#define apiextensions_fn_proto_v1_RunFunctionResponse fnv1_RunFunctionResponse +#define apiextensions_fn_proto_v1_RequestMeta fnv1_RequestMeta +#define apiextensions_fn_proto_v1_Requirements fnv1_Requirements +#define apiextensions_fn_proto_v1_Requirements_ExtraResourcesEntry fnv1_Requirements_ExtraResourcesEntry +#define apiextensions_fn_proto_v1_Requirements_ResourcesEntry fnv1_Requirements_ResourcesEntry +#define apiextensions_fn_proto_v1_Requirements_SchemasEntry fnv1_Requirements_SchemasEntry +#define apiextensions_fn_proto_v1_SchemaSelector fnv1_SchemaSelector +#define apiextensions_fn_proto_v1_Schema fnv1_Schema +#define apiextensions_fn_proto_v1_ResourceSelector fnv1_ResourceSelector +#define apiextensions_fn_proto_v1_MatchLabels fnv1_MatchLabels +#define apiextensions_fn_proto_v1_MatchLabels_LabelsEntry fnv1_MatchLabels_LabelsEntry +#define apiextensions_fn_proto_v1_ResponseMeta fnv1_ResponseMeta +#define apiextensions_fn_proto_v1_State fnv1_State +#define apiextensions_fn_proto_v1_State_ResourcesEntry fnv1_State_ResourcesEntry +#define apiextensions_fn_proto_v1_Resource fnv1_Resource +#define apiextensions_fn_proto_v1_Resource_ConnectionDetailsEntry fnv1_Resource_ConnectionDetailsEntry +#define apiextensions_fn_proto_v1_Result fnv1_Result +#define apiextensions_fn_proto_v1_Condition fnv1_Condition +#define _apiextensions_fn_proto_v1_Capability_MIN _fnv1_Capability_MIN +#define _apiextensions_fn_proto_v1_Capability_MAX _fnv1_Capability_MAX +#define _apiextensions_fn_proto_v1_Capability_ARRAYSIZE _fnv1_Capability_ARRAYSIZE +#define _apiextensions_fn_proto_v1_Ready_MIN _fnv1_Ready_MIN +#define _apiextensions_fn_proto_v1_Ready_MAX _fnv1_Ready_MAX +#define _apiextensions_fn_proto_v1_Ready_ARRAYSIZE _fnv1_Ready_ARRAYSIZE +#define _apiextensions_fn_proto_v1_Severity_MIN _fnv1_Severity_MIN +#define _apiextensions_fn_proto_v1_Severity_MAX _fnv1_Severity_MAX +#define _apiextensions_fn_proto_v1_Severity_ARRAYSIZE _fnv1_Severity_ARRAYSIZE +#define _apiextensions_fn_proto_v1_Target_MIN _fnv1_Target_MIN +#define _apiextensions_fn_proto_v1_Target_MAX _fnv1_Target_MAX +#define _apiextensions_fn_proto_v1_Target_ARRAYSIZE _fnv1_Target_ARRAYSIZE +#define _apiextensions_fn_proto_v1_Status_MIN _fnv1_Status_MIN +#define _apiextensions_fn_proto_v1_Status_MAX _fnv1_Status_MAX +#define _apiextensions_fn_proto_v1_Status_ARRAYSIZE _fnv1_Status_ARRAYSIZE +#define apiextensions_fn_proto_v1_RunFunctionRequest_init_default fnv1_RunFunctionRequest_init_default +#define apiextensions_fn_proto_v1_RunFunctionRequest_ExtraResourcesEntry_init_default fnv1_RunFunctionRequest_ExtraResourcesEntry_init_default +#define apiextensions_fn_proto_v1_RunFunctionRequest_CredentialsEntry_init_default fnv1_RunFunctionRequest_CredentialsEntry_init_default +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredResourcesEntry_init_default fnv1_RunFunctionRequest_RequiredResourcesEntry_init_default +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredSchemasEntry_init_default fnv1_RunFunctionRequest_RequiredSchemasEntry_init_default +#define apiextensions_fn_proto_v1_Credentials_init_default fnv1_Credentials_init_default +#define apiextensions_fn_proto_v1_CredentialData_init_default fnv1_CredentialData_init_default +#define apiextensions_fn_proto_v1_CredentialData_DataEntry_init_default fnv1_CredentialData_DataEntry_init_default +#define apiextensions_fn_proto_v1_Resources_init_default fnv1_Resources_init_default +#define apiextensions_fn_proto_v1_RunFunctionResponse_init_default fnv1_RunFunctionResponse_init_default +#define apiextensions_fn_proto_v1_RequestMeta_init_default fnv1_RequestMeta_init_default +#define apiextensions_fn_proto_v1_Requirements_init_default fnv1_Requirements_init_default +#define apiextensions_fn_proto_v1_Requirements_ExtraResourcesEntry_init_default fnv1_Requirements_ExtraResourcesEntry_init_default +#define apiextensions_fn_proto_v1_Requirements_ResourcesEntry_init_default fnv1_Requirements_ResourcesEntry_init_default +#define apiextensions_fn_proto_v1_Requirements_SchemasEntry_init_default fnv1_Requirements_SchemasEntry_init_default +#define apiextensions_fn_proto_v1_SchemaSelector_init_default fnv1_SchemaSelector_init_default +#define apiextensions_fn_proto_v1_Schema_init_default fnv1_Schema_init_default +#define apiextensions_fn_proto_v1_ResourceSelector_init_default fnv1_ResourceSelector_init_default +#define apiextensions_fn_proto_v1_MatchLabels_init_default fnv1_MatchLabels_init_default +#define apiextensions_fn_proto_v1_MatchLabels_LabelsEntry_init_default fnv1_MatchLabels_LabelsEntry_init_default +#define apiextensions_fn_proto_v1_ResponseMeta_init_default fnv1_ResponseMeta_init_default +#define apiextensions_fn_proto_v1_State_init_default fnv1_State_init_default +#define apiextensions_fn_proto_v1_State_ResourcesEntry_init_default fnv1_State_ResourcesEntry_init_default +#define apiextensions_fn_proto_v1_Resource_init_default fnv1_Resource_init_default +#define apiextensions_fn_proto_v1_Resource_ConnectionDetailsEntry_init_default fnv1_Resource_ConnectionDetailsEntry_init_default +#define apiextensions_fn_proto_v1_Result_init_default fnv1_Result_init_default +#define apiextensions_fn_proto_v1_Condition_init_default fnv1_Condition_init_default +#define apiextensions_fn_proto_v1_RunFunctionRequest_init_zero fnv1_RunFunctionRequest_init_zero +#define apiextensions_fn_proto_v1_RunFunctionRequest_ExtraResourcesEntry_init_zero fnv1_RunFunctionRequest_ExtraResourcesEntry_init_zero +#define apiextensions_fn_proto_v1_RunFunctionRequest_CredentialsEntry_init_zero fnv1_RunFunctionRequest_CredentialsEntry_init_zero +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredResourcesEntry_init_zero fnv1_RunFunctionRequest_RequiredResourcesEntry_init_zero +#define apiextensions_fn_proto_v1_RunFunctionRequest_RequiredSchemasEntry_init_zero fnv1_RunFunctionRequest_RequiredSchemasEntry_init_zero +#define apiextensions_fn_proto_v1_Credentials_init_zero fnv1_Credentials_init_zero +#define apiextensions_fn_proto_v1_CredentialData_init_zero fnv1_CredentialData_init_zero +#define apiextensions_fn_proto_v1_CredentialData_DataEntry_init_zero fnv1_CredentialData_DataEntry_init_zero +#define apiextensions_fn_proto_v1_Resources_init_zero fnv1_Resources_init_zero +#define apiextensions_fn_proto_v1_RunFunctionResponse_init_zero fnv1_RunFunctionResponse_init_zero +#define apiextensions_fn_proto_v1_RequestMeta_init_zero fnv1_RequestMeta_init_zero +#define apiextensions_fn_proto_v1_Requirements_init_zero fnv1_Requirements_init_zero +#define apiextensions_fn_proto_v1_Requirements_ExtraResourcesEntry_init_zero fnv1_Requirements_ExtraResourcesEntry_init_zero +#define apiextensions_fn_proto_v1_Requirements_ResourcesEntry_init_zero fnv1_Requirements_ResourcesEntry_init_zero +#define apiextensions_fn_proto_v1_Requirements_SchemasEntry_init_zero fnv1_Requirements_SchemasEntry_init_zero +#define apiextensions_fn_proto_v1_SchemaSelector_init_zero fnv1_SchemaSelector_init_zero +#define apiextensions_fn_proto_v1_Schema_init_zero fnv1_Schema_init_zero +#define apiextensions_fn_proto_v1_ResourceSelector_init_zero fnv1_ResourceSelector_init_zero +#define apiextensions_fn_proto_v1_MatchLabels_init_zero fnv1_MatchLabels_init_zero +#define apiextensions_fn_proto_v1_MatchLabels_LabelsEntry_init_zero fnv1_MatchLabels_LabelsEntry_init_zero +#define apiextensions_fn_proto_v1_ResponseMeta_init_zero fnv1_ResponseMeta_init_zero +#define apiextensions_fn_proto_v1_State_init_zero fnv1_State_init_zero +#define apiextensions_fn_proto_v1_State_ResourcesEntry_init_zero fnv1_State_ResourcesEntry_init_zero +#define apiextensions_fn_proto_v1_Resource_init_zero fnv1_Resource_init_zero +#define apiextensions_fn_proto_v1_Resource_ConnectionDetailsEntry_init_zero fnv1_Resource_ConnectionDetailsEntry_init_zero +#define apiextensions_fn_proto_v1_Result_init_zero fnv1_Result_init_zero +#define apiextensions_fn_proto_v1_Condition_init_zero fnv1_Condition_init_zero + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/examples/hello-odin/src/gen/function.c b/examples/hello-odin/src/gen/function.c new file mode 100644 index 00000000..43bf8fa8 --- /dev/null +++ b/examples/hello-odin/src/gen/function.c @@ -0,0 +1,5585 @@ +// Generated by `wit-bindgen` 0.62.0. DO NOT EDIT! +#include "function.h" +#include +#include + +// Imported Functions from `wasi:io/poll@0.2.12` + +__attribute__((__import_module__("wasi:io/poll@0.2.12"), __import_name__("[method]pollable.ready"))) +extern int32_t __wasm_import_wasi_io_poll_method_pollable_ready(int32_t); + +__attribute__((__import_module__("wasi:io/poll@0.2.12"), __import_name__("[method]pollable.block"))) +extern void __wasm_import_wasi_io_poll_method_pollable_block(int32_t); + +__attribute__((__import_module__("wasi:io/poll@0.2.12"), __import_name__("poll"))) +extern void __wasm_import_wasi_io_poll_poll(uint8_t *, size_t, uint8_t *); + +// Imported Functions from `wasi:clocks/monotonic-clock@0.2.12` + +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.2.12"), __import_name__("now"))) +extern int64_t __wasm_import_wasi_clocks_monotonic_clock_now(void); + +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.2.12"), __import_name__("resolution"))) +extern int64_t __wasm_import_wasi_clocks_monotonic_clock_resolution(void); + +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.2.12"), __import_name__("subscribe-instant"))) +extern int32_t __wasm_import_wasi_clocks_monotonic_clock_subscribe_instant(int64_t); + +__attribute__((__import_module__("wasi:clocks/monotonic-clock@0.2.12"), __import_name__("subscribe-duration"))) +extern int32_t __wasm_import_wasi_clocks_monotonic_clock_subscribe_duration(int64_t); + +// Imported Functions from `wasi:io/error@0.2.12` + +__attribute__((__import_module__("wasi:io/error@0.2.12"), __import_name__("[method]error.to-debug-string"))) +extern void __wasm_import_wasi_io_error_method_error_to_debug_string(int32_t, uint8_t *); + +// Imported Functions from `wasi:io/streams@0.2.12` + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]input-stream.read"))) +extern void __wasm_import_wasi_io_streams_method_input_stream_read(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]input-stream.blocking-read"))) +extern void __wasm_import_wasi_io_streams_method_input_stream_blocking_read(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]input-stream.skip"))) +extern void __wasm_import_wasi_io_streams_method_input_stream_skip(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]input-stream.blocking-skip"))) +extern void __wasm_import_wasi_io_streams_method_input_stream_blocking_skip(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]input-stream.subscribe"))) +extern int32_t __wasm_import_wasi_io_streams_method_input_stream_subscribe(int32_t); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.check-write"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_check_write(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.write"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_write(int32_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.blocking-write-and-flush"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_blocking_write_and_flush(int32_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.flush"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_flush(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.blocking-flush"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_blocking_flush(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.subscribe"))) +extern int32_t __wasm_import_wasi_io_streams_method_output_stream_subscribe(int32_t); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.write-zeroes"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_write_zeroes(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.blocking-write-zeroes-and-flush"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_blocking_write_zeroes_and_flush(int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.splice"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_splice(int32_t, int32_t, int64_t, uint8_t *); + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[method]output-stream.blocking-splice"))) +extern void __wasm_import_wasi_io_streams_method_output_stream_blocking_splice(int32_t, int32_t, int64_t, uint8_t *); + +// Imported Functions from `wasi:http/types@0.2.12` + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[constructor]fields"))) +extern int32_t __wasm_import_wasi_http_types_constructor_fields(void); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[static]fields.from-list"))) +extern void __wasm_import_wasi_http_types_static_fields_from_list(uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.get"))) +extern void __wasm_import_wasi_http_types_method_fields_get(int32_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.has"))) +extern int32_t __wasm_import_wasi_http_types_method_fields_has(int32_t, uint8_t *, size_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.set"))) +extern void __wasm_import_wasi_http_types_method_fields_set(int32_t, uint8_t *, size_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.delete"))) +extern void __wasm_import_wasi_http_types_method_fields_delete(int32_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.append"))) +extern void __wasm_import_wasi_http_types_method_fields_append(int32_t, uint8_t *, size_t, uint8_t *, size_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.entries"))) +extern void __wasm_import_wasi_http_types_method_fields_entries(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]fields.clone"))) +extern int32_t __wasm_import_wasi_http_types_method_fields_clone(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.method"))) +extern void __wasm_import_wasi_http_types_method_incoming_request_method(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.path-with-query"))) +extern void __wasm_import_wasi_http_types_method_incoming_request_path_with_query(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.scheme"))) +extern void __wasm_import_wasi_http_types_method_incoming_request_scheme(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.authority"))) +extern void __wasm_import_wasi_http_types_method_incoming_request_authority(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.headers"))) +extern int32_t __wasm_import_wasi_http_types_method_incoming_request_headers(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-request.consume"))) +extern void __wasm_import_wasi_http_types_method_incoming_request_consume(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[constructor]outgoing-request"))) +extern int32_t __wasm_import_wasi_http_types_constructor_outgoing_request(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.body"))) +extern void __wasm_import_wasi_http_types_method_outgoing_request_body(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.method"))) +extern void __wasm_import_wasi_http_types_method_outgoing_request_method(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.set-method"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_request_set_method(int32_t, int32_t, uint8_t *, size_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.path-with-query"))) +extern void __wasm_import_wasi_http_types_method_outgoing_request_path_with_query(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.set-path-with-query"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_request_set_path_with_query(int32_t, int32_t, uint8_t *, size_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.scheme"))) +extern void __wasm_import_wasi_http_types_method_outgoing_request_scheme(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.set-scheme"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_request_set_scheme(int32_t, int32_t, int32_t, uint8_t *, size_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.authority"))) +extern void __wasm_import_wasi_http_types_method_outgoing_request_authority(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.set-authority"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_request_set_authority(int32_t, int32_t, uint8_t *, size_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-request.headers"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_request_headers(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[constructor]request-options"))) +extern int32_t __wasm_import_wasi_http_types_constructor_request_options(void); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.connect-timeout"))) +extern void __wasm_import_wasi_http_types_method_request_options_connect_timeout(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.set-connect-timeout"))) +extern int32_t __wasm_import_wasi_http_types_method_request_options_set_connect_timeout(int32_t, int32_t, int64_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.first-byte-timeout"))) +extern void __wasm_import_wasi_http_types_method_request_options_first_byte_timeout(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.set-first-byte-timeout"))) +extern int32_t __wasm_import_wasi_http_types_method_request_options_set_first_byte_timeout(int32_t, int32_t, int64_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.between-bytes-timeout"))) +extern void __wasm_import_wasi_http_types_method_request_options_between_bytes_timeout(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]request-options.set-between-bytes-timeout"))) +extern int32_t __wasm_import_wasi_http_types_method_request_options_set_between_bytes_timeout(int32_t, int32_t, int64_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[static]response-outparam.set"))) +extern void __wasm_import_wasi_http_types_static_response_outparam_set(int32_t, int32_t, int32_t, int32_t, int64_t, uint8_t *, uint8_t *, size_t, int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-response.status"))) +extern int32_t __wasm_import_wasi_http_types_method_incoming_response_status(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-response.headers"))) +extern int32_t __wasm_import_wasi_http_types_method_incoming_response_headers(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-response.consume"))) +extern void __wasm_import_wasi_http_types_method_incoming_response_consume(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]incoming-body.stream"))) +extern void __wasm_import_wasi_http_types_method_incoming_body_stream(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[static]incoming-body.finish"))) +extern int32_t __wasm_import_wasi_http_types_static_incoming_body_finish(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]future-trailers.subscribe"))) +extern int32_t __wasm_import_wasi_http_types_method_future_trailers_subscribe(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]future-trailers.get"))) +extern void __wasm_import_wasi_http_types_method_future_trailers_get(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[constructor]outgoing-response"))) +extern int32_t __wasm_import_wasi_http_types_constructor_outgoing_response(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-response.status-code"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_response_status_code(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-response.set-status-code"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_response_set_status_code(int32_t, int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-response.headers"))) +extern int32_t __wasm_import_wasi_http_types_method_outgoing_response_headers(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-response.body"))) +extern void __wasm_import_wasi_http_types_method_outgoing_response_body(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]outgoing-body.write"))) +extern void __wasm_import_wasi_http_types_method_outgoing_body_write(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[static]outgoing-body.finish"))) +extern void __wasm_import_wasi_http_types_static_outgoing_body_finish(int32_t, int32_t, int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]future-incoming-response.subscribe"))) +extern int32_t __wasm_import_wasi_http_types_method_future_incoming_response_subscribe(int32_t); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[method]future-incoming-response.get"))) +extern void __wasm_import_wasi_http_types_method_future_incoming_response_get(int32_t, uint8_t *); + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("http-error-code"))) +extern void __wasm_import_wasi_http_types_http_error_code(int32_t, uint8_t *); + +// Imported Functions from `wasi:http/outgoing-handler@0.2.12` + +__attribute__((__import_module__("wasi:http/outgoing-handler@0.2.12"), __import_name__("handle"))) +extern void __wasm_import_wasi_http_outgoing_handler_handle(int32_t, int32_t, int32_t, uint8_t *); + +// Imported Functions from `function` + +__attribute__((__import_module__("$root"), __import_name__("log"))) +extern void __wasm_import_function_log(int32_t, uint8_t *, size_t, uint8_t *, size_t); + +// Exported Functions from `function` + +__attribute__((__weak__, __export_name__("cabi_post_run"))) +void __wasm_export_exports_function_run_post_return(uint8_t * arg0) { + switch ((int32_t) (int32_t) *((uint8_t*) (arg0 + 0))) { + case 0: { + size_t len = *((size_t*) (arg0 + (2*sizeof(void*)))); + if (len > 0) { + uint8_t *ptr = *((uint8_t **) (arg0 + sizeof(void*))); + for (size_t i = 0; i < len; i++) { + uint8_t *base = ptr + i * 1; + (void) base; + } + free(ptr); + } + break; + } + case 1: { + if ((*((size_t*) (arg0 + (2*sizeof(void*))))) > 0) { + free(*((uint8_t **) (arg0 + sizeof(void*)))); + } + break; + } + } +} + +// Canonical ABI intrinsics + +__attribute__((__weak__, __export_name__("cabi_realloc"))) +void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { + (void) old_size; + if (new_size == 0) return (void*) align; + void *ret = realloc(ptr, new_size); + if (!ret) abort(); + return ret; +} + +__attribute__((__aligned__(sizeof(void*)))) +static uint8_t RET_AREA[(3*sizeof(void*))]; + +// Helper Functions + +__attribute__((__import_module__("wasi:io/poll@0.2.12"), __import_name__("[resource-drop]pollable"))) +extern void __wasm_import_wasi_io_poll_pollable_drop(int32_t handle); + +void wasi_io_poll_pollable_drop_own(wasi_io_poll_own_pollable_t handle) { + __wasm_import_wasi_io_poll_pollable_drop(handle.__handle); +} + +void wasi_io_poll_pollable_drop_borrow(wasi_io_poll_borrow_pollable_t handle) { + __wasm_import_wasi_io_poll_pollable_drop(handle.__handle); +} + +wasi_io_poll_borrow_pollable_t wasi_io_poll_borrow_pollable(wasi_io_poll_own_pollable_t arg) { + return (wasi_io_poll_borrow_pollable_t) { arg.__handle }; +} + +void wasi_io_poll_list_borrow_pollable_free(wasi_io_poll_list_borrow_pollable_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + wasi_io_poll_borrow_pollable_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + } + free(list_ptr); + } +} + +void function_list_u32_free(function_list_u32_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + uint32_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + } + free(list_ptr); + } +} + +__attribute__((__import_module__("wasi:io/error@0.2.12"), __import_name__("[resource-drop]error"))) +extern void __wasm_import_wasi_io_error_error_drop(int32_t handle); + +void wasi_io_error_error_drop_own(wasi_io_error_own_error_t handle) { + __wasm_import_wasi_io_error_error_drop(handle.__handle); +} + +void wasi_io_error_error_drop_borrow(wasi_io_error_borrow_error_t handle) { + __wasm_import_wasi_io_error_error_drop(handle.__handle); +} + +wasi_io_error_borrow_error_t wasi_io_error_borrow_error(wasi_io_error_own_error_t arg) { + return (wasi_io_error_borrow_error_t) { arg.__handle }; +} + +void wasi_io_streams_stream_error_free(wasi_io_streams_stream_error_t *ptr) { + switch ((int32_t) ptr->tag) { + case 0: { + break; + } + } +} + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[resource-drop]input-stream"))) +extern void __wasm_import_wasi_io_streams_input_stream_drop(int32_t handle); + +void wasi_io_streams_input_stream_drop_own(wasi_io_streams_own_input_stream_t handle) { + __wasm_import_wasi_io_streams_input_stream_drop(handle.__handle); +} + +void wasi_io_streams_input_stream_drop_borrow(wasi_io_streams_borrow_input_stream_t handle) { + __wasm_import_wasi_io_streams_input_stream_drop(handle.__handle); +} + +wasi_io_streams_borrow_input_stream_t wasi_io_streams_borrow_input_stream(wasi_io_streams_own_input_stream_t arg) { + return (wasi_io_streams_borrow_input_stream_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:io/streams@0.2.12"), __import_name__("[resource-drop]output-stream"))) +extern void __wasm_import_wasi_io_streams_output_stream_drop(int32_t handle); + +void wasi_io_streams_output_stream_drop_own(wasi_io_streams_own_output_stream_t handle) { + __wasm_import_wasi_io_streams_output_stream_drop(handle.__handle); +} + +void wasi_io_streams_output_stream_drop_borrow(wasi_io_streams_borrow_output_stream_t handle) { + __wasm_import_wasi_io_streams_output_stream_drop(handle.__handle); +} + +wasi_io_streams_borrow_output_stream_t wasi_io_streams_borrow_output_stream(wasi_io_streams_own_output_stream_t arg) { + return (wasi_io_streams_borrow_output_stream_t) { arg.__handle }; +} + +void function_list_u8_free(function_list_u8_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + uint8_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + } + free(list_ptr); + } +} + +void wasi_io_streams_result_list_u8_stream_error_free(wasi_io_streams_result_list_u8_stream_error_t *ptr) { + if (!ptr->is_err) { + function_list_u8_free(&ptr->val.ok); + } else { + wasi_io_streams_stream_error_free(&ptr->val.err); + } +} + +void wasi_io_streams_result_u64_stream_error_free(wasi_io_streams_result_u64_stream_error_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_io_streams_stream_error_free(&ptr->val.err); + } +} + +void wasi_io_streams_result_void_stream_error_free(wasi_io_streams_result_void_stream_error_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_io_streams_stream_error_free(&ptr->val.err); + } +} + +void wasi_http_types_method_free(wasi_http_types_method_t *ptr) { + switch ((int32_t) ptr->tag) { + case 9: { + function_string_free(&ptr->val.other); + break; + } + } +} + +void wasi_http_types_scheme_free(wasi_http_types_scheme_t *ptr) { + switch ((int32_t) ptr->tag) { + case 2: { + function_string_free(&ptr->val.other); + break; + } + } +} + +void function_option_string_free(function_option_string_t *ptr) { + if (ptr->is_some) { + function_string_free(&ptr->val); + } +} + +void function_option_u16_free(function_option_u16_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_dns_error_payload_free(wasi_http_types_dns_error_payload_t *ptr) { + function_option_string_free(&ptr->rcode); + function_option_u16_free(&ptr->info_code); +} + +void function_option_u8_free(function_option_u8_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_tls_alert_received_payload_free(wasi_http_types_tls_alert_received_payload_t *ptr) { + function_option_u8_free(&ptr->alert_id); + function_option_string_free(&ptr->alert_message); +} + +void function_option_u32_free(function_option_u32_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_field_size_payload_free(wasi_http_types_field_size_payload_t *ptr) { + function_option_string_free(&ptr->field_name); + function_option_u32_free(&ptr->field_size); +} + +void function_option_u64_free(function_option_u64_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_option_field_size_payload_free(wasi_http_types_option_field_size_payload_t *ptr) { + if (ptr->is_some) { + wasi_http_types_field_size_payload_free(&ptr->val); + } +} + +void wasi_http_types_error_code_free(wasi_http_types_error_code_t *ptr) { + switch ((int32_t) ptr->tag) { + case 1: { + wasi_http_types_dns_error_payload_free(&ptr->val.dns_error); + break; + } + case 14: { + wasi_http_types_tls_alert_received_payload_free(&ptr->val.tls_alert_received); + break; + } + case 17: { + function_option_u64_free(&ptr->val.http_request_body_size); + break; + } + case 21: { + function_option_u32_free(&ptr->val.http_request_header_section_size); + break; + } + case 22: { + wasi_http_types_option_field_size_payload_free(&ptr->val.http_request_header_size); + break; + } + case 23: { + function_option_u32_free(&ptr->val.http_request_trailer_section_size); + break; + } + case 24: { + wasi_http_types_field_size_payload_free(&ptr->val.http_request_trailer_size); + break; + } + case 26: { + function_option_u32_free(&ptr->val.http_response_header_section_size); + break; + } + case 27: { + wasi_http_types_field_size_payload_free(&ptr->val.http_response_header_size); + break; + } + case 28: { + function_option_u64_free(&ptr->val.http_response_body_size); + break; + } + case 29: { + function_option_u32_free(&ptr->val.http_response_trailer_section_size); + break; + } + case 30: { + wasi_http_types_field_size_payload_free(&ptr->val.http_response_trailer_size); + break; + } + case 31: { + function_option_string_free(&ptr->val.http_response_transfer_coding); + break; + } + case 32: { + function_option_string_free(&ptr->val.http_response_content_coding); + break; + } + case 38: { + function_option_string_free(&ptr->val.internal_error); + break; + } + } +} + +void wasi_http_types_header_error_free(wasi_http_types_header_error_t *ptr) { + switch ((int32_t) ptr->tag) { + } +} + +void wasi_http_types_field_key_free(wasi_http_types_field_key_t *ptr) { + function_string_free(ptr); +} + +void wasi_http_types_field_name_free(wasi_http_types_field_name_t *ptr) { + wasi_http_types_field_key_free(ptr); +} + +void wasi_http_types_field_value_free(wasi_http_types_field_value_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + uint8_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + } + free(list_ptr); + } +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]fields"))) +extern void __wasm_import_wasi_http_types_fields_drop(int32_t handle); + +void wasi_http_types_fields_drop_own(wasi_http_types_own_fields_t handle) { + __wasm_import_wasi_http_types_fields_drop(handle.__handle); +} + +void wasi_http_types_fields_drop_borrow(wasi_http_types_borrow_fields_t handle) { + __wasm_import_wasi_http_types_fields_drop(handle.__handle); +} + +wasi_http_types_borrow_fields_t wasi_http_types_borrow_fields(wasi_http_types_own_fields_t arg) { + return (wasi_http_types_borrow_fields_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]incoming-request"))) +extern void __wasm_import_wasi_http_types_incoming_request_drop(int32_t handle); + +void wasi_http_types_incoming_request_drop_own(wasi_http_types_own_incoming_request_t handle) { + __wasm_import_wasi_http_types_incoming_request_drop(handle.__handle); +} + +void wasi_http_types_incoming_request_drop_borrow(wasi_http_types_borrow_incoming_request_t handle) { + __wasm_import_wasi_http_types_incoming_request_drop(handle.__handle); +} + +wasi_http_types_borrow_incoming_request_t wasi_http_types_borrow_incoming_request(wasi_http_types_own_incoming_request_t arg) { + return (wasi_http_types_borrow_incoming_request_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]outgoing-request"))) +extern void __wasm_import_wasi_http_types_outgoing_request_drop(int32_t handle); + +void wasi_http_types_outgoing_request_drop_own(wasi_http_types_own_outgoing_request_t handle) { + __wasm_import_wasi_http_types_outgoing_request_drop(handle.__handle); +} + +void wasi_http_types_outgoing_request_drop_borrow(wasi_http_types_borrow_outgoing_request_t handle) { + __wasm_import_wasi_http_types_outgoing_request_drop(handle.__handle); +} + +wasi_http_types_borrow_outgoing_request_t wasi_http_types_borrow_outgoing_request(wasi_http_types_own_outgoing_request_t arg) { + return (wasi_http_types_borrow_outgoing_request_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]request-options"))) +extern void __wasm_import_wasi_http_types_request_options_drop(int32_t handle); + +void wasi_http_types_request_options_drop_own(wasi_http_types_own_request_options_t handle) { + __wasm_import_wasi_http_types_request_options_drop(handle.__handle); +} + +void wasi_http_types_request_options_drop_borrow(wasi_http_types_borrow_request_options_t handle) { + __wasm_import_wasi_http_types_request_options_drop(handle.__handle); +} + +wasi_http_types_borrow_request_options_t wasi_http_types_borrow_request_options(wasi_http_types_own_request_options_t arg) { + return (wasi_http_types_borrow_request_options_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]response-outparam"))) +extern void __wasm_import_wasi_http_types_response_outparam_drop(int32_t handle); + +void wasi_http_types_response_outparam_drop_own(wasi_http_types_own_response_outparam_t handle) { + __wasm_import_wasi_http_types_response_outparam_drop(handle.__handle); +} + +void wasi_http_types_response_outparam_drop_borrow(wasi_http_types_borrow_response_outparam_t handle) { + __wasm_import_wasi_http_types_response_outparam_drop(handle.__handle); +} + +wasi_http_types_borrow_response_outparam_t wasi_http_types_borrow_response_outparam(wasi_http_types_own_response_outparam_t arg) { + return (wasi_http_types_borrow_response_outparam_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]incoming-response"))) +extern void __wasm_import_wasi_http_types_incoming_response_drop(int32_t handle); + +void wasi_http_types_incoming_response_drop_own(wasi_http_types_own_incoming_response_t handle) { + __wasm_import_wasi_http_types_incoming_response_drop(handle.__handle); +} + +void wasi_http_types_incoming_response_drop_borrow(wasi_http_types_borrow_incoming_response_t handle) { + __wasm_import_wasi_http_types_incoming_response_drop(handle.__handle); +} + +wasi_http_types_borrow_incoming_response_t wasi_http_types_borrow_incoming_response(wasi_http_types_own_incoming_response_t arg) { + return (wasi_http_types_borrow_incoming_response_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]incoming-body"))) +extern void __wasm_import_wasi_http_types_incoming_body_drop(int32_t handle); + +void wasi_http_types_incoming_body_drop_own(wasi_http_types_own_incoming_body_t handle) { + __wasm_import_wasi_http_types_incoming_body_drop(handle.__handle); +} + +void wasi_http_types_incoming_body_drop_borrow(wasi_http_types_borrow_incoming_body_t handle) { + __wasm_import_wasi_http_types_incoming_body_drop(handle.__handle); +} + +wasi_http_types_borrow_incoming_body_t wasi_http_types_borrow_incoming_body(wasi_http_types_own_incoming_body_t arg) { + return (wasi_http_types_borrow_incoming_body_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]future-trailers"))) +extern void __wasm_import_wasi_http_types_future_trailers_drop(int32_t handle); + +void wasi_http_types_future_trailers_drop_own(wasi_http_types_own_future_trailers_t handle) { + __wasm_import_wasi_http_types_future_trailers_drop(handle.__handle); +} + +void wasi_http_types_future_trailers_drop_borrow(wasi_http_types_borrow_future_trailers_t handle) { + __wasm_import_wasi_http_types_future_trailers_drop(handle.__handle); +} + +wasi_http_types_borrow_future_trailers_t wasi_http_types_borrow_future_trailers(wasi_http_types_own_future_trailers_t arg) { + return (wasi_http_types_borrow_future_trailers_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]outgoing-response"))) +extern void __wasm_import_wasi_http_types_outgoing_response_drop(int32_t handle); + +void wasi_http_types_outgoing_response_drop_own(wasi_http_types_own_outgoing_response_t handle) { + __wasm_import_wasi_http_types_outgoing_response_drop(handle.__handle); +} + +void wasi_http_types_outgoing_response_drop_borrow(wasi_http_types_borrow_outgoing_response_t handle) { + __wasm_import_wasi_http_types_outgoing_response_drop(handle.__handle); +} + +wasi_http_types_borrow_outgoing_response_t wasi_http_types_borrow_outgoing_response(wasi_http_types_own_outgoing_response_t arg) { + return (wasi_http_types_borrow_outgoing_response_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]outgoing-body"))) +extern void __wasm_import_wasi_http_types_outgoing_body_drop(int32_t handle); + +void wasi_http_types_outgoing_body_drop_own(wasi_http_types_own_outgoing_body_t handle) { + __wasm_import_wasi_http_types_outgoing_body_drop(handle.__handle); +} + +void wasi_http_types_outgoing_body_drop_borrow(wasi_http_types_borrow_outgoing_body_t handle) { + __wasm_import_wasi_http_types_outgoing_body_drop(handle.__handle); +} + +wasi_http_types_borrow_outgoing_body_t wasi_http_types_borrow_outgoing_body(wasi_http_types_own_outgoing_body_t arg) { + return (wasi_http_types_borrow_outgoing_body_t) { arg.__handle }; +} + +__attribute__((__import_module__("wasi:http/types@0.2.12"), __import_name__("[resource-drop]future-incoming-response"))) +extern void __wasm_import_wasi_http_types_future_incoming_response_drop(int32_t handle); + +void wasi_http_types_future_incoming_response_drop_own(wasi_http_types_own_future_incoming_response_t handle) { + __wasm_import_wasi_http_types_future_incoming_response_drop(handle.__handle); +} + +void wasi_http_types_future_incoming_response_drop_borrow(wasi_http_types_borrow_future_incoming_response_t handle) { + __wasm_import_wasi_http_types_future_incoming_response_drop(handle.__handle); +} + +wasi_http_types_borrow_future_incoming_response_t wasi_http_types_borrow_future_incoming_response(wasi_http_types_own_future_incoming_response_t arg) { + return (wasi_http_types_borrow_future_incoming_response_t) { arg.__handle }; +} + +void wasi_http_types_tuple2_field_name_field_value_free(wasi_http_types_tuple2_field_name_field_value_t *ptr) { + wasi_http_types_field_name_free(&ptr->f0); + wasi_http_types_field_value_free(&ptr->f1); +} + +void wasi_http_types_list_tuple2_field_name_field_value_free(wasi_http_types_list_tuple2_field_name_field_value_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + wasi_http_types_tuple2_field_name_field_value_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + wasi_http_types_tuple2_field_name_field_value_free(&list_ptr[i]); + } + free(list_ptr); + } +} + +void wasi_http_types_result_own_fields_header_error_free(wasi_http_types_result_own_fields_header_error_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_types_header_error_free(&ptr->val.err); + } +} + +void wasi_http_types_list_field_value_free(wasi_http_types_list_field_value_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + wasi_http_types_field_value_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + wasi_http_types_field_value_free(&list_ptr[i]); + } + free(list_ptr); + } +} + +void wasi_http_types_result_void_header_error_free(wasi_http_types_result_void_header_error_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_types_header_error_free(&ptr->val.err); + } +} + +void wasi_http_types_option_scheme_free(wasi_http_types_option_scheme_t *ptr) { + if (ptr->is_some) { + wasi_http_types_scheme_free(&ptr->val); + } +} + +void wasi_http_types_result_own_incoming_body_void_free(wasi_http_types_result_own_incoming_body_void_t *ptr) { + if (!ptr->is_err) { + } +} + +void wasi_http_types_result_own_outgoing_body_void_free(wasi_http_types_result_own_outgoing_body_void_t *ptr) { + if (!ptr->is_err) { + } +} + +void wasi_http_types_result_void_void_free(wasi_http_types_result_void_void_t *ptr) { + if (!ptr->is_err) { + } +} + +void wasi_http_types_option_duration_free(wasi_http_types_option_duration_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_result_own_outgoing_response_error_code_free(wasi_http_types_result_own_outgoing_response_error_code_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_types_error_code_free(&ptr->val.err); + } +} + +void wasi_http_types_result_own_input_stream_void_free(wasi_http_types_result_own_input_stream_void_t *ptr) { + if (!ptr->is_err) { + } +} + +void wasi_http_types_option_own_trailers_free(wasi_http_types_option_own_trailers_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_types_result_option_own_trailers_error_code_free(wasi_http_types_result_option_own_trailers_error_code_t *ptr) { + if (!ptr->is_err) { + wasi_http_types_option_own_trailers_free(&ptr->val.ok); + } else { + wasi_http_types_error_code_free(&ptr->val.err); + } +} + +void wasi_http_types_result_result_option_own_trailers_error_code_void_free(wasi_http_types_result_result_option_own_trailers_error_code_void_t *ptr) { + if (!ptr->is_err) { + wasi_http_types_result_option_own_trailers_error_code_free(&ptr->val.ok); + } +} + +void wasi_http_types_option_result_result_option_own_trailers_error_code_void_free(wasi_http_types_option_result_result_option_own_trailers_error_code_void_t *ptr) { + if (ptr->is_some) { + wasi_http_types_result_result_option_own_trailers_error_code_void_free(&ptr->val); + } +} + +void wasi_http_types_result_own_output_stream_void_free(wasi_http_types_result_own_output_stream_void_t *ptr) { + if (!ptr->is_err) { + } +} + +void wasi_http_types_result_void_error_code_free(wasi_http_types_result_void_error_code_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_types_error_code_free(&ptr->val.err); + } +} + +void wasi_http_types_result_own_incoming_response_error_code_free(wasi_http_types_result_own_incoming_response_error_code_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_types_error_code_free(&ptr->val.err); + } +} + +void wasi_http_types_result_result_own_incoming_response_error_code_void_free(wasi_http_types_result_result_own_incoming_response_error_code_void_t *ptr) { + if (!ptr->is_err) { + wasi_http_types_result_own_incoming_response_error_code_free(&ptr->val.ok); + } +} + +void wasi_http_types_option_result_result_own_incoming_response_error_code_void_free(wasi_http_types_option_result_result_own_incoming_response_error_code_void_t *ptr) { + if (ptr->is_some) { + wasi_http_types_result_result_own_incoming_response_error_code_void_free(&ptr->val); + } +} + +void wasi_http_types_option_error_code_free(wasi_http_types_option_error_code_t *ptr) { + if (ptr->is_some) { + wasi_http_types_error_code_free(&ptr->val); + } +} + +void wasi_http_outgoing_handler_error_code_free(wasi_http_outgoing_handler_error_code_t *ptr) { + wasi_http_types_error_code_free(ptr); +} + +void wasi_http_outgoing_handler_option_own_request_options_free(wasi_http_outgoing_handler_option_own_request_options_t *ptr) { + if (ptr->is_some) { + } +} + +void wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_free(wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_t *ptr) { + if (!ptr->is_err) { + } else { + wasi_http_outgoing_handler_error_code_free(&ptr->val.err); + } +} + +void function_tuple2_string_string_free(function_tuple2_string_string_t *ptr) { + function_string_free(&ptr->f0); + function_string_free(&ptr->f1); +} + +void function_list_tuple2_string_string_free(function_list_tuple2_string_string_t *ptr) { + size_t list_len = ptr->len; + if (list_len > 0) { + function_tuple2_string_string_t *list_ptr = ptr->ptr; + for (size_t i = 0; i < list_len; i++) { + function_tuple2_string_string_free(&list_ptr[i]); + } + free(list_ptr); + } +} + +void function_result_list_u8_string_free(function_result_list_u8_string_t *ptr) { + if (!ptr->is_err) { + } else { + function_string_free(&ptr->val.err); + } +} + +void function_string_set(function_string_t *ret, const char*s) { + ret->ptr = (uint8_t*) s; + ret->len = strlen(s); +} + +void function_string_dup(function_string_t *ret, const char*s) { + ret->len = strlen(s); + ret->ptr = (uint8_t*) cabi_realloc(NULL, 0, 1, ret->len * 1); + memcpy(ret->ptr, s, ret->len * 1); +} + +void function_string_dup_n(function_string_t *ret, const char*s, size_t len) { + ret->len = len; + ret->ptr = (uint8_t*) cabi_realloc(NULL, 0, 1, ret->len * 1); + memcpy(ret->ptr, s, ret->len * 1); +} + +void function_string_free(function_string_t *ret) { + if (ret->len > 0) { + free(ret->ptr); + } + ret->ptr = NULL; + ret->len = 0; +} + +// Component Adapters + +bool wasi_io_poll_method_pollable_ready(wasi_io_poll_borrow_pollable_t self) { + int32_t ret = __wasm_import_wasi_io_poll_method_pollable_ready((self).__handle); + return ret; +} + +void wasi_io_poll_method_pollable_block(wasi_io_poll_borrow_pollable_t self) { + __wasm_import_wasi_io_poll_method_pollable_block((self).__handle); +} + +void wasi_io_poll_poll(wasi_io_poll_list_borrow_pollable_t *in, function_list_u32_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(2*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_poll_poll((uint8_t *) (*in).ptr, (*in).len, ptr); + *ret = (function_list_u32_t) { (uint32_t*)(*((uint8_t **) (ptr + 0))), (*((size_t*) (ptr + sizeof(void*)))) }; +} + +wasi_clocks_monotonic_clock_instant_t wasi_clocks_monotonic_clock_now(void) { + int64_t ret = __wasm_import_wasi_clocks_monotonic_clock_now(); + return (uint64_t) (ret); +} + +wasi_clocks_monotonic_clock_duration_t wasi_clocks_monotonic_clock_resolution(void) { + int64_t ret = __wasm_import_wasi_clocks_monotonic_clock_resolution(); + return (uint64_t) (ret); +} + +wasi_clocks_monotonic_clock_own_pollable_t wasi_clocks_monotonic_clock_subscribe_instant(wasi_clocks_monotonic_clock_instant_t when) { + int32_t ret = __wasm_import_wasi_clocks_monotonic_clock_subscribe_instant((int64_t) (when)); + return (wasi_clocks_monotonic_clock_own_pollable_t) { ret }; +} + +wasi_clocks_monotonic_clock_own_pollable_t wasi_clocks_monotonic_clock_subscribe_duration(wasi_clocks_monotonic_clock_duration_t when) { + int32_t ret = __wasm_import_wasi_clocks_monotonic_clock_subscribe_duration((int64_t) (when)); + return (wasi_clocks_monotonic_clock_own_pollable_t) { ret }; +} + +void wasi_io_error_method_error_to_debug_string(wasi_io_error_borrow_error_t self, function_string_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(2*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_error_method_error_to_debug_string((self).__handle, ptr); + *ret = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + 0))), (*((size_t*) (ptr + sizeof(void*)))) }; +} + +bool wasi_io_streams_method_input_stream_read(wasi_io_streams_borrow_input_stream_t self, uint64_t len, function_list_u8_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_input_stream_read((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_list_u8_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (function_list_u8_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + sizeof(void*))); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + (4+1*sizeof(void*)))) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_input_stream_blocking_read(wasi_io_streams_borrow_input_stream_t self, uint64_t len, function_list_u8_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_input_stream_blocking_read((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_list_u8_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (function_list_u8_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + sizeof(void*))); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + (4+1*sizeof(void*)))) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_input_stream_skip(wasi_io_streams_borrow_input_stream_t self, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_input_stream_skip((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_u64_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 12)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_input_stream_blocking_skip(wasi_io_streams_borrow_input_stream_t self, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_input_stream_blocking_skip((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_u64_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 12)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +wasi_io_streams_own_pollable_t wasi_io_streams_method_input_stream_subscribe(wasi_io_streams_borrow_input_stream_t self) { + int32_t ret = __wasm_import_wasi_io_streams_method_input_stream_subscribe((self).__handle); + return (wasi_io_streams_own_pollable_t) { ret }; +} + +bool wasi_io_streams_method_output_stream_check_write(wasi_io_streams_borrow_output_stream_t self, uint64_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_check_write((self).__handle, ptr); + wasi_io_streams_result_u64_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 12)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_write(wasi_io_streams_borrow_output_stream_t self, function_list_u8_t *contents, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_write((self).__handle, (uint8_t *) (*contents).ptr, (*contents).len, ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_blocking_write_and_flush(wasi_io_streams_borrow_output_stream_t self, function_list_u8_t *contents, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_blocking_write_and_flush((self).__handle, (uint8_t *) (*contents).ptr, (*contents).len, ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_flush(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_flush((self).__handle, ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_blocking_flush(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_blocking_flush((self).__handle, ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +wasi_io_streams_own_pollable_t wasi_io_streams_method_output_stream_subscribe(wasi_io_streams_borrow_output_stream_t self) { + int32_t ret = __wasm_import_wasi_io_streams_method_output_stream_subscribe((self).__handle); + return (wasi_io_streams_own_pollable_t) { ret }; +} + +bool wasi_io_streams_method_output_stream_write_zeroes(wasi_io_streams_borrow_output_stream_t self, uint64_t len, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_write_zeroes((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_blocking_write_zeroes_and_flush(wasi_io_streams_borrow_output_stream_t self, uint64_t len, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[12]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_blocking_write_zeroes_and_flush((self).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_void_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_splice(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_borrow_input_stream_t src, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_splice((self).__handle, (src).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_u64_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 12)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_io_streams_method_output_stream_blocking_splice(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_borrow_input_stream_t src, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_io_streams_method_output_stream_blocking_splice((self).__handle, (src).__handle, (int64_t) (len), ptr); + wasi_io_streams_result_u64_stream_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + case 1: { + result.is_err = true; + wasi_io_streams_stream_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + variant.val.last_operation_failed = (wasi_io_streams_own_error_t) { *((int32_t*) (ptr + 12)) }; + break; + } + case 1: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +wasi_http_types_own_fields_t wasi_http_types_constructor_fields(void) { + int32_t ret = __wasm_import_wasi_http_types_constructor_fields(); + return (wasi_http_types_own_fields_t) { ret }; +} + +bool wasi_http_types_static_fields_from_list(wasi_http_types_list_tuple2_field_name_field_value_t *entries, wasi_http_types_own_fields_t *ret, wasi_http_types_header_error_t *err) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_static_fields_from_list((uint8_t *) (*entries).ptr, (*entries).len, ptr); + wasi_http_types_result_own_fields_header_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_fields_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_header_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 4)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +void wasi_http_types_method_fields_get(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_list_field_value_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(2*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_fields_get((self).__handle, (uint8_t *) (*name).ptr, (*name).len, ptr); + *ret = (wasi_http_types_list_field_value_t) { (wasi_http_types_field_value_t*)(*((uint8_t **) (ptr + 0))), (*((size_t*) (ptr + sizeof(void*)))) }; +} + +bool wasi_http_types_method_fields_has(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name) { + int32_t ret = __wasm_import_wasi_http_types_method_fields_has((self).__handle, (uint8_t *) (*name).ptr, (*name).len); + return ret; +} + +bool wasi_http_types_method_fields_set(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_list_field_value_t *value, wasi_http_types_header_error_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_fields_set((self).__handle, (uint8_t *) (*name).ptr, (*name).len, (uint8_t *) (*value).ptr, (*value).len, ptr); + wasi_http_types_result_void_header_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_header_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 1)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_http_types_method_fields_delete(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_header_error_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_fields_delete((self).__handle, (uint8_t *) (*name).ptr, (*name).len, ptr); + wasi_http_types_result_void_header_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_header_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 1)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +bool wasi_http_types_method_fields_append(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_field_value_t *value, wasi_http_types_header_error_t *err) { + __attribute__((__aligned__(1))) + uint8_t ret_area[2]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_fields_append((self).__handle, (uint8_t *) (*name).ptr, (*name).len, (uint8_t *) (*value).ptr, (*value).len, ptr); + wasi_http_types_result_void_header_error_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_header_error_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 1)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +void wasi_http_types_method_fields_entries(wasi_http_types_borrow_fields_t self, wasi_http_types_list_tuple2_field_name_field_value_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(2*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_fields_entries((self).__handle, ptr); + *ret = (wasi_http_types_list_tuple2_field_name_field_value_t) { (wasi_http_types_tuple2_field_name_field_value_t*)(*((uint8_t **) (ptr + 0))), (*((size_t*) (ptr + sizeof(void*)))) }; +} + +wasi_http_types_own_fields_t wasi_http_types_method_fields_clone(wasi_http_types_borrow_fields_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_fields_clone((self).__handle); + return (wasi_http_types_own_fields_t) { ret }; +} + +void wasi_http_types_method_incoming_request_method(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_method_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_request_method((self).__handle, ptr); + wasi_http_types_method_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 0)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + variant.val.other = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = variant; +} + +bool wasi_http_types_method_incoming_request_path_with_query(wasi_http_types_borrow_incoming_request_t self, function_string_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_request_path_with_query((self).__handle, ptr); + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_incoming_request_scheme(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_scheme_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(4*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_request_scheme((self).__handle, ptr); + wasi_http_types_option_scheme_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + wasi_http_types_scheme_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + sizeof(void*))); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + variant.val.other = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (2*sizeof(void*))))), (*((size_t*) (ptr + (3*sizeof(void*))))) }; + break; + } + } + + option.val = variant; + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_incoming_request_authority(wasi_http_types_borrow_incoming_request_t self, function_string_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_request_authority((self).__handle, ptr); + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = option.val; + return option.is_some; +} + +wasi_http_types_own_headers_t wasi_http_types_method_incoming_request_headers(wasi_http_types_borrow_incoming_request_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_incoming_request_headers((self).__handle); + return (wasi_http_types_own_headers_t) { ret }; +} + +bool wasi_http_types_method_incoming_request_consume(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_own_incoming_body_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_request_consume((self).__handle, ptr); + wasi_http_types_result_own_incoming_body_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_incoming_body_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +wasi_http_types_own_outgoing_request_t wasi_http_types_constructor_outgoing_request(wasi_http_types_own_headers_t headers) { + int32_t ret = __wasm_import_wasi_http_types_constructor_outgoing_request((headers).__handle); + return (wasi_http_types_own_outgoing_request_t) { ret }; +} + +bool wasi_http_types_method_outgoing_request_body(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_own_outgoing_body_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_request_body((self).__handle, ptr); + wasi_http_types_result_own_outgoing_body_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_outgoing_body_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +void wasi_http_types_method_outgoing_request_method(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_method_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_request_method((self).__handle, ptr); + wasi_http_types_method_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 0)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + variant.val.other = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = variant; +} + +bool wasi_http_types_method_outgoing_request_set_method(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_method_t *method) { + int32_t variant; + uint8_t * variant9; + size_t variant10; + switch ((int32_t) (*method).tag) { + case 0: { + variant = 0; + variant9 = 0; + variant10 = 0; + break; + } + case 1: { + variant = 1; + variant9 = 0; + variant10 = 0; + break; + } + case 2: { + variant = 2; + variant9 = 0; + variant10 = 0; + break; + } + case 3: { + variant = 3; + variant9 = 0; + variant10 = 0; + break; + } + case 4: { + variant = 4; + variant9 = 0; + variant10 = 0; + break; + } + case 5: { + variant = 5; + variant9 = 0; + variant10 = 0; + break; + } + case 6: { + variant = 6; + variant9 = 0; + variant10 = 0; + break; + } + case 7: { + variant = 7; + variant9 = 0; + variant10 = 0; + break; + } + case 8: { + variant = 8; + variant9 = 0; + variant10 = 0; + break; + } + case 9: { + const function_string_t *payload8 = &(*method).val.other; + variant = 9; + variant9 = (uint8_t *) (*payload8).ptr; + variant10 = (*payload8).len; + break; + } + } + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_request_set_method((self).__handle, variant, variant9, variant10); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_outgoing_request_path_with_query(wasi_http_types_borrow_outgoing_request_t self, function_string_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_request_path_with_query((self).__handle, ptr); + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_outgoing_request_set_path_with_query(wasi_http_types_borrow_outgoing_request_t self, function_string_t *maybe_path_with_query) { + function_option_string_t path_with_query; + path_with_query.is_some = maybe_path_with_query != NULL;if (maybe_path_with_query) { + path_with_query.val = *maybe_path_with_query; + } + int32_t option; + uint8_t * option1; + size_t option2; + if ((path_with_query).is_some) { + const function_string_t *payload0 = &(path_with_query).val; + option = 1; + option1 = (uint8_t *) (*payload0).ptr; + option2 = (*payload0).len; + } else { + option = 0; + option1 = 0; + option2 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_request_set_path_with_query((self).__handle, option, option1, option2); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_outgoing_request_scheme(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_scheme_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(4*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_request_scheme((self).__handle, ptr); + wasi_http_types_option_scheme_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + wasi_http_types_scheme_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + sizeof(void*))); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + break; + } + case 2: { + variant.val.other = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (2*sizeof(void*))))), (*((size_t*) (ptr + (3*sizeof(void*))))) }; + break; + } + } + + option.val = variant; + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_outgoing_request_set_scheme(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_scheme_t *maybe_scheme) { + wasi_http_types_option_scheme_t scheme; + scheme.is_some = maybe_scheme != NULL;if (maybe_scheme) { + scheme.val = *maybe_scheme; + } + int32_t option; + int32_t option6; + uint8_t * option7; + size_t option8; + if ((scheme).is_some) { + const wasi_http_types_scheme_t *payload0 = &(scheme).val; + int32_t variant; + uint8_t * variant4; + size_t variant5; + switch ((int32_t) (*payload0).tag) { + case 0: { + variant = 0; + variant4 = 0; + variant5 = 0; + break; + } + case 1: { + variant = 1; + variant4 = 0; + variant5 = 0; + break; + } + case 2: { + const function_string_t *payload3 = &(*payload0).val.other; + variant = 2; + variant4 = (uint8_t *) (*payload3).ptr; + variant5 = (*payload3).len; + break; + } + } + option = 1; + option6 = variant; + option7 = variant4; + option8 = variant5; + } else { + option = 0; + option6 = 0; + option7 = 0; + option8 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_request_set_scheme((self).__handle, option, option6, option7, option8); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_outgoing_request_authority(wasi_http_types_borrow_outgoing_request_t self, function_string_t *ret) { + __attribute__((__aligned__(sizeof(void*)))) + uint8_t ret_area[(3*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_request_authority((self).__handle, ptr); + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + sizeof(void*)))), (*((size_t*) (ptr + (2*sizeof(void*))))) }; + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_outgoing_request_set_authority(wasi_http_types_borrow_outgoing_request_t self, function_string_t *maybe_authority) { + function_option_string_t authority; + authority.is_some = maybe_authority != NULL;if (maybe_authority) { + authority.val = *maybe_authority; + } + int32_t option; + uint8_t * option1; + size_t option2; + if ((authority).is_some) { + const function_string_t *payload0 = &(authority).val; + option = 1; + option1 = (uint8_t *) (*payload0).ptr; + option2 = (*payload0).len; + } else { + option = 0; + option1 = 0; + option2 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_request_set_authority((self).__handle, option, option1, option2); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +wasi_http_types_own_headers_t wasi_http_types_method_outgoing_request_headers(wasi_http_types_borrow_outgoing_request_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_request_headers((self).__handle); + return (wasi_http_types_own_headers_t) { ret }; +} + +wasi_http_types_own_request_options_t wasi_http_types_constructor_request_options(void) { + int32_t ret = __wasm_import_wasi_http_types_constructor_request_options(); + return (wasi_http_types_own_request_options_t) { ret }; +} + +bool wasi_http_types_method_request_options_connect_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_request_options_connect_timeout((self).__handle, ptr); + wasi_http_types_option_duration_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_request_options_set_connect_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration) { + wasi_http_types_option_duration_t duration; + duration.is_some = maybe_duration != NULL;if (maybe_duration) { + duration.val = *maybe_duration; + } + int32_t option; + int64_t option1; + if ((duration).is_some) { + const wasi_http_types_duration_t *payload0 = &(duration).val; + option = 1; + option1 = (int64_t) (*payload0); + } else { + option = 0; + option1 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_request_options_set_connect_timeout((self).__handle, option, option1); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_request_options_first_byte_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_request_options_first_byte_timeout((self).__handle, ptr); + wasi_http_types_option_duration_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_request_options_set_first_byte_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration) { + wasi_http_types_option_duration_t duration; + duration.is_some = maybe_duration != NULL;if (maybe_duration) { + duration.val = *maybe_duration; + } + int32_t option; + int64_t option1; + if ((duration).is_some) { + const wasi_http_types_duration_t *payload0 = &(duration).val; + option = 1; + option1 = (int64_t) (*payload0); + } else { + option = 0; + option1 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_request_options_set_first_byte_timeout((self).__handle, option, option1); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_request_options_between_bytes_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[16]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_request_options_between_bytes_timeout((self).__handle, ptr); + wasi_http_types_option_duration_t option; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (uint64_t) (*((int64_t*) (ptr + 8))); + break; + } + } + *ret = option.val; + return option.is_some; +} + +bool wasi_http_types_method_request_options_set_between_bytes_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration) { + wasi_http_types_option_duration_t duration; + duration.is_some = maybe_duration != NULL;if (maybe_duration) { + duration.val = *maybe_duration; + } + int32_t option; + int64_t option1; + if ((duration).is_some) { + const wasi_http_types_duration_t *payload0 = &(duration).val; + option = 1; + option1 = (int64_t) (*payload0); + } else { + option = 0; + option1 = 0; + } + int32_t ret = __wasm_import_wasi_http_types_method_request_options_set_between_bytes_timeout((self).__handle, option, option1); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +void wasi_http_types_static_response_outparam_set(wasi_http_types_own_response_outparam_t param, wasi_http_types_result_own_outgoing_response_error_code_t *response) { + int32_t result; + int32_t result146; + int32_t result147; + int64_t result148; + uint8_t * result149; + uint8_t * result150; + size_t result151; + int32_t result152; + if ((*response).is_err) { + const wasi_http_types_error_code_t *payload0 = &(*response).val.err;int32_t variant; + int32_t variant140; + int64_t variant141; + uint8_t * variant142; + uint8_t * variant143; + size_t variant144; + int32_t variant145; + switch ((int32_t) (*payload0).tag) { + case 0: { + variant = 0; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 1: { + const wasi_http_types_dns_error_payload_t *payload2 = &(*payload0).val.dns_error; + int32_t option; + uint8_t * option5; + size_t option6; + if (((*payload2).rcode).is_some) { + const function_string_t *payload4 = &((*payload2).rcode).val; + option = 1; + option5 = (uint8_t *) (*payload4).ptr; + option6 = (*payload4).len; + } else { + option = 0; + option5 = 0; + option6 = 0; + } + int32_t option9; + int32_t option10; + if (((*payload2).info_code).is_some) { + const uint16_t *payload8 = &((*payload2).info_code).val; + option9 = 1; + option10 = (int32_t) (*payload8); + } else { + option9 = 0; + option10 = 0; + } + variant = 1; + variant140 = option; + variant141 = (int64_t) option5; + variant142 = (uint8_t *) option6; + variant143 = (uint8_t *) option9; + variant144 = option10; + variant145 = 0; + break; + } + case 2: { + variant = 2; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 3: { + variant = 3; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 4: { + variant = 4; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 5: { + variant = 5; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 6: { + variant = 6; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 7: { + variant = 7; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 8: { + variant = 8; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 9: { + variant = 9; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 10: { + variant = 10; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 11: { + variant = 11; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 12: { + variant = 12; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 13: { + variant = 13; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 14: { + const wasi_http_types_tls_alert_received_payload_t *payload23 = &(*payload0).val.tls_alert_received; + int32_t option26; + int32_t option27; + if (((*payload23).alert_id).is_some) { + const uint8_t *payload25 = &((*payload23).alert_id).val; + option26 = 1; + option27 = (int32_t) (*payload25); + } else { + option26 = 0; + option27 = 0; + } + int32_t option30; + uint8_t * option31; + size_t option32; + if (((*payload23).alert_message).is_some) { + const function_string_t *payload29 = &((*payload23).alert_message).val; + option30 = 1; + option31 = (uint8_t *) (*payload29).ptr; + option32 = (*payload29).len; + } else { + option30 = 0; + option31 = 0; + option32 = 0; + } + variant = 14; + variant140 = option26; + variant141 = (int64_t) option27; + variant142 = (uint8_t *) option30; + variant143 = option31; + variant144 = option32; + variant145 = 0; + break; + } + case 15: { + variant = 15; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 16: { + variant = 16; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 17: { + const function_option_u64_t *payload35 = &(*payload0).val.http_request_body_size; + int32_t option38; + int64_t option39; + if ((*payload35).is_some) { + const uint64_t *payload37 = &(*payload35).val; + option38 = 1; + option39 = (int64_t) (*payload37); + } else { + option38 = 0; + option39 = 0; + } + variant = 17; + variant140 = option38; + variant141 = option39; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 18: { + variant = 18; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 19: { + variant = 19; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 20: { + variant = 20; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 21: { + const function_option_u32_t *payload43 = &(*payload0).val.http_request_header_section_size; + int32_t option46; + int32_t option47; + if ((*payload43).is_some) { + const uint32_t *payload45 = &(*payload43).val; + option46 = 1; + option47 = (int32_t) (*payload45); + } else { + option46 = 0; + option47 = 0; + } + variant = 21; + variant140 = option46; + variant141 = (int64_t) option47; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 22: { + const wasi_http_types_option_field_size_payload_t *payload48 = &(*payload0).val.http_request_header_size; + int32_t option60; + int32_t option61; + uint8_t * option62; + size_t option63; + int32_t option64; + int32_t option65; + if ((*payload48).is_some) { + const wasi_http_types_field_size_payload_t *payload50 = &(*payload48).val; + int32_t option53; + uint8_t * option54; + size_t option55; + if (((*payload50).field_name).is_some) { + const function_string_t *payload52 = &((*payload50).field_name).val; + option53 = 1; + option54 = (uint8_t *) (*payload52).ptr; + option55 = (*payload52).len; + } else { + option53 = 0; + option54 = 0; + option55 = 0; + } + int32_t option58; + int32_t option59; + if (((*payload50).field_size).is_some) { + const uint32_t *payload57 = &((*payload50).field_size).val; + option58 = 1; + option59 = (int32_t) (*payload57); + } else { + option58 = 0; + option59 = 0; + } + option60 = 1; + option61 = option53; + option62 = option54; + option63 = option55; + option64 = option58; + option65 = option59; + } else { + option60 = 0; + option61 = 0; + option62 = 0; + option63 = 0; + option64 = 0; + option65 = 0; + } + variant = 22; + variant140 = option60; + variant141 = (int64_t) option61; + variant142 = option62; + variant143 = (uint8_t *) option63; + variant144 = option64; + variant145 = option65; + break; + } + case 23: { + const function_option_u32_t *payload66 = &(*payload0).val.http_request_trailer_section_size; + int32_t option69; + int32_t option70; + if ((*payload66).is_some) { + const uint32_t *payload68 = &(*payload66).val; + option69 = 1; + option70 = (int32_t) (*payload68); + } else { + option69 = 0; + option70 = 0; + } + variant = 23; + variant140 = option69; + variant141 = (int64_t) option70; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 24: { + const wasi_http_types_field_size_payload_t *payload71 = &(*payload0).val.http_request_trailer_size; + int32_t option74; + uint8_t * option75; + size_t option76; + if (((*payload71).field_name).is_some) { + const function_string_t *payload73 = &((*payload71).field_name).val; + option74 = 1; + option75 = (uint8_t *) (*payload73).ptr; + option76 = (*payload73).len; + } else { + option74 = 0; + option75 = 0; + option76 = 0; + } + int32_t option79; + int32_t option80; + if (((*payload71).field_size).is_some) { + const uint32_t *payload78 = &((*payload71).field_size).val; + option79 = 1; + option80 = (int32_t) (*payload78); + } else { + option79 = 0; + option80 = 0; + } + variant = 24; + variant140 = option74; + variant141 = (int64_t) option75; + variant142 = (uint8_t *) option76; + variant143 = (uint8_t *) option79; + variant144 = option80; + variant145 = 0; + break; + } + case 25: { + variant = 25; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 26: { + const function_option_u32_t *payload82 = &(*payload0).val.http_response_header_section_size; + int32_t option85; + int32_t option86; + if ((*payload82).is_some) { + const uint32_t *payload84 = &(*payload82).val; + option85 = 1; + option86 = (int32_t) (*payload84); + } else { + option85 = 0; + option86 = 0; + } + variant = 26; + variant140 = option85; + variant141 = (int64_t) option86; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 27: { + const wasi_http_types_field_size_payload_t *payload87 = &(*payload0).val.http_response_header_size; + int32_t option90; + uint8_t * option91; + size_t option92; + if (((*payload87).field_name).is_some) { + const function_string_t *payload89 = &((*payload87).field_name).val; + option90 = 1; + option91 = (uint8_t *) (*payload89).ptr; + option92 = (*payload89).len; + } else { + option90 = 0; + option91 = 0; + option92 = 0; + } + int32_t option95; + int32_t option96; + if (((*payload87).field_size).is_some) { + const uint32_t *payload94 = &((*payload87).field_size).val; + option95 = 1; + option96 = (int32_t) (*payload94); + } else { + option95 = 0; + option96 = 0; + } + variant = 27; + variant140 = option90; + variant141 = (int64_t) option91; + variant142 = (uint8_t *) option92; + variant143 = (uint8_t *) option95; + variant144 = option96; + variant145 = 0; + break; + } + case 28: { + const function_option_u64_t *payload97 = &(*payload0).val.http_response_body_size; + int32_t option100; + int64_t option101; + if ((*payload97).is_some) { + const uint64_t *payload99 = &(*payload97).val; + option100 = 1; + option101 = (int64_t) (*payload99); + } else { + option100 = 0; + option101 = 0; + } + variant = 28; + variant140 = option100; + variant141 = option101; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 29: { + const function_option_u32_t *payload102 = &(*payload0).val.http_response_trailer_section_size; + int32_t option105; + int32_t option106; + if ((*payload102).is_some) { + const uint32_t *payload104 = &(*payload102).val; + option105 = 1; + option106 = (int32_t) (*payload104); + } else { + option105 = 0; + option106 = 0; + } + variant = 29; + variant140 = option105; + variant141 = (int64_t) option106; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 30: { + const wasi_http_types_field_size_payload_t *payload107 = &(*payload0).val.http_response_trailer_size; + int32_t option110; + uint8_t * option111; + size_t option112; + if (((*payload107).field_name).is_some) { + const function_string_t *payload109 = &((*payload107).field_name).val; + option110 = 1; + option111 = (uint8_t *) (*payload109).ptr; + option112 = (*payload109).len; + } else { + option110 = 0; + option111 = 0; + option112 = 0; + } + int32_t option115; + int32_t option116; + if (((*payload107).field_size).is_some) { + const uint32_t *payload114 = &((*payload107).field_size).val; + option115 = 1; + option116 = (int32_t) (*payload114); + } else { + option115 = 0; + option116 = 0; + } + variant = 30; + variant140 = option110; + variant141 = (int64_t) option111; + variant142 = (uint8_t *) option112; + variant143 = (uint8_t *) option115; + variant144 = option116; + variant145 = 0; + break; + } + case 31: { + const function_option_string_t *payload117 = &(*payload0).val.http_response_transfer_coding; + int32_t option120; + uint8_t * option121; + size_t option122; + if ((*payload117).is_some) { + const function_string_t *payload119 = &(*payload117).val; + option120 = 1; + option121 = (uint8_t *) (*payload119).ptr; + option122 = (*payload119).len; + } else { + option120 = 0; + option121 = 0; + option122 = 0; + } + variant = 31; + variant140 = option120; + variant141 = (int64_t) option121; + variant142 = (uint8_t *) option122; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 32: { + const function_option_string_t *payload123 = &(*payload0).val.http_response_content_coding; + int32_t option126; + uint8_t * option127; + size_t option128; + if ((*payload123).is_some) { + const function_string_t *payload125 = &(*payload123).val; + option126 = 1; + option127 = (uint8_t *) (*payload125).ptr; + option128 = (*payload125).len; + } else { + option126 = 0; + option127 = 0; + option128 = 0; + } + variant = 32; + variant140 = option126; + variant141 = (int64_t) option127; + variant142 = (uint8_t *) option128; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 33: { + variant = 33; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 34: { + variant = 34; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 35: { + variant = 35; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 36: { + variant = 36; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 37: { + variant = 37; + variant140 = 0; + variant141 = 0; + variant142 = 0; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + case 38: { + const function_option_string_t *payload134 = &(*payload0).val.internal_error; + int32_t option137; + uint8_t * option138; + size_t option139; + if ((*payload134).is_some) { + const function_string_t *payload136 = &(*payload134).val; + option137 = 1; + option138 = (uint8_t *) (*payload136).ptr; + option139 = (*payload136).len; + } else { + option137 = 0; + option138 = 0; + option139 = 0; + } + variant = 38; + variant140 = option137; + variant141 = (int64_t) option138; + variant142 = (uint8_t *) option139; + variant143 = 0; + variant144 = 0; + variant145 = 0; + break; + } + } + result = 1; + result146 = variant; + result147 = variant140; + result148 = variant141; + result149 = variant142; + result150 = variant143; + result151 = variant144; + result152 = variant145; + } else { + const wasi_http_types_own_outgoing_response_t *payload = &(*response).val.ok;result = 0; + result146 = (*payload).__handle; + result147 = 0; + result148 = 0; + result149 = 0; + result150 = 0; + result151 = 0; + result152 = 0; + } + __wasm_import_wasi_http_types_static_response_outparam_set((param).__handle, result, result146, result147, result148, result149, result150, result151, result152); +} + +wasi_http_types_status_code_t wasi_http_types_method_incoming_response_status(wasi_http_types_borrow_incoming_response_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_incoming_response_status((self).__handle); + return (uint16_t) (ret); +} + +wasi_http_types_own_headers_t wasi_http_types_method_incoming_response_headers(wasi_http_types_borrow_incoming_response_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_incoming_response_headers((self).__handle); + return (wasi_http_types_own_headers_t) { ret }; +} + +bool wasi_http_types_method_incoming_response_consume(wasi_http_types_borrow_incoming_response_t self, wasi_http_types_own_incoming_body_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_response_consume((self).__handle, ptr); + wasi_http_types_result_own_incoming_body_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_incoming_body_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_incoming_body_stream(wasi_http_types_borrow_incoming_body_t self, wasi_http_types_own_input_stream_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_incoming_body_stream((self).__handle, ptr); + wasi_http_types_result_own_input_stream_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_input_stream_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +wasi_http_types_own_future_trailers_t wasi_http_types_static_incoming_body_finish(wasi_http_types_own_incoming_body_t this_) { + int32_t ret = __wasm_import_wasi_http_types_static_incoming_body_finish((this_).__handle); + return (wasi_http_types_own_future_trailers_t) { ret }; +} + +wasi_http_types_own_pollable_t wasi_http_types_method_future_trailers_subscribe(wasi_http_types_borrow_future_trailers_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_future_trailers_subscribe((self).__handle); + return (wasi_http_types_own_pollable_t) { ret }; +} + +bool wasi_http_types_method_future_trailers_get(wasi_http_types_borrow_future_trailers_t self, wasi_http_types_result_result_option_own_trailers_error_code_void_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[(40+4*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_future_trailers_get((self).__handle, ptr); + wasi_http_types_option_result_result_option_own_trailers_error_code_void_t option23; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option23.is_some = false; + break; + } + case 1: { + option23.is_some = true; + wasi_http_types_result_result_option_own_trailers_error_code_void_t result22; + switch ((int32_t) *((uint8_t*) (ptr + 8))) { + case 0: { + result22.is_err = false; + wasi_http_types_result_option_own_trailers_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + result.is_err = false; + wasi_http_types_option_own_trailers_t option; + switch ((int32_t) *((uint8_t*) (ptr + 24))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (wasi_http_types_own_trailers_t) { *((int32_t*) (ptr + 28)) }; + break; + } + } + + result.val.ok = option; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_error_code_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 24)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + function_option_string_t option0; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option0.is_some = false; + break; + } + case 1: { + option0.is_some = true; + option0.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u16_t option1; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option1.is_some = false; + break; + } + case 1: { + option1.is_some = true; + option1.val = (uint16_t) ((int32_t) *((uint16_t*) (ptr + (34+3*sizeof(void*))))); + break; + } + } + variant.val.dns_error = (wasi_http_types_dns_error_payload_t) { + (function_option_string_t) option0, + (function_option_u16_t) option1, + }; + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + break; + } + case 10: { + break; + } + case 11: { + break; + } + case 12: { + break; + } + case 13: { + break; + } + case 14: { + function_option_u8_t option2; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option2.is_some = false; + break; + } + case 1: { + option2.is_some = true; + option2.val = (uint8_t) ((int32_t) *((uint8_t*) (ptr + 33))); + break; + } + } + function_option_string_t option3; + switch ((int32_t) *((uint8_t*) (ptr + (32+1*sizeof(void*))))) { + case 0: { + option3.is_some = false; + break; + } + case 1: { + option3.is_some = true; + option3.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+2*sizeof(void*))))), (*((size_t*) (ptr + (32+3*sizeof(void*))))) }; + break; + } + } + variant.val.tls_alert_received = (wasi_http_types_tls_alert_received_payload_t) { + (function_option_u8_t) option2, + (function_option_string_t) option3, + }; + break; + } + case 15: { + break; + } + case 16: { + break; + } + case 17: { + function_option_u64_t option4; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option4.is_some = false; + break; + } + case 1: { + option4.is_some = true; + option4.val = (uint64_t) (*((int64_t*) (ptr + 40))); + break; + } + } + variant.val.http_request_body_size = option4; + break; + } + case 18: { + break; + } + case 19: { + break; + } + case 20: { + break; + } + case 21: { + function_option_u32_t option5; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option5.is_some = false; + break; + } + case 1: { + option5.is_some = true; + option5.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_request_header_section_size = option5; + break; + } + case 22: { + wasi_http_types_option_field_size_payload_t option8; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option8.is_some = false; + break; + } + case 1: { + option8.is_some = true; + function_option_string_t option6; + switch ((int32_t) *((uint8_t*) (ptr + (32+1*sizeof(void*))))) { + case 0: { + option6.is_some = false; + break; + } + case 1: { + option6.is_some = true; + option6.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+2*sizeof(void*))))), (*((size_t*) (ptr + (32+3*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option7; + switch ((int32_t) *((uint8_t*) (ptr + (32+4*sizeof(void*))))) { + case 0: { + option7.is_some = false; + break; + } + case 1: { + option7.is_some = true; + option7.val = (uint32_t) (*((int32_t*) (ptr + (36+4*sizeof(void*))))); + break; + } + } + + option8.val = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option6, + (function_option_u32_t) option7, + }; + break; + } + } + variant.val.http_request_header_size = option8; + break; + } + case 23: { + function_option_u32_t option9; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option9.is_some = false; + break; + } + case 1: { + option9.is_some = true; + option9.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_request_trailer_section_size = option9; + break; + } + case 24: { + function_option_string_t option10; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option10.is_some = false; + break; + } + case 1: { + option10.is_some = true; + option10.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option11; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option11.is_some = false; + break; + } + case 1: { + option11.is_some = true; + option11.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_request_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option10, + (function_option_u32_t) option11, + }; + break; + } + case 25: { + break; + } + case 26: { + function_option_u32_t option12; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option12.is_some = false; + break; + } + case 1: { + option12.is_some = true; + option12.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_response_header_section_size = option12; + break; + } + case 27: { + function_option_string_t option13; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option13.is_some = false; + break; + } + case 1: { + option13.is_some = true; + option13.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option14; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option14.is_some = false; + break; + } + case 1: { + option14.is_some = true; + option14.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_header_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option13, + (function_option_u32_t) option14, + }; + break; + } + case 28: { + function_option_u64_t option15; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option15.is_some = false; + break; + } + case 1: { + option15.is_some = true; + option15.val = (uint64_t) (*((int64_t*) (ptr + 40))); + break; + } + } + variant.val.http_response_body_size = option15; + break; + } + case 29: { + function_option_u32_t option16; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option16.is_some = false; + break; + } + case 1: { + option16.is_some = true; + option16.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_response_trailer_section_size = option16; + break; + } + case 30: { + function_option_string_t option17; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option17.is_some = false; + break; + } + case 1: { + option17.is_some = true; + option17.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option18; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option18.is_some = false; + break; + } + case 1: { + option18.is_some = true; + option18.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option17, + (function_option_u32_t) option18, + }; + break; + } + case 31: { + function_option_string_t option19; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option19.is_some = false; + break; + } + case 1: { + option19.is_some = true; + option19.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_transfer_coding = option19; + break; + } + case 32: { + function_option_string_t option20; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option20.is_some = false; + break; + } + case 1: { + option20.is_some = true; + option20.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_content_coding = option20; + break; + } + case 33: { + break; + } + case 34: { + break; + } + case 35: { + break; + } + case 36: { + break; + } + case 37: { + break; + } + case 38: { + function_option_string_t option21; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option21.is_some = false; + break; + } + case 1: { + option21.is_some = true; + option21.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.internal_error = option21; + break; + } + } + + result.val.err = variant; + break; + } + } + + result22.val.ok = result; + break; + } + case 1: { + result22.is_err = true; + break; + } + } + + option23.val = result22; + break; + } + } + *ret = option23.val; + return option23.is_some; +} + +wasi_http_types_own_outgoing_response_t wasi_http_types_constructor_outgoing_response(wasi_http_types_own_headers_t headers) { + int32_t ret = __wasm_import_wasi_http_types_constructor_outgoing_response((headers).__handle); + return (wasi_http_types_own_outgoing_response_t) { ret }; +} + +wasi_http_types_status_code_t wasi_http_types_method_outgoing_response_status_code(wasi_http_types_borrow_outgoing_response_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_response_status_code((self).__handle); + return (uint16_t) (ret); +} + +bool wasi_http_types_method_outgoing_response_set_status_code(wasi_http_types_borrow_outgoing_response_t self, wasi_http_types_status_code_t status_code) { + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_response_set_status_code((self).__handle, (int32_t) (status_code)); + wasi_http_types_result_void_void_t result; + switch (ret) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + return 1; + } else { + return 0; + } +} + +wasi_http_types_own_headers_t wasi_http_types_method_outgoing_response_headers(wasi_http_types_borrow_outgoing_response_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_outgoing_response_headers((self).__handle); + return (wasi_http_types_own_headers_t) { ret }; +} + +bool wasi_http_types_method_outgoing_response_body(wasi_http_types_borrow_outgoing_response_t self, wasi_http_types_own_outgoing_body_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_response_body((self).__handle, ptr); + wasi_http_types_result_own_outgoing_body_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_outgoing_body_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_method_outgoing_body_write(wasi_http_types_borrow_outgoing_body_t self, wasi_http_types_own_output_stream_t *ret) { + __attribute__((__aligned__(4))) + uint8_t ret_area[8]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_outgoing_body_write((self).__handle, ptr); + wasi_http_types_result_own_output_stream_void_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_output_stream_t) { *((int32_t*) (ptr + 4)) }; + break; + } + case 1: { + result.is_err = true; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + return 0; + } +} + +bool wasi_http_types_static_outgoing_body_finish(wasi_http_types_own_outgoing_body_t this_, wasi_http_types_own_trailers_t *maybe_trailers, wasi_http_types_error_code_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[(24+4*sizeof(void*))]; + wasi_http_types_option_own_trailers_t trailers; + trailers.is_some = maybe_trailers != NULL;if (maybe_trailers) { + trailers.val = *maybe_trailers; + } + int32_t option; + int32_t option1; + if ((trailers).is_some) { + const wasi_http_types_own_trailers_t *payload0 = &(trailers).val; + option = 1; + option1 = (*payload0).__handle; + } else { + option = 0; + option1 = 0; + } + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_static_outgoing_body_finish((this_).__handle, option, option1, ptr); + wasi_http_types_result_void_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_error_code_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + function_option_string_t option2; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option2.is_some = false; + break; + } + case 1: { + option2.is_some = true; + option2.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u16_t option3; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option3.is_some = false; + break; + } + case 1: { + option3.is_some = true; + option3.val = (uint16_t) ((int32_t) *((uint16_t*) (ptr + (18+3*sizeof(void*))))); + break; + } + } + variant.val.dns_error = (wasi_http_types_dns_error_payload_t) { + (function_option_string_t) option2, + (function_option_u16_t) option3, + }; + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + break; + } + case 10: { + break; + } + case 11: { + break; + } + case 12: { + break; + } + case 13: { + break; + } + case 14: { + function_option_u8_t option4; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option4.is_some = false; + break; + } + case 1: { + option4.is_some = true; + option4.val = (uint8_t) ((int32_t) *((uint8_t*) (ptr + 17))); + break; + } + } + function_option_string_t option5; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option5.is_some = false; + break; + } + case 1: { + option5.is_some = true; + option5.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + variant.val.tls_alert_received = (wasi_http_types_tls_alert_received_payload_t) { + (function_option_u8_t) option4, + (function_option_string_t) option5, + }; + break; + } + case 15: { + break; + } + case 16: { + break; + } + case 17: { + function_option_u64_t option6; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option6.is_some = false; + break; + } + case 1: { + option6.is_some = true; + option6.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_request_body_size = option6; + break; + } + case 18: { + break; + } + case 19: { + break; + } + case 20: { + break; + } + case 21: { + function_option_u32_t option7; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option7.is_some = false; + break; + } + case 1: { + option7.is_some = true; + option7.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_header_section_size = option7; + break; + } + case 22: { + wasi_http_types_option_field_size_payload_t option10; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option10.is_some = false; + break; + } + case 1: { + option10.is_some = true; + function_option_string_t option8; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option8.is_some = false; + break; + } + case 1: { + option8.is_some = true; + option8.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option9; + switch ((int32_t) *((uint8_t*) (ptr + (16+4*sizeof(void*))))) { + case 0: { + option9.is_some = false; + break; + } + case 1: { + option9.is_some = true; + option9.val = (uint32_t) (*((int32_t*) (ptr + (20+4*sizeof(void*))))); + break; + } + } + + option10.val = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option8, + (function_option_u32_t) option9, + }; + break; + } + } + variant.val.http_request_header_size = option10; + break; + } + case 23: { + function_option_u32_t option11; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option11.is_some = false; + break; + } + case 1: { + option11.is_some = true; + option11.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_trailer_section_size = option11; + break; + } + case 24: { + function_option_string_t option12; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option12.is_some = false; + break; + } + case 1: { + option12.is_some = true; + option12.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option13; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option13.is_some = false; + break; + } + case 1: { + option13.is_some = true; + option13.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_request_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option12, + (function_option_u32_t) option13, + }; + break; + } + case 25: { + break; + } + case 26: { + function_option_u32_t option14; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option14.is_some = false; + break; + } + case 1: { + option14.is_some = true; + option14.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_header_section_size = option14; + break; + } + case 27: { + function_option_string_t option15; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option15.is_some = false; + break; + } + case 1: { + option15.is_some = true; + option15.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option16; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option16.is_some = false; + break; + } + case 1: { + option16.is_some = true; + option16.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_header_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option15, + (function_option_u32_t) option16, + }; + break; + } + case 28: { + function_option_u64_t option17; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option17.is_some = false; + break; + } + case 1: { + option17.is_some = true; + option17.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_response_body_size = option17; + break; + } + case 29: { + function_option_u32_t option18; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option18.is_some = false; + break; + } + case 1: { + option18.is_some = true; + option18.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_trailer_section_size = option18; + break; + } + case 30: { + function_option_string_t option19; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option19.is_some = false; + break; + } + case 1: { + option19.is_some = true; + option19.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option20; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option20.is_some = false; + break; + } + case 1: { + option20.is_some = true; + option20.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option19, + (function_option_u32_t) option20, + }; + break; + } + case 31: { + function_option_string_t option21; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option21.is_some = false; + break; + } + case 1: { + option21.is_some = true; + option21.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_transfer_coding = option21; + break; + } + case 32: { + function_option_string_t option22; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option22.is_some = false; + break; + } + case 1: { + option22.is_some = true; + option22.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_content_coding = option22; + break; + } + case 33: { + break; + } + case 34: { + break; + } + case 35: { + break; + } + case 36: { + break; + } + case 37: { + break; + } + case 38: { + function_option_string_t option23; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option23.is_some = false; + break; + } + case 1: { + option23.is_some = true; + option23.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.internal_error = option23; + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +wasi_http_types_own_pollable_t wasi_http_types_method_future_incoming_response_subscribe(wasi_http_types_borrow_future_incoming_response_t self) { + int32_t ret = __wasm_import_wasi_http_types_method_future_incoming_response_subscribe((self).__handle); + return (wasi_http_types_own_pollable_t) { ret }; +} + +bool wasi_http_types_method_future_incoming_response_get(wasi_http_types_borrow_future_incoming_response_t self, wasi_http_types_result_result_own_incoming_response_error_code_void_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[(40+4*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_method_future_incoming_response_get((self).__handle, ptr); + wasi_http_types_option_result_result_own_incoming_response_error_code_void_t option22; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option22.is_some = false; + break; + } + case 1: { + option22.is_some = true; + wasi_http_types_result_result_own_incoming_response_error_code_void_t result21; + switch ((int32_t) *((uint8_t*) (ptr + 8))) { + case 0: { + result21.is_err = false; + wasi_http_types_result_own_incoming_response_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_types_own_incoming_response_t) { *((int32_t*) (ptr + 24)) }; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_error_code_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 24)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u16_t option0; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option0.is_some = false; + break; + } + case 1: { + option0.is_some = true; + option0.val = (uint16_t) ((int32_t) *((uint16_t*) (ptr + (34+3*sizeof(void*))))); + break; + } + } + variant.val.dns_error = (wasi_http_types_dns_error_payload_t) { + (function_option_string_t) option, + (function_option_u16_t) option0, + }; + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + break; + } + case 10: { + break; + } + case 11: { + break; + } + case 12: { + break; + } + case 13: { + break; + } + case 14: { + function_option_u8_t option1; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option1.is_some = false; + break; + } + case 1: { + option1.is_some = true; + option1.val = (uint8_t) ((int32_t) *((uint8_t*) (ptr + 33))); + break; + } + } + function_option_string_t option2; + switch ((int32_t) *((uint8_t*) (ptr + (32+1*sizeof(void*))))) { + case 0: { + option2.is_some = false; + break; + } + case 1: { + option2.is_some = true; + option2.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+2*sizeof(void*))))), (*((size_t*) (ptr + (32+3*sizeof(void*))))) }; + break; + } + } + variant.val.tls_alert_received = (wasi_http_types_tls_alert_received_payload_t) { + (function_option_u8_t) option1, + (function_option_string_t) option2, + }; + break; + } + case 15: { + break; + } + case 16: { + break; + } + case 17: { + function_option_u64_t option3; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option3.is_some = false; + break; + } + case 1: { + option3.is_some = true; + option3.val = (uint64_t) (*((int64_t*) (ptr + 40))); + break; + } + } + variant.val.http_request_body_size = option3; + break; + } + case 18: { + break; + } + case 19: { + break; + } + case 20: { + break; + } + case 21: { + function_option_u32_t option4; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option4.is_some = false; + break; + } + case 1: { + option4.is_some = true; + option4.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_request_header_section_size = option4; + break; + } + case 22: { + wasi_http_types_option_field_size_payload_t option7; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option7.is_some = false; + break; + } + case 1: { + option7.is_some = true; + function_option_string_t option5; + switch ((int32_t) *((uint8_t*) (ptr + (32+1*sizeof(void*))))) { + case 0: { + option5.is_some = false; + break; + } + case 1: { + option5.is_some = true; + option5.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+2*sizeof(void*))))), (*((size_t*) (ptr + (32+3*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option6; + switch ((int32_t) *((uint8_t*) (ptr + (32+4*sizeof(void*))))) { + case 0: { + option6.is_some = false; + break; + } + case 1: { + option6.is_some = true; + option6.val = (uint32_t) (*((int32_t*) (ptr + (36+4*sizeof(void*))))); + break; + } + } + + option7.val = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option5, + (function_option_u32_t) option6, + }; + break; + } + } + variant.val.http_request_header_size = option7; + break; + } + case 23: { + function_option_u32_t option8; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option8.is_some = false; + break; + } + case 1: { + option8.is_some = true; + option8.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_request_trailer_section_size = option8; + break; + } + case 24: { + function_option_string_t option9; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option9.is_some = false; + break; + } + case 1: { + option9.is_some = true; + option9.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option10; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option10.is_some = false; + break; + } + case 1: { + option10.is_some = true; + option10.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_request_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option9, + (function_option_u32_t) option10, + }; + break; + } + case 25: { + break; + } + case 26: { + function_option_u32_t option11; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option11.is_some = false; + break; + } + case 1: { + option11.is_some = true; + option11.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_response_header_section_size = option11; + break; + } + case 27: { + function_option_string_t option12; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option12.is_some = false; + break; + } + case 1: { + option12.is_some = true; + option12.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option13; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option13.is_some = false; + break; + } + case 1: { + option13.is_some = true; + option13.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_header_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option12, + (function_option_u32_t) option13, + }; + break; + } + case 28: { + function_option_u64_t option14; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option14.is_some = false; + break; + } + case 1: { + option14.is_some = true; + option14.val = (uint64_t) (*((int64_t*) (ptr + 40))); + break; + } + } + variant.val.http_response_body_size = option14; + break; + } + case 29: { + function_option_u32_t option15; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option15.is_some = false; + break; + } + case 1: { + option15.is_some = true; + option15.val = (uint32_t) (*((int32_t*) (ptr + 36))); + break; + } + } + variant.val.http_response_trailer_section_size = option15; + break; + } + case 30: { + function_option_string_t option16; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option16.is_some = false; + break; + } + case 1: { + option16.is_some = true; + option16.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option17; + switch ((int32_t) *((uint8_t*) (ptr + (32+3*sizeof(void*))))) { + case 0: { + option17.is_some = false; + break; + } + case 1: { + option17.is_some = true; + option17.val = (uint32_t) (*((int32_t*) (ptr + (36+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option16, + (function_option_u32_t) option17, + }; + break; + } + case 31: { + function_option_string_t option18; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option18.is_some = false; + break; + } + case 1: { + option18.is_some = true; + option18.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_transfer_coding = option18; + break; + } + case 32: { + function_option_string_t option19; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option19.is_some = false; + break; + } + case 1: { + option19.is_some = true; + option19.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_content_coding = option19; + break; + } + case 33: { + break; + } + case 34: { + break; + } + case 35: { + break; + } + case 36: { + break; + } + case 37: { + break; + } + case 38: { + function_option_string_t option20; + switch ((int32_t) *((uint8_t*) (ptr + 32))) { + case 0: { + option20.is_some = false; + break; + } + case 1: { + option20.is_some = true; + option20.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (32+1*sizeof(void*))))), (*((size_t*) (ptr + (32+2*sizeof(void*))))) }; + break; + } + } + variant.val.internal_error = option20; + break; + } + } + + result.val.err = variant; + break; + } + } + + result21.val.ok = result; + break; + } + case 1: { + result21.is_err = true; + break; + } + } + + option22.val = result21; + break; + } + } + *ret = option22.val; + return option22.is_some; +} + +bool wasi_http_types_http_error_code(wasi_http_types_borrow_io_error_t err_, wasi_http_types_error_code_t *ret) { + __attribute__((__aligned__(8))) + uint8_t ret_area[(24+4*sizeof(void*))]; + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_types_http_error_code((err_).__handle, ptr); + wasi_http_types_option_error_code_t option21; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + option21.is_some = false; + break; + } + case 1: { + option21.is_some = true; + wasi_http_types_error_code_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + function_option_string_t option; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option.is_some = false; + break; + } + case 1: { + option.is_some = true; + option.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u16_t option0; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option0.is_some = false; + break; + } + case 1: { + option0.is_some = true; + option0.val = (uint16_t) ((int32_t) *((uint16_t*) (ptr + (18+3*sizeof(void*))))); + break; + } + } + variant.val.dns_error = (wasi_http_types_dns_error_payload_t) { + (function_option_string_t) option, + (function_option_u16_t) option0, + }; + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + break; + } + case 10: { + break; + } + case 11: { + break; + } + case 12: { + break; + } + case 13: { + break; + } + case 14: { + function_option_u8_t option1; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option1.is_some = false; + break; + } + case 1: { + option1.is_some = true; + option1.val = (uint8_t) ((int32_t) *((uint8_t*) (ptr + 17))); + break; + } + } + function_option_string_t option2; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option2.is_some = false; + break; + } + case 1: { + option2.is_some = true; + option2.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + variant.val.tls_alert_received = (wasi_http_types_tls_alert_received_payload_t) { + (function_option_u8_t) option1, + (function_option_string_t) option2, + }; + break; + } + case 15: { + break; + } + case 16: { + break; + } + case 17: { + function_option_u64_t option3; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option3.is_some = false; + break; + } + case 1: { + option3.is_some = true; + option3.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_request_body_size = option3; + break; + } + case 18: { + break; + } + case 19: { + break; + } + case 20: { + break; + } + case 21: { + function_option_u32_t option4; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option4.is_some = false; + break; + } + case 1: { + option4.is_some = true; + option4.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_header_section_size = option4; + break; + } + case 22: { + wasi_http_types_option_field_size_payload_t option7; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option7.is_some = false; + break; + } + case 1: { + option7.is_some = true; + function_option_string_t option5; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option5.is_some = false; + break; + } + case 1: { + option5.is_some = true; + option5.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option6; + switch ((int32_t) *((uint8_t*) (ptr + (16+4*sizeof(void*))))) { + case 0: { + option6.is_some = false; + break; + } + case 1: { + option6.is_some = true; + option6.val = (uint32_t) (*((int32_t*) (ptr + (20+4*sizeof(void*))))); + break; + } + } + + option7.val = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option5, + (function_option_u32_t) option6, + }; + break; + } + } + variant.val.http_request_header_size = option7; + break; + } + case 23: { + function_option_u32_t option8; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option8.is_some = false; + break; + } + case 1: { + option8.is_some = true; + option8.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_trailer_section_size = option8; + break; + } + case 24: { + function_option_string_t option9; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option9.is_some = false; + break; + } + case 1: { + option9.is_some = true; + option9.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option10; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option10.is_some = false; + break; + } + case 1: { + option10.is_some = true; + option10.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_request_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option9, + (function_option_u32_t) option10, + }; + break; + } + case 25: { + break; + } + case 26: { + function_option_u32_t option11; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option11.is_some = false; + break; + } + case 1: { + option11.is_some = true; + option11.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_header_section_size = option11; + break; + } + case 27: { + function_option_string_t option12; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option12.is_some = false; + break; + } + case 1: { + option12.is_some = true; + option12.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option13; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option13.is_some = false; + break; + } + case 1: { + option13.is_some = true; + option13.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_header_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option12, + (function_option_u32_t) option13, + }; + break; + } + case 28: { + function_option_u64_t option14; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option14.is_some = false; + break; + } + case 1: { + option14.is_some = true; + option14.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_response_body_size = option14; + break; + } + case 29: { + function_option_u32_t option15; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option15.is_some = false; + break; + } + case 1: { + option15.is_some = true; + option15.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_trailer_section_size = option15; + break; + } + case 30: { + function_option_string_t option16; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option16.is_some = false; + break; + } + case 1: { + option16.is_some = true; + option16.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option17; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option17.is_some = false; + break; + } + case 1: { + option17.is_some = true; + option17.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option16, + (function_option_u32_t) option17, + }; + break; + } + case 31: { + function_option_string_t option18; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option18.is_some = false; + break; + } + case 1: { + option18.is_some = true; + option18.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_transfer_coding = option18; + break; + } + case 32: { + function_option_string_t option19; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option19.is_some = false; + break; + } + case 1: { + option19.is_some = true; + option19.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_content_coding = option19; + break; + } + case 33: { + break; + } + case 34: { + break; + } + case 35: { + break; + } + case 36: { + break; + } + case 37: { + break; + } + case 38: { + function_option_string_t option20; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option20.is_some = false; + break; + } + case 1: { + option20.is_some = true; + option20.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.internal_error = option20; + break; + } + } + + option21.val = variant; + break; + } + } + *ret = option21.val; + return option21.is_some; +} + +bool wasi_http_outgoing_handler_handle(wasi_http_outgoing_handler_own_outgoing_request_t request, wasi_http_outgoing_handler_own_request_options_t *maybe_options, wasi_http_outgoing_handler_own_future_incoming_response_t *ret, wasi_http_outgoing_handler_error_code_t *err) { + __attribute__((__aligned__(8))) + uint8_t ret_area[(24+4*sizeof(void*))]; + wasi_http_outgoing_handler_option_own_request_options_t options; + options.is_some = maybe_options != NULL;if (maybe_options) { + options.val = *maybe_options; + } + int32_t option; + int32_t option1; + if ((options).is_some) { + const wasi_http_outgoing_handler_own_request_options_t *payload0 = &(options).val; + option = 1; + option1 = (*payload0).__handle; + } else { + option = 0; + option1 = 0; + } + uint8_t *ptr = (uint8_t *) &ret_area; + __wasm_import_wasi_http_outgoing_handler_handle((request).__handle, option, option1, ptr); + wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_t result; + switch ((int32_t) *((uint8_t*) (ptr + 0))) { + case 0: { + result.is_err = false; + result.val.ok = (wasi_http_outgoing_handler_own_future_incoming_response_t) { *((int32_t*) (ptr + 8)) }; + break; + } + case 1: { + result.is_err = true; + wasi_http_types_error_code_t variant; + variant.tag = (int32_t) *((uint8_t*) (ptr + 8)); + switch ((int32_t) variant.tag) { + case 0: { + break; + } + case 1: { + function_option_string_t option2; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option2.is_some = false; + break; + } + case 1: { + option2.is_some = true; + option2.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u16_t option3; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option3.is_some = false; + break; + } + case 1: { + option3.is_some = true; + option3.val = (uint16_t) ((int32_t) *((uint16_t*) (ptr + (18+3*sizeof(void*))))); + break; + } + } + variant.val.dns_error = (wasi_http_types_dns_error_payload_t) { + (function_option_string_t) option2, + (function_option_u16_t) option3, + }; + break; + } + case 2: { + break; + } + case 3: { + break; + } + case 4: { + break; + } + case 5: { + break; + } + case 6: { + break; + } + case 7: { + break; + } + case 8: { + break; + } + case 9: { + break; + } + case 10: { + break; + } + case 11: { + break; + } + case 12: { + break; + } + case 13: { + break; + } + case 14: { + function_option_u8_t option4; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option4.is_some = false; + break; + } + case 1: { + option4.is_some = true; + option4.val = (uint8_t) ((int32_t) *((uint8_t*) (ptr + 17))); + break; + } + } + function_option_string_t option5; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option5.is_some = false; + break; + } + case 1: { + option5.is_some = true; + option5.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + variant.val.tls_alert_received = (wasi_http_types_tls_alert_received_payload_t) { + (function_option_u8_t) option4, + (function_option_string_t) option5, + }; + break; + } + case 15: { + break; + } + case 16: { + break; + } + case 17: { + function_option_u64_t option6; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option6.is_some = false; + break; + } + case 1: { + option6.is_some = true; + option6.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_request_body_size = option6; + break; + } + case 18: { + break; + } + case 19: { + break; + } + case 20: { + break; + } + case 21: { + function_option_u32_t option7; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option7.is_some = false; + break; + } + case 1: { + option7.is_some = true; + option7.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_header_section_size = option7; + break; + } + case 22: { + wasi_http_types_option_field_size_payload_t option10; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option10.is_some = false; + break; + } + case 1: { + option10.is_some = true; + function_option_string_t option8; + switch ((int32_t) *((uint8_t*) (ptr + (16+1*sizeof(void*))))) { + case 0: { + option8.is_some = false; + break; + } + case 1: { + option8.is_some = true; + option8.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+2*sizeof(void*))))), (*((size_t*) (ptr + (16+3*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option9; + switch ((int32_t) *((uint8_t*) (ptr + (16+4*sizeof(void*))))) { + case 0: { + option9.is_some = false; + break; + } + case 1: { + option9.is_some = true; + option9.val = (uint32_t) (*((int32_t*) (ptr + (20+4*sizeof(void*))))); + break; + } + } + + option10.val = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option8, + (function_option_u32_t) option9, + }; + break; + } + } + variant.val.http_request_header_size = option10; + break; + } + case 23: { + function_option_u32_t option11; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option11.is_some = false; + break; + } + case 1: { + option11.is_some = true; + option11.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_request_trailer_section_size = option11; + break; + } + case 24: { + function_option_string_t option12; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option12.is_some = false; + break; + } + case 1: { + option12.is_some = true; + option12.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option13; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option13.is_some = false; + break; + } + case 1: { + option13.is_some = true; + option13.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_request_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option12, + (function_option_u32_t) option13, + }; + break; + } + case 25: { + break; + } + case 26: { + function_option_u32_t option14; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option14.is_some = false; + break; + } + case 1: { + option14.is_some = true; + option14.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_header_section_size = option14; + break; + } + case 27: { + function_option_string_t option15; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option15.is_some = false; + break; + } + case 1: { + option15.is_some = true; + option15.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option16; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option16.is_some = false; + break; + } + case 1: { + option16.is_some = true; + option16.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_header_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option15, + (function_option_u32_t) option16, + }; + break; + } + case 28: { + function_option_u64_t option17; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option17.is_some = false; + break; + } + case 1: { + option17.is_some = true; + option17.val = (uint64_t) (*((int64_t*) (ptr + 24))); + break; + } + } + variant.val.http_response_body_size = option17; + break; + } + case 29: { + function_option_u32_t option18; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option18.is_some = false; + break; + } + case 1: { + option18.is_some = true; + option18.val = (uint32_t) (*((int32_t*) (ptr + 20))); + break; + } + } + variant.val.http_response_trailer_section_size = option18; + break; + } + case 30: { + function_option_string_t option19; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option19.is_some = false; + break; + } + case 1: { + option19.is_some = true; + option19.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + function_option_u32_t option20; + switch ((int32_t) *((uint8_t*) (ptr + (16+3*sizeof(void*))))) { + case 0: { + option20.is_some = false; + break; + } + case 1: { + option20.is_some = true; + option20.val = (uint32_t) (*((int32_t*) (ptr + (20+3*sizeof(void*))))); + break; + } + } + variant.val.http_response_trailer_size = (wasi_http_types_field_size_payload_t) { + (function_option_string_t) option19, + (function_option_u32_t) option20, + }; + break; + } + case 31: { + function_option_string_t option21; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option21.is_some = false; + break; + } + case 1: { + option21.is_some = true; + option21.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_transfer_coding = option21; + break; + } + case 32: { + function_option_string_t option22; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option22.is_some = false; + break; + } + case 1: { + option22.is_some = true; + option22.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.http_response_content_coding = option22; + break; + } + case 33: { + break; + } + case 34: { + break; + } + case 35: { + break; + } + case 36: { + break; + } + case 37: { + break; + } + case 38: { + function_option_string_t option23; + switch ((int32_t) *((uint8_t*) (ptr + 16))) { + case 0: { + option23.is_some = false; + break; + } + case 1: { + option23.is_some = true; + option23.val = (function_string_t) { (uint8_t*)(*((uint8_t **) (ptr + (16+1*sizeof(void*))))), (*((size_t*) (ptr + (16+2*sizeof(void*))))) }; + break; + } + } + variant.val.internal_error = option23; + break; + } + } + + result.val.err = variant; + break; + } + } + if (!result.is_err) { + *ret = result.val.ok; + return 1; + } else { + *err = result.val.err; + return 0; + } +} + +void function_log(function_log_level_t level, function_string_t *msg, function_list_tuple2_string_string_t *kv) { + __wasm_import_function_log((int32_t) level, (uint8_t *) (*msg).ptr, (*msg).len, (uint8_t *) (*kv).ptr, (*kv).len); +} + +__attribute__((__export_name__("run"))) +uint8_t * __wasm_export_exports_function_run(uint8_t * arg, size_t arg0) { + function_list_u8_t arg1 = (function_list_u8_t) { (uint8_t*)(arg), (arg0) }; + function_result_list_u8_string_t ret; + function_list_u8_t ok; + function_string_t err; + ret.is_err = !exports_function_run(&arg1, &ok, &err); + if (ret.is_err) { + ret.val.err = err; + } + if (!ret.is_err) { + ret.val.ok = ok; + } + uint8_t *ptr = (uint8_t *) &RET_AREA; + if ((ret).is_err) { + const function_string_t *payload2 = &(ret).val.err;*((int8_t*)(ptr + 0)) = 1; + *((size_t*)(ptr + (2*sizeof(void*)))) = (*payload2).len; + *((uint8_t **)(ptr + sizeof(void*))) = (uint8_t *) (*payload2).ptr; + } else { + const function_list_u8_t *payload = &(ret).val.ok;*((int8_t*)(ptr + 0)) = 0; + *((size_t*)(ptr + (2*sizeof(void*)))) = (*payload).len; + *((uint8_t **)(ptr + sizeof(void*))) = (uint8_t *) (*payload).ptr; + } + return ptr; +} + +// Ensure that the *_component_type.o object is linked in + +extern void __component_type_object_force_link_function(void); +__attribute__((used)) +void __component_type_object_force_link_function_public_use_in_this_compilation_unit(void) { + __component_type_object_force_link_function(); +} diff --git a/examples/hello-odin/src/gen/function.h b/examples/hello-odin/src/gen/function.h new file mode 100644 index 00000000..3ba63f2f --- /dev/null +++ b/examples/hello-odin/src/gen/function.h @@ -0,0 +1,1336 @@ +// Generated by `wit-bindgen` 0.62.0. DO NOT EDIT! +#ifndef __BINDINGS_FUNCTION_H +#define __BINDINGS_FUNCTION_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef struct function_string_t { + uint8_t*ptr; + size_t len; +} function_string_t; + +typedef struct wasi_io_poll_own_pollable_t { + int32_t __handle; +} wasi_io_poll_own_pollable_t; + +typedef struct wasi_io_poll_borrow_pollable_t { + int32_t __handle; +} wasi_io_poll_borrow_pollable_t; + +typedef struct { + wasi_io_poll_borrow_pollable_t *ptr; + size_t len; +} wasi_io_poll_list_borrow_pollable_t; + +typedef struct { + uint32_t *ptr; + size_t len; +} function_list_u32_t; + +// An instant in time, in nanoseconds. An instant is relative to an +// unspecified initial value, and can only be compared to instances from +// the same monotonic-clock. +typedef uint64_t wasi_clocks_monotonic_clock_instant_t; + +// A duration of time, in nanoseconds. +typedef uint64_t wasi_clocks_monotonic_clock_duration_t; + +typedef wasi_io_poll_own_pollable_t wasi_clocks_monotonic_clock_own_pollable_t; + +typedef struct wasi_io_error_own_error_t { + int32_t __handle; +} wasi_io_error_own_error_t; + +typedef struct wasi_io_error_borrow_error_t { + int32_t __handle; +} wasi_io_error_borrow_error_t; + +typedef wasi_io_error_own_error_t wasi_io_streams_own_error_t; + +// An error for input-stream and output-stream operations. +typedef struct wasi_io_streams_stream_error_t { + uint8_t tag; + union { + wasi_io_streams_own_error_t last_operation_failed; + } val; +} wasi_io_streams_stream_error_t; + +// The last operation (a write or flush) failed before completion. +// +// More information is available in the `error` payload. +// +// After this, the stream will be closed. All future operations return +// `stream-error::closed`. +#define WASI_IO_STREAMS_STREAM_ERROR_LAST_OPERATION_FAILED 0 +// The stream is closed: no more input will be accepted by the +// stream. A closed output-stream will return this error on all +// future operations. +#define WASI_IO_STREAMS_STREAM_ERROR_CLOSED 1 + +typedef struct wasi_io_streams_own_input_stream_t { + int32_t __handle; +} wasi_io_streams_own_input_stream_t; + +typedef struct wasi_io_streams_borrow_input_stream_t { + int32_t __handle; +} wasi_io_streams_borrow_input_stream_t; + +typedef struct wasi_io_streams_own_output_stream_t { + int32_t __handle; +} wasi_io_streams_own_output_stream_t; + +typedef struct wasi_io_streams_borrow_output_stream_t { + int32_t __handle; +} wasi_io_streams_borrow_output_stream_t; + +typedef struct { + uint8_t *ptr; + size_t len; +} function_list_u8_t; + +typedef struct { + bool is_err; + union { + function_list_u8_t ok; + wasi_io_streams_stream_error_t err; + } val; +} wasi_io_streams_result_list_u8_stream_error_t; + +typedef struct { + bool is_err; + union { + uint64_t ok; + wasi_io_streams_stream_error_t err; + } val; +} wasi_io_streams_result_u64_stream_error_t; + +typedef wasi_io_poll_own_pollable_t wasi_io_streams_own_pollable_t; + +typedef struct { + bool is_err; + union { + wasi_io_streams_stream_error_t err; + } val; +} wasi_io_streams_result_void_stream_error_t; + +typedef wasi_clocks_monotonic_clock_duration_t wasi_http_types_duration_t; + +// This type corresponds to HTTP standard Methods. +typedef struct wasi_http_types_method_t { + uint8_t tag; + union { + function_string_t other; + } val; +} wasi_http_types_method_t; + +#define WASI_HTTP_TYPES_METHOD_GET 0 +#define WASI_HTTP_TYPES_METHOD_HEAD 1 +#define WASI_HTTP_TYPES_METHOD_POST 2 +#define WASI_HTTP_TYPES_METHOD_PUT 3 +#define WASI_HTTP_TYPES_METHOD_DELETE 4 +#define WASI_HTTP_TYPES_METHOD_CONNECT 5 +#define WASI_HTTP_TYPES_METHOD_OPTIONS 6 +#define WASI_HTTP_TYPES_METHOD_TRACE 7 +#define WASI_HTTP_TYPES_METHOD_PATCH 8 +#define WASI_HTTP_TYPES_METHOD_OTHER 9 + +// This type corresponds to HTTP standard Related Schemes. +typedef struct wasi_http_types_scheme_t { + uint8_t tag; + union { + function_string_t other; + } val; +} wasi_http_types_scheme_t; + +#define WASI_HTTP_TYPES_SCHEME_HTTP 0 +#define WASI_HTTP_TYPES_SCHEME_HTTPS 1 +#define WASI_HTTP_TYPES_SCHEME_OTHER 2 + +typedef struct { + bool is_some; + function_string_t val; +} function_option_string_t; + +typedef struct { + bool is_some; + uint16_t val; +} function_option_u16_t; + +// Defines the case payload type for `DNS-error` above: +typedef struct wasi_http_types_dns_error_payload_t { + function_option_string_t rcode; + function_option_u16_t info_code; +} wasi_http_types_dns_error_payload_t; + +typedef struct { + bool is_some; + uint8_t val; +} function_option_u8_t; + +// Defines the case payload type for `TLS-alert-received` above: +typedef struct wasi_http_types_tls_alert_received_payload_t { + function_option_u8_t alert_id; + function_option_string_t alert_message; +} wasi_http_types_tls_alert_received_payload_t; + +typedef struct { + bool is_some; + uint32_t val; +} function_option_u32_t; + +// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: +typedef struct wasi_http_types_field_size_payload_t { + function_option_string_t field_name; + function_option_u32_t field_size; +} wasi_http_types_field_size_payload_t; + +typedef struct { + bool is_some; + uint64_t val; +} function_option_u64_t; + +typedef struct { + bool is_some; + wasi_http_types_field_size_payload_t val; +} wasi_http_types_option_field_size_payload_t; + +// These cases are inspired by the IANA HTTP Proxy Error Types: +// +typedef struct wasi_http_types_error_code_t { + uint8_t tag; + union { + wasi_http_types_dns_error_payload_t dns_error; + wasi_http_types_tls_alert_received_payload_t tls_alert_received; + function_option_u64_t http_request_body_size; + function_option_u32_t http_request_header_section_size; + wasi_http_types_option_field_size_payload_t http_request_header_size; + function_option_u32_t http_request_trailer_section_size; + wasi_http_types_field_size_payload_t http_request_trailer_size; + function_option_u32_t http_response_header_section_size; + wasi_http_types_field_size_payload_t http_response_header_size; + function_option_u64_t http_response_body_size; + function_option_u32_t http_response_trailer_section_size; + wasi_http_types_field_size_payload_t http_response_trailer_size; + function_option_string_t http_response_transfer_coding; + function_option_string_t http_response_content_coding; + function_option_string_t internal_error; + } val; +} wasi_http_types_error_code_t; + +#define WASI_HTTP_TYPES_ERROR_CODE_DNS_TIMEOUT 0 +#define WASI_HTTP_TYPES_ERROR_CODE_DNS_ERROR 1 +#define WASI_HTTP_TYPES_ERROR_CODE_DESTINATION_NOT_FOUND 2 +#define WASI_HTTP_TYPES_ERROR_CODE_DESTINATION_UNAVAILABLE 3 +#define WASI_HTTP_TYPES_ERROR_CODE_DESTINATION_IP_PROHIBITED 4 +#define WASI_HTTP_TYPES_ERROR_CODE_DESTINATION_IP_UNROUTABLE 5 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_REFUSED 6 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_TERMINATED 7 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_TIMEOUT 8 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_READ_TIMEOUT 9 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_WRITE_TIMEOUT 10 +#define WASI_HTTP_TYPES_ERROR_CODE_CONNECTION_LIMIT_REACHED 11 +#define WASI_HTTP_TYPES_ERROR_CODE_TLS_PROTOCOL_ERROR 12 +#define WASI_HTTP_TYPES_ERROR_CODE_TLS_CERTIFICATE_ERROR 13 +#define WASI_HTTP_TYPES_ERROR_CODE_TLS_ALERT_RECEIVED 14 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_DENIED 15 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_LENGTH_REQUIRED 16 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_BODY_SIZE 17 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_METHOD_INVALID 18 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_URI_INVALID 19 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_URI_TOO_LONG 20 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_HEADER_SECTION_SIZE 21 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_HEADER_SIZE 22 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_TRAILER_SECTION_SIZE 23 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_REQUEST_TRAILER_SIZE 24 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_INCOMPLETE 25 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_HEADER_SECTION_SIZE 26 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_HEADER_SIZE 27 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_BODY_SIZE 28 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_TRAILER_SECTION_SIZE 29 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_TRAILER_SIZE 30 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_TRANSFER_CODING 31 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_CONTENT_CODING 32 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_RESPONSE_TIMEOUT 33 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_UPGRADE_FAILED 34 +#define WASI_HTTP_TYPES_ERROR_CODE_HTTP_PROTOCOL_ERROR 35 +#define WASI_HTTP_TYPES_ERROR_CODE_LOOP_DETECTED 36 +#define WASI_HTTP_TYPES_ERROR_CODE_CONFIGURATION_ERROR 37 +// This is a catch-all error for anything that doesn't fit cleanly into a +// more specific case. It also includes an optional string for an +// unstructured description of the error. Users should not depend on the +// string for diagnosing errors, as it's not required to be consistent +// between implementations. +#define WASI_HTTP_TYPES_ERROR_CODE_INTERNAL_ERROR 38 + +// This type enumerates the different kinds of errors that may occur when +// setting or appending to a `fields` resource. +typedef struct wasi_http_types_header_error_t { + uint8_t tag; +} wasi_http_types_header_error_t; + +// This error indicates that a `field-name` or `field-value` was +// syntactically invalid when used with an operation that sets headers in a +// `fields`. +#define WASI_HTTP_TYPES_HEADER_ERROR_INVALID_SYNTAX 0 +// This error indicates that a forbidden `field-name` was used when trying +// to set a header in a `fields`. +#define WASI_HTTP_TYPES_HEADER_ERROR_FORBIDDEN 1 +// This error indicates that the operation on the `fields` was not +// permitted because the fields are immutable. +#define WASI_HTTP_TYPES_HEADER_ERROR_IMMUTABLE 2 + +// Field keys are always strings. +// +// Field keys should always be treated as case insensitive by the `fields` +// resource for the purposes of equality checking. +// +// # Deprecation +// +// This type has been deprecated in favor of the `field-name` type. +typedef function_string_t wasi_http_types_field_key_t; + +// Field names are always strings. +// +// Field names should always be treated as case insensitive by the `fields` +// resource for the purposes of equality checking. +typedef wasi_http_types_field_key_t wasi_http_types_field_name_t; + +// Field values should always be ASCII strings. However, in +// reality, HTTP implementations often have to interpret malformed values, +// so they are provided as a list of bytes. +typedef struct wasi_http_types_field_value_t { + uint8_t *ptr; + size_t len; +} wasi_http_types_field_value_t; + +typedef struct wasi_http_types_own_fields_t { + int32_t __handle; +} wasi_http_types_own_fields_t; + +typedef struct wasi_http_types_borrow_fields_t { + int32_t __handle; +} wasi_http_types_borrow_fields_t; + +typedef struct wasi_http_types_own_incoming_request_t { + int32_t __handle; +} wasi_http_types_own_incoming_request_t; + +typedef struct wasi_http_types_borrow_incoming_request_t { + int32_t __handle; +} wasi_http_types_borrow_incoming_request_t; + +typedef struct wasi_http_types_own_outgoing_request_t { + int32_t __handle; +} wasi_http_types_own_outgoing_request_t; + +typedef struct wasi_http_types_borrow_outgoing_request_t { + int32_t __handle; +} wasi_http_types_borrow_outgoing_request_t; + +typedef struct wasi_http_types_own_request_options_t { + int32_t __handle; +} wasi_http_types_own_request_options_t; + +typedef struct wasi_http_types_borrow_request_options_t { + int32_t __handle; +} wasi_http_types_borrow_request_options_t; + +typedef struct wasi_http_types_own_response_outparam_t { + int32_t __handle; +} wasi_http_types_own_response_outparam_t; + +typedef struct wasi_http_types_borrow_response_outparam_t { + int32_t __handle; +} wasi_http_types_borrow_response_outparam_t; + +// This type corresponds to the HTTP standard Status Code. +typedef uint16_t wasi_http_types_status_code_t; + +typedef struct wasi_http_types_own_incoming_response_t { + int32_t __handle; +} wasi_http_types_own_incoming_response_t; + +typedef struct wasi_http_types_borrow_incoming_response_t { + int32_t __handle; +} wasi_http_types_borrow_incoming_response_t; + +typedef struct wasi_http_types_own_incoming_body_t { + int32_t __handle; +} wasi_http_types_own_incoming_body_t; + +typedef struct wasi_http_types_borrow_incoming_body_t { + int32_t __handle; +} wasi_http_types_borrow_incoming_body_t; + +typedef struct wasi_http_types_own_future_trailers_t { + int32_t __handle; +} wasi_http_types_own_future_trailers_t; + +typedef struct wasi_http_types_borrow_future_trailers_t { + int32_t __handle; +} wasi_http_types_borrow_future_trailers_t; + +typedef struct wasi_http_types_own_outgoing_response_t { + int32_t __handle; +} wasi_http_types_own_outgoing_response_t; + +typedef struct wasi_http_types_borrow_outgoing_response_t { + int32_t __handle; +} wasi_http_types_borrow_outgoing_response_t; + +typedef struct wasi_http_types_own_outgoing_body_t { + int32_t __handle; +} wasi_http_types_own_outgoing_body_t; + +typedef struct wasi_http_types_borrow_outgoing_body_t { + int32_t __handle; +} wasi_http_types_borrow_outgoing_body_t; + +typedef struct wasi_http_types_own_future_incoming_response_t { + int32_t __handle; +} wasi_http_types_own_future_incoming_response_t; + +typedef struct wasi_http_types_borrow_future_incoming_response_t { + int32_t __handle; +} wasi_http_types_borrow_future_incoming_response_t; + +typedef struct { + wasi_http_types_field_name_t f0; + wasi_http_types_field_value_t f1; +} wasi_http_types_tuple2_field_name_field_value_t; + +typedef struct { + wasi_http_types_tuple2_field_name_field_value_t *ptr; + size_t len; +} wasi_http_types_list_tuple2_field_name_field_value_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_fields_t ok; + wasi_http_types_header_error_t err; + } val; +} wasi_http_types_result_own_fields_header_error_t; + +typedef struct { + wasi_http_types_field_value_t *ptr; + size_t len; +} wasi_http_types_list_field_value_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_header_error_t err; + } val; +} wasi_http_types_result_void_header_error_t; + +typedef struct { + bool is_some; + wasi_http_types_scheme_t val; +} wasi_http_types_option_scheme_t; + +typedef wasi_http_types_own_fields_t wasi_http_types_own_headers_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_incoming_body_t ok; + } val; +} wasi_http_types_result_own_incoming_body_void_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_outgoing_body_t ok; + } val; +} wasi_http_types_result_own_outgoing_body_void_t; + +typedef struct { + bool is_err; +} wasi_http_types_result_void_void_t; + +typedef struct { + bool is_some; + wasi_http_types_duration_t val; +} wasi_http_types_option_duration_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_outgoing_response_t ok; + wasi_http_types_error_code_t err; + } val; +} wasi_http_types_result_own_outgoing_response_error_code_t; + +typedef wasi_io_streams_own_input_stream_t wasi_http_types_own_input_stream_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_input_stream_t ok; + } val; +} wasi_http_types_result_own_input_stream_void_t; + +typedef wasi_io_poll_own_pollable_t wasi_http_types_own_pollable_t; + +typedef wasi_http_types_own_fields_t wasi_http_types_own_trailers_t; + +typedef struct { + bool is_some; + wasi_http_types_own_trailers_t val; +} wasi_http_types_option_own_trailers_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_option_own_trailers_t ok; + wasi_http_types_error_code_t err; + } val; +} wasi_http_types_result_option_own_trailers_error_code_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_result_option_own_trailers_error_code_t ok; + } val; +} wasi_http_types_result_result_option_own_trailers_error_code_void_t; + +typedef struct { + bool is_some; + wasi_http_types_result_result_option_own_trailers_error_code_void_t val; +} wasi_http_types_option_result_result_option_own_trailers_error_code_void_t; + +typedef wasi_io_streams_own_output_stream_t wasi_http_types_own_output_stream_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_output_stream_t ok; + } val; +} wasi_http_types_result_own_output_stream_void_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_error_code_t err; + } val; +} wasi_http_types_result_void_error_code_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_own_incoming_response_t ok; + wasi_http_types_error_code_t err; + } val; +} wasi_http_types_result_own_incoming_response_error_code_t; + +typedef struct { + bool is_err; + union { + wasi_http_types_result_own_incoming_response_error_code_t ok; + } val; +} wasi_http_types_result_result_own_incoming_response_error_code_void_t; + +typedef struct { + bool is_some; + wasi_http_types_result_result_own_incoming_response_error_code_void_t val; +} wasi_http_types_option_result_result_own_incoming_response_error_code_void_t; + +typedef wasi_io_error_borrow_error_t wasi_http_types_borrow_io_error_t; + +typedef struct { + bool is_some; + wasi_http_types_error_code_t val; +} wasi_http_types_option_error_code_t; + +typedef wasi_http_types_error_code_t wasi_http_outgoing_handler_error_code_t; + +typedef wasi_http_types_own_outgoing_request_t wasi_http_outgoing_handler_own_outgoing_request_t; + +typedef wasi_http_types_own_request_options_t wasi_http_outgoing_handler_own_request_options_t; + +typedef struct { + bool is_some; + wasi_http_outgoing_handler_own_request_options_t val; +} wasi_http_outgoing_handler_option_own_request_options_t; + +typedef wasi_http_types_own_future_incoming_response_t wasi_http_outgoing_handler_own_future_incoming_response_t; + +typedef struct { + bool is_err; + union { + wasi_http_outgoing_handler_own_future_incoming_response_t ok; + wasi_http_outgoing_handler_error_code_t err; + } val; +} wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_t; + +typedef uint8_t function_log_level_t; + +#define FUNCTION_LOG_LEVEL_DEBUG 0 +#define FUNCTION_LOG_LEVEL_INFO 1 +#define FUNCTION_LOG_LEVEL_WARN 2 +#define FUNCTION_LOG_LEVEL_ERROR 3 + +typedef struct { + function_string_t f0; + function_string_t f1; +} function_tuple2_string_string_t; + +typedef struct { + function_tuple2_string_string_t *ptr; + size_t len; +} function_list_tuple2_string_string_t; + +typedef struct { + bool is_err; + union { + function_list_u8_t ok; + function_string_t err; + } val; +} function_result_list_u8_string_t; + +// Imported Functions from `wasi:io/poll@0.2.12` +// Return the readiness of a pollable. This function never blocks. +// +// Returns `true` when the pollable is ready, and `false` otherwise. +extern bool wasi_io_poll_method_pollable_ready(wasi_io_poll_borrow_pollable_t self); +// `block` returns immediately if the pollable is ready, and otherwise +// blocks until ready. +// +// This function is equivalent to calling `poll.poll` on a list +// containing only this pollable. +extern void wasi_io_poll_method_pollable_block(wasi_io_poll_borrow_pollable_t self); +// Poll for completion on a set of pollables. +// +// This function takes a list of pollables, which identify I/O sources of +// interest, and waits until one or more of the events is ready for I/O. +// +// The result `list` contains one or more indices of handles in the +// argument list that is ready for I/O. +// +// This function traps if either: +// - the list is empty, or: +// - the list contains more elements than can be indexed with a `u32` value. +// +// A timeout can be implemented by adding a pollable from the +// wasi-clocks API to the list. +// +// This function does not return a `result`; polling in itself does not +// do any I/O so it doesn't fail. If any of the I/O sources identified by +// the pollables has an error, it is indicated by marking the source as +// being ready for I/O. +extern void wasi_io_poll_poll(wasi_io_poll_list_borrow_pollable_t *in, function_list_u32_t *ret); + +// Imported Functions from `wasi:clocks/monotonic-clock@0.2.12` +// Read the current value of the clock. +// +// The clock is monotonic, therefore calling this function repeatedly will +// produce a sequence of non-decreasing values. +// +// For completeness, this function traps if it's not possible to represent +// the value of the clock in an `instant`. Consequently, implementations +// should ensure that the starting time is low enough to avoid the +// possibility of overflow in practice. +extern wasi_clocks_monotonic_clock_instant_t wasi_clocks_monotonic_clock_now(void); +// Query the resolution of the clock. Returns the duration of time +// corresponding to a clock tick. +extern wasi_clocks_monotonic_clock_duration_t wasi_clocks_monotonic_clock_resolution(void); +// Create a `pollable` which will resolve once the specified instant +// has occurred. +extern wasi_clocks_monotonic_clock_own_pollable_t wasi_clocks_monotonic_clock_subscribe_instant(wasi_clocks_monotonic_clock_instant_t when); +// Create a `pollable` that will resolve after the specified duration has +// elapsed from the time this function is invoked. +extern wasi_clocks_monotonic_clock_own_pollable_t wasi_clocks_monotonic_clock_subscribe_duration(wasi_clocks_monotonic_clock_duration_t when); + +// Imported Functions from `wasi:io/error@0.2.12` +// Returns a string that is suitable to assist humans in debugging +// this error. +// +// WARNING: The returned string should not be consumed mechanically! +// It may change across platforms, hosts, or other implementation +// details. Parsing this string is a major platform-compatibility +// hazard. +extern void wasi_io_error_method_error_to_debug_string(wasi_io_error_borrow_error_t self, function_string_t *ret); + +// Imported Functions from `wasi:io/streams@0.2.12` +// Perform a non-blocking read from the stream. +// +// When the source of a `read` is binary data, the bytes from the source +// are returned verbatim. When the source of a `read` is known to the +// implementation to be text, bytes containing the UTF-8 encoding of the +// text are returned. +// +// This function returns a list of bytes containing the read data, +// when successful. The returned list will contain up to `len` bytes; +// it may return fewer than requested, but not more. The list is +// empty when no bytes are available for reading at this time. The +// pollable given by `subscribe` will be ready when more bytes are +// available. +// +// This function fails with a `stream-error` when the operation +// encounters an error, giving `last-operation-failed`, or when the +// stream is closed, giving `closed`. +// +// When the caller gives a `len` of 0, it represents a request to +// read 0 bytes. If the stream is still open, this call should +// succeed and return an empty list, or otherwise fail with `closed`. +// +// The `len` parameter is a `u64`, which could represent a list of u8 which +// is not possible to allocate in wasm32, or not desirable to allocate as +// as a return value by the callee. The callee may return a list of bytes +// less than `len` in size while more bytes are available for reading. +extern bool wasi_io_streams_method_input_stream_read(wasi_io_streams_borrow_input_stream_t self, uint64_t len, function_list_u8_t *ret, wasi_io_streams_stream_error_t *err); +// Read bytes from a stream, after blocking until at least one byte can +// be read. Except for blocking, behavior is identical to `read`. +extern bool wasi_io_streams_method_input_stream_blocking_read(wasi_io_streams_borrow_input_stream_t self, uint64_t len, function_list_u8_t *ret, wasi_io_streams_stream_error_t *err); +// Skip bytes from a stream. Returns number of bytes skipped. +// +// Behaves identical to `read`, except instead of returning a list +// of bytes, returns the number of bytes consumed from the stream. +extern bool wasi_io_streams_method_input_stream_skip(wasi_io_streams_borrow_input_stream_t self, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err); +// Skip bytes from a stream, after blocking until at least one byte +// can be skipped. Except for blocking behavior, identical to `skip`. +extern bool wasi_io_streams_method_input_stream_blocking_skip(wasi_io_streams_borrow_input_stream_t self, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err); +// Create a `pollable` which will resolve once either the specified stream +// has bytes available to read or the other end of the stream has been +// closed. +// The created `pollable` is a child resource of the `input-stream`. +// Implementations may trap if the `input-stream` is dropped before +// all derived `pollable`s created with this function are dropped. +extern wasi_io_streams_own_pollable_t wasi_io_streams_method_input_stream_subscribe(wasi_io_streams_borrow_input_stream_t self); +// Check readiness for writing. This function never blocks. +// +// Returns the number of bytes permitted for the next call to `write`, +// or an error. Calling `write` with more bytes than this function has +// permitted will trap. +// +// When this function returns 0 bytes, the `subscribe` pollable will +// become ready when this function will report at least 1 byte, or an +// error. +extern bool wasi_io_streams_method_output_stream_check_write(wasi_io_streams_borrow_output_stream_t self, uint64_t *ret, wasi_io_streams_stream_error_t *err); +// Perform a write. This function never blocks. +// +// When the destination of a `write` is binary data, the bytes from +// `contents` are written verbatim. When the destination of a `write` is +// known to the implementation to be text, the bytes of `contents` are +// transcoded from UTF-8 into the encoding of the destination and then +// written. +// +// Precondition: check-write gave permit of Ok(n) and contents has a +// length of less than or equal to n. Otherwise, this function will trap. +// +// returns Err(closed) without writing if the stream has closed since +// the last call to check-write provided a permit. +extern bool wasi_io_streams_method_output_stream_write(wasi_io_streams_borrow_output_stream_t self, function_list_u8_t *contents, wasi_io_streams_stream_error_t *err); +// Perform a write of up to 4096 bytes, and then flush the stream. Block +// until all of these operations are complete, or an error occurs. +// +// Returns success when all of the contents written are successfully +// flushed to output. If an error occurs at any point before all +// contents are successfully flushed, that error is returned as soon as +// possible. If writing and flushing the complete contents causes the +// stream to become closed, this call should return success, and +// subsequent calls to check-write or other interfaces should return +// stream-error::closed. +extern bool wasi_io_streams_method_output_stream_blocking_write_and_flush(wasi_io_streams_borrow_output_stream_t self, function_list_u8_t *contents, wasi_io_streams_stream_error_t *err); +// Request to flush buffered output. This function never blocks. +// +// This tells the output-stream that the caller intends any buffered +// output to be flushed. the output which is expected to be flushed +// is all that has been passed to `write` prior to this call. +// +// Upon calling this function, the `output-stream` will not accept any +// writes (`check-write` will return `ok(0)`) until the flush has +// completed. The `subscribe` pollable will become ready when the +// flush has completed and the stream can accept more writes. +extern bool wasi_io_streams_method_output_stream_flush(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_stream_error_t *err); +// Request to flush buffered output, and block until flush completes +// and stream is ready for writing again. +extern bool wasi_io_streams_method_output_stream_blocking_flush(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_stream_error_t *err); +// Create a `pollable` which will resolve once the output-stream +// is ready for more writing, or an error has occurred. When this +// pollable is ready, `check-write` will return `ok(n)` with n>0, or an +// error. +// +// If the stream is closed, this pollable is always ready immediately. +// +// The created `pollable` is a child resource of the `output-stream`. +// Implementations may trap if the `output-stream` is dropped before +// all derived `pollable`s created with this function are dropped. +extern wasi_io_streams_own_pollable_t wasi_io_streams_method_output_stream_subscribe(wasi_io_streams_borrow_output_stream_t self); +// Write zeroes to a stream. +// +// This should be used precisely like `write` with the exact same +// preconditions (must use check-write first), but instead of +// passing a list of bytes, you simply pass the number of zero-bytes +// that should be written. +extern bool wasi_io_streams_method_output_stream_write_zeroes(wasi_io_streams_borrow_output_stream_t self, uint64_t len, wasi_io_streams_stream_error_t *err); +// Perform a write of up to 4096 zeroes, and then flush the stream. +// Block until all of these operations are complete, or an error +// occurs. +// +// Functionality is equivelant to `blocking-write-and-flush` with +// contents given as a list of len containing only zeroes. +extern bool wasi_io_streams_method_output_stream_blocking_write_zeroes_and_flush(wasi_io_streams_borrow_output_stream_t self, uint64_t len, wasi_io_streams_stream_error_t *err); +// Read from one stream and write to another. +// +// The behavior of splice is equivalent to: +// 1. calling `check-write` on the `output-stream` +// 2. calling `read` on the `input-stream` with the smaller of the +// `check-write` permitted length and the `len` provided to `splice` +// 3. calling `write` on the `output-stream` with that read data. +// +// Any error reported by the call to `check-write`, `read`, or +// `write` ends the splice and reports that error. +// +// This function returns the number of bytes transferred; it may be less +// than `len`. +extern bool wasi_io_streams_method_output_stream_splice(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_borrow_input_stream_t src, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err); +// Read from one stream and write to another, with blocking. +// +// This is similar to `splice`, except that it blocks until the +// `output-stream` is ready for writing, and the `input-stream` +// is ready for reading, before performing the `splice`. +extern bool wasi_io_streams_method_output_stream_blocking_splice(wasi_io_streams_borrow_output_stream_t self, wasi_io_streams_borrow_input_stream_t src, uint64_t len, uint64_t *ret, wasi_io_streams_stream_error_t *err); + +// Imported Functions from `wasi:http/types@0.2.12` +// Construct an empty HTTP Fields. +// +// The resulting `fields` is mutable. +extern wasi_http_types_own_fields_t wasi_http_types_constructor_fields(void); +// Construct an HTTP Fields. +// +// The resulting `fields` is mutable. +// +// The list represents each name-value pair in the Fields. Names +// which have multiple values are represented by multiple entries in this +// list with the same name. +// +// The tuple is a pair of the field name, represented as a string, and +// Value, represented as a list of bytes. +// +// An error result will be returned if any `field-name` or `field-value` is +// syntactically invalid, or if a field is forbidden. +extern bool wasi_http_types_static_fields_from_list(wasi_http_types_list_tuple2_field_name_field_value_t *entries, wasi_http_types_own_fields_t *ret, wasi_http_types_header_error_t *err); +// Get all of the values corresponding to a name. If the name is not present +// in this `fields` or is syntactically invalid, an empty list is returned. +// However, if the name is present but empty, this is represented by a list +// with one or more empty field-values present. +extern void wasi_http_types_method_fields_get(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_list_field_value_t *ret); +// Returns `true` when the name is present in this `fields`. If the name is +// syntactically invalid, `false` is returned. +extern bool wasi_http_types_method_fields_has(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name); +// Set all of the values for a name. Clears any existing values for that +// name, if they have been set. +// +// Fails with `header-error.immutable` if the `fields` are immutable. +// +// Fails with `header-error.invalid-syntax` if the `field-name` or any of +// the `field-value`s are syntactically invalid. +extern bool wasi_http_types_method_fields_set(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_list_field_value_t *value, wasi_http_types_header_error_t *err); +// Delete all values for a name. Does nothing if no values for the name +// exist. +// +// Fails with `header-error.immutable` if the `fields` are immutable. +// +// Fails with `header-error.invalid-syntax` if the `field-name` is +// syntactically invalid. +extern bool wasi_http_types_method_fields_delete(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_header_error_t *err); +// Append a value for a name. Does not change or delete any existing +// values for that name. +// +// Fails with `header-error.immutable` if the `fields` are immutable. +// +// Fails with `header-error.invalid-syntax` if the `field-name` or +// `field-value` are syntactically invalid. +extern bool wasi_http_types_method_fields_append(wasi_http_types_borrow_fields_t self, wasi_http_types_field_name_t *name, wasi_http_types_field_value_t *value, wasi_http_types_header_error_t *err); +// Retrieve the full set of names and values in the Fields. Like the +// constructor, the list represents each name-value pair. +// +// The outer list represents each name-value pair in the Fields. Names +// which have multiple values are represented by multiple entries in this +// list with the same name. +// +// The names and values are always returned in the original casing and in +// the order in which they will be serialized for transport. +extern void wasi_http_types_method_fields_entries(wasi_http_types_borrow_fields_t self, wasi_http_types_list_tuple2_field_name_field_value_t *ret); +// Make a deep copy of the Fields. Equivalent in behavior to calling the +// `fields` constructor on the return value of `entries`. The resulting +// `fields` is mutable. +extern wasi_http_types_own_fields_t wasi_http_types_method_fields_clone(wasi_http_types_borrow_fields_t self); +// Returns the method of the incoming request. +extern void wasi_http_types_method_incoming_request_method(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_method_t *ret); +// Returns the path with query parameters from the request, as a string. +extern bool wasi_http_types_method_incoming_request_path_with_query(wasi_http_types_borrow_incoming_request_t self, function_string_t *ret); +// Returns the protocol scheme from the request. +extern bool wasi_http_types_method_incoming_request_scheme(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_scheme_t *ret); +// Returns the authority of the Request's target URI, if present. +extern bool wasi_http_types_method_incoming_request_authority(wasi_http_types_borrow_incoming_request_t self, function_string_t *ret); +// Get the `headers` associated with the request. +// +// The returned `headers` resource is immutable: `set`, `append`, and +// `delete` operations will fail with `header-error.immutable`. +// +// The `headers` returned are a child resource: it must be dropped before +// the parent `incoming-request` is dropped. Dropping this +// `incoming-request` before all children are dropped will trap. +extern wasi_http_types_own_headers_t wasi_http_types_method_incoming_request_headers(wasi_http_types_borrow_incoming_request_t self); +// Gives the `incoming-body` associated with this request. Will only +// return success at most once, and subsequent calls will return error. +extern bool wasi_http_types_method_incoming_request_consume(wasi_http_types_borrow_incoming_request_t self, wasi_http_types_own_incoming_body_t *ret); +// Construct a new `outgoing-request` with a default `method` of `GET`, and +// `none` values for `path-with-query`, `scheme`, and `authority`. +// +// * `headers` is the HTTP Headers for the Request. +// +// It is possible to construct, or manipulate with the accessor functions +// below, an `outgoing-request` with an invalid combination of `scheme` +// and `authority`, or `headers` which are not permitted to be sent. +// It is the obligation of the `outgoing-handler.handle` implementation +// to reject invalid constructions of `outgoing-request`. +extern wasi_http_types_own_outgoing_request_t wasi_http_types_constructor_outgoing_request(wasi_http_types_own_headers_t headers); +// Returns the resource corresponding to the outgoing Body for this +// Request. +// +// Returns success on the first call: the `outgoing-body` resource for +// this `outgoing-request` can be retrieved at most once. Subsequent +// calls will return error. +extern bool wasi_http_types_method_outgoing_request_body(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_own_outgoing_body_t *ret); +// Get the Method for the Request. +extern void wasi_http_types_method_outgoing_request_method(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_method_t *ret); +// Set the Method for the Request. Fails if the string present in a +// `method.other` argument is not a syntactically valid method. +extern bool wasi_http_types_method_outgoing_request_set_method(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_method_t *method); +// Get the combination of the HTTP Path and Query for the Request. +// When `none`, this represents an empty Path and empty Query. +extern bool wasi_http_types_method_outgoing_request_path_with_query(wasi_http_types_borrow_outgoing_request_t self, function_string_t *ret); +// Set the combination of the HTTP Path and Query for the Request. +// When `none`, this represents an empty Path and empty Query. Fails is the +// string given is not a syntactically valid path and query uri component. +extern bool wasi_http_types_method_outgoing_request_set_path_with_query(wasi_http_types_borrow_outgoing_request_t self, function_string_t *maybe_path_with_query); +// Get the HTTP Related Scheme for the Request. When `none`, the +// implementation may choose an appropriate default scheme. +extern bool wasi_http_types_method_outgoing_request_scheme(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_scheme_t *ret); +// Set the HTTP Related Scheme for the Request. When `none`, the +// implementation may choose an appropriate default scheme. Fails if the +// string given is not a syntactically valid uri scheme. +extern bool wasi_http_types_method_outgoing_request_set_scheme(wasi_http_types_borrow_outgoing_request_t self, wasi_http_types_scheme_t *maybe_scheme); +// Get the authority of the Request's target URI. A value of `none` may be used +// with Related Schemes which do not require an authority. The HTTP and +// HTTPS schemes always require an authority. +extern bool wasi_http_types_method_outgoing_request_authority(wasi_http_types_borrow_outgoing_request_t self, function_string_t *ret); +// Set the authority of the Request's target URI. A value of `none` may be used +// with Related Schemes which do not require an authority. The HTTP and +// HTTPS schemes always require an authority. Fails if the string given is +// not a syntactically valid URI authority. +extern bool wasi_http_types_method_outgoing_request_set_authority(wasi_http_types_borrow_outgoing_request_t self, function_string_t *maybe_authority); +// Get the headers associated with the Request. +// +// The returned `headers` resource is immutable: `set`, `append`, and +// `delete` operations will fail with `header-error.immutable`. +// +// This headers resource is a child: it must be dropped before the parent +// `outgoing-request` is dropped, or its ownership is transferred to +// another component by e.g. `outgoing-handler.handle`. +extern wasi_http_types_own_headers_t wasi_http_types_method_outgoing_request_headers(wasi_http_types_borrow_outgoing_request_t self); +// Construct a default `request-options` value. +extern wasi_http_types_own_request_options_t wasi_http_types_constructor_request_options(void); +// The timeout for the initial connect to the HTTP Server. +extern bool wasi_http_types_method_request_options_connect_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret); +// Set the timeout for the initial connect to the HTTP Server. An error +// return value indicates that this timeout is not supported. +extern bool wasi_http_types_method_request_options_set_connect_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration); +// The timeout for receiving the first byte of the Response body. +extern bool wasi_http_types_method_request_options_first_byte_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret); +// Set the timeout for receiving the first byte of the Response body. An +// error return value indicates that this timeout is not supported. +extern bool wasi_http_types_method_request_options_set_first_byte_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration); +// The timeout for receiving subsequent chunks of bytes in the Response +// body stream. +extern bool wasi_http_types_method_request_options_between_bytes_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *ret); +// Set the timeout for receiving subsequent chunks of bytes in the Response +// body stream. An error return value indicates that this timeout is not +// supported. +extern bool wasi_http_types_method_request_options_set_between_bytes_timeout(wasi_http_types_borrow_request_options_t self, wasi_http_types_duration_t *maybe_duration); +// Set the value of the `response-outparam` to either send a response, +// or indicate an error. +// +// This method consumes the `response-outparam` to ensure that it is +// called at most once. If it is never called, the implementation +// will respond with an error. +// +// The user may provide an `error` to `response` to allow the +// implementation determine how to respond with an HTTP error response. +extern void wasi_http_types_static_response_outparam_set(wasi_http_types_own_response_outparam_t param, wasi_http_types_result_own_outgoing_response_error_code_t *response); +// Returns the status code from the incoming response. +extern wasi_http_types_status_code_t wasi_http_types_method_incoming_response_status(wasi_http_types_borrow_incoming_response_t self); +// Returns the headers from the incoming response. +// +// The returned `headers` resource is immutable: `set`, `append`, and +// `delete` operations will fail with `header-error.immutable`. +// +// This headers resource is a child: it must be dropped before the parent +// `incoming-response` is dropped. +extern wasi_http_types_own_headers_t wasi_http_types_method_incoming_response_headers(wasi_http_types_borrow_incoming_response_t self); +// Returns the incoming body. May be called at most once. Returns error +// if called additional times. +extern bool wasi_http_types_method_incoming_response_consume(wasi_http_types_borrow_incoming_response_t self, wasi_http_types_own_incoming_body_t *ret); +// Returns the contents of the body, as a stream of bytes. +// +// Returns success on first call: the stream representing the contents +// can be retrieved at most once. Subsequent calls will return error. +// +// The returned `input-stream` resource is a child: it must be dropped +// before the parent `incoming-body` is dropped, or consumed by +// `incoming-body.finish`. +// +// This invariant ensures that the implementation can determine whether +// the user is consuming the contents of the body, waiting on the +// `future-trailers` to be ready, or neither. This allows for network +// backpressure is to be applied when the user is consuming the body, +// and for that backpressure to not inhibit delivery of the trailers if +// the user does not read the entire body. +extern bool wasi_http_types_method_incoming_body_stream(wasi_http_types_borrow_incoming_body_t self, wasi_http_types_own_input_stream_t *ret); +// Takes ownership of `incoming-body`, and returns a `future-trailers`. +// This function will trap if the `input-stream` child is still alive. +extern wasi_http_types_own_future_trailers_t wasi_http_types_static_incoming_body_finish(wasi_http_types_own_incoming_body_t this_); +// Returns a pollable which becomes ready when either the trailers have +// been received, or an error has occurred. When this pollable is ready, +// the `get` method will return `some`. +extern wasi_http_types_own_pollable_t wasi_http_types_method_future_trailers_subscribe(wasi_http_types_borrow_future_trailers_t self); +// Returns the contents of the trailers, or an error which occurred, +// once the future is ready. +// +// The outer `option` represents future readiness. Users can wait on this +// `option` to become `some` using the `subscribe` method. +// +// The outer `result` is used to retrieve the trailers or error at most +// once. It will be success on the first call in which the outer option +// is `some`, and error on subsequent calls. +// +// The inner `result` represents that either the HTTP Request or Response +// body, as well as any trailers, were received successfully, or that an +// error occurred receiving them. The optional `trailers` indicates whether +// or not trailers were present in the body. +// +// When some `trailers` are returned by this method, the `trailers` +// resource is immutable, and a child. Use of the `set`, `append`, or +// `delete` methods will return an error, and the resource must be +// dropped before the parent `future-trailers` is dropped. +extern bool wasi_http_types_method_future_trailers_get(wasi_http_types_borrow_future_trailers_t self, wasi_http_types_result_result_option_own_trailers_error_code_void_t *ret); +// Construct an `outgoing-response`, with a default `status-code` of `200`. +// If a different `status-code` is needed, it must be set via the +// `set-status-code` method. +// +// * `headers` is the HTTP Headers for the Response. +extern wasi_http_types_own_outgoing_response_t wasi_http_types_constructor_outgoing_response(wasi_http_types_own_headers_t headers); +// Get the HTTP Status Code for the Response. +extern wasi_http_types_status_code_t wasi_http_types_method_outgoing_response_status_code(wasi_http_types_borrow_outgoing_response_t self); +// Set the HTTP Status Code for the Response. Fails if the status-code +// given is not a valid http status code. +extern bool wasi_http_types_method_outgoing_response_set_status_code(wasi_http_types_borrow_outgoing_response_t self, wasi_http_types_status_code_t status_code); +// Get the headers associated with the Request. +// +// The returned `headers` resource is immutable: `set`, `append`, and +// `delete` operations will fail with `header-error.immutable`. +// +// This headers resource is a child: it must be dropped before the parent +// `outgoing-request` is dropped, or its ownership is transferred to +// another component by e.g. `outgoing-handler.handle`. +extern wasi_http_types_own_headers_t wasi_http_types_method_outgoing_response_headers(wasi_http_types_borrow_outgoing_response_t self); +// Returns the resource corresponding to the outgoing Body for this Response. +// +// Returns success on the first call: the `outgoing-body` resource for +// this `outgoing-response` can be retrieved at most once. Subsequent +// calls will return error. +extern bool wasi_http_types_method_outgoing_response_body(wasi_http_types_borrow_outgoing_response_t self, wasi_http_types_own_outgoing_body_t *ret); +// Returns a stream for writing the body contents. +// +// The returned `output-stream` is a child resource: it must be dropped +// before the parent `outgoing-body` resource is dropped (or finished), +// otherwise the `outgoing-body` drop or `finish` will trap. +// +// Returns success on the first call: the `output-stream` resource for +// this `outgoing-body` may be retrieved at most once. Subsequent calls +// will return error. +extern bool wasi_http_types_method_outgoing_body_write(wasi_http_types_borrow_outgoing_body_t self, wasi_http_types_own_output_stream_t *ret); +// Finalize an outgoing body, optionally providing trailers. This must be +// called to signal that the response is complete. If the `outgoing-body` +// is dropped without calling `outgoing-body.finalize`, the implementation +// should treat the body as corrupted. +// +// Fails if the body's `outgoing-request` or `outgoing-response` was +// constructed with a Content-Length header, and the contents written +// to the body (via `write`) does not match the value given in the +// Content-Length. +extern bool wasi_http_types_static_outgoing_body_finish(wasi_http_types_own_outgoing_body_t this_, wasi_http_types_own_trailers_t *maybe_trailers, wasi_http_types_error_code_t *err); +// Returns a pollable which becomes ready when either the Response has +// been received, or an error has occurred. When this pollable is ready, +// the `get` method will return `some`. +extern wasi_http_types_own_pollable_t wasi_http_types_method_future_incoming_response_subscribe(wasi_http_types_borrow_future_incoming_response_t self); +// Returns the incoming HTTP Response, or an error, once one is ready. +// +// The outer `option` represents future readiness. Users can wait on this +// `option` to become `some` using the `subscribe` method. +// +// The outer `result` is used to retrieve the response or error at most +// once. It will be success on the first call in which the outer option +// is `some`, and error on subsequent calls. +// +// The inner `result` represents that either the incoming HTTP Response +// status and headers have received successfully, or that an error +// occurred. Errors may also occur while consuming the response body, +// but those will be reported by the `incoming-body` and its +// `output-stream` child. +extern bool wasi_http_types_method_future_incoming_response_get(wasi_http_types_borrow_future_incoming_response_t self, wasi_http_types_result_result_own_incoming_response_error_code_void_t *ret); +// Attempts to extract a http-related `error` from the wasi:io `error` +// provided. +// +// Stream operations which return +// `wasi:io/stream.stream-error.last-operation-failed` have a payload of +// type `wasi:io/error.error` with more information about the operation +// that failed. This payload can be passed through to this function to see +// if there's http-related information about the error to return. +// +// Note that this function is fallible because not all io-errors are +// http-related errors. +extern bool wasi_http_types_http_error_code(wasi_http_types_borrow_io_error_t err_, wasi_http_types_error_code_t *ret); + +// Imported Functions from `wasi:http/outgoing-handler@0.2.12` +// This function is invoked with an outgoing HTTP Request, and it returns +// a resource `future-incoming-response` which represents an HTTP Response +// which may arrive in the future. +// +// The `options` argument accepts optional parameters for the HTTP +// protocol's transport layer. +// +// This function may return an error if the `outgoing-request` is invalid +// or not allowed to be made. Otherwise, protocol errors are reported +// through the `future-incoming-response`. +extern bool wasi_http_outgoing_handler_handle(wasi_http_outgoing_handler_own_outgoing_request_t request, wasi_http_outgoing_handler_own_request_options_t *maybe_options, wasi_http_outgoing_handler_own_future_incoming_response_t *ret, wasi_http_outgoing_handler_error_code_t *err); + +// Imported Functions from `function` +extern void function_log(function_log_level_t level, function_string_t *msg, function_list_tuple2_string_string_t *kv); + +// Exported Functions from `function` +bool exports_function_run(function_list_u8_t *request, function_list_u8_t *ret, function_string_t *err); + +// Helper Functions + +extern void wasi_io_poll_pollable_drop_own(wasi_io_poll_own_pollable_t handle); + +extern void wasi_io_poll_pollable_drop_borrow(wasi_io_poll_borrow_pollable_t handle); + +extern wasi_io_poll_borrow_pollable_t wasi_io_poll_borrow_pollable(wasi_io_poll_own_pollable_t handle); + +void wasi_io_poll_list_borrow_pollable_free(wasi_io_poll_list_borrow_pollable_t *ptr); + +void function_list_u32_free(function_list_u32_t *ptr); + +extern void wasi_io_error_error_drop_own(wasi_io_error_own_error_t handle); + +extern void wasi_io_error_error_drop_borrow(wasi_io_error_borrow_error_t handle); + +extern wasi_io_error_borrow_error_t wasi_io_error_borrow_error(wasi_io_error_own_error_t handle); + +void wasi_io_streams_stream_error_free(wasi_io_streams_stream_error_t *ptr); + +extern void wasi_io_streams_input_stream_drop_own(wasi_io_streams_own_input_stream_t handle); + +extern void wasi_io_streams_input_stream_drop_borrow(wasi_io_streams_borrow_input_stream_t handle); + +extern wasi_io_streams_borrow_input_stream_t wasi_io_streams_borrow_input_stream(wasi_io_streams_own_input_stream_t handle); + +extern void wasi_io_streams_output_stream_drop_own(wasi_io_streams_own_output_stream_t handle); + +extern void wasi_io_streams_output_stream_drop_borrow(wasi_io_streams_borrow_output_stream_t handle); + +extern wasi_io_streams_borrow_output_stream_t wasi_io_streams_borrow_output_stream(wasi_io_streams_own_output_stream_t handle); + +void function_list_u8_free(function_list_u8_t *ptr); + +void wasi_io_streams_result_list_u8_stream_error_free(wasi_io_streams_result_list_u8_stream_error_t *ptr); + +void wasi_io_streams_result_u64_stream_error_free(wasi_io_streams_result_u64_stream_error_t *ptr); + +void wasi_io_streams_result_void_stream_error_free(wasi_io_streams_result_void_stream_error_t *ptr); + +void wasi_http_types_method_free(wasi_http_types_method_t *ptr); + +void wasi_http_types_scheme_free(wasi_http_types_scheme_t *ptr); + +void function_option_string_free(function_option_string_t *ptr); + +void function_option_u16_free(function_option_u16_t *ptr); + +void wasi_http_types_dns_error_payload_free(wasi_http_types_dns_error_payload_t *ptr); + +void function_option_u8_free(function_option_u8_t *ptr); + +void wasi_http_types_tls_alert_received_payload_free(wasi_http_types_tls_alert_received_payload_t *ptr); + +void function_option_u32_free(function_option_u32_t *ptr); + +void wasi_http_types_field_size_payload_free(wasi_http_types_field_size_payload_t *ptr); + +void function_option_u64_free(function_option_u64_t *ptr); + +void wasi_http_types_option_field_size_payload_free(wasi_http_types_option_field_size_payload_t *ptr); + +void wasi_http_types_error_code_free(wasi_http_types_error_code_t *ptr); + +void wasi_http_types_header_error_free(wasi_http_types_header_error_t *ptr); + +void wasi_http_types_field_key_free(wasi_http_types_field_key_t *ptr); + +void wasi_http_types_field_name_free(wasi_http_types_field_name_t *ptr); + +void wasi_http_types_field_value_free(wasi_http_types_field_value_t *ptr); + +extern void wasi_http_types_fields_drop_own(wasi_http_types_own_fields_t handle); + +extern void wasi_http_types_fields_drop_borrow(wasi_http_types_borrow_fields_t handle); + +extern wasi_http_types_borrow_fields_t wasi_http_types_borrow_fields(wasi_http_types_own_fields_t handle); + +extern void wasi_http_types_incoming_request_drop_own(wasi_http_types_own_incoming_request_t handle); + +extern void wasi_http_types_incoming_request_drop_borrow(wasi_http_types_borrow_incoming_request_t handle); + +extern wasi_http_types_borrow_incoming_request_t wasi_http_types_borrow_incoming_request(wasi_http_types_own_incoming_request_t handle); + +extern void wasi_http_types_outgoing_request_drop_own(wasi_http_types_own_outgoing_request_t handle); + +extern void wasi_http_types_outgoing_request_drop_borrow(wasi_http_types_borrow_outgoing_request_t handle); + +extern wasi_http_types_borrow_outgoing_request_t wasi_http_types_borrow_outgoing_request(wasi_http_types_own_outgoing_request_t handle); + +extern void wasi_http_types_request_options_drop_own(wasi_http_types_own_request_options_t handle); + +extern void wasi_http_types_request_options_drop_borrow(wasi_http_types_borrow_request_options_t handle); + +extern wasi_http_types_borrow_request_options_t wasi_http_types_borrow_request_options(wasi_http_types_own_request_options_t handle); + +extern void wasi_http_types_response_outparam_drop_own(wasi_http_types_own_response_outparam_t handle); + +extern void wasi_http_types_response_outparam_drop_borrow(wasi_http_types_borrow_response_outparam_t handle); + +extern wasi_http_types_borrow_response_outparam_t wasi_http_types_borrow_response_outparam(wasi_http_types_own_response_outparam_t handle); + +extern void wasi_http_types_incoming_response_drop_own(wasi_http_types_own_incoming_response_t handle); + +extern void wasi_http_types_incoming_response_drop_borrow(wasi_http_types_borrow_incoming_response_t handle); + +extern wasi_http_types_borrow_incoming_response_t wasi_http_types_borrow_incoming_response(wasi_http_types_own_incoming_response_t handle); + +extern void wasi_http_types_incoming_body_drop_own(wasi_http_types_own_incoming_body_t handle); + +extern void wasi_http_types_incoming_body_drop_borrow(wasi_http_types_borrow_incoming_body_t handle); + +extern wasi_http_types_borrow_incoming_body_t wasi_http_types_borrow_incoming_body(wasi_http_types_own_incoming_body_t handle); + +extern void wasi_http_types_future_trailers_drop_own(wasi_http_types_own_future_trailers_t handle); + +extern void wasi_http_types_future_trailers_drop_borrow(wasi_http_types_borrow_future_trailers_t handle); + +extern wasi_http_types_borrow_future_trailers_t wasi_http_types_borrow_future_trailers(wasi_http_types_own_future_trailers_t handle); + +extern void wasi_http_types_outgoing_response_drop_own(wasi_http_types_own_outgoing_response_t handle); + +extern void wasi_http_types_outgoing_response_drop_borrow(wasi_http_types_borrow_outgoing_response_t handle); + +extern wasi_http_types_borrow_outgoing_response_t wasi_http_types_borrow_outgoing_response(wasi_http_types_own_outgoing_response_t handle); + +extern void wasi_http_types_outgoing_body_drop_own(wasi_http_types_own_outgoing_body_t handle); + +extern void wasi_http_types_outgoing_body_drop_borrow(wasi_http_types_borrow_outgoing_body_t handle); + +extern wasi_http_types_borrow_outgoing_body_t wasi_http_types_borrow_outgoing_body(wasi_http_types_own_outgoing_body_t handle); + +extern void wasi_http_types_future_incoming_response_drop_own(wasi_http_types_own_future_incoming_response_t handle); + +extern void wasi_http_types_future_incoming_response_drop_borrow(wasi_http_types_borrow_future_incoming_response_t handle); + +extern wasi_http_types_borrow_future_incoming_response_t wasi_http_types_borrow_future_incoming_response(wasi_http_types_own_future_incoming_response_t handle); + +void wasi_http_types_tuple2_field_name_field_value_free(wasi_http_types_tuple2_field_name_field_value_t *ptr); + +void wasi_http_types_list_tuple2_field_name_field_value_free(wasi_http_types_list_tuple2_field_name_field_value_t *ptr); + +void wasi_http_types_result_own_fields_header_error_free(wasi_http_types_result_own_fields_header_error_t *ptr); + +void wasi_http_types_list_field_value_free(wasi_http_types_list_field_value_t *ptr); + +void wasi_http_types_result_void_header_error_free(wasi_http_types_result_void_header_error_t *ptr); + +void wasi_http_types_option_scheme_free(wasi_http_types_option_scheme_t *ptr); + +void wasi_http_types_result_own_incoming_body_void_free(wasi_http_types_result_own_incoming_body_void_t *ptr); + +void wasi_http_types_result_own_outgoing_body_void_free(wasi_http_types_result_own_outgoing_body_void_t *ptr); + +void wasi_http_types_result_void_void_free(wasi_http_types_result_void_void_t *ptr); + +void wasi_http_types_option_duration_free(wasi_http_types_option_duration_t *ptr); + +void wasi_http_types_result_own_outgoing_response_error_code_free(wasi_http_types_result_own_outgoing_response_error_code_t *ptr); + +void wasi_http_types_result_own_input_stream_void_free(wasi_http_types_result_own_input_stream_void_t *ptr); + +void wasi_http_types_option_own_trailers_free(wasi_http_types_option_own_trailers_t *ptr); + +void wasi_http_types_result_option_own_trailers_error_code_free(wasi_http_types_result_option_own_trailers_error_code_t *ptr); + +void wasi_http_types_result_result_option_own_trailers_error_code_void_free(wasi_http_types_result_result_option_own_trailers_error_code_void_t *ptr); + +void wasi_http_types_option_result_result_option_own_trailers_error_code_void_free(wasi_http_types_option_result_result_option_own_trailers_error_code_void_t *ptr); + +void wasi_http_types_result_own_output_stream_void_free(wasi_http_types_result_own_output_stream_void_t *ptr); + +void wasi_http_types_result_void_error_code_free(wasi_http_types_result_void_error_code_t *ptr); + +void wasi_http_types_result_own_incoming_response_error_code_free(wasi_http_types_result_own_incoming_response_error_code_t *ptr); + +void wasi_http_types_result_result_own_incoming_response_error_code_void_free(wasi_http_types_result_result_own_incoming_response_error_code_void_t *ptr); + +void wasi_http_types_option_result_result_own_incoming_response_error_code_void_free(wasi_http_types_option_result_result_own_incoming_response_error_code_void_t *ptr); + +void wasi_http_types_option_error_code_free(wasi_http_types_option_error_code_t *ptr); + +void wasi_http_outgoing_handler_error_code_free(wasi_http_outgoing_handler_error_code_t *ptr); + +void wasi_http_outgoing_handler_option_own_request_options_free(wasi_http_outgoing_handler_option_own_request_options_t *ptr); + +void wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_free(wasi_http_outgoing_handler_result_own_future_incoming_response_error_code_t *ptr); + +void function_tuple2_string_string_free(function_tuple2_string_string_t *ptr); + +void function_list_tuple2_string_string_free(function_list_tuple2_string_string_t *ptr); + +void function_result_list_u8_string_free(function_result_list_u8_string_t *ptr); + +// Sets the string `ret` to reference the input string `s` without copying it +void function_string_set(function_string_t *ret, const char*s); + +// Creates a copy of the input nul-terminated string `s` and +// stores it into the component model string `ret`. +void function_string_dup(function_string_t *ret, const char*s); + +// Creates a copy of the input string `s` with length `len` and +// stores it into the component model string `ret`. +// The length is specified in code units (bytes for UTF-8, 16-bit values for UTF-16). +void function_string_dup_n(function_string_t *ret, const char*s, size_t len); + +// Deallocates the string pointed to by `ret`, deallocating +// the memory behind the string. +void function_string_free(function_string_t *ret); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/examples/hello-odin/src/gen/function_component_type.o b/examples/hello-odin/src/gen/function_component_type.o new file mode 100644 index 0000000000000000000000000000000000000000..adf21652160eee8ce6e3afe834be7e8ee76b4dcf GIT binary patch literal 6664 zcma)B>5m*o6@PEK_q2D{>%DxRN$kY#@!G+`b~tQfp+p=CvBPDebxY2|5+~W|i!1Fx&`e|)5LgxnO#9cjW#SB}M9>Ud zGU(Ve^V17_t;W}m^7VO}X8WPBlYvcBHrYxJPg}II?Z)zo49}^BtDE%;_45~|sAkd78os_% z!-2VIARMs`^JNexZje}1Q$J^0gUD4Ux5(zJ@RChd5N`9d`T?c$k%&WopeT5TB`e#v zJpuAro0j82BW^~rA)HJq&l!R#MX+~BVD#|3MJLh&G}SrdbGKG;EGVix9}&&@J4aqb*jx+bx6sAW=49-2(MOI7o^s z?9Fih5#Qx`vRQA~;<-fh!~vAZdD-~mTLjdw$I8p@LBg-N30 zuI%&T2a48YEG>iMIa;#m$XI*w`12n2W(~tK!G`08q2!c$(-Y0EvmMDq@Ls-4L(eSF zHp3u6%Et4wV$;F#{F-ysruz8(+(Rj$;|49K?GIv)SBKV3maa+HYKPy9%sMDiaKg;*#t&T{L)*kW*AN?@KFAK>_G~E)uNCeRg@EC|D zmS)1fs*o{CW)itg>`nFEr0L-^Ogs^Bi~=#OuLFzb`JQFJaO>7f*j67m%VaT9peHQa z&E1&04>_t$MYw##;+zcHA?~D>0GO6NoKtAjGB1#t1kV=X2Im}POX6WmX5v{4kCc-4!vI%3%dP-al5UH?_*A1bZl+UO)+N+ct-y=cj+EaNWA}2-9YyrFYE_*$buPEJFG_uC&5Tn1F z)0L(xb}Tvq@xzj2(NXkFHto_&P%=QRJdX03F2t(On$Z$ti%#OQ$l{@Y?MYFgJESz5 z6#X7lk4{)wTr%mF)pkX=jBZ$iOI^oqq}n=u2xHJvCxbXU|1%&gsL>p0|Cg^S_^6eo z_8=KV!pUt^N($B#c=J`myD#I-g&N~vlRT;V_X{?y+(ry>^$waz7`>`p#LseAJ9dKm zA3}e4fe)ienE{p}DdLOtoK5>~tK-OKMqY16VbAepobZR)JIVbMrcJqIt4rb-UB=a5 z8Un4Nj@y&3RO#?2s?vFG%+ISf4_4?_BojK7M)op&WRxd{?2lGugKn*2gTANvV`C+s zP?D=0Zoe;r7JuBdZI|d`;f0nREpruUve(`v<>=Llay$$I!PnS(%8>nnR9BxjfrYT8 zK&?m~h0b)@BFWxC1WPZm1N5e4o5&sQ|! zO0;~UAo>l6J~q*=Ecy5amJR^+OT0TXN5KQXdMvBL>Yyk1Q!Gz`$>i}HM85{#;S!ef ze8}>YKf~TBmYY!d)==e}M88Q{v$uGatFE$%KW8iic`-&K)LD#P24Zn4{j7S^bauPw zw@`J`IA(+yxOFlCw+af2K_20$2Kkkt)}_kcVygb^W7St!`11ujN`M(LBm>MBhWe-V z((Ckp96RIwVgYU=8isHy9C9vS)yI44vB%4a`Ada^mEby}*1+}4EKjSV`8&k$Pzh<3 zi-5nv-f8ZpqYyRhd7J1R@SHN1RmkfAwR$C(Hj=lD3*V;v{qv4?;+aV@6m+U`?%4Fq zB>J|D&?q)`&{$?IDsL5@#8nfO_%STd;7roc5XrU>L8>DzDmg!iLn#^0b%*8CEYBfx z-z7c>_u%z}yY=@pYp%3EU?!&uKz1>iWe3qrN$U{KE%wfuu>XU4 zeHK43dGvm%|2mVFqo)lDM-(ckU?!LMYy7aFy##?#Rs(^r7Fg8vk`KQ|SiGFDN*Lm!0;^$rOz8% zzs)HW@|rQJeJo(&JLn|O!s_pG3W)D90P+32@Il}YU_w3$nT0pttE;t%?XlV{yjQYOIcE7I zqAfiVMn_OpVCe}H=CBjhK#Q6zVVYJ@X3?~oD5Df~=QJR8VXS_&Hj`E4Su;tRC&-@m zFrM@UFIaRu9iyc_$s?_IBQsH3#_}auU3R9=XPHmy|7t0L($hdg9zL~BzWYFs1c4M4{M61nis{eG(Y;EO#&TJ`^Y=w=xxMjES%xsD+MZ9IK_#eau6o>!- literal 0 HcmV?d00001 diff --git a/examples/hello-odin/src/main.odin b/examples/hello-odin/src/main.odin new file mode 100644 index 00000000..3bf0bd63 --- /dev/null +++ b/examples/hello-odin/src/main.odin @@ -0,0 +1,132 @@ +// The hello-odin guest: a Crossplane composition function in Odin, compiled +// to a wasm32 object that zig links (with nanopb and the c flavour's +// bindings and glue) into the core module guestfn build wraps into an ABI +// v2 component, run by function-wasm. It composes a ConfigMap greeting the +// composite resource. +// +// run_function is ordinary Odin over the nanopb structs src/fnv1.odin +// mirrors; the world's run export and the log / wasi:http host imports live +// in wasmfn.odin, behind the bindings wit-bindgen generated from wit/ +// (src/gen). +package guest + +import "core:strings" + +// run_function composes a response to req into rsp, which the glue hands +// over zero-initialised except for meta (the request's tag and a 60 s TTL), +// and returns "" - or the message of a fatal result, in which case the glue +// discards rsp. +run_function :: proc(req: ^Run_Function_Request, rsp: ^Run_Function_Response) -> (fatal: string) { + tag := string(req.meta.tag) if req.has_meta && req.meta.tag != nil else "" + log_info("Running function", {"tag", tag}) + + greeting := "hello" + switch g, r := config_string(req, "greeting"); r { + case .Not_String: + return "cannot read config: greeting must be a string" + case .String: + greeting = g + case .Absent: + } + // greetingUrl fetches the greeting through the host instead - the + // requires.egress grant of the module's manifest decides whether it may. + switch url, r := config_string(req, "greetingUrl"); r { + case .Not_String: + return "cannot read config: greetingUrl must be a string" + case .String: + text, err := http_get_text(url) + if err != "" { + return strings.concatenate({"cannot fetch greeting: ", err}) + } + greeting = text + case .Absent: + } + + name, has_name := observed_name(req) + if !has_name { + return "cannot get observed composite resource: none in request" + } + + // The ConfigMap greeting the composite, added to the desired state the + // request carried. + data: Struct + struct_set(&data, "greeting", string_value(strings.concatenate({greeting, " ", name}))) + cm: Struct + struct_set(&cm, "apiVersion", string_value("v1")) + struct_set(&cm, "kind", string_value("ConfigMap")) + struct_set(&cm, "data", struct_value(data)) + if req.has_desired { + rsp.desired = req.desired + } + rsp.has_desired = true + state_add_resource(&rsp.desired, "greeting", cm) + + result := new(Result) + result^ = { + severity = .NORMAL, + message = strings.clone_to_cstring(strings.concatenate({"greeted ", name})), + has_target = true, + target = .COMPOSITE, + } + rsp.results = ([^]Result)(result) + rsp.results_count = 1 + condition := new(Condition) + condition^ = { + type = "FunctionSuccess", + status = .TRUE, + reason = "Success", + has_target = true, + target = .COMPOSITE_AND_CLAIM, + } + rsp.conditions = ([^]Condition)(condition) + rsp.conditions_count = 1 + + log_debug("Composed the greeting", {"name", name}, {"greeting", greeting}) + return "" +} + +Config_Result :: enum { + Absent, + String, + Not_String, +} + +// config_string reads a string field of the Input's config block. +config_string :: proc(req: ^Run_Function_Request, key: string) -> (value: string, result: Config_Result) { + if !req.has_input { + return "", .Absent + } + v := struct_lookup(&req.input, "config", key) + if v == nil { + return "", .Absent + } + s, ok := value_string(v) + if !ok { + return "", .Not_String + } + return s, .String +} + +observed_name :: proc(req: ^Run_Function_Request) -> (string, bool) { + if !req.has_observed || !req.observed.has_composite || !req.observed.composite.has_resource { + return "", false + } + return value_string(struct_lookup(&req.observed.composite.resource, "metadata", "name")) +} + +// state_add_resource adds resource under key to the state's resources, in a +// new array: a state copied from the request is never modified in place. +state_add_resource :: proc(state: ^State, key: string, resource: Struct) { + n := int(state.resources_count) + entries := make([]State_Resources_Entry, n + 1) + if n > 0 { + copy(entries, state.resources[:n]) + } + entries[n] = { + key = strings.clone_to_cstring(key), + has_value = true, + value = {has_resource = true, resource = resource}, + } + state.resources = raw_data(entries) + state.resources_count = pb_size_t(n + 1) +} diff --git a/examples/hello-odin/src/structpb.odin b/examples/hello-odin/src/structpb.odin new file mode 100644 index 00000000..cd331279 --- /dev/null +++ b/examples/hello-odin/src/structpb.odin @@ -0,0 +1,110 @@ +// Helpers over the mirrored google.protobuf.Struct and Value - the shape of +// the Input's config, of every observed and desired resource and of the +// context - for reading what a request carries and building what a response +// returns. What the builders make is heap memory that is never freed: a +// fresh instance serves each request. +package guest + +import "core:strings" + +// Reading: every proc takes nil and answers "not there" for it. + +// struct_get returns the value of key, or nil. +struct_get :: proc(s: ^Struct, key: string) -> ^Value { + if s == nil { + return nil + } + for i in 0 ..< s.fields_count { + e := &s.fields[i] + if e.key != nil && e.has_value && string(e.key) == key { + return &e.value + } + } + return nil +} + +// struct_lookup walks nested objects by the keys: +// +// struct_lookup(resource, "metadata", "name") +struct_lookup :: proc(s: ^Struct, keys: ..string) -> ^Value { + s := s + v: ^Value + for key in keys { + v = struct_get(s, key) + if v == nil { + return nil + } + s = value_struct(v) + } + return v +} + +// value_string returns the string of a string value; false for any other kind. +value_string :: proc(v: ^Value) -> (string, bool) { + if v == nil || v.which_kind != VALUE_STRING_TAG { + return "", false + } + return string(v.kind.string_value), true +} + +// value_struct returns the object of a struct value, nil for any other kind. +value_struct :: proc(v: ^Value) -> ^Struct { + if v == nil || v.which_kind != VALUE_STRUCT_TAG { + return nil + } + return &v.kind.struct_value +} + +// Building. The codec reads C strings, so a string is copied with its NUL. + +string_value :: proc(s: string) -> Value { + v: Value + v.which_kind = VALUE_STRING_TAG + v.kind.string_value = strings.clone_to_cstring(s) + return v +} + +number_value :: proc(d: f64) -> Value { + v: Value + v.which_kind = VALUE_NUMBER_TAG + v.kind.number_value = d + return v +} + +bool_value :: proc(b: bool) -> Value { + v: Value + v.which_kind = VALUE_BOOL_TAG + v.kind.bool_value = b + return v +} + +struct_value :: proc(s: Struct) -> Value { + v: Value + v.which_kind = VALUE_STRUCT_TAG + v.kind.struct_value = s + return v +} + +// struct_set sets key to v, replacing an existing field of that key; the +// fields array is grown into a new allocation (never freed). +struct_set :: proc(s: ^Struct, key: string, v: Value) { + for i in 0 ..< s.fields_count { + if s.fields[i].key != nil && string(s.fields[i].key) == key { + s.fields[i].has_value = true + s.fields[i].value = v + return + } + } + n := int(s.fields_count) + fields := make([]Struct_Fields_Entry, n + 1) + if n > 0 { + copy(fields, s.fields[:n]) + } + fields[n] = { + key = strings.clone_to_cstring(key), + has_value = true, + value = v, + } + s.fields = raw_data(fields) + s.fields_count = pb_size_t(n + 1) +} diff --git a/examples/hello-odin/src/wasmfn.c b/examples/hello-odin/src/wasmfn.c new file mode 100644 index 00000000..82543e0e --- /dev/null +++ b/examples/hello-odin/src/wasmfn.c @@ -0,0 +1,366 @@ +// The wasi:http@0.2 client of the c flavour's glue (see wasmfn.h), unchanged +// but for what was cut: the run export, the nanopb handle and the log import, +// which src/wasmfn.odin implements. Memory discipline: a fresh component +// instance serves each request and the host drops it afterwards, so nothing +// here is ever freed except scratch the client itself allocated. +#include "wasmfn.h" + +#include +#include +#include +#include +#include + +// The wit-bindgen c bindings of this guest's world (src/gen): the wasi:http +// client interfaces. +#include "function.h" + +enum { read_chunk = 64 * 1024, write_chunk = 4096 }; + +// ─── strings ──────────────────────────────────────────────────────────────── + +char *wasmfn_sprintf(const char *format, ...) { + va_list ap, copy; + va_start(ap, format); + va_copy(copy, ap); + int n = vsnprintf(NULL, 0, format, ap); + va_end(ap); + char *s = n < 0 ? NULL : malloc((size_t)n + 1); + if (s) { + vsnprintf(s, (size_t)n + 1, format, copy); + } + va_end(copy); + return s; +} + +static bool is_space(char c) { + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; +} + +static bool fail(char **err, const char *msg) { + if (err) { + *err = strdup(msg); + } + return false; +} + +// ─── HTTP over wasi:http@0.2 ──────────────────────────────────────────────── + +// The WIT names of wasi:http's error-code cases, in tag order. +static const char *const error_code_names[] = { + "dns-timeout", + "dns-error", + "destination-not-found", + "destination-unavailable", + "destination-ip-prohibited", + "destination-ip-unroutable", + "connection-refused", + "connection-terminated", + "connection-timeout", + "connection-read-timeout", + "connection-write-timeout", + "connection-limit-reached", + "tls-protocol-error", + "tls-certificate-error", + "tls-alert-received", + "http-request-denied", + "http-request-length-required", + "http-request-body-size", + "http-request-method-invalid", + "http-request-uri-invalid", + "http-request-uri-too-long", + "http-request-header-section-size", + "http-request-header-size", + "http-request-trailer-section-size", + "http-request-trailer-size", + "http-response-incomplete", + "http-response-header-section-size", + "http-response-header-size", + "http-response-body-size", + "http-response-trailer-section-size", + "http-response-trailer-size", + "http-response-transfer-coding", + "http-response-content-coding", + "http-response-timeout", + "http-upgrade-failed", + "http-protocol-error", + "loop-detected", + "configuration-error", + "internal-error", +}; + +// fail_with hands an allocated message to *err (or frees it when nobody +// listens). +static bool fail_with(char **err, char *msg) { + if (err) { + *err = msg ? msg : strdup("out of memory"); + } else { + free(msg); + } + return false; +} + +// describe_error_code words a wasi:http error-code. internal-error carries +// the host's own reason - the refusal of the egress grant or policy, a +// budget, a transport failure - verbatim; every other case is named. +static char *describe_error_code(const wasi_http_types_error_code_t *code) { + if (code->tag == WASI_HTTP_TYPES_ERROR_CODE_INTERNAL_ERROR && code->val.internal_error.is_some) { + const function_string_t *reason = &code->val.internal_error.val; + return strndup((const char *)reason->ptr, reason->len); + } + size_t known = sizeof error_code_names / sizeof *error_code_names; + return wasmfn_sprintf("wasi:http error-code %s", code->tag < known ? error_code_names[code->tag] : "unknown"); +} + +static bool split_url(const char *url, wasi_http_types_scheme_t *scheme, function_string_t *authority, function_string_t *path, char **err) { + const char *rest; + if (url && strncmp(url, "https://", 8) == 0) { + scheme->tag = WASI_HTTP_TYPES_SCHEME_HTTPS; + rest = url + 8; + } else if (url && strncmp(url, "http://", 7) == 0) { + scheme->tag = WASI_HTTP_TYPES_SCHEME_HTTP; + rest = url + 7; + } else { + return fail(err, "only http and https URLs work"); + } + const char *slash = strchr(rest, '/'); + size_t authority_len = slash ? (size_t)(slash - rest) : strlen(rest); + if (!authority_len) { + return fail(err, "the URL has no host"); + } + function_string_dup_n(authority, rest, authority_len); + function_string_dup(path, slash ? slash : "/"); + return true; +} + +static void method_of(const char *name, wasi_http_types_method_t *method) { + static const struct { + const char *name; + uint8_t tag; + } standard[] = { + {"GET", WASI_HTTP_TYPES_METHOD_GET}, {"HEAD", WASI_HTTP_TYPES_METHOD_HEAD}, + {"POST", WASI_HTTP_TYPES_METHOD_POST}, {"PUT", WASI_HTTP_TYPES_METHOD_PUT}, + {"DELETE", WASI_HTTP_TYPES_METHOD_DELETE}, {"CONNECT", WASI_HTTP_TYPES_METHOD_CONNECT}, + {"OPTIONS", WASI_HTTP_TYPES_METHOD_OPTIONS}, {"TRACE", WASI_HTTP_TYPES_METHOD_TRACE}, + {"PATCH", WASI_HTTP_TYPES_METHOD_PATCH}, + }; + if (!name || !*name) { + method->tag = WASI_HTTP_TYPES_METHOD_GET; + return; + } + for (size_t i = 0; i < sizeof standard / sizeof *standard; i++) { + if (strcmp(standard[i].name, name) == 0) { + method->tag = standard[i].tag; + return; + } + } + method->tag = WASI_HTTP_TYPES_METHOD_OTHER; + function_string_dup(&method->val.other, name); +} + +// request_headers builds the fields resource of the request's headers. +static bool request_headers(const wasmfn_http_request *req, wasi_http_types_own_fields_t *headers, char **err) { + *headers = wasi_http_types_constructor_fields(); + for (size_t i = 0; req->headers && req->headers[i] && req->headers[i + 1]; i += 2) { + wasi_http_types_field_name_t name; + function_string_set(&name, req->headers[i]); + wasi_http_types_field_value_t value = {(uint8_t *)req->headers[i + 1], strlen(req->headers[i + 1])}; + wasi_http_types_header_error_t herr; + if (!wasi_http_types_method_fields_append(wasi_http_types_borrow_fields(*headers), &name, &value, &herr)) { + return fail_with(err, wasmfn_sprintf("the host refused the request header %s", req->headers[i])); + } + } + return true; +} + +// write_body streams the request body and finishes it; the request has +// already been handed to the handler, which reads as we write. +static bool write_body(wasi_http_types_own_outgoing_body_t body, const uint8_t *bytes, size_t len, char **err) { + wasi_http_types_own_output_stream_t stream; + if (!wasi_http_types_method_outgoing_body_write(wasi_http_types_borrow_outgoing_body(body), &stream)) { + return fail(err, "the request body stream was already taken"); + } + for (size_t off = 0; off < len; off += write_chunk) { + size_t n = len - off < write_chunk ? len - off : write_chunk; + function_list_u8_t chunk = {(uint8_t *)bytes + off, n}; + wasi_io_streams_stream_error_t serr; + if (!wasi_io_streams_method_output_stream_blocking_write_and_flush(wasi_io_streams_borrow_output_stream(stream), &chunk, &serr)) { + wasi_io_streams_output_stream_drop_own(stream); + return fail(err, "writing the request body failed"); + } + } + wasi_io_streams_output_stream_drop_own(stream); + wasi_http_types_error_code_t code; + if (!wasi_http_types_static_outgoing_body_finish(body, NULL, &code)) { + return fail_with(err, describe_error_code(&code)); + } + return true; +} + +// response_headers copies the response's headers out as alternating +// name/value C strings (values are bytes on the wire; a NUL inside one ends +// it here). +static bool response_headers(wasi_http_types_borrow_incoming_response_t response, const char ***out) { + wasi_http_types_own_headers_t headers = wasi_http_types_method_incoming_response_headers(response); + wasi_http_types_list_tuple2_field_name_field_value_t entries; + wasi_http_types_method_fields_entries(wasi_http_types_borrow_fields(headers), &entries); + const char **pairs = calloc(2 * entries.len + 1, sizeof *pairs); + if (pairs) { + for (size_t i = 0; i < entries.len; i++) { + pairs[2 * i] = strndup((const char *)entries.ptr[i].f0.ptr, entries.ptr[i].f0.len); + pairs[2 * i + 1] = strndup((const char *)entries.ptr[i].f1.ptr, entries.ptr[i].f1.len); + } + } + wasi_http_types_list_tuple2_field_name_field_value_free(&entries); + wasi_http_types_fields_drop_own(headers); + *out = pairs; + return pairs != NULL; +} + +// read_body drains the response body stream into one NUL-terminated buffer. +static bool read_body(wasi_http_types_borrow_incoming_response_t response, uint8_t **out, size_t *out_len, char **err) { + wasi_http_types_own_incoming_body_t body; + if (!wasi_http_types_method_incoming_response_consume(response, &body)) { + return fail(err, "the response body was already taken"); + } + wasi_http_types_own_input_stream_t stream; + if (!wasi_http_types_method_incoming_body_stream(wasi_http_types_borrow_incoming_body(body), &stream)) { + wasi_http_types_incoming_body_drop_own(body); + return fail(err, "the response body stream was already taken"); + } + uint8_t *buf = malloc(1); + size_t len = 0; + bool ok = buf != NULL; + while (ok) { + function_list_u8_t chunk; + wasi_io_streams_stream_error_t serr; + if (!wasi_io_streams_method_input_stream_blocking_read(wasi_io_streams_borrow_input_stream(stream), read_chunk, &chunk, &serr)) { + ok = serr.tag == WASI_IO_STREAMS_STREAM_ERROR_CLOSED || fail(err, "reading the response body failed"); + break; + } + uint8_t *grown = realloc(buf, len + chunk.len + 1); + if (!grown) { + ok = fail(err, "out of memory"); + function_list_u8_free(&chunk); + break; + } + buf = grown; + memcpy(buf + len, chunk.ptr, chunk.len); + len += chunk.len; + function_list_u8_free(&chunk); + } + wasi_io_streams_input_stream_drop_own(stream); + wasi_http_types_future_trailers_drop_own(wasi_http_types_static_incoming_body_finish(body)); + if (!ok) { + free(buf); + return false; + } + buf[len] = '\0'; + *out = buf; + *out_len = len; + return true; +} + +// send_through_host performs req over wasi:http/outgoing-handler: build the +// request, hand it to the handler, stream the body, block on the response +// future, then read status, headers and body. +static bool send_through_host(const wasmfn_http_request *req, wasmfn_http_response *rsp, char **err) { + wasi_http_types_scheme_t scheme; + function_string_t authority, path; + if (!split_url(req->url, &scheme, &authority, &path, err)) { + return false; + } + wasi_http_types_own_fields_t headers; + if (!request_headers(req, &headers, err)) { + return false; + } + wasi_http_types_own_outgoing_request_t request = wasi_http_types_constructor_outgoing_request(headers); + wasi_http_types_borrow_outgoing_request_t r = wasi_http_types_borrow_outgoing_request(request); + wasi_http_types_method_t method; + method_of(req->method, &method); + if (!wasi_http_types_method_outgoing_request_set_method(r, &method)) { + return fail(err, "the host refused the request method"); + } + if (!wasi_http_types_method_outgoing_request_set_scheme(r, &scheme) || + !wasi_http_types_method_outgoing_request_set_authority(r, &authority) || + !wasi_http_types_method_outgoing_request_set_path_with_query(r, &path)) { + return fail(err, "the host refused the URL"); + } + bool has_body = req->body && req->body_len; + wasi_http_types_own_outgoing_body_t body; + if (has_body && !wasi_http_types_method_outgoing_request_body(r, &body)) { + return fail(err, "the request body was already taken"); + } + + wasi_http_outgoing_handler_own_future_incoming_response_t future; + wasi_http_outgoing_handler_error_code_t code; + if (!wasi_http_outgoing_handler_handle(request, NULL, &future, &code)) { + return fail_with(err, describe_error_code(&code)); + } + if (has_body && !write_body(body, req->body, req->body_len, err)) { + return false; + } + + wasi_http_types_borrow_future_incoming_response_t f = wasi_http_types_borrow_future_incoming_response(future); + wasi_io_poll_own_pollable_t ready = wasi_http_types_method_future_incoming_response_subscribe(f); + wasi_io_poll_method_pollable_block(wasi_io_poll_borrow_pollable(ready)); + wasi_io_poll_pollable_drop_own(ready); + wasi_http_types_result_result_own_incoming_response_error_code_void_t got; + if (!wasi_http_types_method_future_incoming_response_get(f, &got)) { + return fail(err, "the host answered nothing"); + } + wasi_http_types_future_incoming_response_drop_own(future); + if (got.is_err) { + return fail(err, "the response was already taken"); + } + if (got.val.ok.is_err) { + return fail_with(err, describe_error_code(&got.val.ok.val.err)); + } + wasi_http_types_own_incoming_response_t response = got.val.ok.val.ok; + wasi_http_types_borrow_incoming_response_t ir = wasi_http_types_borrow_incoming_response(response); + rsp->status = wasi_http_types_method_incoming_response_status(ir); + if (!response_headers(ir, &rsp->headers)) { + return fail(err, "out of memory"); + } + bool ok = read_body(ir, &rsp->body, &rsp->body_len, err); + wasi_http_types_incoming_response_drop_own(response); + return ok; +} + +bool wasmfn_http_send(const wasmfn_http_request *req, wasmfn_http_response *rsp, char **err) { + return send_through_host(req, rsp, err); +} + +const char *wasmfn_http_header(const wasmfn_http_response *rsp, const char *name) { + for (size_t i = 0; rsp->headers && rsp->headers[i] && rsp->headers[i + 1]; i += 2) { + if (strcasecmp(rsp->headers[i], name) == 0) { + return rsp->headers[i + 1]; + } + } + return NULL; +} + +char *wasmfn_http_get_text(const char *url, char **err) { + wasmfn_http_request req = {.url = url}; + wasmfn_http_response rsp = {0}; + if (!wasmfn_http_send(&req, &rsp, err)) { + return NULL; + } + if (rsp.status != 200) { + char *msg = wasmfn_sprintf("GET %s: status %d", url, rsp.status); + if (err) { + *err = msg ? msg : strdup("unexpected status"); + } + return NULL; + } + char *text = (char *)rsp.body; + char *end = text + rsp.body_len; + while (text < end && is_space(*text)) { + text++; + } + while (end > text && is_space(end[-1])) { + end--; + } + *end = '\0'; + return text; +} diff --git a/examples/hello-odin/src/wasmfn.h b/examples/hello-odin/src/wasmfn.h new file mode 100644 index 00000000..1a8c9bf4 --- /dev/null +++ b/examples/hello-odin/src/wasmfn.h @@ -0,0 +1,51 @@ +// The C half of the function-wasm ABI v2 glue of this guest: the c flavour's +// wasi:http@0.2 client (examples/hello-c/src/wasmfn.c) kept as it is, so the +// Odin half (src/wasmfn.odin) reaches the host's HTTP egress through one +// C call instead of driving wasi:http's resources and streams itself. The +// run export, the codec and the log import live on the Odin side. +#ifndef WASMFN_H +#define WASMFN_H + +#include +#include +#include + +// HTTP through the host (wasi:http/outgoing-handler). The guest never opens a +// socket: the host performs the request within the egress grant of the +// module's manifest and the operator's policy, or answers with a refusal. +typedef struct wasmfn_http_request { + const char *method; // NULL or "" is GET + const char *url; // absolute, http or https + const char *const *headers; // alternating name/value C strings, NULL-terminated; NULL for none + const uint8_t *body; // NULL for none + size_t body_len; +} wasmfn_http_request; + +typedef struct wasmfn_http_response { + int status; // the server's status, whatever it is (a 503 is a response, not an error) + const char **headers; // alternating name/value C strings, NULL-terminated, names lower-case + uint8_t *body; // body bytes, NUL-terminated for convenience + size_t body_len; +} wasmfn_http_response; + +// wasmfn_http_send performs req through the host. It returns true and fills +// rsp, or false and sets *err to the host's reason (refused by the grant or the +// policy, over a budget, failed: the error-code's internal-error string) or a +// guest-side problem talking to the host. Everything returned is heap +// allocated and never freed: a fresh instance serves each request. +bool wasmfn_http_send(const wasmfn_http_request *req, wasmfn_http_response *rsp, char **err); + +// wasmfn_http_header returns the first value of the named response header +// (names compare case-insensitively), or NULL. +const char *wasmfn_http_header(const wasmfn_http_response *rsp, const char *name); + +// wasmfn_http_get_text GETs url and returns the body of a 200 as a +// whitespace-trimmed C string, or NULL with *err set (a non-200 status is an +// error here). This is the call the Odin side makes. +char *wasmfn_http_get_text(const char *url, char **err); + +// wasmfn_sprintf is printf into a heap-allocated string (NULL when out of +// memory). +char *wasmfn_sprintf(const char *format, ...); + +#endif diff --git a/examples/hello-odin/src/wasmfn.odin b/examples/hello-odin/src/wasmfn.odin new file mode 100644 index 00000000..a349e87b --- /dev/null +++ b/examples/hello-odin/src/wasmfn.odin @@ -0,0 +1,359 @@ +// The function-wasm ABI v2 glue for an Odin guest (docs/abi-v2.md): the +// world's `run` export (decode the request, run `run_function`, encode the +// response; every failure becomes a fatal result), the typed `log` import as +// a logger and the host's HTTP egress behind one call. The component's +// surface is wit-bindgen's C bindings for wit/world.wit (src/gen, the c +// flavour's): their run shim calls the one C function they expect, +// `exports_function_run`, which this file defines, and their log import and +// wasi:http client are reached through Odin's foreign procedures. Only the +// export and the imports are wasm-specific: natively the logger prints to +// stderr and a test may install a fake host for HTTP, so the function builds +// and tests as ordinary Odin (zig build test). +// +// Memory: the canonical ABI frees with libc's free - the request buffer it +// lowered into our memory (cabi_realloc, freed once decoded) and the response +// buffer we hand back (freed by the generated cabi_post_run after the host +// has read it) - so the context's allocator is libc's heap, the one heap of +// the module: anything Odin allocates may be given to the C side and back. +// Nothing else is ever freed: a fresh instance serves each request and the +// host drops it afterwards. +package guest + +import "base:runtime" +import "core:c" +import "core:strings" + +IS_WASM :: ODIN_ARCH == .wasm32 + +// ─── the canonical ABI's types (src/gen/function.h) ───────────────────────── + +// function_string_t and function_list_u8_t: {uint8_t *ptr; size_t len;}. +Bindings_String :: struct { + ptr: [^]u8, + len: c.size_t, +} + +Bindings_List_U8 :: struct { + ptr: [^]u8, + len: c.size_t, +} + +Bindings_Tuple2_String_String :: struct { + f0: Bindings_String, + f1: Bindings_String, +} + +Bindings_List_Tuple2_String_String :: struct { + ptr: [^]Bindings_Tuple2_String_String, + len: c.size_t, +} + +when IS_WASM { + #assert(size_of(Bindings_String) == 8 && size_of(Bindings_Tuple2_String_String) == 16) + + // The generated C (src/gen/function.c): the world's log import behind + // its shim, and the list free the run shim's argument wants after + // decoding. A foreign import whose name ends in .o is, on a wasm + // target, a set of plain link-time symbols (no wasm import module), and + // Odin never opens the file: the names say where zig links them from. + foreign import bindings "function.o" + + @(default_calling_convention = "c") + foreign bindings { + function_log :: proc(level: u8, msg: ^Bindings_String, kv: ^Bindings_List_Tuple2_String_String) --- + function_list_u8_free :: proc(list: ^Bindings_List_U8) --- + } + + // The C half of the glue (src/wasmfn.c): the wasi:http@0.2 client. + foreign import wasmfn "wasmfn.o" + + @(default_calling_convention = "c") + foreign wasmfn { + wasmfn_http_get_text :: proc(url: cstring, err: ^cstring) -> cstring --- + } + + // wasi-libc's heap, the module's one heap (see the top of this file). + foreign import libc "libc.o" +} else { + // Natively (the unit tests) the same procedures are the system libc's. + foreign import libc "system:c" +} + +@(default_calling_convention = "c") +foreign libc { + malloc :: proc(size: c.size_t) -> rawptr --- + realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr --- + free :: proc(ptr: rawptr) --- + aligned_alloc :: proc(alignment, size: c.size_t) -> rawptr --- +} + +DEFAULT_TTL_SECONDS :: 60 + +// ─── the run export ───────────────────────────────────────────────────────── + +when IS_WASM { + // The world's run, behind the generated shim: the host lowered the + // request bytes into a buffer of ours (cabi_realloc), the encoded + // response goes back as an owned list the generated cabi_post_run frees + // once the host has copied it out. An error string here becomes the + // request's fatal result on the host's side; the glue only reaches it + // when it cannot even encode a reply. @(require): nothing in Odin + // references it; "strong" linkage makes it a plain defined symbol for + // the shim (an @(export) would make it a wasm export of its own beside + // the world's). + @(require, linkage = "strong", link_name = "exports_function_run") + exports_function_run :: proc "c" (request: ^Bindings_List_U8, ret: ^Bindings_List_U8, err: ^Bindings_String) -> bool { + context = guest_context() + input := request.ptr[:request.len] + out, ok := handle(input) + function_list_u8_free(request) + if !ok { + // Owned by the canonical ABI from here (cabi_post_run frees + // it): a copy on the libc heap, not the literal. + msg := strings.clone("cannot encode RunFunctionResponse") + err^ = {raw_data(msg), c.size_t(len(msg))} + return false + } + ret^ = {raw_data(out), c.size_t(len(out))} + return true + } +} + +// guest_context is the context every Odin procedure runs under: the default +// one with its allocators on the libc heap. On freestanding wasm the default +// temp allocator is the nil allocator and a panic traps without a message +// (the runtime has nowhere to write it); the host reports the trap. +guest_context :: proc "contextless" () -> runtime.Context { + ctx := runtime.default_context() + ctx.allocator = libc_allocator() + ctx.temp_allocator = ctx.allocator + return ctx +} + +// handle is the guest half of the contract: decode, run, encode. Every +// failure the guest can describe becomes a fatal result so the host can +// always decode the reply; only a response that cannot be encoded uses +// run's error. +handle :: proc(input: []u8) -> (out: []u8, ok: bool) { + req: Run_Function_Request + rsp: Run_Function_Response + is := pb_istream_from_buffer(raw_data(input), c.size_t(len(input))) + if !pb_decode(&is, &Run_Function_Request_msg, &req) { + reason := string(is.errmsg) if is.errmsg != nil else "(none)" + fatal_response(&rsp, "", strings.concatenate({"cannot decode RunFunctionRequest: ", reason})) + return encode(&rsp) + } + tag := string(req.meta.tag) if req.has_meta && req.meta.tag != nil else "" + set_meta(&rsp, tag) + if msg := run_function(&req, &rsp); msg != "" { + fatal_response(&rsp, tag, msg) + } + return encode(&rsp) +} + +// encode writes rsp into a buffer on the context's heap, sized by the codec, +// that the canonical ABI owns from the moment it is returned. +encode :: proc(rsp: ^Run_Function_Response) -> (out: []u8, ok: bool) { + size: c.size_t + if !pb_get_encoded_size(&size, &Run_Function_Response_msg, rsp) { + return nil, false + } + buf := make([]u8, max(int(size), 1)) + os := pb_ostream_from_buffer(raw_data(buf), size) + if !pb_encode(&os, &Run_Function_Response_msg, rsp) { + return nil, false + } + return buf[:os.bytes_written], true +} + +set_meta :: proc(rsp: ^Run_Function_Response, tag: string) { + rsp.has_meta = true + rsp.meta.tag = strings.clone_to_cstring(tag) + rsp.meta.has_ttl = true + rsp.meta.ttl = {DEFAULT_TTL_SECONDS, 0} +} + +// fatal_response makes rsp a fresh response carrying one fatal result. +fatal_response :: proc(rsp: ^Run_Function_Response, tag, msg: string) { + rsp^ = {} + set_meta(rsp, tag) + result := new(Result) + result^ = { + severity = .FATAL, + message = strings.clone_to_cstring(msg), + has_target = true, + target = .COMPOSITE, + } + rsp.results = ([^]Result)(result) + rsp.results_count = 1 +} + +// ─── log: the world's typed import ────────────────────────────────────────── + +// Logging through the host's logger (the world's log import): a message and +// key/value pairs, typed, no payload encoding. debug lines show only when the +// runtime runs under --debug. +Log_Level :: enum u8 { + Debug = 0, + Info = 1, + Warn = 2, + Error = 3, +} + +Log_Pair :: struct { + key, value: string, +} + +log_debug :: proc(msg: string, kv: ..Log_Pair) { + log_at(.Debug, msg, kv) +} + +log_info :: proc(msg: string, kv: ..Log_Pair) { + log_at(.Info, msg, kv) +} + +log_warn :: proc(msg: string, kv: ..Log_Pair) { + log_at(.Warn, msg, kv) +} + +log_error :: proc(msg: string, kv: ..Log_Pair) { + log_at(.Error, msg, kv) +} + +log_at :: proc(level: Log_Level, msg: string, kv: []Log_Pair) { + when IS_WASM { + items := make([]Bindings_Tuple2_String_String, len(kv)) + for p, i in kv { + items[i] = {bindings_string(p.key), bindings_string(p.value)} + } + m := bindings_string(msg) + list := Bindings_List_Tuple2_String_String{raw_data(items), c.size_t(len(items))} + function_log(u8(level), &m, &list) + } else { + // Natively the line goes to stderr, as the other flavours' native + // builds print it: built whole first, since the test runner's + // threads would interleave the pieces. + names := [Log_Level]string { + .Debug = "debug", + .Info = "info", + .Warn = "warn", + .Error = "error", + } + line := strings.concatenate({"wasmfn log ", names[level], ": ", msg}) + for p in kv { + line = strings.concatenate({line, " ", p.key, "=", p.value}) + } + runtime.print_string(strings.concatenate({line, "\n"})) + } +} + +// bindings_string views an Odin string as the bindings' string (the +// canonical ABI never writes through a string it is handed, the pointer is +// mutable only in the C type). +bindings_string :: proc(s: string) -> Bindings_String { + return {raw_data(s), c.size_t(len(s))} +} + +// ─── HTTP through the host ────────────────────────────────────────────────── + +when !IS_WASM { + // The host a native build talks to: none (every request fails with "no + // host HTTP in this build") unless a test installs a procedure with + // http_get_text's contract. + test_host: proc(url: string) -> (text: string, err: string) +} + +// http_get_text GETs url through the host (the c glue's wasi:http client) +// and returns the trimmed body of a 200, or the host's reason: the refusal +// of the egress grant or policy, a budget, a transport failure - never a +// trap. +http_get_text :: proc(url: string) -> (text: string, err: string) { + when IS_WASM { + reason: cstring + body := wasmfn_http_get_text(strings.clone_to_cstring(url), &reason) + if body == nil { + return "", string(reason) if reason != nil else "unknown error" + } + return string(body), "" + } else { + if test_host == nil { + return "", "no host HTTP in this build" + } + return test_host(url) + } +} + +// ─── the libc heap as an Odin allocator ───────────────────────────────────── + +// dlmalloc's guaranteed alignment on wasm32; anything stricter goes through +// aligned_alloc. +MALLOC_ALIGNMENT :: 8 + +libc_allocator :: proc "contextless" () -> runtime.Allocator { + return {procedure = libc_allocator_proc, data = nil} +} + +libc_allocator_proc :: proc( + _: rawptr, + mode: runtime.Allocator_Mode, + size, alignment: int, + old_memory: rawptr, + old_size: int, + loc := #caller_location, +) -> ( + data: []byte, + err: runtime.Allocator_Error, +) { + switch mode { + case .Alloc, .Alloc_Non_Zeroed: + p := libc_alloc(size, alignment) + if p == nil { + return nil, .Out_Of_Memory + } + if mode == .Alloc { + runtime.mem_zero(p, size) + } + return ([^]byte)(p)[:size], nil + case .Free: + free(old_memory) + return nil, nil + case .Free_All: + return nil, .Mode_Not_Implemented + case .Resize, .Resize_Non_Zeroed: + p: rawptr + if alignment <= MALLOC_ALIGNMENT { + p = realloc(old_memory, c.size_t(size)) + } else { + p = libc_alloc(size, alignment) + if p != nil && old_memory != nil { + runtime.mem_copy_non_overlapping(p, old_memory, min(size, old_size)) + free(old_memory) + } + } + if p == nil { + return nil, .Out_Of_Memory + } + if mode == .Resize && size > old_size { + runtime.mem_zero(([^]byte)(p)[old_size:], size - old_size) + } + return ([^]byte)(p)[:size], nil + case .Query_Features: + set := (^runtime.Allocator_Mode_Set)(old_memory) + if set != nil { + set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features} + } + return nil, nil + case .Query_Info: + return nil, .Mode_Not_Implemented + } + return nil, nil +} + +libc_alloc :: proc(size, alignment: int) -> rawptr { + if alignment <= MALLOC_ALIGNMENT { + return malloc(c.size_t(size)) + } + // aligned_alloc wants a size that is a multiple of the alignment. + rounded := (size + alignment - 1) / alignment * alignment + return aligned_alloc(c.size_t(alignment), c.size_t(rounded)) +} diff --git a/examples/hello-odin/wasmfn.yaml b/examples/hello-odin/wasmfn.yaml new file mode 100644 index 00000000..8cad1f79 --- /dev/null +++ b/examples/hello-odin/wasmfn.yaml @@ -0,0 +1,22 @@ +# The module manifest: what this module declares about itself. guestfn build +# validates it, guestfn push publishes it beside the module as the artifact's +# manifest layer, and the runtime holds it against what the policy layers grant +# before every run - a manifest can refuse a run earlier and say why, never +# make one possible. +abi: 2 +name: hello-odin +version: 0.1.0 +# requires: the sandbox capabilities the module cannot run without +# (egress.http rules, filesystem.privateTmp, env credential bindings), +# granted where the compositionPolicy and the operator's Cedar policy permit. This guest fetches a +# greeting only when config.greetingUrl is set, so it requires nothing and +# renders without any grant. +config: + # The JSON Schema (draft 2020-12) of the Input's config; the runtime refuses + # a request whose config does not match, naming the field. + schema: + type: object + properties: + greeting: {type: string} + greetingUrl: {type: string, format: uri} + additionalProperties: false diff --git a/examples/hello-odin/wit/deps/cli.wit b/examples/hello-odin/wit/deps/cli.wit new file mode 100644 index 00000000..aab94201 --- /dev/null +++ b/examples/hello-odin/wit/deps/cli.wit @@ -0,0 +1,235 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:cli@0.2.12; + +@since(version = 0.2.0) +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + @since(version = 0.2.0) + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + @since(version = 0.2.0) + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + @since(version = 0.2.0) + initial-cwd: func() -> option; +} + +@since(version = 0.2.0) +interface exit { + /// Exit the current instance and any linked instances. + @since(version = 0.2.0) + exit: func(status: result); + + /// Exit the current instance and any linked instances, reporting the + /// specified status code to the host. + /// + /// The meaning of the code depends on the context, with 0 usually meaning + /// "success", and other values indicating various types of failure. + /// + /// This function does not return; the effect is analogous to a trap, but + /// without the connotation that something bad has happened. + @since(version = 0.2.12) + exit-with-code: func(status-code: u8); +} + +@since(version = 0.2.0) +interface run { + /// Run the program. + @since(version = 0.2.0) + run: func() -> result; +} + +@since(version = 0.2.0) +interface stdin { + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{input-stream}; + + @since(version = 0.2.0) + get-stdin: func() -> input-stream; +} + +@since(version = 0.2.0) +interface stdout { + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{output-stream}; + + @since(version = 0.2.0) + get-stdout: func() -> output-stream; +} + +@since(version = 0.2.0) +interface stderr { + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{output-stream}; + + @since(version = 0.2.0) + get-stderr: func() -> output-stream; +} + +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +@since(version = 0.2.0) +interface terminal-input { + /// The input side of a terminal. + @since(version = 0.2.0) + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +@since(version = 0.2.0) +interface terminal-output { + /// The output side of a terminal. + @since(version = 0.2.0) + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stdin { + @since(version = 0.2.0) + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stdout { + @since(version = 0.2.0) + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +@since(version = 0.2.0) +interface terminal-stderr { + @since(version = 0.2.0) + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + @since(version = 0.2.0) + get-terminal-stderr: func() -> option; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import environment; + @since(version = 0.2.0) + import exit; + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import stdin; + @since(version = 0.2.0) + import stdout; + @since(version = 0.2.0) + import stderr; + @since(version = 0.2.0) + import terminal-input; + @since(version = 0.2.0) + import terminal-output; + @since(version = 0.2.0) + import terminal-stdin; + @since(version = 0.2.0) + import terminal-stdout; + @since(version = 0.2.0) + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.12; + import wasi:clocks/wall-clock@0.2.12; + @unstable(feature = clocks-timezone) + import wasi:clocks/timezone@0.2.12; + import wasi:filesystem/types@0.2.12; + import wasi:filesystem/preopens@0.2.12; + import wasi:sockets/network@0.2.12; + import wasi:sockets/instance-network@0.2.12; + import wasi:sockets/udp@0.2.12; + import wasi:sockets/udp-create-socket@0.2.12; + import wasi:sockets/tcp@0.2.12; + import wasi:sockets/tcp-create-socket@0.2.12; + import wasi:sockets/ip-name-lookup@0.2.12; + import wasi:random/random@0.2.12; + import wasi:random/insecure@0.2.12; + import wasi:random/insecure-seed@0.2.12; +} +@since(version = 0.2.0) +world command { + @since(version = 0.2.0) + import environment; + @since(version = 0.2.0) + import exit; + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import stdin; + @since(version = 0.2.0) + import stdout; + @since(version = 0.2.0) + import stderr; + @since(version = 0.2.0) + import terminal-input; + @since(version = 0.2.0) + import terminal-output; + @since(version = 0.2.0) + import terminal-stdin; + @since(version = 0.2.0) + import terminal-stdout; + @since(version = 0.2.0) + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.12; + import wasi:clocks/wall-clock@0.2.12; + @unstable(feature = clocks-timezone) + import wasi:clocks/timezone@0.2.12; + import wasi:filesystem/types@0.2.12; + import wasi:filesystem/preopens@0.2.12; + import wasi:sockets/network@0.2.12; + import wasi:sockets/instance-network@0.2.12; + import wasi:sockets/udp@0.2.12; + import wasi:sockets/udp-create-socket@0.2.12; + import wasi:sockets/tcp@0.2.12; + import wasi:sockets/tcp-create-socket@0.2.12; + import wasi:sockets/ip-name-lookup@0.2.12; + import wasi:random/random@0.2.12; + import wasi:random/insecure@0.2.12; + import wasi:random/insecure-seed@0.2.12; + + @since(version = 0.2.0) + export run; +} diff --git a/examples/hello-odin/wit/deps/clocks.wit b/examples/hello-odin/wit/deps/clocks.wit new file mode 100644 index 00000000..2ecf7d0c --- /dev/null +++ b/examples/hello-odin/wit/deps/clocks.wit @@ -0,0 +1,164 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:clocks@0.2.12; + +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +@since(version = 0.2.0) +interface monotonic-clock { + @since(version = 0.2.0) + use wasi:io/poll@0.2.12.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + @since(version = 0.2.0) + type instant = u64; + + /// A duration of time, in nanoseconds. + @since(version = 0.2.0) + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + /// + /// For completeness, this function traps if it's not possible to represent + /// the value of the clock in an `instant`. Consequently, implementations + /// should ensure that the starting time is low enough to avoid the + /// possibility of overflow in practice. + @since(version = 0.2.0) + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + @since(version = 0.2.0) + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// has occurred. + @since(version = 0.2.0) + subscribe-instant: func(when: instant) -> pollable; + + /// Create a `pollable` that will resolve after the specified duration has + /// elapsed from the time this function is invoked. + @since(version = 0.2.0) + subscribe-duration: func(when: duration) -> pollable; +} + +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +@since(version = 0.2.0) +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + @since(version = 0.2.0) + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + @since(version = 0.2.0) + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + @since(version = 0.2.0) + resolution: func() -> datetime; +} + +@unstable(feature = clocks-timezone) +interface timezone { + @unstable(feature = clocks-timezone) + use wall-clock.{datetime}; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + @unstable(feature = clocks-timezone) + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + @unstable(feature = clocks-timezone) + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + @unstable(feature = clocks-timezone) + utc-offset: func(when: datetime) -> s32; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import monotonic-clock; + @since(version = 0.2.0) + import wall-clock; + @unstable(feature = clocks-timezone) + import timezone; +} diff --git a/examples/hello-odin/wit/deps/filesystem.wit b/examples/hello-odin/wit/deps/filesystem.wit new file mode 100644 index 00000000..90fba18d --- /dev/null +++ b/examples/hello-odin/wit/deps/filesystem.wit @@ -0,0 +1,591 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:filesystem@0.2.12; + +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +@since(version = 0.2.0) +interface types { + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{input-stream, output-stream, error}; + @since(version = 0.2.0) + use wasi:clocks/wall-clock@0.2.12.{datetime}; + + /// File size or length of a region within a file. + @since(version = 0.2.0) + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + @since(version = 0.2.0) + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + @since(version = 0.2.0) + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrity + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// Flags determining the method of how paths are resolved. + @since(version = 0.2.0) + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + @since(version = 0.2.0) + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + @since(version = 0.2.0) + type link-count = u64; + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + @since(version = 0.2.0) + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// When setting a timestamp, this gives the value to set it to. + @since(version = 0.2.0) + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + @since(version = 0.2.0) + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + @since(version = 0.2.0) + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + @since(version = 0.2.0) + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + @since(version = 0.2.0) + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + @since(version = 0.2.0) + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + @since(version = 0.2.0) + read-via-stream: func(offset: filesize) -> result; + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + @since(version = 0.2.0) + write-via-stream: func(offset: filesize) -> result; + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in POSIX. + @since(version = 0.2.0) + append-via-stream: func() -> result; + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + @since(version = 0.2.0) + advise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>; + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + @since(version = 0.2.0) + sync-data: func() -> result<_, error-code>; + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-flags: func() -> result; + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + @since(version = 0.2.0) + get-type: func() -> result; + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + @since(version = 0.2.0) + set-size: func(size: filesize) -> result<_, error-code>; + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + @since(version = 0.2.0) + set-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + @since(version = 0.2.0) + read: func(length: filesize, offset: filesize) -> result, bool>, error-code>; + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + @since(version = 0.2.0) + write: func(buffer: list, offset: filesize) -> result; + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + @since(version = 0.2.0) + read-directory: func() -> result; + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + @since(version = 0.2.0) + sync: func() -> result<_, error-code>; + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + @since(version = 0.2.0) + create-directory-at: func(path: string) -> result<_, error-code>; + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat: func() -> result; + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + @since(version = 0.2.0) + stat-at: func(path-flags: path-flags, path: string) -> result; + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + @since(version = 0.2.0) + set-times-at: func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + /// Create a hard link. + /// + /// Fails with `error-code::no-entry` if the old path does not exist, + /// with `error-code::exist` if the new path already exists, and + /// `error-code::not-permitted` if the old path is not a file. + /// + /// Note: This is similar to `linkat` in POSIX. + @since(version = 0.2.0) + link-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + /// Open a file or directory. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + @since(version = 0.2.0) + open-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result; + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + @since(version = 0.2.0) + readlink-at: func(path: string) -> result; + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + @since(version = 0.2.0) + remove-directory-at: func(path: string) -> result<_, error-code>; + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + @since(version = 0.2.0) + rename-at: func(old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + @since(version = 0.2.0) + symlink-at: func(old-path: string, new-path: string) -> result<_, error-code>; + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + @since(version = 0.2.0) + unlink-file-at: func(path: string) -> result<_, error-code>; + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + @since(version = 0.2.0) + is-same-object: func(other: borrow) -> bool; + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encouraged to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + @since(version = 0.2.0) + metadata-hash: func() -> result; + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + @since(version = 0.2.0) + metadata-hash-at: func(path-flags: path-flags, path: string) -> result; + } + + /// A stream of directory entries. + @since(version = 0.2.0) + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + @since(version = 0.2.0) + read-directory-entry: func() -> result, error-code>; + } + + /// Attempts to extract a filesystem-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// filesystem-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are filesystem-related errors. + @since(version = 0.2.0) + filesystem-error-code: func(err: borrow) -> option; +} + +@since(version = 0.2.0) +interface preopens { + @since(version = 0.2.0) + use types.{descriptor}; + + /// Return the set of preopened directories, and their paths. + @since(version = 0.2.0) + get-directories: func() -> list>; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/wall-clock@0.2.12; + @since(version = 0.2.0) + import types; + @since(version = 0.2.0) + import preopens; +} diff --git a/examples/hello-odin/wit/deps/http.wit b/examples/hello-odin/wit/deps/http.wit new file mode 100644 index 00000000..cb204be4 --- /dev/null +++ b/examples/hello-odin/wit/deps/http.wit @@ -0,0 +1,735 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:http@0.2.12; + +/// This interface defines all of the types and methods for implementing +/// HTTP Requests and Responses, both incoming and outgoing, as well as +/// their headers, trailers, and bodies. +@since(version = 0.2.0) +interface types { + @since(version = 0.2.0) + use wasi:clocks/monotonic-clock@0.2.12.{duration}; + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{input-stream, output-stream}; + @since(version = 0.2.0) + use wasi:io/error@0.2.12.{error as io-error}; + @since(version = 0.2.0) + use wasi:io/poll@0.2.12.{pollable}; + + /// This type corresponds to HTTP standard Methods. + @since(version = 0.2.0) + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string), + } + + /// This type corresponds to HTTP standard Related Schemes. + @since(version = 0.2.0) + variant scheme { + HTTP, + HTTPS, + other(string), + } + + /// Defines the case payload type for `DNS-error` above: + @since(version = 0.2.0) + record DNS-error-payload { + rcode: option, + info-code: option, + } + + /// Defines the case payload type for `TLS-alert-received` above: + @since(version = 0.2.0) + record TLS-alert-received-payload { + alert-id: option, + alert-message: option, + } + + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + @since(version = 0.2.0) + record field-size-payload { + field-name: option, + field-size: option, + } + + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// + @since(version = 0.2.0) + variant error-code { + DNS-timeout, + DNS-error(DNS-error-payload), + destination-not-found, + destination-unavailable, + destination-IP-prohibited, + destination-IP-unroutable, + connection-refused, + connection-terminated, + connection-timeout, + connection-read-timeout, + connection-write-timeout, + connection-limit-reached, + TLS-protocol-error, + TLS-certificate-error, + TLS-alert-received(TLS-alert-received-payload), + HTTP-request-denied, + HTTP-request-length-required, + HTTP-request-body-size(option), + HTTP-request-method-invalid, + HTTP-request-URI-invalid, + HTTP-request-URI-too-long, + HTTP-request-header-section-size(option), + HTTP-request-header-size(option), + HTTP-request-trailer-section-size(option), + HTTP-request-trailer-size(field-size-payload), + HTTP-response-incomplete, + HTTP-response-header-section-size(option), + HTTP-response-header-size(field-size-payload), + HTTP-response-body-size(option), + HTTP-response-trailer-section-size(option), + HTTP-response-trailer-size(field-size-payload), + HTTP-response-transfer-coding(option), + HTTP-response-content-coding(option), + HTTP-response-timeout, + HTTP-upgrade-failed, + HTTP-protocol-error, + loop-detected, + configuration-error, + /// This is a catch-all error for anything that doesn't fit cleanly into a + /// more specific case. It also includes an optional string for an + /// unstructured description of the error. Users should not depend on the + /// string for diagnosing errors, as it's not required to be consistent + /// between implementations. + internal-error(option), + } + + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + @since(version = 0.2.0) + variant header-error { + /// This error indicates that a `field-name` or `field-value` was + /// syntactically invalid when used with an operation that sets headers in a + /// `fields`. + invalid-syntax, + /// This error indicates that a forbidden `field-name` was used when trying + /// to set a header in a `fields`. + forbidden, + /// This error indicates that the operation on the `fields` was not + /// permitted because the fields are immutable. + immutable, + } + + /// Field keys are always strings. + /// + /// Field keys should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + /// + /// # Deprecation + /// + /// This type has been deprecated in favor of the `field-name` type. + @since(version = 0.2.0) + @deprecated(version = 0.2.2) + type field-key = string; + + /// Field names are always strings. + /// + /// Field names should always be treated as case insensitive by the `fields` + /// resource for the purposes of equality checking. + @since(version = 0.2.1) + type field-name = field-key; + + /// Field values should always be ASCII strings. However, in + /// reality, HTTP implementations often have to interpret malformed values, + /// so they are provided as a list of bytes. + @since(version = 0.2.0) + type field-value = list; + + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. Fields are a common representation used for both + /// Headers and Trailers. + /// + /// A `fields` may be mutable or immutable. A `fields` created using the + /// constructor, `from-list`, or `clone` will be mutable, but a `fields` + /// resource given by other means (including, but not limited to, + /// `incoming-request.headers`, `outgoing-request.headers`) might be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + @since(version = 0.2.0) + resource fields { + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + @since(version = 0.2.0) + constructor(); + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The tuple is a pair of the field name, represented as a string, and + /// Value, represented as a list of bytes. + /// + /// An error result will be returned if any `field-name` or `field-value` is + /// syntactically invalid, or if a field is forbidden. + @since(version = 0.2.0) + from-list: static func(entries: list>) -> result; + /// Get all of the values corresponding to a name. If the name is not present + /// in this `fields` or is syntactically invalid, an empty list is returned. + /// However, if the name is present but empty, this is represented by a list + /// with one or more empty field-values present. + @since(version = 0.2.0) + get: func(name: field-name) -> list; + /// Returns `true` when the name is present in this `fields`. If the name is + /// syntactically invalid, `false` is returned. + @since(version = 0.2.0) + has: func(name: field-name) -> bool; + /// Set all of the values for a name. Clears any existing values for that + /// name, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or any of + /// the `field-value`s are syntactically invalid. + @since(version = 0.2.0) + set: func(name: field-name, value: list) -> result<_, header-error>; + /// Delete all values for a name. Does nothing if no values for the name + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` is + /// syntactically invalid. + @since(version = 0.2.0) + delete: func(name: field-name) -> result<_, header-error>; + /// Append a value for a name. Does not change or delete any existing + /// values for that name. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + /// + /// Fails with `header-error.invalid-syntax` if the `field-name` or + /// `field-value` are syntactically invalid. + @since(version = 0.2.0) + append: func(name: field-name, value: field-value) -> result<_, header-error>; + /// Retrieve the full set of names and values in the Fields. Like the + /// constructor, the list represents each name-value pair. + /// + /// The outer list represents each name-value pair in the Fields. Names + /// which have multiple values are represented by multiple entries in this + /// list with the same name. + /// + /// The names and values are always returned in the original casing and in + /// the order in which they will be serialized for transport. + @since(version = 0.2.0) + entries: func() -> list>; + /// Make a deep copy of the Fields. Equivalent in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + @since(version = 0.2.0) + clone: func() -> fields; + } + + /// Headers is an alias for Fields. + @since(version = 0.2.0) + type headers = fields; + + /// Trailers is an alias for Fields. + @since(version = 0.2.0) + type trailers = fields; + + /// Represents an incoming HTTP Request. + @since(version = 0.2.0) + resource incoming-request { + /// Returns the method of the incoming request. + @since(version = 0.2.0) + method: func() -> method; + /// Returns the path with query parameters from the request, as a string. + @since(version = 0.2.0) + path-with-query: func() -> option; + /// Returns the protocol scheme from the request. + @since(version = 0.2.0) + scheme: func() -> option; + /// Returns the authority of the Request's target URI, if present. + @since(version = 0.2.0) + authority: func() -> option; + /// Get the `headers` associated with the request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// The `headers` returned are a child resource: it must be dropped before + /// the parent `incoming-request` is dropped. Dropping this + /// `incoming-request` before all children are dropped will trap. + @since(version = 0.2.0) + headers: func() -> headers; + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + @since(version = 0.2.0) + consume: func() -> result; + } + + /// Represents an outgoing HTTP Request. + @since(version = 0.2.0) + resource outgoing-request { + /// Construct a new `outgoing-request` with a default `method` of `GET`, and + /// `none` values for `path-with-query`, `scheme`, and `authority`. + /// + /// * `headers` is the HTTP Headers for the Request. + /// + /// It is possible to construct, or manipulate with the accessor functions + /// below, an `outgoing-request` with an invalid combination of `scheme` + /// and `authority`, or `headers` which are not permitted to be sent. + /// It is the obligation of the `outgoing-handler.handle` implementation + /// to reject invalid constructions of `outgoing-request`. + @since(version = 0.2.0) + constructor(headers: headers); + /// Returns the resource corresponding to the outgoing Body for this + /// Request. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-request` can be retrieved at most once. Subsequent + /// calls will return error. + @since(version = 0.2.0) + body: func() -> result; + /// Get the Method for the Request. + @since(version = 0.2.0) + method: func() -> method; + /// Set the Method for the Request. Fails if the string present in a + /// `method.other` argument is not a syntactically valid method. + @since(version = 0.2.0) + set-method: func(method: method) -> result; + /// Get the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. + @since(version = 0.2.0) + path-with-query: func() -> option; + /// Set the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. Fails is the + /// string given is not a syntactically valid path and query uri component. + @since(version = 0.2.0) + set-path-with-query: func(path-with-query: option) -> result; + /// Get the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. + @since(version = 0.2.0) + scheme: func() -> option; + /// Set the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. Fails if the + /// string given is not a syntactically valid uri scheme. + @since(version = 0.2.0) + set-scheme: func(scheme: option) -> result; + /// Get the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. + @since(version = 0.2.0) + authority: func() -> option; + /// Set the authority of the Request's target URI. A value of `none` may be used + /// with Related Schemes which do not require an authority. The HTTP and + /// HTTPS schemes always require an authority. Fails if the string given is + /// not a syntactically valid URI authority. + @since(version = 0.2.0) + set-authority: func(authority: option) -> result; + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + @since(version = 0.2.0) + headers: func() -> headers; + } + + /// Parameters for making an HTTP Request. Each of these parameters is + /// currently an optional timeout applicable to the transport layer of the + /// HTTP protocol. + /// + /// These timeouts are separate from any the user may use to bound a + /// blocking call to `wasi:io/poll.poll`. + @since(version = 0.2.0) + resource request-options { + /// Construct a default `request-options` value. + @since(version = 0.2.0) + constructor(); + /// The timeout for the initial connect to the HTTP Server. + @since(version = 0.2.0) + connect-timeout: func() -> option; + /// Set the timeout for the initial connect to the HTTP Server. An error + /// return value indicates that this timeout is not supported. + @since(version = 0.2.0) + set-connect-timeout: func(duration: option) -> result; + /// The timeout for receiving the first byte of the Response body. + @since(version = 0.2.0) + first-byte-timeout: func() -> option; + /// Set the timeout for receiving the first byte of the Response body. An + /// error return value indicates that this timeout is not supported. + @since(version = 0.2.0) + set-first-byte-timeout: func(duration: option) -> result; + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + @since(version = 0.2.0) + between-bytes-timeout: func() -> option; + /// Set the timeout for receiving subsequent chunks of bytes in the Response + /// body stream. An error return value indicates that this timeout is not + /// supported. + @since(version = 0.2.0) + set-between-bytes-timeout: func(duration: option) -> result; + } + + /// Represents the ability to send an HTTP Response. + /// + /// This resource is used by the `wasi:http/incoming-handler` interface to + /// allow a Response to be sent corresponding to the Request provided as the + /// other argument to `incoming-handler.handle`. + @since(version = 0.2.0) + resource response-outparam { + /// Send an HTTP 1xx response. + /// + /// Unlike `response-outparam.set`, this does not consume the + /// `response-outparam`, allowing the guest to send an arbitrary number of + /// informational responses before sending the final response using + /// `response-outparam.set`. + /// + /// This will return an `HTTP-protocol-error` if `status` is not in the + /// range [100-199], or an `internal-error` if the implementation does not + /// support informational responses. + @unstable(feature = informational-outbound-responses) + send-informational: func(status: u16, headers: headers) -> result<_, error-code>; + /// Set the value of the `response-outparam` to either send a response, + /// or indicate an error. + /// + /// This method consumes the `response-outparam` to ensure that it is + /// called at most once. If it is never called, the implementation + /// will respond with an error. + /// + /// The user may provide an `error` to `response` to allow the + /// implementation determine how to respond with an HTTP error response. + @since(version = 0.2.0) + set: static func(param: response-outparam, response: result); + } + + /// This type corresponds to the HTTP standard Status Code. + @since(version = 0.2.0) + type status-code = u16; + + /// Represents an incoming HTTP Response. + @since(version = 0.2.0) + resource incoming-response { + /// Returns the status code from the incoming response. + @since(version = 0.2.0) + status: func() -> status-code; + /// Returns the headers from the incoming response. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `incoming-response` is dropped. + @since(version = 0.2.0) + headers: func() -> headers; + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + @since(version = 0.2.0) + consume: func() -> result; + } + + /// Represents an incoming HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, indicating that the full contents of the + /// body have been received. This resource represents the contents as + /// an `input-stream` and the delivery of trailers as a `future-trailers`, + /// and ensures that the user of this interface may only be consuming either + /// the body contents or waiting on trailers at any given time. + @since(version = 0.2.0) + resource incoming-body { + /// Returns the contents of the body, as a stream of bytes. + /// + /// Returns success on first call: the stream representing the contents + /// can be retrieved at most once. Subsequent calls will return error. + /// + /// The returned `input-stream` resource is a child: it must be dropped + /// before the parent `incoming-body` is dropped, or consumed by + /// `incoming-body.finish`. + /// + /// This invariant ensures that the implementation can determine whether + /// the user is consuming the contents of the body, waiting on the + /// `future-trailers` to be ready, or neither. This allows for network + /// backpressure is to be applied when the user is consuming the body, + /// and for that backpressure to not inhibit delivery of the trailers if + /// the user does not read the entire body. + @since(version = 0.2.0) + %stream: func() -> result; + /// Takes ownership of `incoming-body`, and returns a `future-trailers`. + /// This function will trap if the `input-stream` child is still alive. + @since(version = 0.2.0) + finish: static func(this: incoming-body) -> future-trailers; + } + + /// Represents a future which may eventually return trailers, or an error. + /// + /// In the case that the incoming HTTP Request or Response did not have any + /// trailers, this future will resolve to the empty set of trailers once the + /// complete Request or Response body has been received. + @since(version = 0.2.0) + resource future-trailers { + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + @since(version = 0.2.0) + subscribe: func() -> pollable; + /// Returns the contents of the trailers, or an error which occurred, + /// once the future is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the trailers or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the HTTP Request or Response + /// body, as well as any trailers, were received successfully, or that an + /// error occurred receiving them. The optional `trailers` indicates whether + /// or not trailers were present in the body. + /// + /// When some `trailers` are returned by this method, the `trailers` + /// resource is immutable, and a child. Use of the `set`, `append`, or + /// `delete` methods will return an error, and the resource must be + /// dropped before the parent `future-trailers` is dropped. + @since(version = 0.2.0) + get: func() -> option, error-code>>>; + } + + /// Represents an outgoing HTTP Response. + @since(version = 0.2.0) + resource outgoing-response { + /// Construct an `outgoing-response`, with a default `status-code` of `200`. + /// If a different `status-code` is needed, it must be set via the + /// `set-status-code` method. + /// + /// * `headers` is the HTTP Headers for the Response. + @since(version = 0.2.0) + constructor(headers: headers); + /// Get the HTTP Status Code for the Response. + @since(version = 0.2.0) + status-code: func() -> status-code; + /// Set the HTTP Status Code for the Response. Fails if the status-code + /// given is not a valid http status code. + @since(version = 0.2.0) + set-status-code: func(status-code: status-code) -> result; + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transferred to + /// another component by e.g. `outgoing-handler.handle`. + @since(version = 0.2.0) + headers: func() -> headers; + /// Returns the resource corresponding to the outgoing Body for this Response. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-response` can be retrieved at most once. Subsequent + /// calls will return error. + @since(version = 0.2.0) + body: func() -> result; + } + + /// Represents an outgoing HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, inducating the full contents of the body + /// have been sent. This resource represents the contents as an + /// `output-stream` child resource, and the completion of the body (with + /// optional trailers) with a static function that consumes the + /// `outgoing-body` resource, and ensures that the user of this interface + /// may not write to the body contents after the body has been finished. + /// + /// If the user code drops this resource, as opposed to calling the static + /// method `finish`, the implementation should treat the body as incomplete, + /// and that an error has occurred. The implementation should propagate this + /// error to the HTTP protocol by whatever means it has available, + /// including: corrupting the body on the wire, aborting the associated + /// Request, or sending a late status code for the Response. + @since(version = 0.2.0) + resource outgoing-body { + /// Returns a stream for writing the body contents. + /// + /// The returned `output-stream` is a child resource: it must be dropped + /// before the parent `outgoing-body` resource is dropped (or finished), + /// otherwise the `outgoing-body` drop or `finish` will trap. + /// + /// Returns success on the first call: the `output-stream` resource for + /// this `outgoing-body` may be retrieved at most once. Subsequent calls + /// will return error. + @since(version = 0.2.0) + write: func() -> result; + /// Finalize an outgoing body, optionally providing trailers. This must be + /// called to signal that the response is complete. If the `outgoing-body` + /// is dropped without calling `outgoing-body.finalize`, the implementation + /// should treat the body as corrupted. + /// + /// Fails if the body's `outgoing-request` or `outgoing-response` was + /// constructed with a Content-Length header, and the contents written + /// to the body (via `write`) does not match the value given in the + /// Content-Length. + @since(version = 0.2.0) + finish: static func(this: outgoing-body, trailers: option) -> result<_, error-code>; + } + + /// Represents a future which may eventually return an incoming HTTP + /// Response, or an error. + /// + /// This resource is returned by the `wasi:http/outgoing-handler` interface to + /// provide the HTTP Response corresponding to the sent Request. + @since(version = 0.2.0) + resource future-incoming-response { + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occurred. When this pollable is ready, + /// the `get` method will return `some`. + @since(version = 0.2.0) + subscribe: func() -> pollable; + /// Returns the incoming HTTP Response, or an error, once one is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the response or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the incoming HTTP Response + /// status and headers have received successfully, or that an error + /// occurred. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + @since(version = 0.2.0) + get: func() -> option>>; + } + + /// Attempts to extract a http-related `error` from the wasi:io `error` + /// provided. + /// + /// Stream operations which return + /// `wasi:io/stream.stream-error.last-operation-failed` have a payload of + /// type `wasi:io/error.error` with more information about the operation + /// that failed. This payload can be passed through to this function to see + /// if there's http-related information about the error to return. + /// + /// Note that this function is fallible because not all io-errors are + /// http-related errors. + @since(version = 0.2.0) + http-error-code: func(err: borrow) -> option; +} + +/// This interface defines a handler of incoming HTTP Requests. It should +/// be exported by components which can respond to HTTP Requests. +@since(version = 0.2.0) +interface incoming-handler { + @since(version = 0.2.0) + use types.{incoming-request, response-outparam}; + + /// This function is invoked with an incoming HTTP Request, and a resource + /// `response-outparam` which provides the capability to reply with an HTTP + /// Response. The response is sent by calling the `response-outparam.set` + /// method, which allows execution to continue after the response has been + /// sent. This enables both streaming to the response body, and performing other + /// work. + /// + /// The implementor of this function must write a response to the + /// `response-outparam` before returning, or else the caller will respond + /// with an error on its behalf. + @since(version = 0.2.0) + handle: func(request: incoming-request, response-out: response-outparam); +} + +/// This interface defines a handler of outgoing HTTP Requests. It should be +/// imported by components which wish to make HTTP Requests. +@since(version = 0.2.0) +interface outgoing-handler { + @since(version = 0.2.0) + use types.{outgoing-request, request-options, future-incoming-response, error-code}; + + /// This function is invoked with an outgoing HTTP Request, and it returns + /// a resource `future-incoming-response` which represents an HTTP Response + /// which may arrive in the future. + /// + /// The `options` argument accepts optional parameters for the HTTP + /// protocol's transport layer. + /// + /// This function may return an error if the `outgoing-request` is invalid + /// or not allowed to be made. Otherwise, protocol errors are reported + /// through the `future-incoming-response`. + @since(version = 0.2.0) + handle: func(request: outgoing-request, options: option) -> result; +} + +/// The `wasi:http/imports` world imports all the APIs for HTTP proxies. +/// It is intended to be `include`d in other worlds. +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/monotonic-clock@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/wall-clock@0.2.12; + @since(version = 0.2.0) + import wasi:random/random@0.2.12; + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stdout@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stderr@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stdin@0.2.12; + @since(version = 0.2.0) + import types; + @since(version = 0.2.0) + import outgoing-handler; +} +/// The `wasi:http/proxy` world captures a widely-implementable intersection of +/// hosts that includes HTTP forward and reverse proxies. Components targeting +/// this world may concurrently stream in and out any number of incoming and +/// outgoing HTTP requests. +@since(version = 0.2.0) +world proxy { + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/monotonic-clock@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/wall-clock@0.2.12; + @since(version = 0.2.0) + import wasi:random/random@0.2.12; + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stdout@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stderr@0.2.12; + @since(version = 0.2.0) + import wasi:cli/stdin@0.2.12; + @since(version = 0.2.0) + import types; + @since(version = 0.2.0) + import outgoing-handler; + + @since(version = 0.2.0) + export incoming-handler; +} diff --git a/examples/hello-odin/wit/deps/io.wit b/examples/hello-odin/wit/deps/io.wit new file mode 100644 index 00000000..d992ce13 --- /dev/null +++ b/examples/hello-odin/wit/deps/io.wit @@ -0,0 +1,301 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:io@0.2.12; + +@since(version = 0.2.0) +interface error { + /// A resource which represents some error information. + /// + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. + /// + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams.stream-error` type. + /// + /// To provide more specific error information, other interfaces may + /// offer functions to "downcast" this error into more specific types. For example, + /// errors returned from streams derived from filesystem types can be described using + /// the filesystem's own error-code type. This is done using the function + /// `wasi:filesystem/types.filesystem-error-code`, which takes a `borrow` + /// parameter and returns an `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + @since(version = 0.2.0) + resource error { + /// Returns a string that is suitable to assist humans in debugging + /// this error. + /// + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. + @since(version = 0.2.0) + to-debug-string: func() -> string; + } +} + +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +@since(version = 0.2.0) +interface poll { + /// `pollable` represents a single I/O event which may be ready, or not. + @since(version = 0.2.0) + resource pollable { + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + @since(version = 0.2.0) + ready: func() -> bool; + /// `block` returns immediately if the pollable is ready, and otherwise + /// blocks until ready. + /// + /// This function is equivalent to calling `poll.poll` on a list + /// containing only this pollable. + @since(version = 0.2.0) + block: func(); + } + + /// Poll for completion on a set of pollables. + /// + /// This function takes a list of pollables, which identify I/O sources of + /// interest, and waits until one or more of the events is ready for I/O. + /// + /// The result `list` contains one or more indices of handles in the + /// argument list that is ready for I/O. + /// + /// This function traps if either: + /// - the list is empty, or: + /// - the list contains more elements than can be indexed with a `u32` value. + /// + /// A timeout can be implemented by adding a pollable from the + /// wasi-clocks API to the list. + /// + /// This function does not return a `result`; polling in itself does not + /// do any I/O so it doesn't fail. If any of the I/O sources identified by + /// the pollables has an error, it is indicated by marking the source as + /// being ready for I/O. + @since(version = 0.2.0) + poll: func(in: list>) -> list; +} + +/// WASI I/O is an I/O abstraction API which is currently focused on providing +/// stream types. +/// +/// In the future, the component model is expected to add built-in stream types; +/// when it does, they are expected to subsume this API. +@since(version = 0.2.0) +interface streams { + @since(version = 0.2.0) + use error.{error}; + @since(version = 0.2.0) + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + @since(version = 0.2.0) + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + /// + /// After this, the stream will be closed. All future operations return + /// `stream-error::closed`. + last-operation-failed(error), + /// The stream is closed: no more input will be accepted by the + /// stream. A closed output-stream will return this error on all + /// future operations. + closed, + } + + /// An input bytestream. + /// + /// `input-stream`s are *non-blocking* to the extent practical on underlying + /// platforms. I/O operations always return promptly; if fewer bytes are + /// promptly available than requested, they return the number of bytes promptly + /// available, which could even be zero. To wait for data to be available, + /// use the `subscribe` function to obtain a `pollable` which can be polled + /// for using `wasi:io/poll`. + @since(version = 0.2.0) + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// When the source of a `read` is binary data, the bytes from the source + /// are returned verbatim. When the source of a `read` is known to the + /// implementation to be text, bytes containing the UTF-8 encoding of the + /// text are returned. + /// + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// available. + /// + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. + /// + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. + /// + /// The `len` parameter is a `u64`, which could represent a list of u8 which + /// is not possible to allocate in wasm32, or not desirable to allocate as + /// as a return value by the callee. The callee may return a list of bytes + /// less than `len` in size while more bytes are available for reading. + @since(version = 0.2.0) + read: func(len: u64) -> result, stream-error>; + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, behavior is identical to `read`. + @since(version = 0.2.0) + blocking-read: func(len: u64) -> result, stream-error>; + /// Skip bytes from a stream. Returns number of bytes skipped. + /// + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. + @since(version = 0.2.0) + skip: func(len: u64) -> result; + /// Skip bytes from a stream, after blocking until at least one byte + /// can be skipped. Except for blocking behavior, identical to `skip`. + @since(version = 0.2.0) + blocking-skip: func(len: u64) -> result; + /// Create a `pollable` which will resolve once either the specified stream + /// has bytes available to read or the other end of the stream has been + /// closed. + /// The created `pollable` is a child resource of the `input-stream`. + /// Implementations may trap if the `input-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + /// An output bytestream. + /// + /// `output-stream`s are *non-blocking* to the extent practical on + /// underlying platforms. Except where specified otherwise, I/O operations also + /// always return promptly, after the number of bytes that can be written + /// promptly, which could even be zero. To wait for the stream to be ready to + /// accept data, the `subscribe` function to obtain a `pollable` which can be + /// polled for using `wasi:io/poll`. + /// + /// Dropping an `output-stream` while there's still an active write in + /// progress may result in the data being lost. Before dropping the stream, + /// be sure to fully flush your writes. + @since(version = 0.2.0) + resource output-stream { + /// Check readiness for writing. This function never blocks. + /// + /// Returns the number of bytes permitted for the next call to `write`, + /// or an error. Calling `write` with more bytes than this function has + /// permitted will trap. + /// + /// When this function returns 0 bytes, the `subscribe` pollable will + /// become ready when this function will report at least 1 byte, or an + /// error. + @since(version = 0.2.0) + check-write: func() -> result; + /// Perform a write. This function never blocks. + /// + /// When the destination of a `write` is binary data, the bytes from + /// `contents` are written verbatim. When the destination of a `write` is + /// known to the implementation to be text, the bytes of `contents` are + /// transcoded from UTF-8 into the encoding of the destination and then + /// written. + /// + /// Precondition: check-write gave permit of Ok(n) and contents has a + /// length of less than or equal to n. Otherwise, this function will trap. + /// + /// returns Err(closed) without writing if the stream has closed since + /// the last call to check-write provided a permit. + @since(version = 0.2.0) + write: func(contents: list) -> result<_, stream-error>; + /// Perform a write of up to 4096 bytes, and then flush the stream. Block + /// until all of these operations are complete, or an error occurs. + /// + /// Returns success when all of the contents written are successfully + /// flushed to output. If an error occurs at any point before all + /// contents are successfully flushed, that error is returned as soon as + /// possible. If writing and flushing the complete contents causes the + /// stream to become closed, this call should return success, and + /// subsequent calls to check-write or other interfaces should return + /// stream-error::closed. + @since(version = 0.2.0) + blocking-write-and-flush: func(contents: list) -> result<_, stream-error>; + /// Request to flush buffered output. This function never blocks. + /// + /// This tells the output-stream that the caller intends any buffered + /// output to be flushed. the output which is expected to be flushed + /// is all that has been passed to `write` prior to this call. + /// + /// Upon calling this function, the `output-stream` will not accept any + /// writes (`check-write` will return `ok(0)`) until the flush has + /// completed. The `subscribe` pollable will become ready when the + /// flush has completed and the stream can accept more writes. + @since(version = 0.2.0) + flush: func() -> result<_, stream-error>; + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + @since(version = 0.2.0) + blocking-flush: func() -> result<_, stream-error>; + /// Create a `pollable` which will resolve once the output-stream + /// is ready for more writing, or an error has occurred. When this + /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an + /// error. + /// + /// If the stream is closed, this pollable is always ready immediately. + /// + /// The created `pollable` is a child resource of the `output-stream`. + /// Implementations may trap if the `output-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + @since(version = 0.2.0) + subscribe: func() -> pollable; + /// Write zeroes to a stream. + /// + /// This should be used precisely like `write` with the exact same + /// preconditions (must use check-write first), but instead of + /// passing a list of bytes, you simply pass the number of zero-bytes + /// that should be written. + @since(version = 0.2.0) + write-zeroes: func(len: u64) -> result<_, stream-error>; + /// Perform a write of up to 4096 zeroes, and then flush the stream. + /// Block until all of these operations are complete, or an error + /// occurs. + /// + /// Functionality is equivelant to `blocking-write-and-flush` with + /// contents given as a list of len containing only zeroes. + @since(version = 0.2.0) + blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>; + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivalent to: + /// 1. calling `check-write` on the `output-stream` + /// 2. calling `read` on the `input-stream` with the smaller of the + /// `check-write` permitted length and the `len` provided to `splice` + /// 3. calling `write` on the `output-stream` with that read data. + /// + /// Any error reported by the call to `check-write`, `read`, or + /// `write` ends the splice and reports that error. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + @since(version = 0.2.0) + splice: func(src: borrow, len: u64) -> result; + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until the + /// `output-stream` is ready for writing, and the `input-stream` + /// is ready for reading, before performing the `splice`. + @since(version = 0.2.0) + blocking-splice: func(src: borrow, len: u64) -> result; + } +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import error; + @since(version = 0.2.0) + import poll; + @since(version = 0.2.0) + import streams; +} diff --git a/examples/hello-odin/wit/deps/random.wit b/examples/hello-odin/wit/deps/random.wit new file mode 100644 index 00000000..2e433d30 --- /dev/null +++ b/examples/hello-odin/wit/deps/random.wit @@ -0,0 +1,94 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:random@0.2.12; + +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure-seed { + /// Return a 128-bit value that may contain a pseudo-random value. + /// + /// The returned value is not required to be computed from a CSPRNG, and may + /// even be entirely deterministic. Host implementations are encouraged to + /// provide pseudo-random values to any program exposed to + /// attacker-controlled content, to enable DoS protection built into many + /// languages' hash-map implementations. + /// + /// This function is intended to only be called once, by a source language + /// to initialize Denial Of Service (DoS) protection in its hash-map + /// implementation. + /// + /// # Expected future evolution + /// + /// This will likely be changed to a value import, to prevent it from being + /// called multiple times and potentially used for purposes other than DoS + /// protection. + @since(version = 0.2.0) + insecure-seed: func() -> tuple; +} + +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure { + /// Return `len` insecure pseudo-random bytes. + /// + /// This function is not cryptographically secure. Do not use it for + /// anything related to security. + /// + /// There are no requirements on the values of the returned bytes, however + /// implementations are encouraged to return evenly distributed values with + /// a long period. + @since(version = 0.2.0) + get-insecure-random-bytes: func(len: u64) -> list; + + /// Return an insecure pseudo-random `u64` value. + /// + /// This function returns the same type of pseudo-random data as + /// `get-insecure-random-bytes`, represented as a `u64`. + @since(version = 0.2.0) + get-insecure-random-u64: func() -> u64; +} + +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface random { + /// Return `len` cryptographically-secure random or pseudo-random bytes. + /// + /// This function must produce data at least as cryptographically secure and + /// fast as an adequately seeded cryptographically-secure pseudo-random + /// number generator (CSPRNG). It must not block, from the perspective of + /// the calling program, under any circumstances, including on the first + /// request and on requests for numbers of bytes. The returned data must + /// always be unpredictable. + /// + /// This function must always return fresh data. Deterministic environments + /// must omit this function, rather than implementing it with deterministic + /// data. + @since(version = 0.2.0) + get-random-bytes: func(len: u64) -> list; + + /// Return a cryptographically-secure random or pseudo-random `u64` value. + /// + /// This function returns the same type of data as `get-random-bytes`, + /// represented as a `u64`. + @since(version = 0.2.0) + get-random-u64: func() -> u64; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import random; + @since(version = 0.2.0) + import insecure; + @since(version = 0.2.0) + import insecure-seed; +} diff --git a/examples/hello-odin/wit/deps/sockets.wit b/examples/hello-odin/wit/deps/sockets.wit new file mode 100644 index 00000000..df2d868e --- /dev/null +++ b/examples/hello-odin/wit/deps/sockets.wit @@ -0,0 +1,951 @@ +// Vendored from wasmtime-wasi-http 49.0.2 (wit/deps): the wasi:http@0.2 client surface a +// wit-bindgen c guest fetches with. Keep in step with the wasmtime the runtime pins. +package wasi:sockets@0.2.12; + +@since(version = 0.2.0) +interface network { + @unstable(feature = network-error-code) + use wasi:io/error@0.2.12.{error}; + + /// An opaque resource that represents access to (a subset of) the network. + /// This enables context-based security for networking. + /// There is no need for this to map 1:1 to a physical network interface. + @since(version = 0.2.0) + resource network; + + /// Error codes. + /// + /// In theory, every API can return any error code. + /// In practice, API's typically only return the errors documented per API + /// combined with a couple of errors that are always possible: + /// - `unknown` + /// - `access-denied` + /// - `not-supported` + /// - `out-of-memory` + /// - `concurrency-conflict` + /// + /// See each individual API for what the POSIX equivalents are. They sometimes differ per API. + @since(version = 0.2.0) + enum error-code { + /// Unknown error + unknown, + /// Access denied. + /// + /// POSIX equivalent: EACCES, EPERM + access-denied, + /// The operation is not supported. + /// + /// POSIX equivalent: EOPNOTSUPP + not-supported, + /// One of the arguments is invalid. + /// + /// POSIX equivalent: EINVAL + invalid-argument, + /// Not enough memory to complete the operation. + /// + /// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY + out-of-memory, + /// The operation timed out before it could finish completely. + timeout, + /// This operation is incompatible with another asynchronous operation that is already in progress. + /// + /// POSIX equivalent: EALREADY + concurrency-conflict, + /// Trying to finish an asynchronous operation that: + /// - has not been started yet, or: + /// - was already finished by a previous `finish-*` call. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + not-in-progress, + /// The operation has been aborted because it could not be completed immediately. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + would-block, + /// The operation is not valid in the socket's current state. + invalid-state, + /// A new socket resource could not be created because of a system limit. + new-socket-limit, + /// A bind operation failed because the provided address is not an address that the `network` can bind to. + address-not-bindable, + /// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. + address-in-use, + /// The remote address is not reachable + remote-unreachable, + /// The TCP connection was forcefully rejected + connection-refused, + /// The TCP connection was reset. + connection-reset, + /// A TCP connection was aborted. + connection-aborted, + /// The size of a datagram sent to a UDP socket exceeded the maximum + /// supported size. + datagram-too-large, + /// Name does not exist or has no suitable associated IP addresses. + name-unresolvable, + /// A temporary failure in name resolution occurred. + temporary-resolver-failure, + /// A permanent failure in name resolution occurred. + permanent-resolver-failure, + } + + @since(version = 0.2.0) + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + @since(version = 0.2.0) + type ipv4-address = tuple; + + @since(version = 0.2.0) + type ipv6-address = tuple; + + @since(version = 0.2.0) + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + @since(version = 0.2.0) + record ipv4-socket-address { + /// sin_port + port: u16, + /// sin_addr + address: ipv4-address, + } + + @since(version = 0.2.0) + record ipv6-socket-address { + /// sin6_port + port: u16, + /// sin6_flowinfo + flow-info: u32, + /// sin6_addr + address: ipv6-address, + /// sin6_scope_id + scope-id: u32, + } + + @since(version = 0.2.0) + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + + /// Attempts to extract a network-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// network-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are network-related errors. + @unstable(feature = network-error-code) + network-error-code: func(err: borrow) -> option; +} + +/// This interface provides a value-export of the default network handle.. +@since(version = 0.2.0) +interface instance-network { + @since(version = 0.2.0) + use network.{network}; + + /// Get a handle to the default network. + @since(version = 0.2.0) + instance-network: func() -> network; +} + +@since(version = 0.2.0) +interface ip-name-lookup { + @since(version = 0.2.0) + use wasi:io/poll@0.2.12.{pollable}; + @since(version = 0.2.0) + use network.{network, error-code, ip-address}; + + @since(version = 0.2.0) + resource resolve-address-stream { + /// Returns the next address from the resolver. + /// + /// This function should be called multiple times. On each call, it will + /// return the next address in connection order preference. If all + /// addresses have been exhausted, this function returns `none`. + /// + /// This function never returns IPv4-mapped IPv6 addresses. + /// + /// # Typical errors + /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) + /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) + /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) + /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) + @since(version = 0.2.0) + resolve-next-address: func() -> result, error-code>; + /// Create a `pollable` which will resolve once the stream is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + /// Resolve an internet host name to a list of IP addresses. + /// + /// Unicode domain names are automatically converted to ASCII using IDNA encoding. + /// If the input is an IP address string, the address is parsed and returned + /// as-is without making any external requests. + /// + /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. + /// + /// This function never blocks. It either immediately fails or immediately + /// returns successfully with a `resolve-address-stream` that can be used + /// to (asynchronously) fetch the results. + /// + /// # Typical errors + /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. + /// + /// # References: + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + resolve-addresses: func(network: borrow, name: string) -> result; +} + +@since(version = 0.2.0) +interface tcp { + @since(version = 0.2.0) + use wasi:io/streams@0.2.12.{input-stream, output-stream}; + @since(version = 0.2.0) + use wasi:io/poll@0.2.12.{pollable}; + @since(version = 0.2.0) + use wasi:clocks/monotonic-clock@0.2.12.{duration}; + @since(version = 0.2.0) + use network.{network, error-code, ip-socket-address, ip-address-family}; + + @since(version = 0.2.0) + enum shutdown-type { + /// Similar to `SHUT_RD` in POSIX. + receive, + /// Similar to `SHUT_WR` in POSIX. + send, + /// Similar to `SHUT_RDWR` in POSIX. + both, + } + + /// A TCP socket resource. + /// + /// The socket can be in one of the following states: + /// - `unbound` + /// - `bind-in-progress` + /// - `bound` (See note below) + /// - `listen-in-progress` + /// - `listening` + /// - `connect-in-progress` + /// - `connected` + /// - `closed` + /// See + /// for more information. + /// + /// Note: Except where explicitly mentioned, whenever this documentation uses + /// the term "bound" without backticks it actually means: in the `bound` state *or higher*. + /// (i.e. `bound`, `listen-in-progress`, `listening`, `connect-in-progress` or `connected`) + /// + /// In addition to the general error codes documented on the + /// `network::error-code` type, TCP socket methods may always return + /// `error(invalid-state)` when in the `closed` state. + @since(version = 0.2.0) + resource tcp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// Bind can be attempted multiple times on the same socket, even with + /// different arguments on each iteration. But never concurrently and + /// only as long as the previous bind failed. Once a bind succeeds, the + /// binding can't be changed anymore. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) + /// - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT + /// state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR + /// socket option should be set implicitly on all platforms, except on Windows where this is the default behavior + /// and SO_REUSEADDR performs something different entirely. + /// + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-bind: func() -> result<_, error-code>; + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the `connected` state. + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// After a failed connection attempt, the socket will be in the `closed` + /// state and the only valid action left is to `drop` the socket. A single + /// socket can not be used to connect more than once. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) + /// - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN) + /// - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows) + /// - `timeout`: Connection timed out. (ETIMEDOUT) + /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) + /// - `connection-reset`: The connection was reset. (ECONNRESET) + /// - `connection-aborted`: The connection was aborted. (ECONNABORTED) + /// - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `not-in-progress`: A connect operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// The POSIX equivalent of `start-connect` is the regular `connect` syscall. + /// Because all WASI sockets are non-blocking this is expected to return + /// EINPROGRESS, which should be translated to `ok()` in WASI. + /// + /// The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT` + /// with a timeout of 0 on the socket descriptor. Followed by a check for + /// the `SO_ERROR` socket option, in case the poll signaled readiness. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-connect: func() -> result, error-code>; + /// Start listening for new connections. + /// + /// Transitions the socket into the `listening` state. + /// + /// Unlike POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the `listening` state. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) + /// - `not-in-progress`: A listen operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the listen operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `listen` as part of either `start-listen` or `finish-listen`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-listen: func() -> result<_, error-code>; + @since(version = 0.2.0) + finish-listen: func() -> result<_, error-code>; + /// Accept a new client socket. + /// + /// The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `keep-alive-enabled` + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// - `hop-limit` + /// - `receive-buffer-size` + /// - `send-buffer-size` + /// + /// On success, this function returns the newly accepted client socket along with + /// a pair of streams that can be used to read & write to the connection. + /// + /// # Typical errors + /// - `invalid-state`: Socket is not in the `listening` state. (EINVAL) + /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) + /// - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + accept: func() -> result, error-code>; + /// Get the bound local address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + local-address: func() -> result; + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + remote-address: func() -> result; + /// Whether the socket is in the `listening` state. + /// + /// Equivalent to the SO_ACCEPTCONN socket option. + @since(version = 0.2.0) + is-listening: func() -> bool; + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + @since(version = 0.2.0) + address-family: func() -> ip-address-family; + /// Hints the desired listen queue size. Implementations are free to ignore this. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// + /// # Typical errors + /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. + /// - `invalid-argument`: (set) The provided value was 0. + /// - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state. + @since(version = 0.2.0) + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + /// Enables or disables keepalive. + /// + /// The keepalive behavior can be adjusted using: + /// - `keep-alive-idle-time` + /// - `keep-alive-interval` + /// - `keep-alive-count` + /// These properties can be configured while `keep-alive-enabled` is false, but only come into effect when `keep-alive-enabled` is true. + /// + /// Equivalent to the SO_KEEPALIVE socket option. + @since(version = 0.2.0) + keep-alive-enabled: func() -> result; + @since(version = 0.2.0) + set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; + /// Amount of time the connection has to be idle before TCP starts sending keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS) + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-idle-time: func() -> result; + @since(version = 0.2.0) + set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; + /// The time between keepalive packets. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPINTVL socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-interval: func() -> result; + @since(version = 0.2.0) + set-keep-alive-interval: func(value: duration) -> result<_, error-code>; + /// The maximum amount of keepalive packets TCP should send before aborting the connection. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the TCP_KEEPCNT socket option. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + keep-alive-count: func() -> result; + @since(version = 0.2.0) + set-keep-alive-count: func(value: u32) -> result<_, error-code>; + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + @since(version = 0.2.0) + hop-limit: func() -> result; + @since(version = 0.2.0) + set-hop-limit: func(value: u8) -> result<_, error-code>; + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + receive-buffer-size: func() -> result; + @since(version = 0.2.0) + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + @since(version = 0.2.0) + send-buffer-size: func() -> result; + @since(version = 0.2.0) + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + /// Create a `pollable` which can be used to poll for, or block on, + /// completion of any of the asynchronous operations of this socket. + /// + /// When `finish-bind`, `finish-listen`, `finish-connect` or `accept` + /// return `error(would-block)`, this pollable can be used to wait for + /// their success or failure, after which the method can be retried. + /// + /// The pollable is not limited to the async operation that happens to be + /// in progress at the time of calling `subscribe` (if any). Theoretically, + /// `subscribe` only has to be called once per socket and can then be + /// (re)used for the remainder of the socket's lifetime. + /// + /// See + /// for more information. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + /// Initiate a graceful shutdown. + /// + /// - `receive`: The socket is not expecting to receive any data from + /// the peer. The `input-stream` associated with this socket will be + /// closed. Any data still in the receive queue at time of calling + /// this method will be discarded. + /// - `send`: The socket has no more data to send to the peer. The `output-stream` + /// associated with this socket will be closed and a FIN packet will be sent. + /// - `both`: Same effect as `receive` & `send` combined. + /// + /// This function is idempotent; shutting down a direction more than once + /// has no effect and returns `ok`. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} + +@since(version = 0.2.0) +interface tcp-create-socket { + @since(version = 0.2.0) + use network.{network, error-code, ip-address-family}; + @since(version = 0.2.0) + use tcp.{tcp-socket}; + + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` + /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + create-tcp-socket: func(address-family: ip-address-family) -> result; +} + +@since(version = 0.2.0) +interface udp { + @since(version = 0.2.0) + use wasi:io/poll@0.2.12.{pollable}; + @since(version = 0.2.0) + use network.{network, error-code, ip-socket-address, ip-address-family}; + + /// A received datagram. + @since(version = 0.2.0) + record incoming-datagram { + /// The payload. + /// + /// Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + data: list, + /// The source address. + /// + /// This field is guaranteed to match the remote address the stream was initialized with, if any. + /// + /// Equivalent to the `src_addr` out parameter of `recvfrom`. + remote-address: ip-socket-address, + } + + /// A datagram to be sent out. + @since(version = 0.2.0) + record outgoing-datagram { + /// The payload. + data: list, + /// The destination address. + /// + /// The requirements on this field depend on how the stream was initialized: + /// - with a remote address: this field must be None or match the stream's remote address exactly. + /// - without a remote address: this field is required. + /// + /// If this value is None, the send operation is equivalent to `send` in POSIX. Otherwise it is equivalent to `sendto`. + remote-address: option, + } + + /// A UDP socket handle. + @since(version = 0.2.0) + resource udp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the port is zero, the socket will be bound to a random free port. + /// + /// # Typical errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # Implementors note + /// Unlike in POSIX, in WASI the bind operation is async. This enables + /// interactive WASI hosts to inject permission prompts. Runtimes that + /// don't want to make use of this ability can simply call the native + /// `bind` as part of either `start-bind` or `finish-bind`. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + @since(version = 0.2.0) + finish-bind: func() -> result<_, error-code>; + /// Set up inbound & outbound communication channels, optionally to a specific peer. + /// + /// This function only changes the local socket configuration and does not generate any network traffic. + /// On success, the `remote-address` of the socket is updated. The `local-address` may be updated as well, + /// based on the best network path to `remote-address`. + /// + /// When a `remote-address` is provided, the returned streams are limited to communicating with that specific peer: + /// - `send` can only be used to send to this destination. + /// - `receive` will only return datagrams sent from the provided `remote-address`. + /// + /// This method may be called multiple times on the same socket to change its association, but + /// only the most recently returned pair of streams will be operational. Implementations may trap if + /// the streams returned by a previous invocation haven't been dropped yet before calling `stream` again. + /// + /// The POSIX equivalent in pseudo-code is: + /// ```text + /// if (was previously connected) { + /// connect(s, AF_UNSPEC) + /// } + /// if (remote_address is Some) { + /// connect(s, remote_address) + /// } + /// ``` + /// + /// Unlike in POSIX, the socket must already be explicitly bound. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-state`: The socket is not bound. + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + %stream: func(remote-address: option) -> result, error-code>; + /// Get the current bound address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + local-address: func() -> result; + /// Get the address the socket is currently streaming to. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not streaming to a specific remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + remote-address: func() -> result; + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + @since(version = 0.2.0) + address-family: func() -> ip-address-family; + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + @since(version = 0.2.0) + unicast-hop-limit: func() -> result; + @since(version = 0.2.0) + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// If the provided value is 0, an `invalid-argument` error is returned. + /// Any other value will never cause an error, but it might be silently clamped and/or rounded. + /// I.e. after setting a value, reading the same setting back may return a different value. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The provided value was 0. + @since(version = 0.2.0) + receive-buffer-size: func() -> result; + @since(version = 0.2.0) + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + @since(version = 0.2.0) + send-buffer-size: func() -> result; + @since(version = 0.2.0) + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + /// Create a `pollable` which will resolve once the socket is ready for I/O. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + @since(version = 0.2.0) + resource incoming-datagram-stream { + /// Receive messages on the socket. + /// + /// This function attempts to receive up to `max-results` datagrams on the socket without blocking. + /// The returned list may contain fewer elements than requested, but never more. + /// + /// This function returns successfully with an empty list when either: + /// - `max-results` is 0, or: + /// - `max-results` is greater than 0, but no results are immediately available. + /// This function never returns `error(would-block)`. + /// + /// # Typical errors + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + receive: func(max-results: u64) -> result, error-code>; + /// Create a `pollable` which will resolve once the stream is ready to receive again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } + + @since(version = 0.2.0) + resource outgoing-datagram-stream { + /// Check readiness for sending. This function never blocks. + /// + /// Returns the number of datagrams permitted for the next call to `send`, + /// or an error. Calling `send` with more datagrams than this function has + /// permitted will trap. + /// + /// When this function returns ok(0), the `subscribe` pollable will + /// become ready when this function will report at least ok(1), or an + /// error. + /// + /// Never returns `would-block`. + check-send: func() -> result; + /// Send messages on the socket. + /// + /// This function attempts to send all provided `datagrams` on the socket without blocking and + /// returns how many messages were actually sent (or queued for sending). This function never + /// returns `error(would-block)`. If none of the datagrams were able to be sent, `ok(0)` is returned. + /// + /// This function semantically behaves the same as iterating the `datagrams` list and sequentially + /// sending each individual datagram until either the end of the list has been reached or the first error occurred. + /// If at least one datagram has been sent successfully, this function never returns an error. + /// + /// If the input list is empty, the function returns `ok(0)`. + /// + /// Each call to `send` must be permitted by a preceding `check-send`. Implementations must trap if + /// either `check-send` was not called or `datagrams` contains more items than `check-send` permitted. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The socket is in "connected" mode and `remote-address` is `some` value that does not match the address passed to `stream`. (EISCONN) + /// - `invalid-argument`: The socket is not "connected" and no value for `remote-address` was provided. (EDESTADDRREQ) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) + /// - `connection-refused`: The connection was refused. (ECONNREFUSED) + /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + send: func(datagrams: list) -> result; + /// Create a `pollable` which will resolve once the stream is ready to send again. + /// + /// Note: this function is here for WASI 0.2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + @since(version = 0.2.0) + subscribe: func() -> pollable; + } +} + +@since(version = 0.2.0) +interface udp-create-socket { + @since(version = 0.2.0) + use network.{network, error-code, ip-address-family}; + @since(version = 0.2.0) + use udp.{udp-socket}; + + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, + /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References: + /// - + /// - + /// - + /// - + @since(version = 0.2.0) + create-udp-socket: func(address-family: ip-address-family) -> result; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/error@0.2.12; + @since(version = 0.2.0) + import network; + @since(version = 0.2.0) + import instance-network; + @since(version = 0.2.0) + import wasi:io/poll@0.2.12; + @since(version = 0.2.0) + import udp; + @since(version = 0.2.0) + import udp-create-socket; + @since(version = 0.2.0) + import wasi:io/streams@0.2.12; + @since(version = 0.2.0) + import wasi:clocks/monotonic-clock@0.2.12; + @since(version = 0.2.0) + import tcp; + @since(version = 0.2.0) + import tcp-create-socket; + @since(version = 0.2.0) + import ip-name-lookup; +} diff --git a/examples/hello-odin/wit/world.wit b/examples/hello-odin/wit/world.wit new file mode 100644 index 00000000..b935405d --- /dev/null +++ b/examples/hello-odin/wit/world.wit @@ -0,0 +1,25 @@ +/// This guest's world: the wasmfn:function contract (the runtime's +/// wit/wasmfn-function.wit) restated with two deliberate differences: `run` +/// is declared sync (the shape wit-bindgen c binds without a callback-driven +/// task - a sync-lifted implementation satisfies the runtime's async world, +/// docs/abi-v2.md), and the guest imports wasi:http@0.2's outgoing-handler +/// for its greeting fetch - the runtime serves both wasi:http generations +/// through one egress policy. It lives in a local package of its own: a WIT +/// package name must always carry the same contents, and the runtime checks +/// a component's types, not the package its world came from. +package local:guest; + +world function { + enum log-level { + debug, + info, + warn, + error, + } + + import log: func(level: log-level, msg: string, kv: list>); + + import wasi:http/outgoing-handler@0.2.12; + + export run: func(request: list) -> result, string>; +} From 037504a0185607cb54de48cef4aa866bad068bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonasz=20Ma=C5=82ecki?= Date: Wed, 7 Oct 2026 15:59:30 +0200 Subject: [PATCH 2/4] ci(e2e): render hello-odin A render (odin) job modelled on render (c): Odin from its GitHub release for linux amd64, pinned by version and sha256 (the binary is statically linked, its collections sit beside it), Zig as the c job installs it, the c job's codec and bindings drift checks over the example's copies, lint and the native tests, then make render-check with the prebuilt runtime, guestfn and xprin. The report job counts it. --- .github/workflows/e2e.yml | 131 +++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index c2937be4..b442a02d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -539,6 +539,133 @@ jobs: - name: Render the C Guest run: make -C examples/hello-c render-check + # The same guest in Odin, an ABI v2 component on the c flavour's plumbing + # (its C bindings, nanopb codec, WIT and proto byte for byte): odin + # compiles the guest to a freestanding wasm32 object, zig cc compiles the + # C half and links the core module behind its build.zig, and guestfn + # wraps it like the c guest (no wasm-tools, no adapter download). Odin is + # its GitHub release for linux amd64, pinned by checksum like wit-bindgen + # (the binary is statically linked, its base and core collections sit + # beside it); the codec and bindings drift checks are the c job's, over + # this example's copies. + render-odin: + name: render (odin) + runs-on: ubuntu-26.04 + needs: + - start + - build-tools + env: + XP_CHANNEL: stable + XP_VERSION: 'v2.5.0' + # The wit-bindgen that wrote the checked-in bindings (their header + # names it), as a release binary pinned by checksum like xprin. + WIT_BINDGEN_VERSION: 0.62.0 + WIT_BINDGEN_SHA256: 3e81cc6523729f7532b4aa7968648a04abf0c711b7d1677150e9121f4e6458fe + # The Odin release the example builds with (its README names it). + ODIN_VERSION: dev-2026-10 + ODIN_SHA256: c3c8b095621fd0c75f7f73e3a0829f1b4d45324225f20ba11ed8dc4da310a8ab + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: refs/pull/${{ github.event.issue.number }}/merge + persist-credentials: false + + # The runtime, guestfn and xprin come from build-tools; render.sh and + # the Makefiles take them from FUNCTION_BIN, GUESTFN and XPRIN instead + # of building or installing them. + - name: Download the Runtime, guestfn and xprin + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: e2e-tools + path: ${{ runner.temp }}/e2e-tools + + - name: Use the Prebuilt Runtime, guestfn and xprin + run: | + chmod +x "${RUNNER_TEMP}/e2e-tools/function" "${RUNNER_TEMP}/e2e-tools/guestfn" \ + "${RUNNER_TEMP}/e2e-tools/xprin" + { + echo "FUNCTION_BIN=${RUNNER_TEMP}/e2e-tools/function" + echo "GUESTFN=${RUNNER_TEMP}/e2e-tools/guestfn" + echo "XPRIN=${RUNNER_TEMP}/e2e-tools/xprin" + } >> "$GITHUB_ENV" + + - name: Setup Zig + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 + with: + use-cache: false + version: 0.16.0 + + - name: Setup protoc + uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + # The nanopb version must match the one the checked-in codec was + # generated with (its header names it) and the one build.zig fetches. + - name: Setup Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: '3.14' + + - name: Setup nanopb_generator + run: pip install nanopb==0.4.9.1 + + - name: Check Generated Codec + working-directory: examples/hello-odin + run: | + zig build gen-proto + if [ -n "$(git status --porcelain)" ]; then + echo "examples/hello-odin/src/fnv1 is not up to date with its proto; commit the result of zig build gen-proto:" + git status --porcelain + git diff + exit 1 + fi + + - name: Setup wit-bindgen + run: | + curl -fsSL -o "${RUNNER_TEMP}/wit-bindgen.tar.gz" \ + "https://github.com/bytecodealliance/wit-bindgen/releases/download/v${WIT_BINDGEN_VERSION}/wit-bindgen-${WIT_BINDGEN_VERSION}-x86_64-linux.tar.gz" + echo "${WIT_BINDGEN_SHA256} ${RUNNER_TEMP}/wit-bindgen.tar.gz" | sha256sum -c - + tar -xzf "${RUNNER_TEMP}/wit-bindgen.tar.gz" -C "${RUNNER_TEMP}" + echo "${RUNNER_TEMP}/wit-bindgen-${WIT_BINDGEN_VERSION}-x86_64-linux" >> "$GITHUB_PATH" + + - name: Check Generated Bindings + working-directory: examples/hello-odin + run: | + zig build gen-bindings + if [ -n "$(git status --porcelain)" ]; then + echo "examples/hello-odin/src/gen is not up to date with its wit; commit the result of zig build gen-bindings:" + git status --porcelain + git diff + exit 1 + fi + + - name: Setup Odin + run: | + curl -fsSL -o "${RUNNER_TEMP}/odin.tar.gz" \ + "https://github.com/odin-lang/Odin/releases/download/${ODIN_VERSION}/odin-linux-amd64-${ODIN_VERSION}.tar.gz" + echo "${ODIN_SHA256} ${RUNNER_TEMP}/odin.tar.gz" | sha256sum -c - + mkdir -p "${RUNNER_TEMP}/odin" + tar -xzf "${RUNNER_TEMP}/odin.tar.gz" -C "${RUNNER_TEMP}/odin" --strip-components=1 + echo "${RUNNER_TEMP}/odin" >> "$GITHUB_PATH" + "${RUNNER_TEMP}/odin/odin" version + + - name: Lint and Test the Odin Guest + working-directory: examples/hello-odin + run: | + zig fmt --check build.zig + zig build lint + zig build test + + - name: Setup the Crossplane CLI + run: | + curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh + sudo mv crossplane /usr/local/bin/crossplane + + - name: Render the Odin Guest + run: make -C examples/hello-odin render-check + # The TypeScript guest, an ABI v2 component (jco): the policy-gate use # case, the last step after function-go-templating (which render runs in # Docker). It asks for its environment's EnvironmentConfig through @@ -767,7 +894,7 @@ jobs: report: runs-on: ubuntu-26.04 - needs: [start, guest-suite, render-go, render-rust, render-zig, render-c, render-ts, render-python, render-dotnet, e2e-oci] + needs: [start, guest-suite, render-go, render-rust, render-zig, render-c, render-odin, render-ts, render-python, render-dotnet, e2e-oci] if: always() && needs.start.result == 'success' permissions: statuses: write @@ -781,7 +908,7 @@ jobs: for result in "${{ needs.guest-suite.result }}" "${{ needs.render-go.result }}" \ "${{ needs.render-rust.result }}" \ "${{ needs.render-zig.result }}" "${{ needs.render-c.result }}" \ - "${{ needs.render-ts.result }}" \ + "${{ needs.render-odin.result }}" "${{ needs.render-ts.result }}" \ "${{ needs.render-python.result }}" "${{ needs.render-dotnet.result }}" \ "${{ needs.e2e-oci.result }}"; do if [ "$result" != "success" ]; then From b39f57e02f027e87676a93c5bf9a08bfc0665089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonasz=20Ma=C5=82ecki?= Date: Wed, 7 Oct 2026 15:59:30 +0200 Subject: [PATCH 3/4] docs: add Odin to the tested languages Odin moves from the possible-untested list to the tested set on the other-languages page, with a paragraph on the example beside the C# one; the README names it as an example only; AGENTS.md gains the examples tree entry, the per-example test, lint and render commands, and the seventeen-copy count of the vendored proto; the language one-pager's 2026-10-07 paragraph records it (revision 0.6); the Renovate comments listing the examples name it. --- .github/renovate.json5 | 12 +++++++----- AGENTS.md | 26 +++++++++++++++++++++++-- README.md | 5 +++-- docs/guests/other-languages.md | 31 +++++++++++++++++++++++++----- docs/one-pager-language-support.md | 9 +++++++-- 5 files changed, 67 insertions(+), 16 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index b06aa039..f36028d9 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -110,7 +110,7 @@ // The wasmtime-wasi-http release every vendored WASI WIT file under a // wit/deps/ was copied from: its src/p3/wit/deps for the rust scaffold // and cloudflare-origin, its wit/deps for the python, c, zig and go - // scaffolds, team-tags, hello-c, hello-zig, pdb-addon and + // scaffolds, team-tags, hello-c, hello-zig, hello-odin, pdb-addon and // dashboard-bundle (templates and goldens included: the // files are plain .wit in all of them). Same tripwire as the proto: a // bump PR moves the version in every header at once; it does NOT @@ -208,7 +208,8 @@ }, // The WASI WIT headers, for the same reason: one dep across the rust, // python, c, zig and go templates, their goldens, cloudflare-origin, - // team-tags, hello-c, hello-zig, pdb-addon and dashboard-bundle. + // team-tags, hello-c, hello-zig, hello-odin, pdb-addon and + // dashboard-bundle. // Their group is the wasmtime one above. { matchManagers: ['custom.regex'], @@ -281,9 +282,10 @@ // time (the cut-release skill), never in this batch - pip_requirements // is not an enabled manager. // - // hello-zig and hello-c name their dependencies in build.zig.zon by URL - // and content hash, which no Renovate manager reads: they move by hand, - // with the zig and c templates, at release time. + // hello-zig, hello-c and hello-odin name their dependencies in + // build.zig.zon by URL and content hash, which no Renovate manager + // reads: they move by hand, with the zig and c templates, at release + // time (hello-odin's nanopb pin is hello-c's). // // One batch, early on the 1st of the month. Renovate does not group lock // file maintenance with other updates - a grouped one gets its own diff --git a/AGENTS.md b/AGENTS.md index b376b193..de47c019 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -270,6 +270,25 @@ examples/hello-c the same guest in C, an ABI v2 component on the c sc configured greeting and one fetched through the host's egress (example/policy.cedar, example/wasmfn.local.yaml named by module.manifestPath, example/fixtures). ~62 KB +examples/hello-odin the same guest in Odin, an ABI v2 component on the c scaffold's + plumbing (examples-share-the-scaffold-plumbing: wit/, src/gen/, + src/fnv1/ and proto/ byte for byte; no scaffold of its own, #155): + src/main.odin is the function over src/fnv1.odin, nanopb's + generated structs declared again in Odin with their wasm32 + layout held by #asserts and the codec called over the foreign + interface; src/wasmfn.odin is the glue (the bindings' + exports_function_run, the typed log, an allocator over + wasi-libc's heap - the module's one heap, which the canonical + ABI frees into) and src/wasmfn.c the c glue's wasi:http client + kept as it is. odin builds a freestanding wasm32 object, + build.zig compiles the C half and links the core module through + zig cc (not build-exe: Odin's runtime defines bzero with a + return value, and wasm-ld's mismatch warning fails build-exe), + guestfn build takes it for a c project and wraps it with no + adapter. make test runs odin test natively over the C half + compiled for the host, make lint runs odin check -vet + -strict-style and zig fmt. Its xprin suite is the c example's. + ~71 KB examples/cloudflare-origin #112's Rust use case, an ABI v2 component on the rust scaffold's plumbing (examples-share-the-scaffold-plumbing): an Origin XR's AWS security group plus, for exposure: cloudflare, one ingress rule per @@ -458,10 +477,11 @@ cargo test -p guestfn # scaffold goldens, the examples' shar (cd examples/pdb-addon && go test -race ./...) (cd examples/hello-zig && zig build test) (cd examples/hello-c && zig build test) +(cd examples/hello-odin && zig build test) # odin and zig on PATH make -C examples/dashboard-bundle test # dotnet test (in the .NET SDK container off Linux) ``` -`crates/function/tests/guests.rs` builds every language's scaffold - its golden under `crates/guestfn/testdata`, copied fresh into the OS temp dir (outside the workspace), so the suite proves what `guestfn init` writes and runs each through the whole host with the same expectations: default and configured greeting, a greeting fetched through the host's egress (via an OCI manifest layer and via `module.manifestPath`) and refused without a grant, guest-side fatal on a bad config, guest logs. The guests must stay behaviourally identical; the examples under `examples/` are free to solve their own use cases and are checked by their render jobs - C#, whose only guest is the dashboard-bundle example (it does not greet), has no place in the suite and is covered by that example's unit tests and render job. A scaffold has no lockfile, so the suite resolves dependencies the way a user's first build does (`go mod tidy`, `npm install`, a fresh `Cargo.lock`). A guest whose toolchain is not on PATH is skipped. Toolchains: the rust scaffold's `rust-toolchain.toml` brings its own pinned toolchain with `wasm32-wasip3`, installed by rustup on first use; Zig 0.16; `protoc` for the rust scaffold's prost-build and the codec regeneration targets; `nanopb_generator` (`pip install nanopb==0.4.9.1`) only for `zig build gen-proto` in hello-c; `wit-bindgen-cli` 0.62.0 only for `zig build gen-bindings` in hello-c and hello-zig and `make gen-bindings` in pdb-addon (`make gen-bindings` at the root installs it pinned, regenerates all three, mirrors the results into the templates and refreshes the goldens). +`crates/function/tests/guests.rs` builds every language's scaffold - its golden under `crates/guestfn/testdata`, copied fresh into the OS temp dir (outside the workspace), so the suite proves what `guestfn init` writes and runs each through the whole host with the same expectations: default and configured greeting, a greeting fetched through the host's egress (via an OCI manifest layer and via `module.manifestPath`) and refused without a grant, guest-side fatal on a bad config, guest logs. The guests must stay behaviourally identical; the examples under `examples/` are free to solve their own use cases and are checked by their render jobs - C#, whose only guest is the dashboard-bundle example (it does not greet), and Odin, whose only guest is the hello-odin example (no scaffold), have no place in the suite and are covered by their examples' unit tests and render jobs. A scaffold has no lockfile, so the suite resolves dependencies the way a user's first build does (`go mod tidy`, `npm install`, a fresh `Cargo.lock`). A guest whose toolchain is not on PATH is skipped. Toolchains: the rust scaffold's `rust-toolchain.toml` brings its own pinned toolchain with `wasm32-wasip3`, installed by rustup on first use; Zig 0.16; `protoc` for the rust scaffold's prost-build and the codec regeneration targets; `nanopb_generator` (`pip install nanopb==0.4.9.1`) only for `zig build gen-proto` in hello-c and hello-odin; `wit-bindgen-cli` 0.62.0 only for `zig build gen-bindings` in hello-c, hello-zig and hello-odin and `make gen-bindings` in pdb-addon (`make gen-bindings` at the root installs it pinned, regenerates all four, mirrors the c, zig and go results into the templates and refreshes the goldens); Odin (dev-2026-10) only for hello-odin. Goldens: `UPDATE_CONFORMANCE=1 cargo test -p function-wasm --test conformance` re-records the conformance goldens (deliberate behaviour changes only); `UPDATE_GOLDENS=1 cargo test -p guestfn` regenerates the scaffold goldens after a template change. @@ -479,6 +499,7 @@ cargo clippy --workspace --all-targets -- -D warnings (cd examples/pdb-addon && golangci-lint run ./...) # the Go guests keep Go lint (cd examples/hello-zig && zig fmt --check build.zig src/main.zig src/wasmfn.zig) (cd examples/hello-c && zig fmt --check build.zig) +(cd examples/hello-odin && make lint) # odin check -vet -strict-style, zig fmt --check build.zig make -C examples/dashboard-bundle lint # dotnet format (in the .NET SDK container off Linux) ``` @@ -514,7 +535,7 @@ A guest reaches the host through the world (`wit/wasmfn-function.wit`, final at ### Changing the scaffold -Edit the template set under `crates/guestfn/templates/` (templates use `[[ ]]` delimiters so source braces survive; each template set is a minimal greeting project; `wasmfn.yaml.tmpl` is the manifest every flavour ships; the zig and c `build.zig.zon.tmpl` take the project's identifier and fingerprint from the `zigid`/`zigfp` template helpers), then `UPDATE_GOLDENS=1 cargo test -p guestfn` to refresh the goldens; the guest suite builds the goldens, so `/e2e` proves the change. A change to the plumbing - the vendored ABI glue (`internal/wasmfn`), the generated codecs, the proto, the vendored WIT - goes into the paired example too: the examples-share-the-scaffold-plumbing test holds each example's copy of those files identical to its template (its list of shared paths per language is in `scaffold.rs`); everything else in an example is its own. The sixteen vendored `run_function.proto` copies (five templates, five goldens, six examples) are one wire contract: `crossplane/crossplane`'s `proto/fn/v1/run_function.proto`, stated in each file's header as `Vendored from crossplane/crossplane vX.Y.Z.` and tracked by Renovate through that header - the same tripwire function-sdk-rust carries. A Renovate bump moves the version in every copy at once but **does not re-download the file** or regenerate the codecs checked in beside it: treat the PR as the signal to run `make vendor-proto` on its branch (`VERSION=vX.Y.Z` vendors ahead of Renovate), which fetches the upstream file at that release into every copy under its own header, regenerates every guest's codec with the protoc and nanopb_generator the root `Makefile` pins (it needs Zig, npm, python3 and cargo), mirrors them into the templates and refreshes the goldens; then comment /e2e, whose render jobs fail on codec drift. Per-language identity of the plumbing (template ↔ golden ↔ example) is enforced by the goldens and the examples-share-the-scaffold-plumbing test. The rust scaffold's `wit/deps/wasmfn-function.wit` is the root `wit/wasmfn-function.wit` (the world the engine compiles) byte for byte, enforced by the render-matches-the-runtime-world test: change the world at the root, copy it into `templates/rust/wit/deps/` and `examples/cloudflare-origin/wit/deps/` (and move the version in `wit/world.wit`'s `include` if the package version changed), then refresh the goldens; the guest's own world, `wit/world.wit`, is a `local:guest` package, so a scaffold never redefines the contract's package (the ts, python, c, zig and go scaffolds' `wit/world.wit` restates the world with a sync `run` instead of including it, so only the contract's copies carry its name). The vendored WASI WIT under `wit/deps/` (wasi:*@0.3 from wasmtime-wasi-http's `src/p3/wit/deps` in the rust template, its golden and cloudflare-origin, the p3 `http.wit` trimmed of its service/middleware worlds; wasi:*@0.2 from its `wit/deps` in the python, c, zig and go templates, their goldens, team-tags, hello-c, hello-zig, pdb-addon and dashboard-bundle) carries a `Vendored from wasmtime-wasi-http X.Y.Z` header under the same tripwire, grouped into Renovate's wasmtime PR: that PR moves the headers with the crates, and is the signal to re-vendor the files by hand from the new crate (keeping the trim). The c and zig scaffolds' `src/gen` is wit-bindgen's C output over their `wit/` - one world, one output, the two copies held identical by the c-and-zig-share-the-bindings test (Zig reads `function.h` through translate-c as its `bindings` module and compiles `function.c` beside its own glue) - `function.c`, `function.h` and `function_component_type.o`, the object carrying the component-type section `guestfn build` wraps by; their header names the generator's version: after a change to the world or a re-vendoring of the WASI WIT, `make gen-bindings` at the root regenerates it in hello-c and hello-zig with the pinned `wit-bindgen-cli`, mirrors each into its template and refreshes the goldens, and the render-c and render-zig jobs regenerate it and fail on drift, like the codecs. The go scaffold's `internal/bindings` is wit-bindgen's Go output over its `wit/` (a `wit_bindings.go` and an `empty.s` per package plus `wit_exports`, the generated files' header naming the generator's version; the hand-written `export_wit_world/run.go` slot beside them; a generated file names the guest's module path in its imports, so the template carries it as `.go.tmpl` with `[[ .Module ]]`): the same `make gen-bindings` regenerates it in pdb-addon, mirrors it into the template and refreshes the goldens, and the render-go job regenerates it and fails on drift. `go.bytecodealliance.org/pkg`, the bindings' runtime in `go.mod.tmpl` and pdb-addon's go.mod, is pinned at the version the generator targets (`wit-bindgen go --print-remote-pkg-version`) and moves with it. +Edit the template set under `crates/guestfn/templates/` (templates use `[[ ]]` delimiters so source braces survive; each template set is a minimal greeting project; `wasmfn.yaml.tmpl` is the manifest every flavour ships; the zig and c `build.zig.zon.tmpl` take the project's identifier and fingerprint from the `zigid`/`zigfp` template helpers), then `UPDATE_GOLDENS=1 cargo test -p guestfn` to refresh the goldens; the guest suite builds the goldens, so `/e2e` proves the change. A change to the plumbing - the vendored ABI glue (`internal/wasmfn`), the generated codecs, the proto, the vendored WIT - goes into the paired example too: the examples-share-the-scaffold-plumbing test holds each example's copy of those files identical to its template (its list of shared paths per example is in `scaffold.rs`; hello-odin, which has no scaffold, rides the c template's `wit/`, `src/gen/`, `src/fnv1/` and `proto/`); everything else in an example is its own. The seventeen vendored `run_function.proto` copies (five templates, five goldens, seven examples) are one wire contract: `crossplane/crossplane`'s `proto/fn/v1/run_function.proto`, stated in each file's header as `Vendored from crossplane/crossplane vX.Y.Z.` and tracked by Renovate through that header - the same tripwire function-sdk-rust carries. A Renovate bump moves the version in every copy at once but **does not re-download the file** or regenerate the codecs checked in beside it: treat the PR as the signal to run `make vendor-proto` on its branch (`VERSION=vX.Y.Z` vendors ahead of Renovate), which fetches the upstream file at that release into every copy under its own header, regenerates every guest's codec with the protoc and nanopb_generator the root `Makefile` pins (it needs Zig, npm, python3 and cargo), mirrors them into the templates and refreshes the goldens; then comment /e2e, whose render jobs fail on codec drift. Per-language identity of the plumbing (template ↔ golden ↔ example) is enforced by the goldens and the examples-share-the-scaffold-plumbing test. The rust scaffold's `wit/deps/wasmfn-function.wit` is the root `wit/wasmfn-function.wit` (the world the engine compiles) byte for byte, enforced by the render-matches-the-runtime-world test: change the world at the root, copy it into `templates/rust/wit/deps/` and `examples/cloudflare-origin/wit/deps/` (and move the version in `wit/world.wit`'s `include` if the package version changed), then refresh the goldens; the guest's own world, `wit/world.wit`, is a `local:guest` package, so a scaffold never redefines the contract's package (the ts, python, c, zig and go scaffolds' `wit/world.wit` restates the world with a sync `run` instead of including it, so only the contract's copies carry its name). The vendored WASI WIT under `wit/deps/` (wasi:*@0.3 from wasmtime-wasi-http's `src/p3/wit/deps` in the rust template, its golden and cloudflare-origin, the p3 `http.wit` trimmed of its service/middleware worlds; wasi:*@0.2 from its `wit/deps` in the python, c, zig and go templates, their goldens, team-tags, hello-c, hello-zig, hello-odin, pdb-addon and dashboard-bundle) carries a `Vendored from wasmtime-wasi-http X.Y.Z` header under the same tripwire, grouped into Renovate's wasmtime PR: that PR moves the headers with the crates, and is the signal to re-vendor the files by hand from the new crate (keeping the trim). The c and zig scaffolds' `src/gen` is wit-bindgen's C output over their `wit/` - one world, one output, the two copies held identical by the c-and-zig-share-the-bindings test (Zig reads `function.h` through translate-c as its `bindings` module and compiles `function.c` beside its own glue) - `function.c`, `function.h` and `function_component_type.o`, the object carrying the component-type section `guestfn build` wraps by; their header names the generator's version: after a change to the world or a re-vendoring of the WASI WIT, `make gen-bindings` at the root regenerates it in hello-c, hello-zig and hello-odin with the pinned `wit-bindgen-cli`, mirrors the c and zig copies into their templates (hello-odin carries the c flavour's, which the plumbing test holds identical) and refreshes the goldens, and the render-c, render-zig and render-odin jobs regenerate it and fail on drift, like the codecs. The go scaffold's `internal/bindings` is wit-bindgen's Go output over its `wit/` (a `wit_bindings.go` and an `empty.s` per package plus `wit_exports`, the generated files' header naming the generator's version; the hand-written `export_wit_world/run.go` slot beside them; a generated file names the guest's module path in its imports, so the template carries it as `.go.tmpl` with `[[ .Module ]]`): the same `make gen-bindings` regenerates it in pdb-addon, mirrors it into the template and refreshes the goldens, and the render-go job regenerates it and fails on drift. `go.bytecodealliance.org/pkg`, the bindings' runtime in `go.mod.tmpl` and pdb-addon's go.mod, is pinned at the version the generator targets (`wit-bindgen go --print-remote-pkg-version`) and moves with it. ### Rendering Locally @@ -525,6 +546,7 @@ make -C examples/pdb-addon render # build fn.wasm (guestfn via cargo), s make -C examples/pdb-addon render-check # same, running example/xprin.yaml (xprin on PATH, or XPRIN) - what the /e2e render job runs make -C examples/hello-zig render # the Zig guest (zig on PATH: zig builds the core module, guestfn wraps it) make -C examples/hello-c render # the C guest (zig on PATH: zig cc builds the core module, guestfn wraps it) +make -C examples/hello-odin render # the Odin guest (odin and zig on PATH: odin builds the object, zig cc links, guestfn wraps it) ``` By hand: `cargo run -p function-wasm -- --insecure --debug --module-dir=examples/pdb-addon`, then in the example: `cargo run -p guestfn -- build` and `crossplane render example/xr.yaml example/composition.yaml example/functions.yaml --include-function-results`. `functions.yaml` uses the Development runtime, so the function must be running locally; the render engine itself runs in Docker. diff --git a/README.md b/README.md index d565a9c2..a0a51db0 100644 --- a/README.md +++ b/README.md @@ -110,8 +110,9 @@ implementing the world can target the runtime: | `ts` | node + npm (esbuild, jco) | ~14 MB | [`examples/policy-gate`](examples/policy-gate) | | `python` | `python3` (componentize-py) | ~21 MB | [`examples/team-tags`](examples/team-tags) | -C# is an example only ([`examples/dashboard-bundle`](examples/dashboard-bundle), -~4.5 MB). The supported, tested and untested languages, with what each +C# and Odin are examples only ([`examples/dashboard-bundle`](examples/dashboard-bundle), +~4.5 MB; [`examples/hello-odin`](examples/hello-odin), ~71 KB, on the `c` +flavour's bindings and codec). The supported, tested and untested languages, with what each toolchain brings, are on [Other languages](https://jonasz-lasut.github.io/function-wasm/guests/other-languages.html). diff --git a/docs/guests/other-languages.md b/docs/guests/other-languages.md index 27d3ae7b..8bb4115a 100644 --- a/docs/guests/other-languages.md +++ b/docs/guests/other-languages.md @@ -13,7 +13,7 @@ and .NET A language is *tested* when this repository works with it: a scaffold or an example here, built and run through the host by the guest suite and the render jobs on every `/e2e`. Tested on ABI v2: Go, Rust, Zig, C, TypeScript, -Python and C# - every scaffold and example here, since +Python, C# and Odin - every scaffold and example here, since [#114](https://github.com/jonasz-lasut/function-wasm/issues/114) moved the last of them (Go, 2026-10-07) off ABI v1. A supported language that is not tested is expected to work, and a @@ -67,6 +67,31 @@ macOS compiler, so on macOS the Makefile builds in the .NET SDK container and its render test cover it rather than the behaviour tests the other flavours share, and `guestfn` neither scaffolds nor builds it yet. +An **Odin** ABI v2 guest is an example only too +([`examples/hello-odin`](https://github.com/jonasz-lasut/function-wasm/tree/main/examples/hello-odin), +~71 KB; Odin dev-2026-10 and Zig 0.16, `make build`): the hello guest again, +on the `c` flavour's plumbing - its wit-bindgen C bindings, nanopb codec, +WIT and proto byte for byte, held identical by the plumbing test. `odin +build -target:freestanding_wasm32 -build-mode:obj` compiles the guest to one +object in 0.2 s, `zig cc` compiles the C half and links the core module (a +wasip1 reactor that imports nothing from `wasi_snapshot_preview1`), and +`guestfn build` takes the project for a `c` one by its `build.zig` and wraps +the result with no adapter: about 7 s cold, 0.2 s warm, and the runtime +compiles the component in about 10 ms, as it does the C and Zig ones. The +Odin side defines the bindings' `exports_function_run` through Odin's +foreign interface, declares nanopb's generated structs again with their +wasm32 layout held by `#assert`s, and reaches the host's HTTP egress through +the `c` glue's `wasi:http@0.2` client; its allocator is wasi-libc's heap, +the module's one heap, so what Odin allocates may be handed to the canonical +ABI and freed there. `core:fmt` is left out on purpose: its reflection +tables would make the module 198 KB. Two things to know: Odin's runtime +defines `bzero` on every wasm target with a return value where libc's has +none, which `wasm-ld` reports as a signature mismatch and `zig build-exe` +treats as an error, so the example links through `zig cc`, which only +warns; and a panic traps without a message on the freestanding runtime. Its +unit tests run natively (`make test`, over the C half compiled for the +host), and `guestfn` builds it but does not scaffold it. + The **TypeScript** flavour (`npm install` is the whole toolchain) is typed end to end (protobuf-es generated types, `tsc --noEmit` in the test gate), and its greeting is fetched with the platform's own `fetch()`, which the @@ -118,10 +143,6 @@ is in the tested set, and none needs a world change: measurement is a 27 KB component. `protoc-gen-mbt` for the codec, its well-known types unverified. A guest must never `println` (it imports `spectest.print_char`). The spike is tracked in #155. -- **Odin**: its `wasi_wasm32` target over the c flavour's C bindings through - Odin's foreign interface, linked by `zig cc` and wrapped like the c guest; - nanopb through the FFI or a small hand-written codec. The spike is tracked - in #155. - **D**: wit-bindgen's `d` backend (since 0.61.0) with `ldc2 -betterC`, the core module wrapped like a Go guest; LDC 1.43 brings druntime to wasip1 and wasip2; nanopb for the codec. diff --git a/docs/one-pager-language-support.md b/docs/one-pager-language-support.md index f58cc099..453e45ec 100644 --- a/docs/one-pager-language-support.md +++ b/docs/one-pager-language-support.md @@ -2,7 +2,7 @@ * Owner: Jonasz Małecki (@jonasz-lasut) * Reviewers: Function WASM Maintainers -* Status: Draft, revision 0.5 +* Status: Draft, revision 0.6 Which languages a function-wasm module can be written in today, which could come next and at what cost, which are blocked and by what, and what @@ -49,7 +49,12 @@ egress over `wasi:http@0.2` behind the same `*http.Client`; `go build` still emits a wasip1 reactor, and `guestfn build` embeds the world and wraps it with the runtime's own adapter (no componentize-go, no wasm-tools). The module's size and compile cost did not move (~74 MB, ~2 s). The Go, C and -Zig rows below describe their v1 era; no scaffold is left on ABI v1. +Zig rows below describe their v1 era; no scaffold is left on ABI v1. Odin +joined on 2026-10-07 as an example only, after #155's spike +(`examples/hello-odin`, ~71 KB): the `c` flavour's bindings and nanopb codec +through Odin's foreign interface, a freestanding wasm32 object linked by +`zig cc` and wrapped by `guestfn build` through the `c` path; the decision +of that day is no further scaffolds unless an issue asks for one. ## What the host requires From 5e8fa500cc43146d4913a02cad547187a6f54431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonasz=20Ma=C5=82ecki?= Date: Wed, 7 Oct 2026 16:13:18 +0200 Subject: [PATCH 4/4] chore(examples): name hello-odin's fixture response.txt --- examples/hello-odin/example/composition-egress.yaml | 2 +- examples/hello-odin/example/fixtures/{en => response.txt} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/hello-odin/example/fixtures/{en => response.txt} (100%) diff --git a/examples/hello-odin/example/composition-egress.yaml b/examples/hello-odin/example/composition-egress.yaml index f7e6692f..df3b06de 100644 --- a/examples/hello-odin/example/composition-egress.yaml +++ b/examples/hello-odin/example/composition-egress.yaml @@ -25,4 +25,4 @@ spec: manifestPath: example/wasmfn.local.yaml config: # The fixture server render.sh starts, serving example/fixtures/. - greetingUrl: http://127.0.0.1:9480/en + greetingUrl: http://127.0.0.1:9480/response.txt diff --git a/examples/hello-odin/example/fixtures/en b/examples/hello-odin/example/fixtures/response.txt similarity index 100% rename from examples/hello-odin/example/fixtures/en rename to examples/hello-odin/example/fixtures/response.txt