diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42befb43..9728b104 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,28 +13,24 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Go + - name: Install Go uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.25' - - name: Setup TinyGo - uses: acifani/setup-tinygo@v2 - with: - tinygo-version: '0.35.0' + - name: Install latest Rust stable toolchain + uses: dtolnay/rust-toolchain@stable - - name: Setup Spin - uses: fermyon/actions/spin/setup@v1 - with: - version: "v3.1.2" + - name: Install componentize-go + # TODO: Switch to an upstream (pre-built) release once new one is + # available and includes + # https://github.com/bytecodealliance/componentize-go/pull/35 + run: cargo install --locked --git https://github.com/dicej/componentize-go --rev fad2c00f - - name: Setup Wasmtime - uses: bytecodealliance/actions/wasmtime/setup@v1 + - name: Install Spin + uses: fermyon/actions/spin/setup@v1 with: - version: "28.0.0" - - - name: Run unit tests - run: make test + version: "v3.6.2" - name: Run integration tests run: make test-integration diff --git a/.gitignore b/.gitignore index 32e954b6..2c6315af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .spin -main.wasm +*.wasm */sdk-version-go.c diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..b73c13d3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +## Generating the WIT bindings + +Whenever WIT files are changed, added to, or removed from the `wit` directory, the bindings in `internal` should be regenerated. + +### Prerequisites + +- Make +- BASH or compatible shell +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version + +### Run +```sh +make regenerate-bindings +``` diff --git a/Makefile b/Makefile index b26772b4..61f286d0 100644 --- a/Makefile +++ b/Makefile @@ -1,94 +1,27 @@ -VERSION = 2.3.0-pre0 - -# ---------------------------------------------------------------------- -# Test -# ---------------------------------------------------------------------- -.PHONY: test -test: - tinygo test -target=wasip1 -gc=leaking -buildmode=c-shared -v ./http - tinygo test -target=wasip1 -gc=leaking -buildmode=c-shared -v ./redis - .PHONY: test-integration test-integration: go test -v -count=1 . -# ---------------------------------------------------------------------- -# Generate C bindings -# ---------------------------------------------------------------------- -GENERATED_SPIN_VARIABLES = variables/spin-config.c variables/spin-config.h -GENERATED_OUTBOUND_HTTP = http/wasi-outbound-http.c http/wasi-outbound-http.h -GENERATED_SPIN_HTTP = http/spin-http.c http/spin-http.h -GENERATED_OUTBOUND_REDIS = redis/outbound-redis.c redis/outbound-redis.h -GENERATED_SPIN_REDIS = redis/spin-redis.c redis/spin-redis.h -GENERATED_KEY_VALUE = kv/key-value.c kv/key-value.h -GENERATED_SQLITE = sqlite/sqlite.c sqlite/sqlite.h -GENERATED_LLM = llm/llm.c llm/llm.h -GENERATED_OUTBOUND_MYSQL = mysql/outbound-mysql.c mysql/outbound-mysql.h -GENERATED_OUTBOUND_PG = pg/outbound-pg.c pg/outbound-pg.h - -SDK_VERSION_SOURCE_FILE = sdk_version/sdk-version-go-template.c - -# NOTE: Please update this list if you add a new directory to the SDK: -SDK_VERSION_DEST_FILES = variables/sdk-version-go.c http/sdk-version-go.c \ - kv/sdk-version-go.c redis/sdk-version-go.c \ - sqlite/sdk-version-go.c llm/sdk-version-go.c - -# NOTE: To generate the C bindings you need to install a forked version of wit-bindgen. -# -# cargo install wit-bindgen-cli --git https://github.com/fermyon/wit-bindgen-backport --rev "b89d5079ba5b07b319631a1b191d2139f126c976" -# -.PHONY: generate -generate: $(GENERATED_OUTBOUND_HTTP) $(GENERATED_SPIN_HTTP) -generate: $(GENERATED_OUTBOUND_REDIS) $(GENERATED_SPIN_REDIS) -generate: $(GENERATED_SPIN_VARIABLES) $(GENERATED_KEY_VALUE) -generate: $(GENERATED_SQLITE) $(GENERATED_LLM) -generate: $(GENERATED_OUTBOUND_MYSQL) $(GENERATED_OUTBOUND_PG) -generate: $(SDK_VERSION_DEST_FILES) - -$(SDK_VERSION_DEST_FILES): $(SDK_VERSION_SOURCE_FILE) - export commit="$$(git rev-parse HEAD)"; \ - sed -e "s/{{VERSION}}/${VERSION}/" -e "s/{{COMMIT}}/$${commit}/" < $< > $@ - -$(GENERATED_SPIN_VARIABLES): - wit-bindgen c --import wit/spin-config.wit --out-dir ./variables - -$(GENERATED_OUTBOUND_HTTP): - wit-bindgen c --import wit/wasi-outbound-http.wit --out-dir ./http - -$(GENERATED_SPIN_HTTP): - wit-bindgen c --export wit/spin-http.wit --out-dir ./http - -$(GENERATED_OUTBOUND_REDIS): - wit-bindgen c --import wit/outbound-redis.wit --out-dir ./redis - -$(GENERATED_SPIN_REDIS): - wit-bindgen c --export wit/spin-redis.wit --out-dir ./redis - -$(GENERATED_KEY_VALUE): - wit-bindgen c --import wit/key-value.wit --out-dir ./kv - -$(GENERATED_SQLITE): - wit-bindgen c --import wit/sqlite.wit --out-dir ./sqlite - -$(GENERATED_LLM): - wit-bindgen c --import wit/llm.wit --out-dir ./llm - -$(GENERATED_OUTBOUND_MYSQL): - wit-bindgen c --import wit/outbound-mysql.wit --out-dir ./mysql - -$(GENERATED_OUTBOUND_PG): - wit-bindgen c --import wit/outbound-pg.wit --out-dir ./pg - -# ---------------------------------------------------------------------- -# Cleanup -# ---------------------------------------------------------------------- -.PHONY: clean -clean: - rm -f $(GENERATED_SPIN_CONFIG) - rm -f $(GENERATED_OUTBOUND_HTTP) $(GENERATED_SPIN_HTTP) - rm -f $(GENERATED_OUTBOUND_REDIS) $(GENERATED_SPIN_REDIS) - rm -f $(GENERATED_KEY_VALUE) $(GENERATED_SQLITE) - rm -f $(GENERATED_LLM) - rm -f $(GENERATED_OUTBOUND_MYSQL) - rm -f $(GENERATED_SDK_VERSION) - rm -f $(SDK_VERSION_DEST_FILES) +.PHONY: build-examples +build-examples: + for x in examples/*; do echo $$x && (cd $$x && spin build) || exit 1; done + +.PHONY: regenerate-bindings +regenerate-bindings: + find $$(pwd)/internal/ \ + -mindepth 1 \ + -maxdepth 1 \ + -type d \ + ! -name 'db' \ + ! -name 'export_fermyon_spin_inbound_redis' \ + ! -name 'export_wasi_http_0_2_0_incoming_handler' \ + -exec rm -rf {} + + componentize-go \ + --ignore-toml-files \ + -w "fermyon:spin/http-trigger@3.0.0" \ + -w "fermyon:spin/redis-trigger" \ + -d ./wit \ + bindings \ + --format \ + -o internal \ + --pkg-name github.com/spinframework/spin-go-sdk/v3/internal diff --git a/README.md b/README.md new file mode 100644 index 00000000..20fe9432 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +## The Go SDK for Spin + +This is an SDK for developing [Spin](https://github.com/spinframework/spin) applications using the Go programming language. + +> Note: This SDK temporarily relies on [a fork](https://github.com/dicej/componentize-go) of [componentize-go](https://github.com/bytecodealliance/componentize-go) until [this PR](https://github.com/bytecodealliance/componentize-go/pull/35) has been accepted. For the time being, please install [this build](https://github.com/dicej/componentize-go/releases/tag/canary). + +## Example + +```go +package main + +import ( + "fmt" + "net/http" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Hello, Spin!") + }) +} + +func main() {} +``` + +See the [examples](./examples) directory for more examples. diff --git a/componentize-go.toml b/componentize-go.toml new file mode 100644 index 00000000..7b1985d5 --- /dev/null +++ b/componentize-go.toml @@ -0,0 +1,2 @@ +worlds = [ "fermyon:spin/http-trigger@3.0.0" ] +wit_paths = [ "wit" ] diff --git a/examples/http-outbound/README.md b/examples/http-outbound/README.md index 974491a8..c99bfdc8 100644 --- a/examples/http-outbound/README.md +++ b/examples/http-outbound/README.md @@ -1,25 +1,19 @@ -# Making outbound HTTP requests from TinyGo Spin components +# Making outbound HTTP requests from Go Spin components -The TinyGo SDK for building Spin components allows us to granularly allow -components to send HTTP requests to certain hosts. This is configured in -`spin.toml`. - -> For more information and examples for using TinyGo with WebAssembly, check -> [the official TinyGo documentation](https://tinygo.org/docs/guides/webassembly/) -> and -> [the Wasm examples](https://github.com/tinygo-org/tinygo/tree/release/src/examples/wasm). +The Go SDK for building Spin components allows us to granularly allow components +to send HTTP requests to certain hosts. This is configured in `spin.toml`. Creating and sending HTTP requests from Spin components closely follows the Go -`net/http` API. See [tinygo-hello/main.go](./tinygo-hello/main.go). +`net/http` API. See [hello/main.go](./hello/main.go). -Building this as a WebAssembly module can be done using the `tinygo` compiler: +Building this as a WebAssembly module can be done using `spin build`: ```shell $ spin build -Building component outbound-http-to-same-app with `tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm .` -Working directory: "./outbound-http-to-same-app" -Building component tinygo-hello with `tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm .` -Working directory: "./tinygo-hello" +Building component http-to-same-app with `componentize-go --world http-trigger build` +Working directory: "./http-to-same-app" +Building component hello with `componentize-go --world http-trigger build` +Working directory: "./hello" Finished building all Spin components ``` @@ -30,11 +24,11 @@ HTTP requests to, otherwise sending the request results in an error: Cannot send HTTP request: Destination not allowed: ``` -The `tinygo-hello` component has the following allowed hosts set: +The `hello` component has the following allowed hosts set: ```toml -[component.tinygo-hello] -source = "tinygo-hello/main.wasm" +[component.hello] +source = "hello/main.wasm" allowed_outbound_hosts = [ "https://random-data-api.fermyon.app", "https://postman-echo.com", @@ -43,7 +37,7 @@ allowed_outbound_hosts = [ And the `outbound-http-to-same-app` uses the dedicated `self` keyword to enable making a request to another component in this same app, via a relative path (in this case, the component -is `tinygo-hello` at `/hello`): +is `hello` at `/hello`): ```toml [component.outbound-http-to-same-app] @@ -70,7 +64,7 @@ date: Thu, 26 Oct 2023 18:26:17 GMT ... ``` -As well as via the `/outbound-http-to-same-app` path to verify outbound http to the `tinygo-hello` component: +As well as via the `/outbound-http-to-same-app` path to verify outbound http to the `hello` component: ```shell $ curl -i localhost:3000/outbound-http-to-same-app diff --git a/examples/http-outbound/hello/go.mod b/examples/http-outbound/hello/go.mod index 6d0204ed..b52d93a6 100644 --- a/examples/http-outbound/hello/go.mod +++ b/examples/http-outbound/hello/go.mod @@ -1,9 +1,11 @@ -module examples/http-outbound/hello +module github.com/spinframework/spin-go-sdk/v3/examples/http-outbound/hello -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../../ diff --git a/examples/http-outbound/hello/go.sum b/examples/http-outbound/hello/go.sum index 096c54e6..7b8de78d 100644 --- a/examples/http-outbound/hello/go.sum +++ b/examples/http-outbound/hello/go.sum @@ -1,2 +1,4 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/http-outbound/hello/main.go b/examples/http-outbound/hello/main.go index d03faa5e..059ffab0 100644 --- a/examples/http-outbound/hello/main.go +++ b/examples/http-outbound/hello/main.go @@ -6,7 +6,7 @@ import ( "net/http" "os" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" ) func init() { diff --git a/examples/http-outbound/http-to-same-app/go.mod b/examples/http-outbound/http-to-same-app/go.mod index 3ced5b01..b52d93a6 100644 --- a/examples/http-outbound/http-to-same-app/go.mod +++ b/examples/http-outbound/http-to-same-app/go.mod @@ -1,9 +1,11 @@ -module examples/http-outbound/http-to-same-app +module github.com/spinframework/spin-go-sdk/v3/examples/http-outbound/hello -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../../ diff --git a/examples/http-outbound/http-to-same-app/go.sum b/examples/http-outbound/http-to-same-app/go.sum index 096c54e6..7b8de78d 100644 --- a/examples/http-outbound/http-to-same-app/go.sum +++ b/examples/http-outbound/http-to-same-app/go.sum @@ -1,2 +1,4 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/http-outbound/http-to-same-app/main.go b/examples/http-outbound/http-to-same-app/main.go index 27c9c89d..24eb804b 100644 --- a/examples/http-outbound/http-to-same-app/main.go +++ b/examples/http-outbound/http-to-same-app/main.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" ) func init() { diff --git a/examples/http-outbound/spin.toml b/examples/http-outbound/spin.toml index 3b5f585b..05764eb7 100644 --- a/examples/http-outbound/spin.toml +++ b/examples/http-outbound/spin.toml @@ -2,7 +2,7 @@ spin_manifest_version = 2 [application] authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go that performs outbound HTTP requests." +description = "A simple Spin application written in Go that performs outbound HTTP requests." name = "http-outbound-example" version = "1.0.0" @@ -22,7 +22,7 @@ allowed_outbound_hosts = [ ] [component.hello.build] workdir = "hello" -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" [component.http-to-same-app] source = "http-to-same-app/main.wasm" @@ -30,4 +30,5 @@ source = "http-to-same-app/main.wasm" allowed_outbound_hosts = ["http://self"] [component.http-to-same-app.build] workdir = "http-to-same-app" -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" + diff --git a/examples/http-router/README.md b/examples/http-router/README.md index 1a138fe9..3bd50626 100644 --- a/examples/http-router/README.md +++ b/examples/http-router/README.md @@ -1,8 +1,7 @@ -# Spin component in TinyGo using the Spin router +# Spin component in Go using the Spin router ```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up +$ spin build --up ``` The application can now receive requests on `http://localhost:3000`: diff --git a/examples/http-router/go.mod b/examples/http-router/go.mod index 7856c3ba..4a0b91cd 100644 --- a/examples/http-router/go.mod +++ b/examples/http-router/go.mod @@ -1,9 +1,11 @@ -module examples/http-router +module github.com/spinframework/spin-go-sdk/v3/examples/http-router -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/http-router/go.sum b/examples/http-router/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/http-router/go.sum +++ b/examples/http-router/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/http-router/main.go b/examples/http-router/main.go index 3c4fd482..41bd03a1 100644 --- a/examples/http-router/main.go +++ b/examples/http-router/main.go @@ -4,7 +4,7 @@ import ( "fmt" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" ) func init() { diff --git a/examples/http-router/spin.toml b/examples/http-router/spin.toml index 99630052..162c6c1a 100644 --- a/examples/http-router/spin.toml +++ b/examples/http-router/spin.toml @@ -2,7 +2,7 @@ spin_manifest_version = 2 [application] authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." +description = "A simple Spin application written in Go." name = "hello-router-example" version = "1.0.0" @@ -13,4 +13,4 @@ component = "hello" [component.hello] source = "main.wasm" [component.hello.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" diff --git a/examples/http/README.md b/examples/http/README.md index 741cddc6..72ecc137 100644 --- a/examples/http/README.md +++ b/examples/http/README.md @@ -1,35 +1,15 @@ -# Spin component in TinyGo - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version + +# Usage +Build and run the Spin app: +```sh +spin up --build ``` -The application can now receive requests on `http://localhost:3000`: - -```shell -$ curl -i localhost:3000/hello -HTTP/1.1 200 OK -content-type: text/plain -foo: bar -content-length: 440 -date: Thu, 26 Oct 2023 18:18:19 GMT - -== REQUEST == -URL: http://localhost:3000/hello -Method: GET -Headers: - "Host": "localhost:3000" - "User-Agent": "curl/8.1.2" - "Spin-Full-Url": "http://localhost:3000/hello" - "Spin-Base-Path": "/" - "Spin-Client-Addr": "127.0.0.1:52164" - "Accept": "*/*" - "Spin-Path-Info": "" - "Spin-Matched-Route": "/hello" - "Spin-Raw-Component-Route": "/hello" - "Spin-Component-Route": "/hello" -Body: -== RESPONSE == -Hello Fermyon! +In another terminal window, you can interact with the Spin app: +```sh +curl localhost:3000/hello ``` diff --git a/examples/http/go.mod b/examples/http/go.mod index c3c31c53..3ab20ea5 100644 --- a/examples/http/go.mod +++ b/examples/http/go.mod @@ -1,9 +1,11 @@ -module examples/http +module github.com/spinframework/spin-go-sdk/v3/examples/http -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/http/go.sum b/examples/http/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/http/go.sum +++ b/examples/http/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/http/main.go b/examples/http/main.go index 50212816..596779e3 100644 --- a/examples/http/main.go +++ b/examples/http/main.go @@ -2,10 +2,9 @@ package main import ( "fmt" - "io" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" ) func init() { @@ -13,23 +12,9 @@ func init() { w.Header().Set("Content-Type", "text/plain") w.Header().Set("foo", "bar") - fmt.Fprintln(w, "== REQUEST ==") - fmt.Fprintln(w, "URL: ", r.URL) - fmt.Fprintln(w, "Method: ", r.Method) - fmt.Fprintln(w, "Headers:") - for k, v := range r.Header { - fmt.Fprintf(w, " %q: %q \n", k, v[0]) - } - - body, err := io.ReadAll(r.Body) - if err != nil { - fmt.Fprintln(w, "Body Error: ", err) - } else { - fmt.Fprintln(w, "Body: ", string(body)) - } - fmt.Fprintln(w, "== RESPONSE ==") - fmt.Fprintln(w, "Hello Fermyon!") + fmt.Fprintln(w, "Hello spinframework!") + fmt.Fprintln(w, "Hello again spinframework!") }) } diff --git a/examples/http/spin.toml b/examples/http/spin.toml index 72a0d5df..c4403dc9 100644 --- a/examples/http/spin.toml +++ b/examples/http/spin.toml @@ -1,8 +1,8 @@ spin_manifest_version = 2 [application] -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." +authors = ["Rajat Jindal "] +description = "A simple Spin application written in Go." name = "hello-example" version = "1.0.0" @@ -13,4 +13,4 @@ component = "hello" [component.hello] source = "main.wasm" [component.hello.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" diff --git a/examples/key-value/README.md b/examples/key-value/README.md index 11487602..40751739 100644 --- a/examples/key-value/README.md +++ b/examples/key-value/README.md @@ -1,36 +1,20 @@ -# Spin Key Value component in TinyGo - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version + +# Usage +Build and run the Spin app: +```sh +spin up --build ``` -The application can now receive requests on `http://localhost:3000`: - -```shell -$ curl -i -X POST -d "ok!" localhost:3000/test -HTTP/1.1 200 OK -content-length: 0 -date: Tue, 25 Apr 2023 14:25:43 GMT - -$ curl -i -X GET localhost:3000/test -HTTP/1.1 200 OK -content-length: 3 -date: Tue, 25 Apr 2023 14:25:54 GMT - -ok! - -$ curl -i -X DELETE localhost:3000/test -HTTP/1.1 200 OK -content-length: 0 -date: Tue, 25 Apr 2023 14:26:30 GMT - -$ curl -i -X GET localhost:3000/test -HTTP/1.1 500 Internal Server Error -content-type: text/plain; charset=utf-8 -x-content-type-options: nosniff -content-length: 12 -date: Tue, 25 Apr 2023 14:26:32 GMT +In another terminal window, you can interact with the Spin app: +```sh +curl localhost:3000/hello +``` -no such key +You should receive the following output: +``` +["foo"] ``` diff --git a/examples/key-value/go.mod b/examples/key-value/go.mod index fa7b05b3..9cf933b2 100644 --- a/examples/key-value/go.mod +++ b/examples/key-value/go.mod @@ -1,9 +1,11 @@ -module examples/key-value +module github.com/spinframework/spin-go-sdk/v3/examples/key-value -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/key-value/go.sum b/examples/key-value/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/key-value/go.sum +++ b/examples/key-value/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/key-value/main.go b/examples/key-value/main.go index b61b63df..9ac000e8 100644 --- a/examples/key-value/main.go +++ b/examples/key-value/main.go @@ -1,70 +1,48 @@ package main import ( - "io" + "encoding/json" + "fmt" "net/http" - spin_http "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/kv" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/kv" ) func init() { - // handler for the http trigger - spin_http.Handle(func(w http.ResponseWriter, r *http.Request) { - store, err := kv.OpenStore("default") + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + store, err := kv.OpenDefault() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - defer store.Close() - body, err := io.ReadAll(r.Body) + err = store.Set("foo", []byte("bar")) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - switch r.Method { - case http.MethodPost: - err := store.Set(r.URL.Path, body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.WriteHeader(http.StatusOK) - case http.MethodGet: - value, err := store.Get(r.URL.Path) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + value, err := store.Get("foo") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } - w.WriteHeader(http.StatusOK) - w.Write(value) - case http.MethodDelete: - if err := store.Delete(r.URL.Path); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + if string(value) != "bar" { + http.Error(w, fmt.Sprintf("expected: %q, got: %q", "bar", value), http.StatusInternalServerError) + return + } - w.WriteHeader(http.StatusOK) - case http.MethodHead: - exists, err := store.Exists(r.URL.Path) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + keys, err := store.GetKeys() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } - if exists { - w.WriteHeader(http.StatusOK) - return - } + w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusNotFound) - default: - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - } + _ = json.NewEncoder(w).Encode(keys) }) } diff --git a/examples/key-value/spin.toml b/examples/key-value/spin.toml index 3bda7ec2..a6c0ecfa 100644 --- a/examples/key-value/spin.toml +++ b/examples/key-value/spin.toml @@ -1,16 +1,17 @@ spin_manifest_version = 2 [application] -authors = ["Fermyon Engineering "] -name = "key-value-example" -version = "0.1.0" +authors = ["Rajat Jindal "] +description = "A simple Spin application written in Go." +name = "hello-kv" +version = "1.0.0" [[trigger.http]] -route = "/..." -component = "key-value" +route = "/hello" +component = "hello" -[component.key-value] +[component.hello] source = "main.wasm" key_value_stores = ["default"] -[component.key-value.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +[component.hello.build] +command = "componentize-go build" diff --git a/examples/llm/go.mod b/examples/llm/go.mod index fd0c993e..3e71047b 100644 --- a/examples/llm/go.mod +++ b/examples/llm/go.mod @@ -1,9 +1,11 @@ -module examples/llm +module github.com/spinframework/spin-go-sdk/v3/examples/llm -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/llm/go.sum b/examples/llm/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/llm/go.sum +++ b/examples/llm/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/llm/main.go b/examples/llm/main.go index 55dae4ec..c0712980 100644 --- a/examples/llm/main.go +++ b/examples/llm/main.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/llm" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/llm" ) func init() { diff --git a/examples/llm/spin.toml b/examples/llm/spin.toml index 218c2dfe..bdfe3bb7 100644 --- a/examples/llm/spin.toml +++ b/examples/llm/spin.toml @@ -15,5 +15,5 @@ source = "main.wasm" allowed_outbound_hosts = [] ai_models = ["llama2-chat", "all-minilm-l6-v2"] [component.llm.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" watch = ["**/*.go", "go.mod"] diff --git a/examples/mqtt-outbound/.gitignore b/examples/mqtt-outbound/.gitignore new file mode 100644 index 00000000..b5650104 --- /dev/null +++ b/examples/mqtt-outbound/.gitignore @@ -0,0 +1,2 @@ +main.wasm +.spin/ diff --git a/examples/mqtt-outbound/README.md b/examples/mqtt-outbound/README.md new file mode 100644 index 00000000..1c8b2054 --- /dev/null +++ b/examples/mqtt-outbound/README.md @@ -0,0 +1,32 @@ +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**docker**](https://docs.docker.com/get-started/get-docker/) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version + +# Usage +In one terminal window, run: +```sh +# Note that the `-d` flag is intentionally omitted +docker compose up +``` + +In another terminal, you'll run your Spin app: +```sh +spin up --build +``` + +In yet another terminal, you'll interact with the Spin app: +```sh +curl localhost:3000/publish +``` + +You will see logs appear in the `docker compose` window that look something like this: +```sh +$ docker compose up +... +broker | 1754324646: New connection from 172.18.0.1:36970 on port 1883. +broker | 1754324646: New client connected from 172.18.0.1:36970 as client001 (p2, c1, k30, u'user'). +subscriber | telemetry Eureka! +broker | 1754324646: Client client001 closed its connection. +``` diff --git a/examples/mqtt-outbound/compose.yaml b/examples/mqtt-outbound/compose.yaml new file mode 100644 index 00000000..d7d82070 --- /dev/null +++ b/examples/mqtt-outbound/compose.yaml @@ -0,0 +1,15 @@ +services: + mosquitto: + image: eclipse-mosquitto:2.0.22 + container_name: broker + ports: + - "1883:1883" + command: mosquitto -c /mosquitto-no-auth.conf + + subscriber: + image: eclipse-mosquitto:2.0.22 + container_name: subscriber + depends_on: + - mosquitto + command: mosquitto_sub -h mosquitto -t '#' -v + restart: "no" # Clean up container when stopped \ No newline at end of file diff --git a/examples/mqtt-outbound/go.mod b/examples/mqtt-outbound/go.mod new file mode 100644 index 00000000..38f5229a --- /dev/null +++ b/examples/mqtt-outbound/go.mod @@ -0,0 +1,11 @@ +module github.com/spinframework/spin-go-sdk/v3/examples/mqtt-outbound + +go 1.25.5 + +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) + +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/mqtt-outbound/go.sum b/examples/mqtt-outbound/go.sum new file mode 100644 index 00000000..b5bca15f --- /dev/null +++ b/examples/mqtt-outbound/go.sum @@ -0,0 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/mqtt-outbound/main.go b/examples/mqtt-outbound/main.go new file mode 100644 index 00000000..c515959c --- /dev/null +++ b/examples/mqtt-outbound/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "net/http" + "os" + "strconv" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/mqtt" +) + +func main() {} + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + addr := os.Getenv("MQTT_ADDRESS") + usr := os.Getenv("MQTT_USERNAME") + pass := os.Getenv("MQTT_PASSWORD") + keepAliveStr := os.Getenv("MQTT_KEEP_ALIVE_INTERVAL") + topic := os.Getenv("MQTT_TOPIC") + + keepAlive, err := strconv.Atoi(keepAliveStr) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("MQTT_KEEP_ALIVE_INTERVAL is not valid: must be an integer")) + } + + conn, err := mqtt.OpenConnection(addr, usr, pass, uint64(keepAlive)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + } + + message := []byte("Eureka!") + + if err := conn.Publish(topic, message, mqtt.QosAtMostOnce); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + } + + w.Write([]byte("Message successfully published!\n")) + }) +} diff --git a/examples/mqtt-outbound/spin.toml b/examples/mqtt-outbound/spin.toml new file mode 100644 index 00000000..ee7f6fef --- /dev/null +++ b/examples/mqtt-outbound/spin.toml @@ -0,0 +1,20 @@ +spin_manifest_version = 2 + +[application] +name = "go-mqtt-outbound-example" +version = "0.1.0" +authors = ["Andrew Steurer <94206073+asteurer@users.noreply.github.com>"] +description = "Using Spin with MQTT" + +[[trigger.http]] +route = "/publish" +component = "mqtt-outbound" + +[component.mqtt-outbound] +source = "main.wasm" +# To test anonymous MQTT authentication, remove the values from MQTT_USERNAME and MQTT_PASSWORD env variables. +environment = { MQTT_ADDRESS = "mqtt://127.0.0.1:1883?client_id=client001", MQTT_USERNAME = "user", MQTT_PASSWORD = "password", MQTT_KEEP_ALIVE_INTERVAL = "30", MQTT_TOPIC = "telemetry" } +allowed_outbound_hosts = ["mqtt://127.0.0.1:1883"] +[component.mqtt-outbound.build] +command = "componentize-go build" +watch = ["**/*.go", "go.mod"] diff --git a/examples/mysql-outbound/README.md b/examples/mysql-outbound/README.md new file mode 100644 index 00000000..dc11e9bf --- /dev/null +++ b/examples/mysql-outbound/README.md @@ -0,0 +1,31 @@ +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**docker**](https://docs.docker.com/get-started/get-docker/) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version + +# Usage +In a terminal window, use the below command to run MySQL: +```sh +docker compose up -d +``` + +Then, you'll build and run your Spin app: +```sh +spin up --build +``` + +In another terminal window, you can interact with the Spin app: +```sh +curl localhost:3000 +``` + +You should see the output: +```json +[{"ID":1,"Name":"Splodge","Prey":null,"IsFinicky":false},{"ID":2,"Name":"Kiki","Prey":"Cicadas","IsFinicky":false},{"ID":3,"Name":"Slats","Prey":"Temptations","IsFinicky":true},{"ID":4,"Name":"Maya","Prey":"bananas","IsFinicky":true},{"ID":5,"Name":"Copper","Prey":"Foxes","IsFinicky":false}] +``` + +To stop and clean up the MySQL container, run the following: +```sh +docker compose down -v +``` diff --git a/examples/mysql-outbound/compose.yaml b/examples/mysql-outbound/compose.yaml new file mode 100644 index 00000000..6d9c4430 --- /dev/null +++ b/examples/mysql-outbound/compose.yaml @@ -0,0 +1,24 @@ +services: + mysql: + image: mysql:8 + container_name: mysql + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: spin_data + MYSQL_USER: spin + MYSQL_PASSWORD: spin + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + - ./init.sql:/docker-entrypoint-initdb.d/init.sql + networks: + - mysql_network + +volumes: + mysql_data: + +networks: + mysql_network: + driver: bridge \ No newline at end of file diff --git a/examples/mysql-outbound/go.mod b/examples/mysql-outbound/go.mod index 3806168e..03746c62 100644 --- a/examples/mysql-outbound/go.mod +++ b/examples/mysql-outbound/go.mod @@ -1,9 +1,11 @@ -module examples/mysql-outbound +module github.com/spinframework/spin-go-sdk/v3/examples/mysql-outbound -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/mysql-outbound/go.sum b/examples/mysql-outbound/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/mysql-outbound/go.sum +++ b/examples/mysql-outbound/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/mysql-outbound/db/pets.sql b/examples/mysql-outbound/init.sql similarity index 83% rename from examples/mysql-outbound/db/pets.sql rename to examples/mysql-outbound/init.sql index bbf91d68..c2d5384a 100644 --- a/examples/mysql-outbound/db/pets.sql +++ b/examples/mysql-outbound/init.sql @@ -1,3 +1,5 @@ +CREATE DATABASE IF NOT EXISTS spin_data; +USE spin_data; CREATE TABLE pets (id INT PRIMARY KEY, name VARCHAR(100) NOT NULL, prey VARCHAR(100), is_finicky BOOL NOT NULL); INSERT INTO pets VALUES (1, 'Splodge', NULL, false); INSERT INTO pets VALUES (2, 'Kiki', 'Cicadas', false); diff --git a/examples/mysql-outbound/main.go b/examples/mysql-outbound/main.go index 08c49e7c..f20e9091 100644 --- a/examples/mysql-outbound/main.go +++ b/examples/mysql-outbound/main.go @@ -6,8 +6,8 @@ import ( "net/http" "os" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/mysql" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/mysql" ) type Pet struct { @@ -27,8 +27,12 @@ func init() { db := mysql.Open(addr) defer db.Close() - _, err := db.Query("REPLACE INTO pets VALUES (?, 'Maya', ?, ?);", 4, "bananas", true) - if err != nil { + if _, err := db.Query("REPLACE INTO pets VALUES (?, 'Maya', ?, ?);", 4, "bananas", true); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if _, err := db.Exec("INSERT INTO pets VALUES (?, ?, ?, ?)", 5, "Copper", "Foxes", false); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/examples/mysql-outbound/spin.toml b/examples/mysql-outbound/spin.toml index dcb15df9..6c57bd93 100644 --- a/examples/mysql-outbound/spin.toml +++ b/examples/mysql-outbound/spin.toml @@ -1,19 +1,19 @@ spin_manifest_version = 2 [application] -authors = ["Patrick Jiang "] -description = "" -name = "mysql-outbound-example" +name = "go-mysql-outbound-example" version = "0.1.0" +authors = ["Andrew Steurer <94206073+asteurer@users.noreply.github.com>"] +description = "Using Spin with MySQL" [[trigger.http]] route = "/..." component = "mysql" [component.mysql] -environment = { DB_URL = "mysql://spin:spin@127.0.0.1/spin_dev" } +environment = { DB_URL = "mysql://spin:spin@127.0.0.1/spin_data" } source = "main.wasm" allowed_outbound_hosts = ["mysql://127.0.0.1"] [component.mysql.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" watch = ["**/*.go", "go.mod"] diff --git a/examples/pg-outbound/go.mod b/examples/pg-outbound/go.mod index adcf1136..bcb32f67 100644 --- a/examples/pg-outbound/go.mod +++ b/examples/pg-outbound/go.mod @@ -1,9 +1,11 @@ -module examples/pg-outbound +module github.com/spinframework/spin-go-sdk/v3/examples/pg-outbound -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/pg-outbound/go.sum b/examples/pg-outbound/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/pg-outbound/go.sum +++ b/examples/pg-outbound/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/pg-outbound/main.go b/examples/pg-outbound/main.go index 0f897305..ef2ab975 100644 --- a/examples/pg-outbound/main.go +++ b/examples/pg-outbound/main.go @@ -6,8 +6,8 @@ import ( "net/http" "os" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/pg" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/pg" ) type Pet struct { diff --git a/examples/pg-outbound/spin.toml b/examples/pg-outbound/spin.toml index ca8739b2..80005a55 100644 --- a/examples/pg-outbound/spin.toml +++ b/examples/pg-outbound/spin.toml @@ -15,5 +15,5 @@ environment = { DB_URL = "host=localhost user=postgres dbname=spin_dev" } source = "main.wasm" allowed_outbound_hosts = ["postgres://localhost"] [component.pg-outbound.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" watch = ["**/*.go", "go.mod"] diff --git a/examples/redis-outbound/README.md b/examples/redis-outbound/README.md index fdcb43cf..17dd7746 100644 --- a/examples/redis-outbound/README.md +++ b/examples/redis-outbound/README.md @@ -1,18 +1,27 @@ -# Spin component in TinyGo making an outbound http call to Redis +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**docker**](https://docs.docker.com/get-started/get-docker/) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up +# Usage +In one terminal window, you'll run a Redis container: +```sh +docker run -p 6379:6379 redis:8.2 ``` -The application can now receive requests on `http://localhost:3000/publish`: +In another terminal, you'll run your Spin app: +```sh +spin up --build +``` -```shell -$ curl -i localhost:3000/publish -HTTP/1.1 200 OK -content-length: 67 -date: Tue, 29 Nov 2022 07:03:52 GMT +In yet another terminal, you'll interact with the Spin app: +```sh +curl localhost:3000 +``` +You should see the following output: +``` mykey value was: myvalue spin-go-incr value: 1 deleted keys num: 2 diff --git a/examples/redis-outbound/go.mod b/examples/redis-outbound/go.mod index 6cdd8e89..d96fe05d 100644 --- a/examples/redis-outbound/go.mod +++ b/examples/redis-outbound/go.mod @@ -1,9 +1,11 @@ -module examples/redis-outbound +module github.com/spinframework/spin-go-sdk/v3/examples/redis-outbound -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/redis-outbound/go.sum b/examples/redis-outbound/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/redis-outbound/go.sum +++ b/examples/redis-outbound/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/redis-outbound/main.go b/examples/redis-outbound/main.go index 824bdbde..2a09a371 100644 --- a/examples/redis-outbound/main.go +++ b/examples/redis-outbound/main.go @@ -8,8 +8,8 @@ import ( "sort" "strconv" - spin_http "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/redis" + spin_http "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/redis" ) func init() { @@ -26,9 +26,13 @@ func init() { channel := os.Getenv("REDIS_CHANNEL") // payload is the data publish to the redis channel. - payload := []byte(`Hello redis from tinygo!`) + payload := []byte(`Hello redis from Go!`) - rdb := redis.NewClient(addr) + rdb, err := redis.NewClient(addr) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } if err := rdb.Publish(channel, payload); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -66,7 +70,7 @@ func init() { http.Error(w, err.Error(), http.StatusInternalServerError) } else { w.Write([]byte("deleted keys num: ")) - w.Write([]byte(strconv.FormatInt(payload, 10))) + w.Write([]byte(strconv.FormatInt(int64(payload), 10))) w.Write([]byte("\n")) } @@ -140,7 +144,9 @@ func init() { Kind: redis.ResultKindBinary, Val: []byte("hello world"), }}) { + http.Error(w, "unexpected GET result", http.StatusInternalServerError) + fmt.Println() return } }) diff --git a/examples/redis-outbound/spin.toml b/examples/redis-outbound/spin.toml index 80400543..35066139 100644 --- a/examples/redis-outbound/spin.toml +++ b/examples/redis-outbound/spin.toml @@ -1,17 +1,20 @@ spin_manifest_version = 2 [application] -authors = ["Fermyon Engineering "] -name = "redis-outbound-example" +name = "go-redis-outbound-example" version = "0.1.0" +authors = ["Andrew Steurer <94206073+asteurer@users.noreply.github.com>"] +description = "Using Spin with Redis" [[trigger.http]] -route = "/publish" -component = "outbound-redis" +route = "/" +component = "redis-outbound" -[component.outbound-redis] +[component.redis-outbound] source = "main.wasm" -environment = { REDIS_ADDRESS = "redis://127.0.0.1:6379", REDIS_CHANNEL = "messages" } -allowed_outbound_hosts = ["redis://127.0.0.1"] -[component.outbound-redis.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +environment = { REDIS_ADDRESS = "redis://localhost:6379", REDIS_CHANNEL = "messages" } +allowed_outbound_hosts = ["redis://localhost:6379"] + +[component.redis-outbound.build] +command = "componentize-go build" +watch = ["**/*.go", "go.mod"] diff --git a/examples/redis/README.md b/examples/redis/README.md index 67a7174c..d1276828 100644 --- a/examples/redis/README.md +++ b/examples/redis/README.md @@ -1,7 +1,7 @@ -# Spin component in TinyGo using the Redis trigger +# Spin component in Go using the Redis trigger ```shell -$ RUST_LOG=spin=trace spin build --up +$ spin build --up ``` ```shell diff --git a/examples/redis/go.mod b/examples/redis/go.mod index 5f777f66..1b67c8d7 100644 --- a/examples/redis/go.mod +++ b/examples/redis/go.mod @@ -1,9 +1,11 @@ -module examples/redis +module github.com/spinframework/spin-go-sdk/v3/examples/redis -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/redis/go.sum b/examples/redis/go.sum index e69de29b..b5bca15f 100644 --- a/examples/redis/go.sum +++ b/examples/redis/go.sum @@ -0,0 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/redis/main.go b/examples/redis/main.go index db709a97..32511798 100644 --- a/examples/redis/main.go +++ b/examples/redis/main.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/spinframework/spin-go-sdk/v2/redis" + "github.com/spinframework/spin-go-sdk/v3/redis" ) func init() { diff --git a/examples/redis/spin.toml b/examples/redis/spin.toml index 2c1458f6..ca563c15 100644 --- a/examples/redis/spin.toml +++ b/examples/redis/spin.toml @@ -16,4 +16,5 @@ component = "echo-message" [component.echo-message] source = "main.wasm" [component.echo-message.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go --world fermyon:spin/redis-trigger build" + diff --git a/examples/sqlite/go.mod b/examples/sqlite/go.mod index 6f24121b..65b8592b 100644 --- a/examples/sqlite/go.mod +++ b/examples/sqlite/go.mod @@ -1,9 +1,11 @@ -module examples/sqlite +module github.com/spinframework/spin-go-sdk/v3/examples/sqlite -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/sqlite/go.sum b/examples/sqlite/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/sqlite/go.sum +++ b/examples/sqlite/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/sqlite/main.go b/examples/sqlite/main.go index b63426c9..36548d70 100644 --- a/examples/sqlite/main.go +++ b/examples/sqlite/main.go @@ -5,8 +5,8 @@ import ( "fmt" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/sqlite" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/sqlite" ) type Pet struct { diff --git a/examples/sqlite/spin.toml b/examples/sqlite/spin.toml index 205483c4..e35e72cf 100644 --- a/examples/sqlite/spin.toml +++ b/examples/sqlite/spin.toml @@ -15,5 +15,5 @@ source = "main.wasm" allowed_outbound_hosts = [] sqlite_databases = ["default"] [component.sqlite.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" watch = ["**/*.go", "go.mod"] diff --git a/examples/variables/README.md b/examples/variables/README.md index e56da555..ca75f048 100644 --- a/examples/variables/README.md +++ b/examples/variables/README.md @@ -1,17 +1,20 @@ -# Spin component in TinyGo using variables +# Requirements +- [**go**](https://go.dev/dl/) - v1.25+ +- [**spin**](https://github.com/spinframework/spin) - Latest version +- [**componentize-go**](https://github.com/bytecodealliance/componentize-go) - Latest version -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up +# Usage +Build and run the Spin app: +```sh +spin up --build ``` -The application can now receive requests on `http://localhost:3000`: - -```shell -$ curl -i localhost:3000 -HTTP/1.1 200 OK -content-length: 23 -date: Tue, 29 Nov 2022 06:59:24 GMT +In another terminal window, you can interact with the Spin app: +```sh +curl localhost:3000/hello +``` +You should receive the following output: +``` message: I'm a teapot ``` diff --git a/examples/variables/go.mod b/examples/variables/go.mod index 3b8d9f44..c85e5eaf 100644 --- a/examples/variables/go.mod +++ b/examples/variables/go.mod @@ -1,9 +1,11 @@ -module examples/variables +module github.com/spinframework/spin-go-sdk/v3/examples/variables -go 1.20 +go 1.25.5 -require github.com/spinframework/spin-go-sdk/v2 v2.2.1 +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/spinframework/spin-go-sdk/v2 v2.2.1 => ../../ +replace github.com/spinframework/spin-go-sdk/v3 => ../../ diff --git a/examples/variables/go.sum b/examples/variables/go.sum index 096c54e6..b5bca15f 100644 --- a/examples/variables/go.sum +++ b/examples/variables/go.sum @@ -1,2 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/examples/variables/main.go b/examples/variables/main.go index e0a4091d..4791c8b1 100644 --- a/examples/variables/main.go +++ b/examples/variables/main.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" - "github.com/spinframework/spin-go-sdk/v2/variables" + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/variables" ) func init() { diff --git a/examples/variables/spin.toml b/examples/variables/spin.toml index 5f5c91e6..c289a444 100644 --- a/examples/variables/spin.toml +++ b/examples/variables/spin.toml @@ -3,7 +3,7 @@ spin_manifest_version = 2 [application] name = "variables-example" authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." +description = "A simple Spin application written in Go." version = "1.0.0" [variables] @@ -17,5 +17,6 @@ component = "variables" source = "main.wasm" [component.variables.variables] message = "I'm a {{object}}" + [component.variables.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +command = "componentize-go build" diff --git a/go.mod b/go.mod index 003ac4f2..d12c6b20 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,9 @@ -module github.com/spinframework/spin-go-sdk/v2 +module github.com/spinframework/spin-go-sdk/v3 -go 1.20 +go 1.25.5 + +require ( + go.bytecodealliance.org/pkg v0.2.1 + github.com/julienschmidt/httprouter v1.3.0 +) -require github.com/julienschmidt/httprouter v1.3.0 diff --git a/go.sum b/go.sum index 096c54e6..7b8de78d 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/http/client.go b/http/client.go new file mode 100644 index 00000000..77960964 --- /dev/null +++ b/http/client.go @@ -0,0 +1,100 @@ +package http + +import ( + "fmt" + "io" + "net/http" + + outgoinghandler "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_outgoing_handler" + types "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + wit "go.bytecodealliance.org/pkg/wit/types" +) + +// NewTransport returns http.RoundTripper backed by Spin SDK +func NewTransport() http.RoundTripper { + return &Transport{} +} + +// Transport implements http.RoundTripper +type Transport struct{} + +// RoundTrip makes roundtrip using Spin SDK +func (r *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + return Send(req) +} + +// NewClient returns a new HTTP client compatible with the Spin SDK +func NewClient() *http.Client { + return &http.Client{ + Transport: &Transport{}, + } +} + +func Send(req *http.Request) (*http.Response, error) { + or, err := NewOutgoingHttpRequest(req) + if err != nil { + return nil, err + } + + result := outgoinghandler.Handle(&or, wit.None[*types.RequestOptions]()) + if result.IsErr() { + return nil, fmt.Errorf("TODO: convert to readable error") + } + + if result.IsErr() { + return nil, fmt.Errorf("error is %v", result.Err()) + } + + okresult := result.Ok() + + //wait until resp is returned + okresult.Subscribe().Block() + + incomingResp := okresult.Get() + if incomingResp.IsNone() { + return nil, fmt.Errorf("incoming resp is None") + } else if incomingResp.Some().IsErr() { + return nil, fmt.Errorf("error is %v", incomingResp.Some().Err()) + } else if incomingResp.Some().Ok().IsErr() { + return nil, fmt.Errorf("error is %v", incomingResp.Some().Ok().Err()) + } + + okresp := incomingResp.Some().Ok().Ok() + var body io.ReadCloser + if consumeResult := okresp.Consume(); consumeResult.IsErr() { + return nil, fmt.Errorf("failed to consume incoming request %s", consumeResult.Err()) + } else if streamResult := consumeResult.Ok().Stream(); streamResult.IsErr() { + return nil, fmt.Errorf("failed to consume incoming requests's stream %s", streamResult.Err()) + } else { + body = NewReadCloser(*streamResult.Ok()) + } + + resp := &http.Response{ + StatusCode: int(okresp.Status()), + Body: body, + } + + return resp, nil +} + +func Get(url string) (*http.Response, error) { + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + return Send(req) +} + +func Post(url string, contentType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(http.MethodPost, url, body) + if err != nil { + return nil, err + } + + if contentType != "" { + req.Header.Set("Content-Type", contentType) + } + + return Send(req) +} diff --git a/http/convertor_incoming_request.go b/http/convertor_incoming_request.go new file mode 100644 index 00000000..b92b2317 --- /dev/null +++ b/http/convertor_incoming_request.go @@ -0,0 +1,84 @@ +package http + +import ( + "fmt" + "io" + "net/http" + + types "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" +) + +type IncomingRequest = types.IncomingRequest + +// convert the IncomingRequest to http.Request +func NewHttpRequest(ir IncomingRequest) (req *http.Request, err error) { + // convert the http method to string + method, err := methodToString(ir.Method()) + if err != nil { + return nil, err + } + + // convert the path with query to a url + var url string + if pathWithQuery := ir.PathWithQuery(); pathWithQuery.IsNone() { + url = "" + } else { + url = pathWithQuery.Some() + } + + // convert the body to a reader + var body io.Reader + if consumeResult := ir.Consume(); consumeResult.IsErr() { + return nil, fmt.Errorf("failed to consume incoming request %s", consumeResult.Err()) + } else if streamResult := consumeResult.Ok().Stream(); streamResult.IsErr() { + return nil, fmt.Errorf("failed to consume incoming requests's stream %s", streamResult.Err()) + } else { + body = NewReader(*streamResult.Ok()) + } + + // create a new request + req, err = http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + // update additional fields + toHttpHeader(*ir.Headers(), &req.Header) + + return req, nil +} + +func methodToString(m types.Method) (string, error) { + switch m.Tag() { + case types.MethodConnect: + return "CONNECT", nil + case types.MethodDelete: + return "DELETE", nil + case types.MethodGet: + return "GET", nil + case types.MethodHead: + return "HEAD", nil + case types.MethodOptions: + return "OPTIONS", nil + case types.MethodPatch: + return "PATCH", nil + case types.MethodPost: + return "POST", nil + case types.MethodPut: + return "PUT", nil + case types.MethodTrace: + return "TRACE", nil + case types.MethodOther: + return m.Other(), fmt.Errorf("unknown http method 'other'") + default: + return "", fmt.Errorf("failed to convert http method") + } +} + +func toHttpHeader(src types.Fields, dest *http.Header) { + for _, f := range src.Entries() { + key := f.F0 + value := string(f.F1) + dest.Add(key, value) + } +} diff --git a/http/convertor_outgoing_request.go b/http/convertor_outgoing_request.go new file mode 100644 index 00000000..99a6c8b0 --- /dev/null +++ b/http/convertor_outgoing_request.go @@ -0,0 +1,70 @@ +package http + +import ( + "net/http" + + types "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + wit "go.bytecodealliance.org/pkg/wit/types" +) + +// convert the IncomingRequest to http.Request +func NewOutgoingHttpRequest(req *http.Request) (types.OutgoingRequest, error) { + headers := types.MakeFields() + toWasiHeader(req.Header, *headers) + + or := types.MakeOutgoingRequest(headers) + or.SetAuthority(wit.Some(req.Host)) + or.SetMethod(toWasiMethod(req.Method)) + or.SetPathWithQuery(wit.Some(req.URL.RawPath)) + + switch req.URL.Scheme { + case "http": + or.SetScheme(wit.Some(types.MakeSchemeHttp())) + case "https": + or.SetScheme(wit.Some(types.MakeSchemeHttps())) + default: + or.SetScheme(wit.Some(types.MakeSchemeOther(req.URL.Scheme))) + } + + return *or, nil +} + +func toWasiHeader(src http.Header, dest types.Fields) { + for k, v := range src { + key := types.FieldKey(k) + fieldVals := []types.FieldValue{} + + for _, val := range v { + fieldVals = append(fieldVals, types.FieldValue(val)) + } + + if result := dest.Set(key, fieldVals); result.IsErr() { + panic("failed to set WASI headers") + } + } +} + +func toWasiMethod(s string) types.Method { + switch s { + case http.MethodConnect: + return types.MakeMethodConnect() + case http.MethodDelete: + return types.MakeMethodDelete() + case http.MethodGet: + return types.MakeMethodGet() + case http.MethodHead: + return types.MakeMethodHead() + case http.MethodOptions: + return types.MakeMethodOptions() + case http.MethodPatch: + return types.MakeMethodPatch() + case http.MethodPost: + return types.MakeMethodPost() + case http.MethodPut: + return types.MakeMethodPut() + case http.MethodTrace: + return types.MakeMethodTrace() + default: + return types.MakeMethodOther(s) + } +} diff --git a/http/convertor_outgoing_response.go b/http/convertor_outgoing_response.go new file mode 100644 index 00000000..c9a828f8 --- /dev/null +++ b/http/convertor_outgoing_response.go @@ -0,0 +1,156 @@ +package http + +import ( + "fmt" + "net/http" + "strings" + + types "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + streams "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" + wit "go.bytecodealliance.org/pkg/wit/types" +) + +var _ http.ResponseWriter = &responseOutparamWriter{} + +type responseOutparamWriter struct { + // wasi response outparam is set at the end of http_trigger_handle + outparam types.ResponseOutparam + // wasi response + response types.OutgoingResponse + // wasi http headers + wasiHeaders types.Fields + // go httpHeaders are reconciled on call to WriteHeader, Flush or at the end of http_trigger_handle + httpHeaders http.Header + // wasi response body is set on first write because it can only be called once + body *types.OutgoingBody + // wasi response stream is set on first write because it can only be called once + stream *streams.OutputStream + + statuscode int + + // this is to track whether a new response object has been created or not. + // if the user don't explicitly call Write(buf []byte) function, we reconcile + // implicitly with default status code 200 and response body OK + reconciled bool +} + +func (row *responseOutparamWriter) Header() http.Header { + return row.httpHeaders +} + +func (row *responseOutparamWriter) Write(buf []byte) (int, error) { + err := row.reconcile() + if err != nil { + return 0, err + } + + // acquire the response body's resource handle on first call to write + if row.body == nil { + bodyResult := row.response.Body() + if bodyResult.IsErr() { + return 0, fmt.Errorf("failed to acquire resource handle to response body: %s", bodyResult.Err()) + } + row.body = bodyResult.Ok() + + writeResult := row.body.Write() + if writeResult.IsErr() { + return 0, fmt.Errorf("failed to acquire resource handle for response body's stream: %s", writeResult.Err()) + } + row.stream = writeResult.Ok() + + result := wit.Ok[*types.OutgoingResponse, types.ErrorCode](&row.response) + + types.ResponseOutparamSet(&row.outparam, result) + } + + // //TODO: determine if we need to do these to fulfill the ResponseWriter contract + // // call WriteHeader(http.StatusOK) if it hasn't been called yet + // // call DetectContentType if headers doesn't contain content-type yet + // // if total data is under "a few" KB and there are no flush calls, Content-Length is added automatically + + contents := buf + writeResult := row.stream.Write(contents) + if writeResult.IsErr() { + if writeResult.Err().Tag() == streams.StreamErrorClosed { + return 0, fmt.Errorf("failed to write to response body's stream: closed") + } + + //TODO: possible nil error here + return 0, fmt.Errorf("failed to write to response body's stream: %s", writeResult.Err().LastOperationFailed().ToDebugString()) + } + + row.stream.BlockingFlush() + + return len(contents), nil +} + +func (row *responseOutparamWriter) WriteHeader(statusCode int) { + row.statuscode = statusCode +} + +// reconcile headers from go to wasi +func (row *responseOutparamWriter) reconcileHeaders() error { + for key, vals := range row.httpHeaders { + // convert each value distincly + fieldVals := []types.FieldValue{} + for _, val := range vals { + fieldVals = append(fieldVals, types.FieldValue(val)) + } + + if result := row.wasiHeaders.Set(types.FieldKey(key), fieldVals); result.IsErr() { + switch result.Err().Tag() { + case types.HeaderErrorInvalidSyntax: + return fmt.Errorf("failed to set header %s to [%s]: invalid syntax", key, strings.Join(vals, ",")) + case types.HeaderErrorForbidden: + return fmt.Errorf("failed to set forbidden header key %s", key) + case types.HeaderErrorImmutable: + return fmt.Errorf("failed to set header on immutable header fields") + default: + return fmt.Errorf("not sure what happened here?") + } + } + } + + //TODO: handle deleted headers + + return nil +} + +// convert the ResponseOutparam to http.ResponseWriter +func NewHttpResponseWriter(out types.ResponseOutparam) *responseOutparamWriter { + row := &responseOutparamWriter{ + outparam: out, + httpHeaders: http.Header{}, + wasiHeaders: *types.MakeFields(), + } + + return row +} + +func (row *responseOutparamWriter) reconcile() error { + // this response has been already reconciled + // which means the user explicitly called response.Write(buf []byte) fn + if row.reconciled { + return nil + } + + err := row.reconcileHeaders() + if err != nil { + return err + } + + // setting any headers after this will cause panic + row.response = *types.MakeOutgoingResponse(&row.wasiHeaders) + + // set status code. default to 200 + if row.statuscode == 0 { + row.statuscode = http.StatusOK + } + + row.response.SetStatusCode(types.StatusCode(row.statuscode)) + + // store that reconcilation has already happened + row.reconciled = true + + return nil +} diff --git a/http/http.go b/http/http.go index ba4a22c2..a8265ef3 100644 --- a/http/http.go +++ b/http/http.go @@ -1,16 +1,22 @@ // Package http contains the helper functions for writing Spin HTTP components -// in TinyGo, as well as for sending outbound HTTP requests. +// in Go, as well as for sending outbound HTTP requests. package http import ( "fmt" - "io" "net/http" "os" "github.com/julienschmidt/httprouter" + incominghandler "github.com/spinframework/spin-go-sdk/v3/internal/export_wasi_http_0_2_0_incoming_handler" + types "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + _ "github.com/spinframework/spin-go-sdk/v3/internal/wit_exports" ) +func init() { + incominghandler.Exports.Handle = wasiHandle +} + const ( // The application base path. HeaderBasePath = "spin-base-path" @@ -31,11 +37,6 @@ const ( HeaderClientAddr = "spin-client-addr" ) -// Override the default HTTP client to be compatible with the Spin SDK. -func init() { - http.DefaultClient = NewClient() -} - // Router is a http.Handler which can be used to dispatch requests to different // handler functions via configurable routes type Router = httprouter.Router @@ -59,26 +60,6 @@ func NewRouter() *Router { return httprouter.New() } -// NewTransport returns http.RoundTripper backed by Spin SDK -func NewTransport() http.RoundTripper { - return &Transport{} -} - -// Transport implements http.RoundTripper -type Transport struct{} - -// RoundTrip makes roundtrip using Spin SDK -func (r *Transport) RoundTrip(req *http.Request) (*http.Response, error) { - return Send(req) -} - -// NewClient returns a new HTTP client compatible with the Spin SDK -func NewClient() *http.Client { - return &http.Client{ - Transport: &Transport{}, - } -} - // handler is the function that will be called by the http trigger in Spin. var handler = defaultHandler @@ -94,23 +75,21 @@ func Handle(fn func(http.ResponseWriter, *http.Request)) { handler = fn } -// Get creates a GET HTTP request to a given URL and returns the HTTP response. -// The destination of the request must be explicitly allowed in the Spin application -// configuration, otherwise the request will not be sent. -func Get(url string) (*http.Response, error) { - return get(url) -} +var wasiHandle = func(request *types.IncomingRequest, responseOut *types.ResponseOutparam) { + // convert the incoming request to go's net/http type + httpReq, err := NewHttpRequest(*request) + if err != nil { + //TODO(rajatjindal): return internal error from here + fmt.Printf("failed to convert wasi/http/types.IncomingRequest to http.Request: %s\n", err) + return + } -// Post creates a POST HTTP request and returns the HTTP response. -// The destination of the request must be explicitly allowed in the Spin application -// configuration, otherwise the request will not be sent. -func Post(url string, contentType string, body io.Reader) (*http.Response, error) { - return post(url, contentType, body) -} + // convert the response outparam to go's net/http type + httpRes := NewHttpResponseWriter(*responseOut) + + // run the user's handler + handler(httpRes, httpReq) -// Send sends an HTTP request and return the HTTP response. -// The destination of the request must be explicitly allowed in the Spin application -// configuration, otherwise the request will not be sent. -func Send(req *http.Request) (*http.Response, error) { - return send(req) + // ensure default status ok and response body are set + _ = httpRes.reconcile() } diff --git a/http/internals.go b/http/internals.go deleted file mode 100644 index 8256a2a4..00000000 --- a/http/internals.go +++ /dev/null @@ -1,140 +0,0 @@ -package http - -// #cgo CFLAGS: -Wno-unused-parameter -Wno-switch-bool -// #include -// #include -import "C" -import ( - "bytes" - "fmt" - "io" - "net/http" - "os" - "unsafe" -) - -//export spin_http_handle_http_request -func handle_http_request(req *C.spin_http_request_t, res *C.spin_http_response_t) { - var body []byte - if req.body.is_some { - body = C.GoBytes(unsafe.Pointer(req.body.val.ptr), C.int(req.body.val.len)) - } - method := methods[req.method] - header := fromSpinHeaders(&req.headers) - url := header.Get(HeaderFullUrl) - - r, err := http.NewRequest(method, url, bytes.NewReader(body)) - if err != nil { - fmt.Fprintln(os.Stderr, err) - res.status = C.uint16_t(http.StatusInternalServerError) - return - } - - r.Header = header - r.Host = r.Header.Get("Host") - r.RequestURI = C.GoStringN(req.uri.ptr, C.int(req.uri.len)) - r.RemoteAddr = r.Header.Get(HeaderClientAddr) - - w := newResponse() - - // call user function - handler(w, r) - - res.status = C.uint16_t(w.status) - if len(w.header) > 0 { - res.headers = C.spin_http_option_headers_t{ - is_some: true, - val: toSpinHeaders(w.header), - } - } else { - res.headers = C.spin_http_option_headers_t{is_some: false} - } - - res.body, err = toSpinBody(w.w) - if err != nil { - fmt.Fprintln(os.Stderr, err) - } -} - -func toSpinHeaders(hm http.Header) C.spin_http_headers_t { - var reqHeaders C.spin_http_headers_t - - headersLen := len(hm) - - if headersLen > 0 { - reqHeaders.len = C.ulong(headersLen) - var x C.spin_http_tuple2_string_string_t - reqHeaders.ptr = (*C.spin_http_tuple2_string_string_t)(C.malloc(C.size_t(headersLen) * C.size_t(unsafe.Sizeof(x)))) - headers := unsafe.Slice(reqHeaders.ptr, headersLen) - - idx := 0 - for k, v := range hm { - headers[idx] = newSpinHeader(k, v[0]) - idx++ - } - } - return reqHeaders -} - -func toSpinBody(body io.Reader) (C.spin_http_option_body_t, error) { - var spinBody C.spin_http_option_body_t - spinBody.is_some = false - - if body == nil { - return spinBody, nil - } - - buf := new(bytes.Buffer) - len, err := buf.ReadFrom(body) - if err != nil { - return spinBody, err - } - - if len > 0 { - bodyPtr := (*C.uint8_t)(C.malloc(C.size_t(len))) - copy(unsafe.Slice(bodyPtr, len), buf.Bytes()) - - spinBody.is_some = true - spinBody.val = C.spin_http_body_t{ - ptr: bodyPtr, - len: C.size_t(len), - } - } - - return spinBody, nil -} - -// newSpinHeader creates a new spinHeader with the given key/value. -func newSpinHeader(k, v string) C.spin_http_tuple2_string_string_t { - return C.spin_http_tuple2_string_string_t{ - f0: C.spin_http_string_t{ptr: C.CString(k), len: C.size_t(len(k))}, - f1: C.spin_http_string_t{ptr: C.CString(v), len: C.size_t(len(v))}, - } -} - -var methods = [...]string{ - "GET", - "POST", - "PUT", - "DELETE", - "PATCH", - "HEAD", - "OPTIONS", -} - -func fromSpinHeaders(hm *C.spin_http_headers_t) http.Header { - headersLen := int(hm.len) - headers := make(http.Header, headersLen) - - var headersArr *C.spin_http_tuple2_string_string_t = hm.ptr - headersSlice := unsafe.Slice(headersArr, headersLen) - for i := 0; i < headersLen; i++ { - tuple := headersSlice[i] - k := C.GoStringN(tuple.f0.ptr, C.int(tuple.f0.len)) - v := C.GoStringN(tuple.f1.ptr, C.int(tuple.f1.len)) - - headers.Add(k, v) - } - - return headers -} diff --git a/http/outbound_internals.go b/http/outbound_internals.go deleted file mode 100644 index c371f673..00000000 --- a/http/outbound_internals.go +++ /dev/null @@ -1,196 +0,0 @@ -//nolint:staticcheck - -// This file contains the manual conversions between Go HTTP objects -// and Spin HTTP objects, through the auto-generated C bindings for -// the outbound HTTP API. - -package http - -// #cgo CFLAGS: -Wno-unused-parameter -Wno-switch-bool -// #include "wasi-outbound-http.h" -// #include -import "C" - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "strings" - "unsafe" -) - -func get(url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - - return send(req) -} - -func post(url string, contentType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", contentType) - - return send(req) -} - -func send(req *http.Request) (*http.Response, error) { - var spinReq C.wasi_outbound_http_request_t - var spinRes C.wasi_outbound_http_response_t - - m, err := method(req.Method) - if err != nil { - return nil, err - } - spinReq.method = uint8(m) - spinReq.uri = C.wasi_outbound_http_uri_t{ - ptr: C.CString(req.URL.String()), - len: C.ulong(len(req.URL.String())), - } - spinReq.headers = toOutboundHeaders(req.Header) - spinReq.body, err = toOutboundReqBody(req.Body) - if err != nil { - return nil, err - } - - code := C.wasi_outbound_http_request(&spinReq, &spinRes) - - if err := toErr(code, req.URL.String()); err != nil { - return nil, err - } - return toResponse(&spinRes) -} - -func method(m string) (int, error) { - switch strings.ToUpper(m) { - case "GET": - return 0, nil - case "POST": - return 1, nil - case "PUT": - return 2, nil - case "DELETE": - return 3, nil - case "PATCH": - return 4, nil - case "HEAD": - return 5, nil - case "OPTIONS": - return 6, nil - default: - return -1, fmt.Errorf("Unknown HTTP method %v", m) - } -} - -// Transform a C outbound HTTP response to a Go *http.Response. -func toResponse(res *C.wasi_outbound_http_response_t) (*http.Response, error) { - var body []byte - if res.body.is_some { - body = C.GoBytes(unsafe.Pointer(res.body.val.ptr), C.int(res.body.val.len)) - } - - t := &http.Response{ - Status: fmt.Sprintf("%v %v", res.status, http.StatusText(int(res.status))), - StatusCode: int(res.status), - Proto: "HTTP/1.1", - ProtoMajor: 1, - ProtoMinor: 1, - Body: ioutil.NopCloser(bytes.NewBuffer(body)), - ContentLength: int64(len(body)), - Request: nil, // we don't really have a request to populate with here - Header: toHeaders(&res.headers), - } - return t, nil -} - -func toOutboundHeaders(hm http.Header) C.wasi_outbound_http_headers_t { - var reqHeaders C.wasi_outbound_http_headers_t - - headersLen := len(hm) - - if headersLen > 0 { - reqHeaders.len = C.ulong(headersLen) - var x C.wasi_outbound_http_tuple2_string_string_t - reqHeaders.ptr = (*C.wasi_outbound_http_tuple2_string_string_t)(C.malloc(C.size_t(headersLen) * C.size_t(unsafe.Sizeof(x)))) - headers := unsafe.Slice(reqHeaders.ptr, headersLen) - - idx := 0 - for k, v := range hm { - headers[idx] = newOutboundHeader(k, v[0]) - idx++ - } - } - return reqHeaders -} - -func toOutboundReqBody(body io.Reader) (C.wasi_outbound_http_option_body_t, error) { - var spinBody C.wasi_outbound_http_option_body_t - spinBody.is_some = false - - if body != nil { - buf := new(bytes.Buffer) - len, err := buf.ReadFrom(body) - if err != nil { - return spinBody, err - } - - if len > 0 { - spinBody.is_some = true - spinBody.val = C.wasi_outbound_http_body_t{ - ptr: &buf.Bytes()[0], - len: C.size_t(len), - } - } - } - - return spinBody, nil -} - -func toHeaders(hm *C.wasi_outbound_http_option_headers_t) http.Header { - if !hm.is_some { - return make(map[string][]string, 0) - } - headersLen := int(hm.val.len) - headers := make(http.Header, headersLen) - - var headersArr *C.wasi_outbound_http_tuple2_string_string_t = hm.val.ptr - headersSlice := unsafe.Slice(headersArr, headersLen) - for i := 0; i < headersLen; i++ { - tuple := headersSlice[i] - k := C.GoStringN(tuple.f0.ptr, C.int(tuple.f0.len)) - v := C.GoStringN(tuple.f1.ptr, C.int(tuple.f1.len)) - - headers.Add(k, v) - } - - return headers -} - -func toErr(code C.uint8_t, url string) error { - switch code { - case 1: - return fmt.Errorf("Destination not allowed: %v", url) - case 2: - return fmt.Errorf("Invalid URL: %v", url) - case 3: - return fmt.Errorf("Error sending request to URL: %v", url) - case 4: - return fmt.Errorf("Runtime error") - default: - return nil - } -} - -// newOutboundHeader creates a new outboundHeader with the given key/value. -func newOutboundHeader(k, v string) C.wasi_outbound_http_tuple2_string_string_t { - return C.wasi_outbound_http_tuple2_string_string_t{ - f0: C.wasi_outbound_http_string_t{ptr: C.CString(k), len: C.size_t(len(k))}, - f1: C.wasi_outbound_http_string_t{ptr: C.CString(v), len: C.size_t(len(v))}, - } -} diff --git a/http/response.go b/http/response.go deleted file mode 100644 index a1b2559c..00000000 --- a/http/response.go +++ /dev/null @@ -1,39 +0,0 @@ -package http - -import ( - "bytes" - "net/http" -) - -var _ http.ResponseWriter = (*response)(nil) - -// response implements http.ResponseWriter -type response struct { - // status code passed to WriteHeader - status int - - header http.Header - w *bytes.Buffer -} - -func newResponse() *response { - return &response{ - // set default status to StatusOK - status: http.StatusOK, - - header: make(http.Header), - w: new(bytes.Buffer), - } -} - -func (r *response) Header() http.Header { - return r.header -} - -func (r *response) WriteHeader(statusCode int) { - r.status = statusCode -} - -func (r *response) Write(data []byte) (int, error) { - return r.w.Write(data) -} diff --git a/http/spin-http.c b/http/spin-http.c deleted file mode 100644 index 780a4adf..00000000 --- a/http/spin-http.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void spin_http_string_set(spin_http_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void spin_http_string_dup(spin_http_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void spin_http_string_free(spin_http_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void spin_http_body_free(spin_http_body_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void spin_http_tuple2_string_string_free(spin_http_tuple2_string_string_t *ptr) { - spin_http_string_free(&ptr->f0); - spin_http_string_free(&ptr->f1); -} -void spin_http_headers_free(spin_http_headers_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - spin_http_tuple2_string_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 4); -} -void spin_http_params_free(spin_http_params_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - spin_http_tuple2_string_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 4); -} -void spin_http_uri_free(spin_http_uri_t *ptr) { - spin_http_string_free(ptr); -} -void spin_http_option_body_free(spin_http_option_body_t *ptr) { - if (ptr->is_some) { - spin_http_body_free(&ptr->val); - } -} -void spin_http_request_free(spin_http_request_t *ptr) { - spin_http_uri_free(&ptr->uri); - spin_http_headers_free(&ptr->headers); - spin_http_params_free(&ptr->params); - spin_http_option_body_free(&ptr->body); -} -void spin_http_option_headers_free(spin_http_option_headers_t *ptr) { - if (ptr->is_some) { - spin_http_headers_free(&ptr->val); - } -} -void spin_http_response_free(spin_http_response_t *ptr) { - spin_http_option_headers_free(&ptr->headers); - spin_http_option_body_free(&ptr->body); -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[28]; -__attribute__((export_name("handle-http-request"))) -int32_t __wasm_export_spin_http_handle_http_request(int32_t arg, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7, int32_t arg8) { - spin_http_option_body_t option; - switch (arg6) { - case 0: { - option.is_some = false; - - break; - } - case 1: { - option.is_some = true; - - option.val = (spin_http_body_t) { (uint8_t*)(arg7), (size_t)(arg8) }; - break; - } - }spin_http_request_t arg9 = (spin_http_request_t) { - arg, - (spin_http_string_t) { (char*)(arg0), (size_t)(arg1) }, - (spin_http_headers_t) { (spin_http_tuple2_string_string_t*)(arg2), (size_t)(arg3) }, - (spin_http_params_t) { (spin_http_tuple2_string_string_t*)(arg4), (size_t)(arg5) }, - option, - }; - spin_http_response_t ret; - spin_http_handle_http_request(&arg9, &ret); - int32_t ptr = (int32_t) &RET_AREA; - *((int16_t*)(ptr + 0)) = (int32_t) ((ret).status); - - if (((ret).headers).is_some) { - const spin_http_headers_t *payload10 = &((ret).headers).val; - *((int8_t*)(ptr + 4)) = 1; - *((int32_t*)(ptr + 12)) = (int32_t) (*payload10).len; - *((int32_t*)(ptr + 8)) = (int32_t) (*payload10).ptr; - - } else { - *((int8_t*)(ptr + 4)) = 0; - - } - - if (((ret).body).is_some) { - const spin_http_body_t *payload12 = &((ret).body).val; - *((int8_t*)(ptr + 16)) = 1; - *((int32_t*)(ptr + 24)) = (int32_t) (*payload12).len; - *((int32_t*)(ptr + 20)) = (int32_t) (*payload12).ptr; - - } else { - *((int8_t*)(ptr + 16)) = 0; - - } - return ptr; -} diff --git a/http/spin-http.h b/http/spin-http.h deleted file mode 100644 index cd47c95c..00000000 --- a/http/spin-http.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __BINDINGS_SPIN_HTTP_H -#define __BINDINGS_SPIN_HTTP_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } spin_http_string_t; - - void spin_http_string_set(spin_http_string_t *ret, const char *s); - void spin_http_string_dup(spin_http_string_t *ret, const char *s); - void spin_http_string_free(spin_http_string_t *ret); - typedef struct { - uint8_t *ptr; - size_t len; - } spin_http_body_t; - void spin_http_body_free(spin_http_body_t *ptr); - typedef struct { - spin_http_string_t f0; - spin_http_string_t f1; - } spin_http_tuple2_string_string_t; - void spin_http_tuple2_string_string_free(spin_http_tuple2_string_string_t *ptr); - typedef struct { - spin_http_tuple2_string_string_t *ptr; - size_t len; - } spin_http_headers_t; - void spin_http_headers_free(spin_http_headers_t *ptr); - typedef uint8_t spin_http_http_error_t; - #define SPIN_HTTP_HTTP_ERROR_SUCCESS 0 - #define SPIN_HTTP_HTTP_ERROR_DESTINATION_NOT_ALLOWED 1 - #define SPIN_HTTP_HTTP_ERROR_INVALID_URL 2 - #define SPIN_HTTP_HTTP_ERROR_REQUEST_ERROR 3 - #define SPIN_HTTP_HTTP_ERROR_RUNTIME_ERROR 4 - #define SPIN_HTTP_HTTP_ERROR_TOO_MANY_REQUESTS 5 - typedef uint16_t spin_http_http_status_t; - typedef uint8_t spin_http_method_t; - #define SPIN_HTTP_METHOD_GET 0 - #define SPIN_HTTP_METHOD_POST 1 - #define SPIN_HTTP_METHOD_PUT 2 - #define SPIN_HTTP_METHOD_DELETE 3 - #define SPIN_HTTP_METHOD_PATCH 4 - #define SPIN_HTTP_METHOD_HEAD 5 - #define SPIN_HTTP_METHOD_OPTIONS 6 - typedef struct { - spin_http_tuple2_string_string_t *ptr; - size_t len; - } spin_http_params_t; - void spin_http_params_free(spin_http_params_t *ptr); - typedef spin_http_string_t spin_http_uri_t; - void spin_http_uri_free(spin_http_uri_t *ptr); - typedef struct { - bool is_some; - spin_http_body_t val; - } spin_http_option_body_t; - void spin_http_option_body_free(spin_http_option_body_t *ptr); - typedef struct { - spin_http_method_t method; - spin_http_uri_t uri; - spin_http_headers_t headers; - spin_http_params_t params; - spin_http_option_body_t body; - } spin_http_request_t; - void spin_http_request_free(spin_http_request_t *ptr); - typedef struct { - bool is_some; - spin_http_headers_t val; - } spin_http_option_headers_t; - void spin_http_option_headers_free(spin_http_option_headers_t *ptr); - typedef struct { - spin_http_http_status_t status; - spin_http_option_headers_t headers; - spin_http_option_body_t body; - } spin_http_response_t; - void spin_http_response_free(spin_http_response_t *ptr); - void spin_http_handle_http_request(spin_http_request_t *req, spin_http_response_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/http/streams.go b/http/streams.go new file mode 100644 index 00000000..04b469d4 --- /dev/null +++ b/http/streams.go @@ -0,0 +1,45 @@ +package http + +import ( + "fmt" + "io" + + streams "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" +) + +type inputStreamReader struct { + stream streams.InputStream +} + +func (r inputStreamReader) Close() error { + //noop + return nil +} + +func (r inputStreamReader) Read(p []byte) (n int, err error) { + readResult := r.stream.Read(uint64(len(p))) + if readResult.IsErr() { + readErr := readResult.Err() + if readErr.Tag() == streams.StreamErrorClosed { + return 0, io.EOF + } + return 0, fmt.Errorf("failed to read from InputStream %s", readErr.LastOperationFailed().ToDebugString()) + } + + readList := readResult.Ok() + copy(p, readList) + return len(readList), nil +} + +// create an io.Reader from the input stream +func NewReader(s streams.InputStream) io.Reader { + return inputStreamReader{ + stream: s, + } +} + +func NewReadCloser(s streams.InputStream) io.ReadCloser { + return inputStreamReader{ + stream: s, + } +} diff --git a/http/testdata/http-tinygo/Makefile b/http/testdata/http-tinygo/Makefile deleted file mode 100644 index b905087a..00000000 --- a/http/testdata/http-tinygo/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -.PHONY: build -build: - tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm . diff --git a/http/testdata/http-tinygo/main.go b/http/testdata/http-tinygo/main.go deleted file mode 100644 index b5a715a6..00000000 --- a/http/testdata/http-tinygo/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Spin-Raw-Component-Route") != "/hello/..." { - http.Error(w, "Spin-Raw-Component-Route is not /hello/...", http.StatusInternalServerError) - return - } - - if r.Method != "GET" { - http.Error(w, "Method should be GET", http.StatusInternalServerError) - return - } - - w.Header().Set("spin-path-info", r.Header.Get("spin-path-info")) - w.Header().Set("foo", "bar") - - fmt.Fprintln(w, "Hello world!") - }) -} - -func main() {} diff --git a/http/testdata/http-tinygo/spin.toml b/http/testdata/http-tinygo/spin.toml deleted file mode 100644 index f132116d..00000000 --- a/http/testdata/http-tinygo/spin.toml +++ /dev/null @@ -1,18 +0,0 @@ -spin_manifest_version = 2 - -[application] -name = "spin-http-tinygo-test" -version = "0.1.0" -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." - -[[trigger.http]] -route = "/hello/..." -component = "http-test" - -[component.http-test] -source = "main.wasm" -allowed_outbound_hosts = [] -[component.http-test.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." -watch = ["**/*.go", "go.mod"] diff --git a/http/testdata/http/go.mod b/http/testdata/http/go.mod new file mode 100644 index 00000000..fb6e93c5 --- /dev/null +++ b/http/testdata/http/go.mod @@ -0,0 +1,11 @@ +module github.com/spinframework/spin-go-sdk/v3/http/testdata/http + +go 1.25.5 + +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) + +replace github.com/spinframework/spin-go-sdk/v3 => ../../../ diff --git a/http/testdata/http/go.sum b/http/testdata/http/go.sum new file mode 100644 index 00000000..b5bca15f --- /dev/null +++ b/http/testdata/http/go.sum @@ -0,0 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/http/testdata/http/main.go b/http/testdata/http/main.go new file mode 100644 index 00000000..596779e3 --- /dev/null +++ b/http/testdata/http/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "net/http" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain") + w.Header().Set("foo", "bar") + + fmt.Fprintln(w, "== RESPONSE ==") + fmt.Fprintln(w, "Hello spinframework!") + fmt.Fprintln(w, "Hello again spinframework!") + }) +} + +func main() {} diff --git a/http/testdata/http/spin.toml b/http/testdata/http/spin.toml new file mode 100644 index 00000000..a951d46c --- /dev/null +++ b/http/testdata/http/spin.toml @@ -0,0 +1,17 @@ +spin_manifest_version = 2 + +[application] +authors = ["Rajat Jindal "] +description = "A simple Spin application written in Go." +name = "hello-example" +version = "1.0.0" + +[[trigger.http]] +route = "/hello" +component = "hello" + +[component.hello] +source = "main.wasm" +[component.hello.build] +command = "componentize-go build" + diff --git a/http/testdata/spin-roundtrip/Makefile b/http/testdata/spin-roundtrip/Makefile deleted file mode 100644 index b905087a..00000000 --- a/http/testdata/spin-roundtrip/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -.PHONY: build -build: - tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm . diff --git a/http/testdata/spin-roundtrip/main.go b/http/testdata/spin-roundtrip/main.go deleted file mode 100644 index d1548280..00000000 --- a/http/testdata/spin-roundtrip/main.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - transport := spinhttp.NewTransport() - - // or you can also do client := spinhttp.NewClient() - client := &http.Client{ - Transport: transport, - } - - resp, err := client.Get("https://example.com") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.WriteHeader(resp.StatusCode) - w.Header().Set("spin-path-info", r.Header.Get("spin-path-info")) - w.Header().Set("foo", "bar") - fmt.Fprintln(w, "Hello world!") - }) -} - -func main() {} diff --git a/http/testdata/spin-roundtrip/spin.toml b/http/testdata/spin-roundtrip/spin.toml deleted file mode 100644 index 66b38805..00000000 --- a/http/testdata/spin-roundtrip/spin.toml +++ /dev/null @@ -1,18 +0,0 @@ -spin_manifest_version = 2 - -[application] -name = "spin-roundtrip-test" -version = "0.1.0" -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." - -[[trigger.http]] -route = "/hello/..." -component = "http-roundtrip-test" - -[component.http-roundtrip-test] -source = "main.wasm" -allowed_outbound_hosts = ["https://example.com"] -[component.http-roundtrip-test.build] -command = "tinygo build -target=wasip1 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." -watch = ["**/*.go", "go.mod"] diff --git a/http/wasi-outbound-http.c b/http/wasi-outbound-http.c deleted file mode 100644 index f7675850..00000000 --- a/http/wasi-outbound-http.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void wasi_outbound_http_string_set(wasi_outbound_http_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void wasi_outbound_http_string_dup(wasi_outbound_http_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void wasi_outbound_http_string_free(wasi_outbound_http_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void wasi_outbound_http_body_free(wasi_outbound_http_body_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void wasi_outbound_http_tuple2_string_string_free(wasi_outbound_http_tuple2_string_string_t *ptr) { - wasi_outbound_http_string_free(&ptr->f0); - wasi_outbound_http_string_free(&ptr->f1); -} -void wasi_outbound_http_headers_free(wasi_outbound_http_headers_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - wasi_outbound_http_tuple2_string_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 4); -} -void wasi_outbound_http_params_free(wasi_outbound_http_params_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - wasi_outbound_http_tuple2_string_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 4); -} -void wasi_outbound_http_uri_free(wasi_outbound_http_uri_t *ptr) { - wasi_outbound_http_string_free(ptr); -} -void wasi_outbound_http_option_body_free(wasi_outbound_http_option_body_t *ptr) { - if (ptr->is_some) { - wasi_outbound_http_body_free(&ptr->val); - } -} -void wasi_outbound_http_request_free(wasi_outbound_http_request_t *ptr) { - wasi_outbound_http_uri_free(&ptr->uri); - wasi_outbound_http_headers_free(&ptr->headers); - wasi_outbound_http_params_free(&ptr->params); - wasi_outbound_http_option_body_free(&ptr->body); -} -void wasi_outbound_http_option_headers_free(wasi_outbound_http_option_headers_t *ptr) { - if (ptr->is_some) { - wasi_outbound_http_headers_free(&ptr->val); - } -} -void wasi_outbound_http_response_free(wasi_outbound_http_response_t *ptr) { - wasi_outbound_http_option_headers_free(&ptr->headers); - wasi_outbound_http_option_body_free(&ptr->body); -} -typedef struct { - bool is_err; - union { - wasi_outbound_http_response_t ok; - wasi_outbound_http_http_error_t err; - } val; -} wasi_outbound_http_expected_response_http_error_t; - -__attribute__((aligned(4))) -static uint8_t RET_AREA[32]; -__attribute__((import_module("wasi-outbound-http"), import_name("request"))) -void __wasm_import_wasi_outbound_http_request(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -wasi_outbound_http_http_error_t wasi_outbound_http_request(wasi_outbound_http_request_t *req, wasi_outbound_http_response_t *ret0) { - int32_t option; - int32_t option1; - int32_t option2; - - if (((*req).body).is_some) { - const wasi_outbound_http_body_t *payload0 = &((*req).body).val; - option = 1; - option1 = (int32_t) (*payload0).ptr; - option2 = (int32_t) (*payload0).len; - - } else { - option = 0; - option1 = 0; - option2 = 0; - - } - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_wasi_outbound_http_request((int32_t) (*req).method, (int32_t) ((*req).uri).ptr, (int32_t) ((*req).uri).len, (int32_t) ((*req).headers).ptr, (int32_t) ((*req).headers).len, (int32_t) ((*req).params).ptr, (int32_t) ((*req).params).len, option, option1, option2, ptr); - wasi_outbound_http_expected_response_http_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - wasi_outbound_http_option_headers_t option3; - switch ((int32_t) (*((uint8_t*) (ptr + 8)))) { - case 0: { - option3.is_some = false; - - break; - } - case 1: { - option3.is_some = true; - - option3.val = (wasi_outbound_http_headers_t) { (wasi_outbound_http_tuple2_string_string_t*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - }wasi_outbound_http_option_body_t option4; - switch ((int32_t) (*((uint8_t*) (ptr + 20)))) { - case 0: { - option4.is_some = false; - - break; - } - case 1: { - option4.is_some = true; - - option4.val = (wasi_outbound_http_body_t) { (uint8_t*)(*((int32_t*) (ptr + 24))), (size_t)(*((int32_t*) (ptr + 28))) }; - break; - } - } - expected.val.ok = (wasi_outbound_http_response_t) { - (uint16_t) ((int32_t) (*((uint16_t*) (ptr + 4)))), - option3, - option4, - }; - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 4))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} diff --git a/http/wasi-outbound-http.h b/http/wasi-outbound-http.h deleted file mode 100644 index ccaac543..00000000 --- a/http/wasi-outbound-http.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __BINDINGS_WASI_OUTBOUND_HTTP_H -#define __BINDINGS_WASI_OUTBOUND_HTTP_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } wasi_outbound_http_string_t; - - void wasi_outbound_http_string_set(wasi_outbound_http_string_t *ret, const char *s); - void wasi_outbound_http_string_dup(wasi_outbound_http_string_t *ret, const char *s); - void wasi_outbound_http_string_free(wasi_outbound_http_string_t *ret); - typedef struct { - uint8_t *ptr; - size_t len; - } wasi_outbound_http_body_t; - void wasi_outbound_http_body_free(wasi_outbound_http_body_t *ptr); - typedef struct { - wasi_outbound_http_string_t f0; - wasi_outbound_http_string_t f1; - } wasi_outbound_http_tuple2_string_string_t; - void wasi_outbound_http_tuple2_string_string_free(wasi_outbound_http_tuple2_string_string_t *ptr); - typedef struct { - wasi_outbound_http_tuple2_string_string_t *ptr; - size_t len; - } wasi_outbound_http_headers_t; - void wasi_outbound_http_headers_free(wasi_outbound_http_headers_t *ptr); - typedef uint8_t wasi_outbound_http_http_error_t; - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_SUCCESS 0 - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_DESTINATION_NOT_ALLOWED 1 - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_INVALID_URL 2 - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_REQUEST_ERROR 3 - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_RUNTIME_ERROR 4 - #define WASI_OUTBOUND_HTTP_HTTP_ERROR_TOO_MANY_REQUESTS 5 - typedef uint16_t wasi_outbound_http_http_status_t; - typedef uint8_t wasi_outbound_http_method_t; - #define WASI_OUTBOUND_HTTP_METHOD_GET 0 - #define WASI_OUTBOUND_HTTP_METHOD_POST 1 - #define WASI_OUTBOUND_HTTP_METHOD_PUT 2 - #define WASI_OUTBOUND_HTTP_METHOD_DELETE 3 - #define WASI_OUTBOUND_HTTP_METHOD_PATCH 4 - #define WASI_OUTBOUND_HTTP_METHOD_HEAD 5 - #define WASI_OUTBOUND_HTTP_METHOD_OPTIONS 6 - typedef struct { - wasi_outbound_http_tuple2_string_string_t *ptr; - size_t len; - } wasi_outbound_http_params_t; - void wasi_outbound_http_params_free(wasi_outbound_http_params_t *ptr); - typedef wasi_outbound_http_string_t wasi_outbound_http_uri_t; - void wasi_outbound_http_uri_free(wasi_outbound_http_uri_t *ptr); - typedef struct { - bool is_some; - wasi_outbound_http_body_t val; - } wasi_outbound_http_option_body_t; - void wasi_outbound_http_option_body_free(wasi_outbound_http_option_body_t *ptr); - typedef struct { - wasi_outbound_http_method_t method; - wasi_outbound_http_uri_t uri; - wasi_outbound_http_headers_t headers; - wasi_outbound_http_params_t params; - wasi_outbound_http_option_body_t body; - } wasi_outbound_http_request_t; - void wasi_outbound_http_request_free(wasi_outbound_http_request_t *ptr); - typedef struct { - bool is_some; - wasi_outbound_http_headers_t val; - } wasi_outbound_http_option_headers_t; - void wasi_outbound_http_option_headers_free(wasi_outbound_http_option_headers_t *ptr); - typedef struct { - wasi_outbound_http_http_status_t status; - wasi_outbound_http_option_headers_t headers; - wasi_outbound_http_option_body_t body; - } wasi_outbound_http_response_t; - void wasi_outbound_http_response_free(wasi_outbound_http_response_t *ptr); - wasi_outbound_http_http_error_t wasi_outbound_http_request(wasi_outbound_http_request_t *req, wasi_outbound_http_response_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/integration_test.go b/integration_test.go index ca01722b..2356f0c3 100644 --- a/integration_test.go +++ b/integration_test.go @@ -42,7 +42,7 @@ type testSpin struct { cmd *exec.Cmd } -func startSpin(t *testing.T, dir string) *testSpin { +func startSpin(t *testing.T, dir string, extraArgs ...string) *testSpin { buildApp(t, dir) url := getFreePort(t) @@ -50,7 +50,7 @@ func startSpin(t *testing.T, dir string) *testSpin { // long timeout because... ci ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - cmd := exec.CommandContext(ctx, spinBinary, "up", "--listen", url) + cmd := exec.CommandContext(ctx, spinBinary, append([]string{"up", "--listen", url}, extraArgs...)...) cmd.Dir = dir stderr := new(bytes.Buffer) cmd.Stderr = stderr @@ -60,7 +60,7 @@ func startSpin(t *testing.T, dir string) *testSpin { } go func() { - cmd.Wait() + _ = cmd.Wait() if ctx.Err() == nil { t.Log("spin exited before the test finished:", cmd.ProcessState) t.Log("stderr:\n", stderr.String()) @@ -91,8 +91,8 @@ func buildApp(t *testing.T, dir string) { } } -func TestSpinRoundTrip(t *testing.T) { - spin := startSpin(t, "http/testdata/spin-roundtrip") +func TestHTTPTrigger(t *testing.T) { + spin := startSpin(t, "http/testdata/http") defer spin.cancel() resp := retryGet(t, spin.url+"/hello") @@ -108,15 +108,20 @@ func TestSpinRoundTrip(t *testing.T) { } // assert response body - want := "Hello world!\n" + want := "== RESPONSE ==\nHello spinframework!\nHello again spinframework!\n" got := string(b) if want != got { t.Fatalf("body is not equal: want = %q got = %q", want, got) } + + // assert response header + if resp.Header.Get("foo") != "bar" { + t.Fatal("header 'foo' was not set") + } } -func TestHTTPTriger(t *testing.T) { - spin := startSpin(t, "http/testdata/http-tinygo") +func TestKeyValue(t *testing.T) { + spin := startSpin(t, "kv/testdata/key-value") defer spin.cancel() resp := retryGet(t, spin.url+"/hello") @@ -132,26 +137,44 @@ func TestHTTPTriger(t *testing.T) { } // assert response body - want := "Hello world!\n" + want := "[\"foo\"]\n" got := string(b) if want != got { t.Fatalf("body is not equal: want = %q got = %q", want, got) } +} - // assert response header - if resp.Header.Get("foo") != "bar" { - t.Fatal("header 'foo' was not set") +func TestVariables(t *testing.T) { + spin := startSpin(t, "variables/testdata/variables") + defer spin.cancel() + + resp := retryGet(t, spin.url) + spin.cancel() + if resp.Body == nil { + t.Fatal("body is nil") + } + t.Log(resp.Status) + b, err := io.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + t.Fatal(err) + } + + // assert response body + want := "message: I'm a teapot\n" + got := string(b) + if want != got { + t.Fatalf("body is not equal: want = %q got = %q", want, got) } } -// TestBuildExamples ensures that the tinygo examples will build successfully. +// TestBuildExamples ensures that the Go examples will build successfully. func TestBuildExamples(t *testing.T) { examples, err := os.ReadDir("examples") if err != nil { t.Fatal(err) } for _, example := range examples { - example := example t.Run(example.Name(), func(t *testing.T) { t.Parallel() buildApp(t, filepath.Join("examples", example.Name())) diff --git a/internal/db/driver.go b/internal/db/driver.go index 2b3ab757..e1c99051 100644 --- a/internal/db/driver.go +++ b/internal/db/driver.go @@ -1,8 +1,6 @@ package db -import ( - "database/sql/driver" -) +import "database/sql/driver" // GlobalParameterConverter is a global valueConverter instance to convert parameters. var GlobalParameterConverter = &valueConverter{} diff --git a/internal/export_fermyon_spin_inbound_redis/wit_bindings.go b/internal/export_fermyon_spin_inbound_redis/wit_bindings.go new file mode 100644 index 00000000..9d10b9b5 --- /dev/null +++ b/internal/export_fermyon_spin_inbound_redis/wit_bindings.go @@ -0,0 +1,14 @@ +package export_fermyon_spin_inbound_redis + +import ( + redis_types "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_redis_types" + wit "go.bytecodealliance.org/pkg/wit/types" +) + +var Exports struct { + Handle func(message []byte) wit.Result[wit.Unit, redis_types.Error] +} + +func HandleMessage(message []byte) wit.Result[wit.Unit, redis_types.Error] { + return Exports.Handle(message) +} diff --git a/internal/export_wasi_http_0_2_0_incoming_handler/wit_bindings.go b/internal/export_wasi_http_0_2_0_incoming_handler/wit_bindings.go new file mode 100644 index 00000000..6c58194a --- /dev/null +++ b/internal/export_wasi_http_0_2_0_incoming_handler/wit_bindings.go @@ -0,0 +1,13 @@ +package export_wasi_http_0_2_0_incoming_handler + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" +) + +var Exports struct { + Handle func(request *wasi_http_0_2_0_types.IncomingRequest, responseOut *wasi_http_0_2_0_types.ResponseOutparam) +} + +func Handle(request *wasi_http_0_2_0_types.IncomingRequest, responseOut *wasi_http_0_2_0_types.ResponseOutparam) { + Exports.Handle(request, responseOut) +} diff --git a/internal/fermyon_spin_2_0_0_key_value/wit_bindings.go b/internal/fermyon_spin_2_0_0_key_value/wit_bindings.go new file mode 100644 index 00000000..f463a80e --- /dev/null +++ b/internal/fermyon_spin_2_0_0_key_value/wit_bindings.go @@ -0,0 +1,440 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_key_value + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +//go:wasmimport fermyon:spin/key-value@2.0.0 [resource-drop]store +func resourceDropStore(handle int32) + +// An open key-value store +type Store struct { + handle *witRuntime.Handle +} + +func (self *Store) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Store) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Store) Handle() int32 { + return self.handle.Use() +} + +func (self *Store) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropStore(handle) + } +} + +func StoreFromOwnHandle(handleValue int32) *Store { + handle := witRuntime.MakeHandle(handleValue) + value := &Store{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropStore(handleValue) + } + }, 0) + return value +} + +func StoreFromBorrowHandle(handleValue int32) *Store { + handle := witRuntime.MakeHandle(handleValue) + return &Store{handle} +} + +const ( + // Too many stores have been opened simultaneously. Closing one or more + // stores prior to retrying may address this. + ErrorStoreTableFull uint8 = 0 + // The host does not recognize the store label requested. + ErrorNoSuchStore uint8 = 1 + // The requesting component does not have access to the specified store + // (which may or may not exist). + ErrorAccessDenied uint8 = 2 + // Some implementation-specific error has occurred (e.g. I/O) + ErrorOther uint8 = 3 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorStoreTableFull() Error { + return Error{ErrorStoreTableFull, nil} +} +func MakeErrorNoSuchStore() Error { + return Error{ErrorNoSuchStore, nil} +} +func MakeErrorAccessDenied() Error { + return Error{ErrorAccessDenied, nil} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [static]store.open +func wasm_import_static_store_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func StoreOpen(label string) witTypes.Result[*Store, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(label)) + pinner.Pin(utf8) + wasm_import_static_store_open(uintptr(utf8), uint32(len(label)), returnArea) + var result witTypes.Result[*Store, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Store, Error](StoreFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Store, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [method]store.get +func wasm_import_method_store_get(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Store) Get(key string) witTypes.Result[witTypes.Option[[]uint8], Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_store_get((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Option[[]uint8], Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[[]uint8]() + case 1: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + option = witTypes.Some[[]uint8](value) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[[]uint8], Error](option) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[[]uint8], Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [method]store.set +func wasm_import_method_store_set(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Store) Set(key string, value []uint8) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_method_store_set((self).Handle(), uintptr(utf8), uint32(len(key)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [method]store.delete +func wasm_import_method_store_delete(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Store) Delete(key string) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_store_delete((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [method]store.exists +func wasm_import_method_store_exists(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Store) Exists(key string) witTypes.Result[bool, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_store_exists((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[bool, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[bool, Error]((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) != 0)) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[bool, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value@2.0.0 [method]store.get-keys +func wasm_import_method_store_get_keys(arg0 int32, arg1 uintptr) + +func (self *Store) GetKeys() witTypes.Result[[]string, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_method_store_get_keys((self).Handle(), returnArea) + var result1 witTypes.Result[[]string, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result1 = witTypes.Ok[[]string, Error](result) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result1 = witTypes.Err[[]string, Error](variant) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} diff --git a/internal/fermyon_spin_2_0_0_llm/wit_bindings.go b/internal/fermyon_spin_2_0_0_llm/wit_bindings.go new file mode 100644 index 00000000..ffe5b8fb --- /dev/null +++ b/internal/fermyon_spin_2_0_0_llm/wit_bindings.go @@ -0,0 +1,278 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_llm + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +// A Large Language Model. +type InferencingModel = string + +// Inference request parameters +type InferencingParams struct { + // The maximum tokens that should be inferred. + // + // Note: the backing implementation may return less tokens. + MaxTokens uint32 + // The amount the model should avoid repeating tokens. + RepeatPenalty float32 + // The number of tokens the model should apply the repeat penalty to. + RepeatPenaltyLastNTokenCount uint32 + // The randomness with which the next token is selected. + Temperature float32 + // The number of possible next tokens the model will choose from. + TopK uint32 + // The probability total of next tokens the model will choose from. + TopP float32 +} + +const ( + ErrorModelNotSupported uint8 = 0 + ErrorRuntimeError uint8 = 1 + ErrorInvalidInput uint8 = 2 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) RuntimeError() string { + if self.tag != ErrorRuntimeError { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) InvalidInput() string { + if self.tag != ErrorInvalidInput { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorModelNotSupported() Error { + return Error{ErrorModelNotSupported, nil} +} +func MakeErrorRuntimeError(value string) Error { + return Error{ErrorRuntimeError, value} +} +func MakeErrorInvalidInput(value string) Error { + return Error{ErrorInvalidInput, value} +} + +// Usage information related to the inferencing result +type InferencingUsage struct { + // Number of tokens in the prompt + PromptTokenCount uint32 + // Number of tokens generated by the inferencing operation + GeneratedTokenCount uint32 +} + +// An inferencing result +type InferencingResult struct { + // The text generated by the model + // TODO: this should be a stream + Text string + // Usage information about the inferencing request + Usage InferencingUsage +} + +// The model used for generating embeddings +type EmbeddingModel = string + +// Usage related to an embeddings generation request +type EmbeddingsUsage struct { + // Number of tokens in the prompt + PromptTokenCount uint32 +} + +// Result of generating embeddings +type EmbeddingsResult struct { + // The embeddings generated by the request + Embeddings [][]float32 + // Usage related to the embeddings generation request + Usage EmbeddingsUsage +} + +//go:wasmimport fermyon:spin/llm@2.0.0 infer +func wasm_import_infer(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 int32, arg5 int32, arg6 float32, arg7 int32, arg8 float32, arg9 int32, arg10 float32, arg11 uintptr) + +func Infer(model string, prompt string, params witTypes.Option[InferencingParams]) witTypes.Result[InferencingResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (8 + 3*4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(model)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(prompt)) + pinner.Pin(utf80) + var option int32 + var option1 int32 + var option2 float32 + var option3 int32 + var option4 float32 + var option5 int32 + var option6 float32 + switch params.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option1 = 0 + option2 = 0 + option3 = 0 + option4 = 0 + option5 = 0 + option6 = 0 + case witTypes.OptionSome: + payload := params.Some() + + option = int32(1) + option1 = int32((payload).MaxTokens) + option2 = (payload).RepeatPenalty + option3 = int32((payload).RepeatPenaltyLastNTokenCount) + option4 = (payload).Temperature + option5 = int32((payload).TopK) + option6 = (payload).TopP + default: + panic("unreachable") + } + wasm_import_infer(uintptr(utf8), uint32(len(model)), uintptr(utf80), uint32(len(prompt)), option, option1, option2, option3, option4, option5, option6, returnArea) + var result witTypes.Result[InferencingResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[InferencingResult, Error](InferencingResult{value, InferencingUsage{uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (4 + 3*4))))}}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorModelNotSupported() + + case 1: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorRuntimeError(value7) + + case 2: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidInput(value8) + + default: + panic("unreachable") + } + + result = witTypes.Err[InferencingResult, Error](variant) + default: + panic("unreachable") + } + result9 := result + return result9 + +} + +//go:wasmimport fermyon:spin/llm@2.0.0 generate-embeddings +func wasm_import_generate_embeddings(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func GenerateEmbeddings(model string, text []string) witTypes.Result[EmbeddingsResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(model)) + pinner.Pin(utf8) + slice := text + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf80 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + + } + + wasm_import_generate_embeddings(uintptr(utf8), uint32(len(model)), uintptr(result), length, returnArea) + var result4 witTypes.Result[EmbeddingsResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([][]float32, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.Slice((*float32)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result1 = append(result1, value) + } + + result4 = witTypes.Ok[EmbeddingsResult, Error](EmbeddingsResult{result1, EmbeddingsUsage{uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))}}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorModelNotSupported() + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorRuntimeError(value2) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidInput(value3) + + default: + panic("unreachable") + } + + result4 = witTypes.Err[EmbeddingsResult, Error](variant) + default: + panic("unreachable") + } + result5 := result4 + return result5 + +} diff --git a/internal/fermyon_spin_2_0_0_mqtt/wit_bindings.go b/internal/fermyon_spin_2_0_0_mqtt/wit_bindings.go new file mode 100644 index 00000000..b4318091 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_mqtt/wit_bindings.go @@ -0,0 +1,248 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_mqtt + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + // An invalid address string + ErrorInvalidAddress uint8 = 0 + // There are too many open connections + ErrorTooManyConnections uint8 = 1 + // Connection failure e.g. address not allowed. + ErrorConnectionFailed uint8 = 2 + // Some other error occurred + ErrorOther uint8 = 3 +) + +// Errors related to interacting with Mqtt +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) ConnectionFailed() string { + if self.tag != ErrorConnectionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorInvalidAddress() Error { + return Error{ErrorInvalidAddress, nil} +} +func MakeErrorTooManyConnections() Error { + return Error{ErrorTooManyConnections, nil} +} +func MakeErrorConnectionFailed(value string) Error { + return Error{ErrorConnectionFailed, value} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +const ( + QosAtMostOnce uint8 = 0 + QosAtLeastOnce uint8 = 1 + QosExactlyOnce uint8 = 2 +) + +// QoS for publishing Mqtt messages +type Qos = uint8 + +//go:wasmimport fermyon:spin/mqtt@2.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +// The message payload. +type Payload = []uint8 + +//go:wasmimport fermyon:spin/mqtt@2.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 int64, arg7 uintptr) + +func ConnectionOpen(address string, username string, password string, keepAliveIntervalInSecs uint64) witTypes.Result[*Connection, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(username)) + pinner.Pin(utf80) + utf81 := unsafe.Pointer(unsafe.StringData(password)) + pinner.Pin(utf81) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(username)), uintptr(utf81), uint32(len(password)), int64(keepAliveIntervalInSecs), returnArea) + var result witTypes.Result[*Connection, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorConnectionFailed(value) + + case 3: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value2) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, Error](variant) + default: + panic("unreachable") + } + result3 := result + return result3 + +} + +//go:wasmimport fermyon:spin/mqtt@2.0.0 [method]connection.publish +func wasm_import_method_connection_publish(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 int32, arg6 uintptr) + +func (self *Connection) Publish(topic string, payload []uint8, qos Qos) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(topic)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + wasm_import_method_connection_publish((self).Handle(), uintptr(utf8), uint32(len(topic)), uintptr(data), uint32(len(payload)), int32(qos), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorConnectionFailed(value) + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} diff --git a/internal/fermyon_spin_2_0_0_mysql/wit_bindings.go b/internal/fermyon_spin_2_0_0_mysql/wit_bindings.go new file mode 100644 index 00000000..ed7fdb65 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_mysql/wit_bindings.go @@ -0,0 +1,535 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_mysql + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_rdbms_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type ParameterValue = fermyon_spin_2_0_0_rdbms_types.ParameterValue +type RowSet = fermyon_spin_2_0_0_rdbms_types.RowSet +type Error = fermyon_spin_2_0_0_rdbms_types.Error + +//go:wasmimport fermyon:spin/mysql@2.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +// A connection to a MySQL database. +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +//go:wasmimport fermyon:spin/mysql@2.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func ConnectionOpen(address string) witTypes.Result[*Connection, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(address)), returnArea) + var result witTypes.Result[*Connection, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, fermyon_spin_2_0_0_rdbms_types.Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value) + + case 1: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value0) + + case 2: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value1) + + case 3: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value2) + + case 4: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value3) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, fermyon_spin_2_0_0_rdbms_types.Error](variant) + default: + panic("unreachable") + } + result4 := result + return result4 + +} + +//go:wasmimport fermyon:spin/mysql@2.0.0 [method]connection.query +func wasm_import_method_connection_query(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Query(statement string, params []fermyon_spin_2_0_0_rdbms_types.ParameterValue) witTypes.Result[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_query((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result13 witTypes.Result[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result2 := make([]fermyon_spin_2_0_0_rdbms_types.Column, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result2 = append(result2, fermyon_spin_2_0_0_rdbms_types.Column{value, uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))}) + } + + result6 := make([][]fermyon_spin_2_0_0_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result5 := make([]fermyon_spin_2_0_0_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant fermyon_spin_2_0_0_rdbms_types.DbValue + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueBoolean((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))) != 0)) + + case 1: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt8(int8(int8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 2: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt16(int16(int16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 3: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 4: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 5: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint8(uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 6: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint16(uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 7: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint32(uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 8: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint64(uint64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 9: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueFloating32(*(*float32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 10: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueFloating64(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 11: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueStr(value3) + + case 12: + value4 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueBinary(value4) + + case 13: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueDbNull() + + case 14: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUnsupported() + + default: + panic("unreachable") + } + + result5 = append(result5, variant) + } + + result6 = append(result6, result5) + } + + result13 = witTypes.Ok[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error](fermyon_spin_2_0_0_rdbms_types.RowSet{result2, result6}) + case 1: + var variant12 fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value7) + + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value8) + + case 2: + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value9) + + case 3: + value10 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value10) + + case 4: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value11) + + default: + panic("unreachable") + } + + result13 = witTypes.Err[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error](variant12) + default: + panic("unreachable") + } + result14 := result13 + return result14 + +} + +//go:wasmimport fermyon:spin/mysql@2.0.0 [method]connection.execute +func wasm_import_method_connection_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Execute(statement string, params []fermyon_spin_2_0_0_rdbms_types.ParameterValue) witTypes.Result[witTypes.Unit, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_execute((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result6 witTypes.Result[witTypes.Unit, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result6 = witTypes.Ok[witTypes.Unit, fermyon_spin_2_0_0_rdbms_types.Error](witTypes.Unit{}) + case 1: + var variant fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value) + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value2) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value3) + + case 3: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value4) + + case 4: + value5 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value5) + + default: + panic("unreachable") + } + + result6 = witTypes.Err[witTypes.Unit, fermyon_spin_2_0_0_rdbms_types.Error](variant) + default: + panic("unreachable") + } + result7 := result6 + return result7 + +} diff --git a/internal/fermyon_spin_2_0_0_postgres/wit_bindings.go b/internal/fermyon_spin_2_0_0_postgres/wit_bindings.go new file mode 100644 index 00000000..bbc4bd35 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_postgres/wit_bindings.go @@ -0,0 +1,535 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_postgres + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_rdbms_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type ParameterValue = fermyon_spin_2_0_0_rdbms_types.ParameterValue +type RowSet = fermyon_spin_2_0_0_rdbms_types.RowSet +type Error = fermyon_spin_2_0_0_rdbms_types.Error + +//go:wasmimport fermyon:spin/postgres@2.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +// A connection to a postgres database. +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +//go:wasmimport fermyon:spin/postgres@2.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func ConnectionOpen(address string) witTypes.Result[*Connection, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(address)), returnArea) + var result witTypes.Result[*Connection, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, fermyon_spin_2_0_0_rdbms_types.Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value) + + case 1: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value0) + + case 2: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value1) + + case 3: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value2) + + case 4: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value3) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, fermyon_spin_2_0_0_rdbms_types.Error](variant) + default: + panic("unreachable") + } + result4 := result + return result4 + +} + +//go:wasmimport fermyon:spin/postgres@2.0.0 [method]connection.query +func wasm_import_method_connection_query(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Query(statement string, params []fermyon_spin_2_0_0_rdbms_types.ParameterValue) witTypes.Result[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_query((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result13 witTypes.Result[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result2 := make([]fermyon_spin_2_0_0_rdbms_types.Column, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result2 = append(result2, fermyon_spin_2_0_0_rdbms_types.Column{value, uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))}) + } + + result6 := make([][]fermyon_spin_2_0_0_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result5 := make([]fermyon_spin_2_0_0_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant fermyon_spin_2_0_0_rdbms_types.DbValue + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueBoolean((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))) != 0)) + + case 1: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt8(int8(int8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 2: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt16(int16(int16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 3: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 4: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 5: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint8(uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 6: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint16(uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 7: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint32(uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 8: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUint64(uint64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 9: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueFloating32(*(*float32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 10: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueFloating64(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 11: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueStr(value3) + + case 12: + value4 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueBinary(value4) + + case 13: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueDbNull() + + case 14: + + variant = fermyon_spin_2_0_0_rdbms_types.MakeDbValueUnsupported() + + default: + panic("unreachable") + } + + result5 = append(result5, variant) + } + + result6 = append(result6, result5) + } + + result13 = witTypes.Ok[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error](fermyon_spin_2_0_0_rdbms_types.RowSet{result2, result6}) + case 1: + var variant12 fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value7) + + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value8) + + case 2: + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value9) + + case 3: + value10 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value10) + + case 4: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value11) + + default: + panic("unreachable") + } + + result13 = witTypes.Err[fermyon_spin_2_0_0_rdbms_types.RowSet, fermyon_spin_2_0_0_rdbms_types.Error](variant12) + default: + panic("unreachable") + } + result14 := result13 + return result14 + +} + +//go:wasmimport fermyon:spin/postgres@2.0.0 [method]connection.execute +func wasm_import_method_connection_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Execute(statement string, params []fermyon_spin_2_0_0_rdbms_types.ParameterValue) witTypes.Result[uint64, fermyon_spin_2_0_0_rdbms_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (16 + 2*4), 8)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_2_0_0_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_execute((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result6 witTypes.Result[uint64, fermyon_spin_2_0_0_rdbms_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result6 = witTypes.Ok[uint64, fermyon_spin_2_0_0_rdbms_types.Error](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant fermyon_spin_2_0_0_rdbms_types.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorConnectionFailed(value) + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorBadParameter(value2) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorQueryFailed(value3) + + case 3: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorValueConversionFailed(value4) + + case 4: + value5 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = fermyon_spin_2_0_0_rdbms_types.MakeErrorOther(value5) + + default: + panic("unreachable") + } + + result6 = witTypes.Err[uint64, fermyon_spin_2_0_0_rdbms_types.Error](variant) + default: + panic("unreachable") + } + result7 := result6 + return result7 + +} diff --git a/internal/fermyon_spin_2_0_0_rdbms_types/wit_bindings.go b/internal/fermyon_spin_2_0_0_rdbms_types/wit_bindings.go new file mode 100644 index 00000000..55cb3bb2 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_rdbms_types/wit_bindings.go @@ -0,0 +1,437 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_rdbms_types + +import () + +const ( + ErrorConnectionFailed uint8 = 0 + ErrorBadParameter uint8 = 1 + ErrorQueryFailed uint8 = 2 + ErrorValueConversionFailed uint8 = 3 + ErrorOther uint8 = 4 +) + +// Errors related to interacting with a database. +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) ConnectionFailed() string { + if self.tag != ErrorConnectionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) BadParameter() string { + if self.tag != ErrorBadParameter { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) QueryFailed() string { + if self.tag != ErrorQueryFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) ValueConversionFailed() string { + if self.tag != ErrorValueConversionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorConnectionFailed(value string) Error { + return Error{ErrorConnectionFailed, value} +} +func MakeErrorBadParameter(value string) Error { + return Error{ErrorBadParameter, value} +} +func MakeErrorQueryFailed(value string) Error { + return Error{ErrorQueryFailed, value} +} +func MakeErrorValueConversionFailed(value string) Error { + return Error{ErrorValueConversionFailed, value} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +const ( + DbDataTypeBoolean uint8 = 0 + DbDataTypeInt8 uint8 = 1 + DbDataTypeInt16 uint8 = 2 + DbDataTypeInt32 uint8 = 3 + DbDataTypeInt64 uint8 = 4 + DbDataTypeUint8 uint8 = 5 + DbDataTypeUint16 uint8 = 6 + DbDataTypeUint32 uint8 = 7 + DbDataTypeUint64 uint8 = 8 + DbDataTypeFloating32 uint8 = 9 + DbDataTypeFloating64 uint8 = 10 + DbDataTypeStr uint8 = 11 + DbDataTypeBinary uint8 = 12 + DbDataTypeOther uint8 = 13 +) + +// Data types for a database column +type DbDataType = uint8 + +const ( + DbValueBoolean uint8 = 0 + DbValueInt8 uint8 = 1 + DbValueInt16 uint8 = 2 + DbValueInt32 uint8 = 3 + DbValueInt64 uint8 = 4 + DbValueUint8 uint8 = 5 + DbValueUint16 uint8 = 6 + DbValueUint32 uint8 = 7 + DbValueUint64 uint8 = 8 + DbValueFloating32 uint8 = 9 + DbValueFloating64 uint8 = 10 + DbValueStr uint8 = 11 + DbValueBinary uint8 = 12 + DbValueDbNull uint8 = 13 + DbValueUnsupported uint8 = 14 +) + +// Database values +type DbValue struct { + tag uint8 + value any +} + +func (self DbValue) Tag() uint8 { + return self.tag +} + +func (self DbValue) Boolean() bool { + if self.tag != DbValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self DbValue) Int8() int8 { + if self.tag != DbValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self DbValue) Int16() int16 { + if self.tag != DbValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self DbValue) Int32() int32 { + if self.tag != DbValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self DbValue) Int64() int64 { + if self.tag != DbValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self DbValue) Uint8() uint8 { + if self.tag != DbValueUint8 { + panic("tag mismatch") + } + return self.value.(uint8) +} +func (self DbValue) Uint16() uint16 { + if self.tag != DbValueUint16 { + panic("tag mismatch") + } + return self.value.(uint16) +} +func (self DbValue) Uint32() uint32 { + if self.tag != DbValueUint32 { + panic("tag mismatch") + } + return self.value.(uint32) +} +func (self DbValue) Uint64() uint64 { + if self.tag != DbValueUint64 { + panic("tag mismatch") + } + return self.value.(uint64) +} +func (self DbValue) Floating32() float32 { + if self.tag != DbValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self DbValue) Floating64() float64 { + if self.tag != DbValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self DbValue) Str() string { + if self.tag != DbValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self DbValue) Binary() []uint8 { + if self.tag != DbValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeDbValueBoolean(value bool) DbValue { + return DbValue{DbValueBoolean, value} +} +func MakeDbValueInt8(value int8) DbValue { + return DbValue{DbValueInt8, value} +} +func MakeDbValueInt16(value int16) DbValue { + return DbValue{DbValueInt16, value} +} +func MakeDbValueInt32(value int32) DbValue { + return DbValue{DbValueInt32, value} +} +func MakeDbValueInt64(value int64) DbValue { + return DbValue{DbValueInt64, value} +} +func MakeDbValueUint8(value uint8) DbValue { + return DbValue{DbValueUint8, value} +} +func MakeDbValueUint16(value uint16) DbValue { + return DbValue{DbValueUint16, value} +} +func MakeDbValueUint32(value uint32) DbValue { + return DbValue{DbValueUint32, value} +} +func MakeDbValueUint64(value uint64) DbValue { + return DbValue{DbValueUint64, value} +} +func MakeDbValueFloating32(value float32) DbValue { + return DbValue{DbValueFloating32, value} +} +func MakeDbValueFloating64(value float64) DbValue { + return DbValue{DbValueFloating64, value} +} +func MakeDbValueStr(value string) DbValue { + return DbValue{DbValueStr, value} +} +func MakeDbValueBinary(value []uint8) DbValue { + return DbValue{DbValueBinary, value} +} +func MakeDbValueDbNull() DbValue { + return DbValue{DbValueDbNull, nil} +} +func MakeDbValueUnsupported() DbValue { + return DbValue{DbValueUnsupported, nil} +} + +const ( + ParameterValueBoolean uint8 = 0 + ParameterValueInt8 uint8 = 1 + ParameterValueInt16 uint8 = 2 + ParameterValueInt32 uint8 = 3 + ParameterValueInt64 uint8 = 4 + ParameterValueUint8 uint8 = 5 + ParameterValueUint16 uint8 = 6 + ParameterValueUint32 uint8 = 7 + ParameterValueUint64 uint8 = 8 + ParameterValueFloating32 uint8 = 9 + ParameterValueFloating64 uint8 = 10 + ParameterValueStr uint8 = 11 + ParameterValueBinary uint8 = 12 + ParameterValueDbNull uint8 = 13 +) + +// Values used in parameterized queries +type ParameterValue struct { + tag uint8 + value any +} + +func (self ParameterValue) Tag() uint8 { + return self.tag +} + +func (self ParameterValue) Boolean() bool { + if self.tag != ParameterValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self ParameterValue) Int8() int8 { + if self.tag != ParameterValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self ParameterValue) Int16() int16 { + if self.tag != ParameterValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self ParameterValue) Int32() int32 { + if self.tag != ParameterValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self ParameterValue) Int64() int64 { + if self.tag != ParameterValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self ParameterValue) Uint8() uint8 { + if self.tag != ParameterValueUint8 { + panic("tag mismatch") + } + return self.value.(uint8) +} +func (self ParameterValue) Uint16() uint16 { + if self.tag != ParameterValueUint16 { + panic("tag mismatch") + } + return self.value.(uint16) +} +func (self ParameterValue) Uint32() uint32 { + if self.tag != ParameterValueUint32 { + panic("tag mismatch") + } + return self.value.(uint32) +} +func (self ParameterValue) Uint64() uint64 { + if self.tag != ParameterValueUint64 { + panic("tag mismatch") + } + return self.value.(uint64) +} +func (self ParameterValue) Floating32() float32 { + if self.tag != ParameterValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self ParameterValue) Floating64() float64 { + if self.tag != ParameterValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self ParameterValue) Str() string { + if self.tag != ParameterValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self ParameterValue) Binary() []uint8 { + if self.tag != ParameterValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeParameterValueBoolean(value bool) ParameterValue { + return ParameterValue{ParameterValueBoolean, value} +} +func MakeParameterValueInt8(value int8) ParameterValue { + return ParameterValue{ParameterValueInt8, value} +} +func MakeParameterValueInt16(value int16) ParameterValue { + return ParameterValue{ParameterValueInt16, value} +} +func MakeParameterValueInt32(value int32) ParameterValue { + return ParameterValue{ParameterValueInt32, value} +} +func MakeParameterValueInt64(value int64) ParameterValue { + return ParameterValue{ParameterValueInt64, value} +} +func MakeParameterValueUint8(value uint8) ParameterValue { + return ParameterValue{ParameterValueUint8, value} +} +func MakeParameterValueUint16(value uint16) ParameterValue { + return ParameterValue{ParameterValueUint16, value} +} +func MakeParameterValueUint32(value uint32) ParameterValue { + return ParameterValue{ParameterValueUint32, value} +} +func MakeParameterValueUint64(value uint64) ParameterValue { + return ParameterValue{ParameterValueUint64, value} +} +func MakeParameterValueFloating32(value float32) ParameterValue { + return ParameterValue{ParameterValueFloating32, value} +} +func MakeParameterValueFloating64(value float64) ParameterValue { + return ParameterValue{ParameterValueFloating64, value} +} +func MakeParameterValueStr(value string) ParameterValue { + return ParameterValue{ParameterValueStr, value} +} +func MakeParameterValueBinary(value []uint8) ParameterValue { + return ParameterValue{ParameterValueBinary, value} +} +func MakeParameterValueDbNull() ParameterValue { + return ParameterValue{ParameterValueDbNull, nil} +} + +// A database column +type Column struct { + Name string + DataType DbDataType +} + +// A database row +type Row = []DbValue + +// A set of database rows +type RowSet struct { + Columns []Column + Rows [][]DbValue +} diff --git a/internal/fermyon_spin_2_0_0_redis/wit_bindings.go b/internal/fermyon_spin_2_0_0_redis/wit_bindings.go new file mode 100644 index 00000000..5b56e8af --- /dev/null +++ b/internal/fermyon_spin_2_0_0_redis/wit_bindings.go @@ -0,0 +1,813 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_redis + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + // An invalid address string + ErrorInvalidAddress uint8 = 0 + // There are too many open connections + ErrorTooManyConnections uint8 = 1 + // A retrieved value was not of the correct type + ErrorTypeError uint8 = 2 + // Some other error occurred + ErrorOther uint8 = 3 +) + +// Errors related to interacting with Redis +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorInvalidAddress() Error { + return Error{ErrorInvalidAddress, nil} +} +func MakeErrorTooManyConnections() Error { + return Error{ErrorTooManyConnections, nil} +} +func MakeErrorTypeError() Error { + return Error{ErrorTypeError, nil} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +// The message payload. +type Payload = []uint8 + +const ( + RedisParameterInt64 uint8 = 0 + RedisParameterBinary uint8 = 1 +) + +// A parameter type for the general-purpose `execute` function. +type RedisParameter struct { + tag uint8 + value any +} + +func (self RedisParameter) Tag() uint8 { + return self.tag +} + +func (self RedisParameter) Int64() int64 { + if self.tag != RedisParameterInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self RedisParameter) Binary() []uint8 { + if self.tag != RedisParameterBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeRedisParameterInt64(value int64) RedisParameter { + return RedisParameter{RedisParameterInt64, value} +} +func MakeRedisParameterBinary(value []uint8) RedisParameter { + return RedisParameter{RedisParameterBinary, value} +} + +const ( + RedisResultNil uint8 = 0 + RedisResultStatus uint8 = 1 + RedisResultInt64 uint8 = 2 + RedisResultBinary uint8 = 3 +) + +// A return type for the general-purpose `execute` function. +type RedisResult struct { + tag uint8 + value any +} + +func (self RedisResult) Tag() uint8 { + return self.tag +} + +func (self RedisResult) Status() string { + if self.tag != RedisResultStatus { + panic("tag mismatch") + } + return self.value.(string) +} +func (self RedisResult) Int64() int64 { + if self.tag != RedisResultInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self RedisResult) Binary() []uint8 { + if self.tag != RedisResultBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeRedisResultNil() RedisResult { + return RedisResult{RedisResultNil, nil} +} +func MakeRedisResultStatus(value string) RedisResult { + return RedisResult{RedisResultStatus, value} +} +func MakeRedisResultInt64(value int64) RedisResult { + return RedisResult{RedisResultInt64, value} +} +func MakeRedisResultBinary(value []uint8) RedisResult { + return RedisResult{RedisResultBinary, value} +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func ConnectionOpen(address string) witTypes.Result[*Connection, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(address)), returnArea) + var result witTypes.Result[*Connection, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.publish +func wasm_import_method_connection_publish(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Publish(channel string, payload []uint8) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(channel)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + wasm_import_method_connection_publish((self).Handle(), uintptr(utf8), uint32(len(channel)), uintptr(data), uint32(len(payload)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.get +func wasm_import_method_connection_get(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Connection) Get(key string) witTypes.Result[witTypes.Option[[]uint8], Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_connection_get((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Option[[]uint8], Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[[]uint8]() + case 1: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + option = witTypes.Some[[]uint8](value) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[[]uint8], Error](option) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[[]uint8], Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.set +func wasm_import_method_connection_set(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Set(key string, value []uint8) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_method_connection_set((self).Handle(), uintptr(utf8), uint32(len(key)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.incr +func wasm_import_method_connection_incr(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Connection) Incr(key string) witTypes.Result[int64, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (16 + 2*4), 8)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_connection_incr((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[int64, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[int64, Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[int64, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.del +func wasm_import_method_connection_del(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Connection) Del(keys []string) witTypes.Result[uint32, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + slice := keys + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf8 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf8) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf8))) + + } + + wasm_import_method_connection_del((self).Handle(), uintptr(result), length, returnArea) + var result0 witTypes.Result[uint32, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[uint32, Error](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result0 = witTypes.Err[uint32, Error](variant) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.sadd +func wasm_import_method_connection_sadd(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Sadd(key string, values []string) witTypes.Result[uint32, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + slice := values + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf80 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + + } + + wasm_import_method_connection_sadd((self).Handle(), uintptr(utf8), uint32(len(key)), uintptr(result), length, returnArea) + var result1 witTypes.Result[uint32, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result1 = witTypes.Ok[uint32, Error](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result1 = witTypes.Err[uint32, Error](variant) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.smembers +func wasm_import_method_connection_smembers(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Connection) Smembers(key string) witTypes.Result[[]string, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_connection_smembers((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result1 witTypes.Result[[]string, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result1 = witTypes.Ok[[]string, Error](result) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result1 = witTypes.Err[[]string, Error](variant) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.srem +func wasm_import_method_connection_srem(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Srem(key string, values []string) witTypes.Result[uint32, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + slice := values + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf80 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + + } + + wasm_import_method_connection_srem((self).Handle(), uintptr(utf8), uint32(len(key)), uintptr(result), length, returnArea) + var result1 witTypes.Result[uint32, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result1 = witTypes.Ok[uint32, Error](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorInvalidAddress() + + case 1: + + variant = MakeErrorTooManyConnections() + + case 2: + + variant = MakeErrorTypeError() + + case 3: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result1 = witTypes.Err[uint32, Error](variant) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/redis@2.0.0 [method]connection.execute +func wasm_import_method_connection_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Execute(command string, arguments []RedisParameter) witTypes.Result[[]RedisResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(command)) + pinner.Pin(utf8) + slice := arguments + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result, index*(8+2*4)) + + switch element.Tag() { + case RedisParameterInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case RedisParameterBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_execute((self).Handle(), uintptr(utf8), uint32(len(command)), uintptr(result), length, returnArea) + var result4 witTypes.Result[[]RedisResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([]RedisResult, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(8+2*4)) + var variant RedisResult + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = MakeRedisResultNil() + + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeRedisResultStatus(value) + + case 2: + + variant = MakeRedisResultInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 3: + value0 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeRedisResultBinary(value0) + + default: + panic("unreachable") + } + + result1 = append(result1, variant) + } + + result4 = witTypes.Ok[[]RedisResult, Error](result1) + case 1: + var variant3 Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant3 = MakeErrorInvalidAddress() + + case 1: + + variant3 = MakeErrorTooManyConnections() + + case 2: + + variant3 = MakeErrorTypeError() + + case 3: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant3 = MakeErrorOther(value2) + + default: + panic("unreachable") + } + + result4 = witTypes.Err[[]RedisResult, Error](variant3) + default: + panic("unreachable") + } + result5 := result4 + return result5 + +} diff --git a/internal/fermyon_spin_2_0_0_sqlite/wit_bindings.go b/internal/fermyon_spin_2_0_0_sqlite/wit_bindings.go new file mode 100644 index 00000000..cea653f3 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_sqlite/wit_bindings.go @@ -0,0 +1,398 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_sqlite + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +//go:wasmimport fermyon:spin/sqlite@2.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +// A handle to an open sqlite instance +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +const ( + // The host does not recognize the database name requested. + ErrorNoSuchDatabase uint8 = 0 + // The requesting component does not have access to the specified database (which may or may not exist). + ErrorAccessDenied uint8 = 1 + // The provided connection is not valid + ErrorInvalidConnection uint8 = 2 + // The database has reached its capacity + ErrorDatabaseFull uint8 = 3 + // Some implementation-specific error has occurred (e.g. I/O) + ErrorIo uint8 = 4 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Io() string { + if self.tag != ErrorIo { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorNoSuchDatabase() Error { + return Error{ErrorNoSuchDatabase, nil} +} +func MakeErrorAccessDenied() Error { + return Error{ErrorAccessDenied, nil} +} +func MakeErrorInvalidConnection() Error { + return Error{ErrorInvalidConnection, nil} +} +func MakeErrorDatabaseFull() Error { + return Error{ErrorDatabaseFull, nil} +} +func MakeErrorIo(value string) Error { + return Error{ErrorIo, value} +} + +const ( + ValueInteger uint8 = 0 + ValueReal uint8 = 1 + ValueText uint8 = 2 + ValueBlob uint8 = 3 + ValueNull uint8 = 4 +) + +// A single column's result from a database query +type Value struct { + tag uint8 + value any +} + +func (self Value) Tag() uint8 { + return self.tag +} + +func (self Value) Integer() int64 { + if self.tag != ValueInteger { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self Value) Real() float64 { + if self.tag != ValueReal { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self Value) Text() string { + if self.tag != ValueText { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Value) Blob() []uint8 { + if self.tag != ValueBlob { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeValueInteger(value int64) Value { + return Value{ValueInteger, value} +} +func MakeValueReal(value float64) Value { + return Value{ValueReal, value} +} +func MakeValueText(value string) Value { + return Value{ValueText, value} +} +func MakeValueBlob(value []uint8) Value { + return Value{ValueBlob, value} +} +func MakeValueNull() Value { + return Value{ValueNull, nil} +} + +// A set of values for each of the columns in a query-result +type RowResult struct { + Values []Value +} + +// A result of a query +type QueryResult struct { + // The names of the columns retrieved in the query + Columns []string + // the row results each containing the values for all the columns for a given row + Rows []RowResult +} + +//go:wasmimport fermyon:spin/sqlite@2.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func ConnectionOpen(database string) witTypes.Result[*Connection, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(database)) + pinner.Pin(utf8) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(database)), returnArea) + var result witTypes.Result[*Connection, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchDatabase() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + + variant = MakeErrorInvalidConnection() + + case 3: + + variant = MakeErrorDatabaseFull() + + case 4: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/sqlite@2.0.0 [method]connection.execute +func wasm_import_method_connection_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Execute(statement string, parameters []Value) witTypes.Result[QueryResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := parameters + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result, index*(8+2*4)) + + switch element.Tag() { + case ValueInteger: + payload := element.Integer() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ValueReal: + payload := element.Real() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ValueText: + payload := element.Text() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case ValueBlob: + payload := element.Blob() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case ValueNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_execute((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result), length, returnArea) + var result8 witTypes.Result[QueryResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result1 = append(result1, value) + } + + result5 := make([]RowResult, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result4 := make([]Value, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant Value + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = MakeValueInteger(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 1: + + variant = MakeValueReal(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 2: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeValueText(value2) + + case 3: + value3 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeValueBlob(value3) + + case 4: + + variant = MakeValueNull() + + default: + panic("unreachable") + } + + result4 = append(result4, variant) + } + + result5 = append(result5, RowResult{result4}) + } + + result8 = witTypes.Ok[QueryResult, Error](QueryResult{result1, result5}) + case 1: + var variant7 Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant7 = MakeErrorNoSuchDatabase() + + case 1: + + variant7 = MakeErrorAccessDenied() + + case 2: + + variant7 = MakeErrorInvalidConnection() + + case 3: + + variant7 = MakeErrorDatabaseFull() + + case 4: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant7 = MakeErrorIo(value6) + + default: + panic("unreachable") + } + + result8 = witTypes.Err[QueryResult, Error](variant7) + default: + panic("unreachable") + } + result9 := result8 + return result9 + +} diff --git a/internal/fermyon_spin_2_0_0_variables/wit_bindings.go b/internal/fermyon_spin_2_0_0_variables/wit_bindings.go new file mode 100644 index 00000000..93ee5451 --- /dev/null +++ b/internal/fermyon_spin_2_0_0_variables/wit_bindings.go @@ -0,0 +1,152 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_2_0_0_variables + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + // The provided variable name is invalid. + ErrorInvalidName uint8 = 0 + // The provided variable is undefined. + ErrorUndefined uint8 = 1 + // A variables provider specific error has occurred. + ErrorProvider uint8 = 2 + // Some implementation-specific error has occurred. + ErrorOther uint8 = 3 +) + +// The set of errors which may be raised by functions in this interface. +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) InvalidName() string { + if self.tag != ErrorInvalidName { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Undefined() string { + if self.tag != ErrorUndefined { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Provider() string { + if self.tag != ErrorProvider { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorInvalidName(value string) Error { + return Error{ErrorInvalidName, value} +} +func MakeErrorUndefined(value string) Error { + return Error{ErrorUndefined, value} +} +func MakeErrorProvider(value string) Error { + return Error{ErrorProvider, value} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +//go:wasmimport fermyon:spin/variables@2.0.0 get +func wasm_import_get(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Get(name string) witTypes.Result[string, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + wasm_import_get(uintptr(utf8), uint32(len(name)), returnArea) + var result witTypes.Result[string, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[string, Error](value) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidName(value0) + + case 1: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorUndefined(value1) + + case 2: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorProvider(value2) + + case 3: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value3) + + default: + panic("unreachable") + } + + result = witTypes.Err[string, Error](variant) + default: + panic("unreachable") + } + result4 := result + return result4 + +} diff --git a/internal/fermyon_spin_config/wit_bindings.go b/internal/fermyon_spin_config/wit_bindings.go new file mode 100644 index 00000000..4935e77a --- /dev/null +++ b/internal/fermyon_spin_config/wit_bindings.go @@ -0,0 +1,147 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_config + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + ErrorProvider uint8 = 0 + ErrorInvalidKey uint8 = 1 + ErrorInvalidSchema uint8 = 2 + ErrorOther uint8 = 3 +) + +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Provider() string { + if self.tag != ErrorProvider { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) InvalidKey() string { + if self.tag != ErrorInvalidKey { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) InvalidSchema() string { + if self.tag != ErrorInvalidSchema { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorProvider(value string) Error { + return Error{ErrorProvider, value} +} +func MakeErrorInvalidKey(value string) Error { + return Error{ErrorInvalidKey, value} +} +func MakeErrorInvalidSchema(value string) Error { + return Error{ErrorInvalidSchema, value} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +//go:wasmimport fermyon:spin/config get-config +func wasm_import_get_config(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func GetConfig(key string) witTypes.Result[string, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_get_config(uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[string, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[string, Error](value) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorProvider(value0) + + case 1: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidKey(value1) + + case 2: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidSchema(value2) + + case 3: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value3) + + default: + panic("unreachable") + } + + result = witTypes.Err[string, Error](variant) + default: + panic("unreachable") + } + result4 := result + return result4 + +} diff --git a/internal/fermyon_spin_http/wit_bindings.go b/internal/fermyon_spin_http/wit_bindings.go new file mode 100644 index 00000000..ab485e1a --- /dev/null +++ b/internal/fermyon_spin_http/wit_bindings.go @@ -0,0 +1,155 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_http + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_http_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Request = fermyon_spin_http_types.Request +type Response = fermyon_spin_http_types.Response +type HttpError = fermyon_spin_http_types.HttpError + +//go:wasmimport fermyon:spin/http send-request +func wasm_import_send_request(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr, arg6 uint32, arg7 int32, arg8 uintptr, arg9 uint32, arg10 uintptr) + +func SendRequest(req fermyon_spin_http_types.Request) witTypes.Result[fermyon_spin_http_types.Response, fermyon_spin_http_types.HttpError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (8 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData((req).Uri)) + pinner.Pin(utf8) + slice := (req).Headers + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(4*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(4*4)) + utf80 := unsafe.Pointer(unsafe.StringData((element).F0)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len((element).F0))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + utf81 := unsafe.Pointer(unsafe.StringData((element).F1)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4))) = uint32(uint32(len((element).F1))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = uint32(uintptr(uintptr(utf81))) + + } + + slice4 := (req).Params + length6 := uint32(len(slice4)) + result5 := witRuntime.Allocate(pinner, uintptr(length6*(4*4)), 4) + for index, element := range slice4 { + base := unsafe.Add(result5, index*(4*4)) + utf82 := unsafe.Pointer(unsafe.StringData((element).F0)) + pinner.Pin(utf82) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len((element).F0))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf82))) + utf83 := unsafe.Pointer(unsafe.StringData((element).F1)) + pinner.Pin(utf83) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4))) = uint32(uint32(len((element).F1))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = uint32(uintptr(uintptr(utf83))) + + } + + var option int32 + var option7 uintptr + var option8 uint32 + switch (req).Body.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option7 = 0 + option8 = 0 + case witTypes.OptionSome: + payload := (req).Body.Some() + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + + option = int32(1) + option7 = uintptr(data) + option8 = uint32(len(payload)) + default: + panic("unreachable") + } + wasm_import_send_request(int32((req).Method), uintptr(utf8), uint32(len((req).Uri)), uintptr(result), length, uintptr(result5), length6, option, option7, option8, returnArea) + var result14 witTypes.Result[fermyon_spin_http_types.Response, fermyon_spin_http_types.HttpError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option11 witTypes.Option[[]witTypes.Tuple2[string, string]] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) { + case 0: + + option11 = witTypes.None[[]witTypes.Tuple2[string, string]]() + case 1: + result10 := make([]witTypes.Tuple2[string, string], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(4*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4)))) + + result10 = append(result10, witTypes.Tuple2[string, string]{value, value9}) + } + + option11 = witTypes.Some[[]witTypes.Tuple2[string, string]](result10) + default: + panic("unreachable") + } + var option13 witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (5 * 4)))) { + case 0: + + option13 = witTypes.None[[]uint8]() + case 1: + value12 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (6 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (7 * 4)))) + + option13 = witTypes.Some[[]uint8](value12) + default: + panic("unreachable") + } + + result14 = witTypes.Ok[fermyon_spin_http_types.Response, fermyon_spin_http_types.HttpError](fermyon_spin_http_types.Response{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), option11, option13}) + case 1: + + result14 = witTypes.Err[fermyon_spin_http_types.Response, fermyon_spin_http_types.HttpError](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result15 := result14 + return result15 + +} diff --git a/internal/fermyon_spin_http_types/wit_bindings.go b/internal/fermyon_spin_http_types/wit_bindings.go new file mode 100644 index 00000000..48efbe47 --- /dev/null +++ b/internal/fermyon_spin_http_types/wit_bindings.go @@ -0,0 +1,80 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_http_types + +import ( + witTypes "go.bytecodealliance.org/pkg/wit/types" +) + +type HttpStatus = uint16 +type Body = []uint8 +type Headers = []witTypes.Tuple2[string, string] +type Params = []witTypes.Tuple2[string, string] +type Uri = string + +const ( + MethodGet uint8 = 0 + MethodPost uint8 = 1 + MethodPut uint8 = 2 + MethodDelete uint8 = 3 + MethodPatch uint8 = 4 + MethodHead uint8 = 5 + MethodOptions uint8 = 6 +) + +type Method = uint8 + +type Request struct { + Method Method + Uri string + Headers []witTypes.Tuple2[string, string] + Params []witTypes.Tuple2[string, string] + Body witTypes.Option[[]uint8] +} + +type Response struct { + Status uint16 + Headers witTypes.Option[[]witTypes.Tuple2[string, string]] + Body witTypes.Option[[]uint8] +} + +const ( + HttpErrorSuccess uint8 = 0 + HttpErrorDestinationNotAllowed uint8 = 1 + HttpErrorInvalidUrl uint8 = 2 + HttpErrorRequestError uint8 = 3 + HttpErrorRuntimeError uint8 = 4 + HttpErrorTooManyRequests uint8 = 5 +) + +type HttpError = uint8 diff --git a/internal/fermyon_spin_inbound_redis/wit_bindings.go b/internal/fermyon_spin_inbound_redis/wit_bindings.go new file mode 100644 index 00000000..98492a17 --- /dev/null +++ b/internal/fermyon_spin_inbound_redis/wit_bindings.go @@ -0,0 +1,40 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_inbound_redis + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_redis_types" +) + +type Payload = []uint8 +type Error = fermyon_spin_redis_types.Error diff --git a/internal/fermyon_spin_key_value/wit_bindings.go b/internal/fermyon_spin_key_value/wit_bindings.go new file mode 100644 index 00000000..72881e36 --- /dev/null +++ b/internal/fermyon_spin_key_value/wit_bindings.go @@ -0,0 +1,459 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_key_value + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +// A handle to an open key-value store +type Store = uint32 + +const ( + // Too many stores have been opened simultaneously. Closing one or more + // stores prior to retrying may address this. + ErrorStoreTableFull uint8 = 0 + // The host does not recognize the store name requested. Defining and + // configuring a store with that name in a runtime configuration file + // may address this. + ErrorNoSuchStore uint8 = 1 + // The requesting component does not have access to the specified store + // (which may or may not exist). + ErrorAccessDenied uint8 = 2 + // The store handle provided is not recognized, i.e. it was either never + // opened or has been closed. + ErrorInvalidStore uint8 = 3 + // No key-value tuple exists for the specified key in the specified + // store. + ErrorNoSuchKey uint8 = 4 + // Some implementation-specific error has occurred (e.g. I/O) + ErrorIo uint8 = 5 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Io() string { + if self.tag != ErrorIo { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorStoreTableFull() Error { + return Error{ErrorStoreTableFull, nil} +} +func MakeErrorNoSuchStore() Error { + return Error{ErrorNoSuchStore, nil} +} +func MakeErrorAccessDenied() Error { + return Error{ErrorAccessDenied, nil} +} +func MakeErrorInvalidStore() Error { + return Error{ErrorInvalidStore, nil} +} +func MakeErrorNoSuchKey() Error { + return Error{ErrorNoSuchKey, nil} +} +func MakeErrorIo(value string) Error { + return Error{ErrorIo, value} +} + +//go:wasmimport fermyon:spin/key-value open +func wasm_import_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Open(name string) witTypes.Result[uint32, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + wasm_import_open(uintptr(utf8), uint32(len(name)), returnArea) + var result witTypes.Result[uint32, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint32, Error](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[uint32, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value get +func wasm_import_get(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func Get(store uint32, key string) witTypes.Result[[]uint8, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_get(int32(store), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[[]uint8, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[[]uint8, Error](value) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[[]uint8, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/key-value set +func wasm_import_set(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func Set(store uint32, key string, value []uint8) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_set(int32(store), uintptr(utf8), uint32(len(key)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/key-value delete +func wasm_import_delete(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func Delete(store uint32, key string) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_delete(int32(store), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value exists +func wasm_import_exists(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func Exists(store uint32, key string) witTypes.Result[bool, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_exists(int32(store), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[bool, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[bool, Error]((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) != 0)) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[bool, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/key-value get-keys +func wasm_import_get_keys(arg0 int32, arg1 uintptr) + +func GetKeys(store uint32) witTypes.Result[[]string, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_get_keys(int32(store), returnArea) + var result1 witTypes.Result[[]string, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result1 = witTypes.Ok[[]string, Error](result) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorStoreTableFull() + + case 1: + + variant = MakeErrorNoSuchStore() + + case 2: + + variant = MakeErrorAccessDenied() + + case 3: + + variant = MakeErrorInvalidStore() + + case 4: + + variant = MakeErrorNoSuchKey() + + case 5: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value0) + + default: + panic("unreachable") + } + + result1 = witTypes.Err[[]string, Error](variant) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/key-value close +func wasm_import_close(arg0 int32) + +func Close(store uint32) { + + wasm_import_close(int32(store)) + +} diff --git a/internal/fermyon_spin_llm/wit_bindings.go b/internal/fermyon_spin_llm/wit_bindings.go new file mode 100644 index 00000000..536cd28f --- /dev/null +++ b/internal/fermyon_spin_llm/wit_bindings.go @@ -0,0 +1,278 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_llm + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +// A Large Language Model. +type InferencingModel = string + +// Inference request parameters +type InferencingParams struct { + // The maximum tokens that should be inferred. + // + // Note: the backing implementation may return less tokens. + MaxTokens uint32 + // The amount the model should avoid repeating tokens. + RepeatPenalty float32 + // The number of tokens the model should apply the repeat penalty to. + RepeatPenaltyLastNTokenCount uint32 + // The randomness with which the next token is selected. + Temperature float32 + // The number of possible next tokens the model will choose from. + TopK uint32 + // The probability total of next tokens the model will choose from. + TopP float32 +} + +const ( + ErrorModelNotSupported uint8 = 0 + ErrorRuntimeError uint8 = 1 + ErrorInvalidInput uint8 = 2 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) RuntimeError() string { + if self.tag != ErrorRuntimeError { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) InvalidInput() string { + if self.tag != ErrorInvalidInput { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorModelNotSupported() Error { + return Error{ErrorModelNotSupported, nil} +} +func MakeErrorRuntimeError(value string) Error { + return Error{ErrorRuntimeError, value} +} +func MakeErrorInvalidInput(value string) Error { + return Error{ErrorInvalidInput, value} +} + +// Usage information related to the inferencing result +type InferencingUsage struct { + // Number of tokens in the prompt + PromptTokenCount uint32 + // Number of tokens generated by the inferencing operation + GeneratedTokenCount uint32 +} + +// An inferencing result +type InferencingResult struct { + // The text generated by the model + // TODO: this should be a stream + Text string + // Usage information about the inferencing request + Usage InferencingUsage +} + +// The model used for generating embeddings +type EmbeddingModel = string + +// Usage related to an embeddings generation request +type EmbeddingsUsage struct { + // Number of tokens in the prompt + PromptTokenCount uint32 +} + +// Result of generating embeddings +type EmbeddingsResult struct { + // The embeddings generated by the request + Embeddings [][]float32 + // Usage related to the embeddings generation request + Usage EmbeddingsUsage +} + +//go:wasmimport fermyon:spin/llm infer +func wasm_import_infer(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 int32, arg5 int32, arg6 float32, arg7 int32, arg8 float32, arg9 int32, arg10 float32, arg11 uintptr) + +func Infer(model string, prompt string, params witTypes.Option[InferencingParams]) witTypes.Result[InferencingResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (8 + 3*4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(model)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(prompt)) + pinner.Pin(utf80) + var option int32 + var option1 int32 + var option2 float32 + var option3 int32 + var option4 float32 + var option5 int32 + var option6 float32 + switch params.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option1 = 0 + option2 = 0 + option3 = 0 + option4 = 0 + option5 = 0 + option6 = 0 + case witTypes.OptionSome: + payload := params.Some() + + option = int32(1) + option1 = int32((payload).MaxTokens) + option2 = (payload).RepeatPenalty + option3 = int32((payload).RepeatPenaltyLastNTokenCount) + option4 = (payload).Temperature + option5 = int32((payload).TopK) + option6 = (payload).TopP + default: + panic("unreachable") + } + wasm_import_infer(uintptr(utf8), uint32(len(model)), uintptr(utf80), uint32(len(prompt)), option, option1, option2, option3, option4, option5, option6, returnArea) + var result witTypes.Result[InferencingResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[InferencingResult, Error](InferencingResult{value, InferencingUsage{uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (4 + 3*4))))}}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorModelNotSupported() + + case 1: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorRuntimeError(value7) + + case 2: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidInput(value8) + + default: + panic("unreachable") + } + + result = witTypes.Err[InferencingResult, Error](variant) + default: + panic("unreachable") + } + result9 := result + return result9 + +} + +//go:wasmimport fermyon:spin/llm generate-embeddings +func wasm_import_generate_embeddings(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func GenerateEmbeddings(model string, text []string) witTypes.Result[EmbeddingsResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(model)) + pinner.Pin(utf8) + slice := text + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf80 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + + } + + wasm_import_generate_embeddings(uintptr(utf8), uint32(len(model)), uintptr(result), length, returnArea) + var result4 witTypes.Result[EmbeddingsResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([][]float32, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.Slice((*float32)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result1 = append(result1, value) + } + + result4 = witTypes.Ok[EmbeddingsResult, Error](EmbeddingsResult{result1, EmbeddingsUsage{uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))}}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorModelNotSupported() + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorRuntimeError(value2) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorInvalidInput(value3) + + default: + panic("unreachable") + } + + result4 = witTypes.Err[EmbeddingsResult, Error](variant) + default: + panic("unreachable") + } + result5 := result4 + return result5 + +} diff --git a/internal/fermyon_spin_mysql/wit_bindings.go b/internal/fermyon_spin_mysql/wit_bindings.go new file mode 100644 index 00000000..141f38ae --- /dev/null +++ b/internal/fermyon_spin_mysql/wit_bindings.go @@ -0,0 +1,514 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_mysql + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_rdbms_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type ParameterValue = fermyon_spin_rdbms_types.ParameterValue +type RowSet = fermyon_spin_rdbms_types.RowSet + +const ( + MysqlErrorSuccess uint8 = 0 + MysqlErrorConnectionFailed uint8 = 1 + MysqlErrorBadParameter uint8 = 2 + MysqlErrorQueryFailed uint8 = 3 + MysqlErrorValueConversionFailed uint8 = 4 + MysqlErrorOtherError uint8 = 5 +) + +// General purpose error. +type MysqlError struct { + tag uint8 + value any +} + +func (self MysqlError) Tag() uint8 { + return self.tag +} + +func (self MysqlError) ConnectionFailed() string { + if self.tag != MysqlErrorConnectionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self MysqlError) BadParameter() string { + if self.tag != MysqlErrorBadParameter { + panic("tag mismatch") + } + return self.value.(string) +} +func (self MysqlError) QueryFailed() string { + if self.tag != MysqlErrorQueryFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self MysqlError) ValueConversionFailed() string { + if self.tag != MysqlErrorValueConversionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self MysqlError) OtherError() string { + if self.tag != MysqlErrorOtherError { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeMysqlErrorSuccess() MysqlError { + return MysqlError{MysqlErrorSuccess, nil} +} +func MakeMysqlErrorConnectionFailed(value string) MysqlError { + return MysqlError{MysqlErrorConnectionFailed, value} +} +func MakeMysqlErrorBadParameter(value string) MysqlError { + return MysqlError{MysqlErrorBadParameter, value} +} +func MakeMysqlErrorQueryFailed(value string) MysqlError { + return MysqlError{MysqlErrorQueryFailed, value} +} +func MakeMysqlErrorValueConversionFailed(value string) MysqlError { + return MysqlError{MysqlErrorValueConversionFailed, value} +} +func MakeMysqlErrorOtherError(value string) MysqlError { + return MysqlError{MysqlErrorOtherError, value} +} + +//go:wasmimport fermyon:spin/mysql query +func wasm_import_query(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Query(address string, statement string, params []fermyon_spin_rdbms_types.ParameterValue) witTypes.Result[fermyon_spin_rdbms_types.RowSet, MysqlError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf80) + slice := params + length := uint32(len(slice)) + result2 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result2, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf81 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf81))) + + case fermyon_spin_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_query(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(statement)), uintptr(result2), length, returnArea) + var result14 witTypes.Result[fermyon_spin_rdbms_types.RowSet, MysqlError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result3 := make([]fermyon_spin_rdbms_types.Column, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result3 = append(result3, fermyon_spin_rdbms_types.Column{value, uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))}) + } + + result7 := make([][]fermyon_spin_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result6 := make([]fermyon_spin_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant fermyon_spin_rdbms_types.DbValue + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = fermyon_spin_rdbms_types.MakeDbValueBoolean((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))) != 0)) + + case 1: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt8(int8(int8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 2: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt16(int16(int16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 3: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 4: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 5: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint8(uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 6: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint16(uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 7: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint32(uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 8: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint64(uint64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 9: + + variant = fermyon_spin_rdbms_types.MakeDbValueFloating32(*(*float32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 10: + + variant = fermyon_spin_rdbms_types.MakeDbValueFloating64(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 11: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_rdbms_types.MakeDbValueStr(value4) + + case 12: + value5 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_rdbms_types.MakeDbValueBinary(value5) + + case 13: + + variant = fermyon_spin_rdbms_types.MakeDbValueDbNull() + + case 14: + + variant = fermyon_spin_rdbms_types.MakeDbValueUnsupported() + + default: + panic("unreachable") + } + + result6 = append(result6, variant) + } + + result7 = append(result7, result6) + } + + result14 = witTypes.Ok[fermyon_spin_rdbms_types.RowSet, MysqlError](fermyon_spin_rdbms_types.RowSet{result3, result7}) + case 1: + var variant13 MysqlError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant13 = MakeMysqlErrorSuccess() + + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakeMysqlErrorConnectionFailed(value8) + + case 2: + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakeMysqlErrorBadParameter(value9) + + case 3: + value10 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakeMysqlErrorQueryFailed(value10) + + case 4: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakeMysqlErrorValueConversionFailed(value11) + + case 5: + value12 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakeMysqlErrorOtherError(value12) + + default: + panic("unreachable") + } + + result14 = witTypes.Err[fermyon_spin_rdbms_types.RowSet, MysqlError](variant13) + default: + panic("unreachable") + } + result15 := result14 + return result15 + +} + +//go:wasmimport fermyon:spin/mysql execute +func wasm_import_execute(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Execute(address string, statement string, params []fermyon_spin_rdbms_types.ParameterValue) witTypes.Result[witTypes.Unit, MysqlError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf80) + slice := params + length := uint32(len(slice)) + result2 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result2, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf81 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf81))) + + case fermyon_spin_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_execute(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(statement)), uintptr(result2), length, returnArea) + var result7 witTypes.Result[witTypes.Unit, MysqlError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result7 = witTypes.Ok[witTypes.Unit, MysqlError](witTypes.Unit{}) + case 1: + var variant MysqlError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeMysqlErrorSuccess() + + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeMysqlErrorConnectionFailed(value) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeMysqlErrorBadParameter(value3) + + case 3: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeMysqlErrorQueryFailed(value4) + + case 4: + value5 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeMysqlErrorValueConversionFailed(value5) + + case 5: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeMysqlErrorOtherError(value6) + + default: + panic("unreachable") + } + + result7 = witTypes.Err[witTypes.Unit, MysqlError](variant) + default: + panic("unreachable") + } + result8 := result7 + return result8 + +} diff --git a/internal/fermyon_spin_postgres/wit_bindings.go b/internal/fermyon_spin_postgres/wit_bindings.go new file mode 100644 index 00000000..31424ed2 --- /dev/null +++ b/internal/fermyon_spin_postgres/wit_bindings.go @@ -0,0 +1,514 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_postgres + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_rdbms_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type ParameterValue = fermyon_spin_rdbms_types.ParameterValue +type RowSet = fermyon_spin_rdbms_types.RowSet + +const ( + PgErrorSuccess uint8 = 0 + PgErrorConnectionFailed uint8 = 1 + PgErrorBadParameter uint8 = 2 + PgErrorQueryFailed uint8 = 3 + PgErrorValueConversionFailed uint8 = 4 + PgErrorOtherError uint8 = 5 +) + +// General purpose error. +type PgError struct { + tag uint8 + value any +} + +func (self PgError) Tag() uint8 { + return self.tag +} + +func (self PgError) ConnectionFailed() string { + if self.tag != PgErrorConnectionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self PgError) BadParameter() string { + if self.tag != PgErrorBadParameter { + panic("tag mismatch") + } + return self.value.(string) +} +func (self PgError) QueryFailed() string { + if self.tag != PgErrorQueryFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self PgError) ValueConversionFailed() string { + if self.tag != PgErrorValueConversionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self PgError) OtherError() string { + if self.tag != PgErrorOtherError { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakePgErrorSuccess() PgError { + return PgError{PgErrorSuccess, nil} +} +func MakePgErrorConnectionFailed(value string) PgError { + return PgError{PgErrorConnectionFailed, value} +} +func MakePgErrorBadParameter(value string) PgError { + return PgError{PgErrorBadParameter, value} +} +func MakePgErrorQueryFailed(value string) PgError { + return PgError{PgErrorQueryFailed, value} +} +func MakePgErrorValueConversionFailed(value string) PgError { + return PgError{PgErrorValueConversionFailed, value} +} +func MakePgErrorOtherError(value string) PgError { + return PgError{PgErrorOtherError, value} +} + +//go:wasmimport fermyon:spin/postgres query +func wasm_import_query(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Query(address string, statement string, params []fermyon_spin_rdbms_types.ParameterValue) witTypes.Result[fermyon_spin_rdbms_types.RowSet, PgError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf80) + slice := params + length := uint32(len(slice)) + result2 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result2, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf81 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf81))) + + case fermyon_spin_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_query(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(statement)), uintptr(result2), length, returnArea) + var result14 witTypes.Result[fermyon_spin_rdbms_types.RowSet, PgError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result3 := make([]fermyon_spin_rdbms_types.Column, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result3 = append(result3, fermyon_spin_rdbms_types.Column{value, uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))}) + } + + result7 := make([][]fermyon_spin_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result6 := make([]fermyon_spin_rdbms_types.DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant fermyon_spin_rdbms_types.DbValue + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = fermyon_spin_rdbms_types.MakeDbValueBoolean((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))) != 0)) + + case 1: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt8(int8(int8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 2: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt16(int16(int16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 3: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 4: + + variant = fermyon_spin_rdbms_types.MakeDbValueInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 5: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint8(uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 6: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint16(uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 7: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint32(uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 8: + + variant = fermyon_spin_rdbms_types.MakeDbValueUint64(uint64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8)))) + + case 9: + + variant = fermyon_spin_rdbms_types.MakeDbValueFloating32(*(*float32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 10: + + variant = fermyon_spin_rdbms_types.MakeDbValueFloating64(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 11: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_rdbms_types.MakeDbValueStr(value4) + + case 12: + value5 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_rdbms_types.MakeDbValueBinary(value5) + + case 13: + + variant = fermyon_spin_rdbms_types.MakeDbValueDbNull() + + case 14: + + variant = fermyon_spin_rdbms_types.MakeDbValueUnsupported() + + default: + panic("unreachable") + } + + result6 = append(result6, variant) + } + + result7 = append(result7, result6) + } + + result14 = witTypes.Ok[fermyon_spin_rdbms_types.RowSet, PgError](fermyon_spin_rdbms_types.RowSet{result3, result7}) + case 1: + var variant13 PgError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant13 = MakePgErrorSuccess() + + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakePgErrorConnectionFailed(value8) + + case 2: + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakePgErrorBadParameter(value9) + + case 3: + value10 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakePgErrorQueryFailed(value10) + + case 4: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakePgErrorValueConversionFailed(value11) + + case 5: + value12 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant13 = MakePgErrorOtherError(value12) + + default: + panic("unreachable") + } + + result14 = witTypes.Err[fermyon_spin_rdbms_types.RowSet, PgError](variant13) + default: + panic("unreachable") + } + result15 := result14 + return result15 + +} + +//go:wasmimport fermyon:spin/postgres execute +func wasm_import_execute(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Execute(address string, statement string, params []fermyon_spin_rdbms_types.ParameterValue) witTypes.Result[uint64, PgError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (16 + 2*4), 8)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf80) + slice := params + length := uint32(len(slice)) + result2 := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result2, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_rdbms_types.ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case fermyon_spin_rdbms_types.ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueUint8: + payload := element.Uint8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint16: + payload := element.Uint16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case fermyon_spin_rdbms_types.ParameterValueUint32: + payload := element.Uint32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = int32(payload) + + case fermyon_spin_rdbms_types.ParameterValueUint64: + payload := element.Uint64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = int64(payload) + + case fermyon_spin_rdbms_types.ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_rdbms_types.ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + utf81 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf81))) + + case fermyon_spin_rdbms_types.ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case fermyon_spin_rdbms_types.ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_execute(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(statement)), uintptr(result2), length, returnArea) + var result7 witTypes.Result[uint64, PgError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result7 = witTypes.Ok[uint64, PgError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant PgError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakePgErrorSuccess() + + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakePgErrorConnectionFailed(value) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakePgErrorBadParameter(value3) + + case 3: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakePgErrorQueryFailed(value4) + + case 4: + value5 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakePgErrorValueConversionFailed(value5) + + case 5: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakePgErrorOtherError(value6) + + default: + panic("unreachable") + } + + result7 = witTypes.Err[uint64, PgError](variant) + default: + panic("unreachable") + } + result8 := result7 + return result8 + +} diff --git a/internal/fermyon_spin_rdbms_types/wit_bindings.go b/internal/fermyon_spin_rdbms_types/wit_bindings.go new file mode 100644 index 00000000..da16fa0c --- /dev/null +++ b/internal/fermyon_spin_rdbms_types/wit_bindings.go @@ -0,0 +1,365 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_rdbms_types + +import () + +const ( + DbDataTypeBoolean uint8 = 0 + DbDataTypeInt8 uint8 = 1 + DbDataTypeInt16 uint8 = 2 + DbDataTypeInt32 uint8 = 3 + DbDataTypeInt64 uint8 = 4 + DbDataTypeUint8 uint8 = 5 + DbDataTypeUint16 uint8 = 6 + DbDataTypeUint32 uint8 = 7 + DbDataTypeUint64 uint8 = 8 + DbDataTypeFloating32 uint8 = 9 + DbDataTypeFloating64 uint8 = 10 + DbDataTypeStr uint8 = 11 + DbDataTypeBinary uint8 = 12 + DbDataTypeOther uint8 = 13 +) + +type DbDataType = uint8 + +const ( + DbValueBoolean uint8 = 0 + DbValueInt8 uint8 = 1 + DbValueInt16 uint8 = 2 + DbValueInt32 uint8 = 3 + DbValueInt64 uint8 = 4 + DbValueUint8 uint8 = 5 + DbValueUint16 uint8 = 6 + DbValueUint32 uint8 = 7 + DbValueUint64 uint8 = 8 + DbValueFloating32 uint8 = 9 + DbValueFloating64 uint8 = 10 + DbValueStr uint8 = 11 + DbValueBinary uint8 = 12 + DbValueDbNull uint8 = 13 + DbValueUnsupported uint8 = 14 +) + +type DbValue struct { + tag uint8 + value any +} + +func (self DbValue) Tag() uint8 { + return self.tag +} + +func (self DbValue) Boolean() bool { + if self.tag != DbValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self DbValue) Int8() int8 { + if self.tag != DbValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self DbValue) Int16() int16 { + if self.tag != DbValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self DbValue) Int32() int32 { + if self.tag != DbValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self DbValue) Int64() int64 { + if self.tag != DbValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self DbValue) Uint8() uint8 { + if self.tag != DbValueUint8 { + panic("tag mismatch") + } + return self.value.(uint8) +} +func (self DbValue) Uint16() uint16 { + if self.tag != DbValueUint16 { + panic("tag mismatch") + } + return self.value.(uint16) +} +func (self DbValue) Uint32() uint32 { + if self.tag != DbValueUint32 { + panic("tag mismatch") + } + return self.value.(uint32) +} +func (self DbValue) Uint64() uint64 { + if self.tag != DbValueUint64 { + panic("tag mismatch") + } + return self.value.(uint64) +} +func (self DbValue) Floating32() float32 { + if self.tag != DbValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self DbValue) Floating64() float64 { + if self.tag != DbValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self DbValue) Str() string { + if self.tag != DbValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self DbValue) Binary() []uint8 { + if self.tag != DbValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeDbValueBoolean(value bool) DbValue { + return DbValue{DbValueBoolean, value} +} +func MakeDbValueInt8(value int8) DbValue { + return DbValue{DbValueInt8, value} +} +func MakeDbValueInt16(value int16) DbValue { + return DbValue{DbValueInt16, value} +} +func MakeDbValueInt32(value int32) DbValue { + return DbValue{DbValueInt32, value} +} +func MakeDbValueInt64(value int64) DbValue { + return DbValue{DbValueInt64, value} +} +func MakeDbValueUint8(value uint8) DbValue { + return DbValue{DbValueUint8, value} +} +func MakeDbValueUint16(value uint16) DbValue { + return DbValue{DbValueUint16, value} +} +func MakeDbValueUint32(value uint32) DbValue { + return DbValue{DbValueUint32, value} +} +func MakeDbValueUint64(value uint64) DbValue { + return DbValue{DbValueUint64, value} +} +func MakeDbValueFloating32(value float32) DbValue { + return DbValue{DbValueFloating32, value} +} +func MakeDbValueFloating64(value float64) DbValue { + return DbValue{DbValueFloating64, value} +} +func MakeDbValueStr(value string) DbValue { + return DbValue{DbValueStr, value} +} +func MakeDbValueBinary(value []uint8) DbValue { + return DbValue{DbValueBinary, value} +} +func MakeDbValueDbNull() DbValue { + return DbValue{DbValueDbNull, nil} +} +func MakeDbValueUnsupported() DbValue { + return DbValue{DbValueUnsupported, nil} +} + +const ( + ParameterValueBoolean uint8 = 0 + ParameterValueInt8 uint8 = 1 + ParameterValueInt16 uint8 = 2 + ParameterValueInt32 uint8 = 3 + ParameterValueInt64 uint8 = 4 + ParameterValueUint8 uint8 = 5 + ParameterValueUint16 uint8 = 6 + ParameterValueUint32 uint8 = 7 + ParameterValueUint64 uint8 = 8 + ParameterValueFloating32 uint8 = 9 + ParameterValueFloating64 uint8 = 10 + ParameterValueStr uint8 = 11 + ParameterValueBinary uint8 = 12 + ParameterValueDbNull uint8 = 13 +) + +type ParameterValue struct { + tag uint8 + value any +} + +func (self ParameterValue) Tag() uint8 { + return self.tag +} + +func (self ParameterValue) Boolean() bool { + if self.tag != ParameterValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self ParameterValue) Int8() int8 { + if self.tag != ParameterValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self ParameterValue) Int16() int16 { + if self.tag != ParameterValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self ParameterValue) Int32() int32 { + if self.tag != ParameterValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self ParameterValue) Int64() int64 { + if self.tag != ParameterValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self ParameterValue) Uint8() uint8 { + if self.tag != ParameterValueUint8 { + panic("tag mismatch") + } + return self.value.(uint8) +} +func (self ParameterValue) Uint16() uint16 { + if self.tag != ParameterValueUint16 { + panic("tag mismatch") + } + return self.value.(uint16) +} +func (self ParameterValue) Uint32() uint32 { + if self.tag != ParameterValueUint32 { + panic("tag mismatch") + } + return self.value.(uint32) +} +func (self ParameterValue) Uint64() uint64 { + if self.tag != ParameterValueUint64 { + panic("tag mismatch") + } + return self.value.(uint64) +} +func (self ParameterValue) Floating32() float32 { + if self.tag != ParameterValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self ParameterValue) Floating64() float64 { + if self.tag != ParameterValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self ParameterValue) Str() string { + if self.tag != ParameterValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self ParameterValue) Binary() []uint8 { + if self.tag != ParameterValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeParameterValueBoolean(value bool) ParameterValue { + return ParameterValue{ParameterValueBoolean, value} +} +func MakeParameterValueInt8(value int8) ParameterValue { + return ParameterValue{ParameterValueInt8, value} +} +func MakeParameterValueInt16(value int16) ParameterValue { + return ParameterValue{ParameterValueInt16, value} +} +func MakeParameterValueInt32(value int32) ParameterValue { + return ParameterValue{ParameterValueInt32, value} +} +func MakeParameterValueInt64(value int64) ParameterValue { + return ParameterValue{ParameterValueInt64, value} +} +func MakeParameterValueUint8(value uint8) ParameterValue { + return ParameterValue{ParameterValueUint8, value} +} +func MakeParameterValueUint16(value uint16) ParameterValue { + return ParameterValue{ParameterValueUint16, value} +} +func MakeParameterValueUint32(value uint32) ParameterValue { + return ParameterValue{ParameterValueUint32, value} +} +func MakeParameterValueUint64(value uint64) ParameterValue { + return ParameterValue{ParameterValueUint64, value} +} +func MakeParameterValueFloating32(value float32) ParameterValue { + return ParameterValue{ParameterValueFloating32, value} +} +func MakeParameterValueFloating64(value float64) ParameterValue { + return ParameterValue{ParameterValueFloating64, value} +} +func MakeParameterValueStr(value string) ParameterValue { + return ParameterValue{ParameterValueStr, value} +} +func MakeParameterValueBinary(value []uint8) ParameterValue { + return ParameterValue{ParameterValueBinary, value} +} +func MakeParameterValueDbNull() ParameterValue { + return ParameterValue{ParameterValueDbNull, nil} +} + +type Column struct { + Name string + DataType DbDataType +} +type Row = []DbValue + +type RowSet struct { + Columns []Column + Rows [][]DbValue +} diff --git a/internal/fermyon_spin_redis/wit_bindings.go b/internal/fermyon_spin_redis/wit_bindings.go new file mode 100644 index 00000000..359fd54c --- /dev/null +++ b/internal/fermyon_spin_redis/wit_bindings.go @@ -0,0 +1,408 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_redis + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_redis_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Payload = []uint8 +type RedisParameter = fermyon_spin_redis_types.RedisParameter +type RedisResult = fermyon_spin_redis_types.RedisResult +type Error = fermyon_spin_redis_types.Error + +//go:wasmimport fermyon:spin/redis publish +func wasm_import_publish(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Publish(address string, channel string, payload []uint8) witTypes.Result[witTypes.Unit, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(channel)) + pinner.Pin(utf80) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + wasm_import_publish(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(channel)), uintptr(data), uint32(len(payload)), returnArea) + var result witTypes.Result[witTypes.Unit, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, fermyon_spin_redis_types.Error](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis get +func wasm_import_get(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func Get(address string, key string) witTypes.Result[[]uint8, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + wasm_import_get(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), returnArea) + var result witTypes.Result[[]uint8, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[[]uint8, fermyon_spin_redis_types.Error](value) + case 1: + + result = witTypes.Err[[]uint8, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis set +func wasm_import_set(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Set(address string, key string, value []uint8) witTypes.Result[witTypes.Unit, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_set(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, fermyon_spin_redis_types.Error](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis incr +func wasm_import_incr(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func Incr(address string, key string) witTypes.Result[int64, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + wasm_import_incr(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), returnArea) + var result witTypes.Result[int64, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[int64, fermyon_spin_redis_types.Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + + result = witTypes.Err[int64, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport fermyon:spin/redis del +func wasm_import_del(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func Del(address string, keys []string) witTypes.Result[int64, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + slice := keys + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf80 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf80))) + + } + + wasm_import_del(uintptr(utf8), uint32(len(address)), uintptr(result), length, returnArea) + var result1 witTypes.Result[int64, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result1 = witTypes.Ok[int64, fermyon_spin_redis_types.Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + + result1 = witTypes.Err[int64, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/redis sadd +func wasm_import_sadd(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Sadd(address string, key string, values []string) witTypes.Result[int64, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + slice := values + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf81 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf81))) + + } + + wasm_import_sadd(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), uintptr(result), length, returnArea) + var result2 witTypes.Result[int64, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result2 = witTypes.Ok[int64, fermyon_spin_redis_types.Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + + result2 = witTypes.Err[int64, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result3 := result2 + return result3 + +} + +//go:wasmimport fermyon:spin/redis smembers +func wasm_import_smembers(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func Smembers(address string, key string) witTypes.Result[[]string, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + wasm_import_smembers(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), returnArea) + var result1 witTypes.Result[[]string, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result1 = witTypes.Ok[[]string, fermyon_spin_redis_types.Error](result) + case 1: + + result1 = witTypes.Err[[]string, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result2 := result1 + return result2 + +} + +//go:wasmimport fermyon:spin/redis srem +func wasm_import_srem(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Srem(address string, key string, values []string) witTypes.Result[int64, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf80) + slice := values + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf81 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf81) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf81))) + + } + + wasm_import_srem(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(key)), uintptr(result), length, returnArea) + var result2 witTypes.Result[int64, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result2 = witTypes.Ok[int64, fermyon_spin_redis_types.Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + + result2 = witTypes.Err[int64, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result3 := result2 + return result3 + +} + +//go:wasmimport fermyon:spin/redis execute +func wasm_import_execute(arg0 uintptr, arg1 uint32, arg2 uintptr, arg3 uint32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func Execute(address string, command string, arguments []fermyon_spin_redis_types.RedisParameter) witTypes.Result[[]fermyon_spin_redis_types.RedisResult, fermyon_spin_redis_types.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(command)) + pinner.Pin(utf80) + slice := arguments + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result, index*(8+2*4)) + + switch element.Tag() { + case fermyon_spin_redis_types.RedisParameterInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case fermyon_spin_redis_types.RedisParameterBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + default: + panic("unreachable") + } + + } + + wasm_import_execute(uintptr(utf8), uint32(len(address)), uintptr(utf80), uint32(len(command)), uintptr(result), length, returnArea) + var result3 witTypes.Result[[]fermyon_spin_redis_types.RedisResult, fermyon_spin_redis_types.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result2 := make([]fermyon_spin_redis_types.RedisResult, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(8+2*4)) + var variant fermyon_spin_redis_types.RedisResult + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = fermyon_spin_redis_types.MakeRedisResultNil() + + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_redis_types.MakeRedisResultStatus(value) + + case 2: + + variant = fermyon_spin_redis_types.MakeRedisResultInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 3: + value1 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = fermyon_spin_redis_types.MakeRedisResultBinary(value1) + + default: + panic("unreachable") + } + + result2 = append(result2, variant) + } + + result3 = witTypes.Ok[[]fermyon_spin_redis_types.RedisResult, fermyon_spin_redis_types.Error](result2) + case 1: + + result3 = witTypes.Err[[]fermyon_spin_redis_types.RedisResult, fermyon_spin_redis_types.Error](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result4 := result3 + return result4 + +} diff --git a/internal/fermyon_spin_redis_types/wit_bindings.go b/internal/fermyon_spin_redis_types/wit_bindings.go new file mode 100644 index 00000000..e9803f3b --- /dev/null +++ b/internal/fermyon_spin_redis_types/wit_bindings.go @@ -0,0 +1,130 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_redis_types + +import () + +const ( + ErrorSuccess uint8 = 0 + ErrorError uint8 = 1 +) + +// General purpose error. +type Error = uint8 + +// The message payload. +type Payload = []uint8 + +const ( + RedisParameterInt64 uint8 = 0 + RedisParameterBinary uint8 = 1 +) + +// A parameter type for the general-purpose `execute` function. +type RedisParameter struct { + tag uint8 + value any +} + +func (self RedisParameter) Tag() uint8 { + return self.tag +} + +func (self RedisParameter) Int64() int64 { + if self.tag != RedisParameterInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self RedisParameter) Binary() []uint8 { + if self.tag != RedisParameterBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeRedisParameterInt64(value int64) RedisParameter { + return RedisParameter{RedisParameterInt64, value} +} +func MakeRedisParameterBinary(value []uint8) RedisParameter { + return RedisParameter{RedisParameterBinary, value} +} + +const ( + RedisResultNil uint8 = 0 + RedisResultStatus uint8 = 1 + RedisResultInt64 uint8 = 2 + RedisResultBinary uint8 = 3 +) + +// A return type for the general-purpose `execute` function. +type RedisResult struct { + tag uint8 + value any +} + +func (self RedisResult) Tag() uint8 { + return self.tag +} + +func (self RedisResult) Status() string { + if self.tag != RedisResultStatus { + panic("tag mismatch") + } + return self.value.(string) +} +func (self RedisResult) Int64() int64 { + if self.tag != RedisResultInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self RedisResult) Binary() []uint8 { + if self.tag != RedisResultBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeRedisResultNil() RedisResult { + return RedisResult{RedisResultNil, nil} +} +func MakeRedisResultStatus(value string) RedisResult { + return RedisResult{RedisResultStatus, value} +} +func MakeRedisResultInt64(value int64) RedisResult { + return RedisResult{RedisResultInt64, value} +} +func MakeRedisResultBinary(value []uint8) RedisResult { + return RedisResult{RedisResultBinary, value} +} diff --git a/internal/fermyon_spin_sqlite/wit_bindings.go b/internal/fermyon_spin_sqlite/wit_bindings.go new file mode 100644 index 00000000..a0893809 --- /dev/null +++ b/internal/fermyon_spin_sqlite/wit_bindings.go @@ -0,0 +1,365 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package fermyon_spin_sqlite + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +// A handle to an open sqlite instance +type Connection = uint32 + +const ( + // The host does not recognize the database name requested. + ErrorNoSuchDatabase uint8 = 0 + // The requesting component does not have access to the specified database (which may or may not exist). + ErrorAccessDenied uint8 = 1 + // The provided connection is not valid + ErrorInvalidConnection uint8 = 2 + // The database has reached its capacity + ErrorDatabaseFull uint8 = 3 + // Some implementation-specific error has occurred (e.g. I/O) + ErrorIo uint8 = 4 +) + +// The set of errors which may be raised by functions in this interface +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Io() string { + if self.tag != ErrorIo { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorNoSuchDatabase() Error { + return Error{ErrorNoSuchDatabase, nil} +} +func MakeErrorAccessDenied() Error { + return Error{ErrorAccessDenied, nil} +} +func MakeErrorInvalidConnection() Error { + return Error{ErrorInvalidConnection, nil} +} +func MakeErrorDatabaseFull() Error { + return Error{ErrorDatabaseFull, nil} +} +func MakeErrorIo(value string) Error { + return Error{ErrorIo, value} +} + +const ( + ValueInteger uint8 = 0 + ValueReal uint8 = 1 + ValueText uint8 = 2 + ValueBlob uint8 = 3 + ValueNull uint8 = 4 +) + +type Value struct { + tag uint8 + value any +} + +func (self Value) Tag() uint8 { + return self.tag +} + +func (self Value) Integer() int64 { + if self.tag != ValueInteger { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self Value) Real() float64 { + if self.tag != ValueReal { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self Value) Text() string { + if self.tag != ValueText { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Value) Blob() []uint8 { + if self.tag != ValueBlob { + panic("tag mismatch") + } + return self.value.([]uint8) +} + +func MakeValueInteger(value int64) Value { + return Value{ValueInteger, value} +} +func MakeValueReal(value float64) Value { + return Value{ValueReal, value} +} +func MakeValueText(value string) Value { + return Value{ValueText, value} +} +func MakeValueBlob(value []uint8) Value { + return Value{ValueBlob, value} +} +func MakeValueNull() Value { + return Value{ValueNull, nil} +} + +// A set of values for each of the columns in a query-result +type RowResult struct { + Values []Value +} + +// A result of a query +type QueryResult struct { + // The names of the columns retrieved in the query + Columns []string + // the row results each containing the values for all the columns for a given row + Rows []RowResult +} + +//go:wasmimport fermyon:spin/sqlite open +func wasm_import_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Open(database string) witTypes.Result[uint32, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(database)) + pinner.Pin(utf8) + wasm_import_open(uintptr(utf8), uint32(len(database)), returnArea) + var result witTypes.Result[uint32, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint32, Error](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchDatabase() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + + variant = MakeErrorInvalidConnection() + + case 3: + + variant = MakeErrorDatabaseFull() + + case 4: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[uint32, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport fermyon:spin/sqlite execute +func wasm_import_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func Execute(conn uint32, statement string, parameters []Value) witTypes.Result[QueryResult, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := parameters + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(8+2*4)), 8) + for index, element := range slice { + base := unsafe.Add(result, index*(8+2*4)) + + switch element.Tag() { + case ValueInteger: + payload := element.Integer() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ValueReal: + payload := element.Real() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ValueText: + payload := element.Text() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case ValueBlob: + payload := element.Blob() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case ValueNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + + default: + panic("unreachable") + } + + } + + wasm_import_execute(int32(conn), uintptr(utf8), uint32(len(statement)), uintptr(result), length, returnArea) + var result8 witTypes.Result[QueryResult, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result1 = append(result1, value) + } + + result5 := make([]RowResult, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result4 := make([]Value, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*(8+2*4)) + var variant Value + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = MakeValueInteger(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 1: + + variant = MakeValueReal(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 2: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeValueText(value2) + + case 3: + value3 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeValueBlob(value3) + + case 4: + + variant = MakeValueNull() + + default: + panic("unreachable") + } + + result4 = append(result4, variant) + } + + result5 = append(result5, RowResult{result4}) + } + + result8 = witTypes.Ok[QueryResult, Error](QueryResult{result1, result5}) + case 1: + var variant7 Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant7 = MakeErrorNoSuchDatabase() + + case 1: + + variant7 = MakeErrorAccessDenied() + + case 2: + + variant7 = MakeErrorInvalidConnection() + + case 3: + + variant7 = MakeErrorDatabaseFull() + + case 4: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant7 = MakeErrorIo(value6) + + default: + panic("unreachable") + } + + result8 = witTypes.Err[QueryResult, Error](variant7) + default: + panic("unreachable") + } + result9 := result8 + return result9 + +} + +//go:wasmimport fermyon:spin/sqlite close +func wasm_import_close(arg0 int32) + +func Close(conn uint32) { + + wasm_import_close(int32(conn)) + +} diff --git a/internal/spin_postgres_postgres/wit_bindings.go b/internal/spin_postgres_postgres/wit_bindings.go new file mode 100644 index 00000000..2c5896d3 --- /dev/null +++ b/internal/spin_postgres_postgres/wit_bindings.go @@ -0,0 +1,964 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package spin_postgres_postgres + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + ErrorConnectionFailed uint8 = 0 + ErrorBadParameter uint8 = 1 + ErrorQueryFailed uint8 = 2 + ErrorValueConversionFailed uint8 = 3 + ErrorOther uint8 = 4 +) + +// Errors related to interacting with a database. +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) ConnectionFailed() string { + if self.tag != ErrorConnectionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) BadParameter() string { + if self.tag != ErrorBadParameter { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) QueryFailed() string { + if self.tag != ErrorQueryFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) ValueConversionFailed() string { + if self.tag != ErrorValueConversionFailed { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorConnectionFailed(value string) Error { + return Error{ErrorConnectionFailed, value} +} +func MakeErrorBadParameter(value string) Error { + return Error{ErrorBadParameter, value} +} +func MakeErrorQueryFailed(value string) Error { + return Error{ErrorQueryFailed, value} +} +func MakeErrorValueConversionFailed(value string) Error { + return Error{ErrorValueConversionFailed, value} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +const ( + DbDataTypeBoolean uint8 = 0 + DbDataTypeInt8 uint8 = 1 + DbDataTypeInt16 uint8 = 2 + DbDataTypeInt32 uint8 = 3 + DbDataTypeInt64 uint8 = 4 + DbDataTypeFloating32 uint8 = 5 + DbDataTypeFloating64 uint8 = 6 + DbDataTypeStr uint8 = 7 + DbDataTypeBinary uint8 = 8 + DbDataTypeDate uint8 = 9 + DbDataTypeTime uint8 = 10 + DbDataTypeDatetime uint8 = 11 + DbDataTypeTimestamp uint8 = 12 + DbDataTypeOther uint8 = 13 +) + +// Data types for a database column +type DbDataType = uint8 + +const ( + DbValueBoolean uint8 = 0 + DbValueInt8 uint8 = 1 + DbValueInt16 uint8 = 2 + DbValueInt32 uint8 = 3 + DbValueInt64 uint8 = 4 + DbValueFloating32 uint8 = 5 + DbValueFloating64 uint8 = 6 + DbValueStr uint8 = 7 + DbValueBinary uint8 = 8 + DbValueDate uint8 = 9 + // (year, month, day) + DbValueTime uint8 = 10 + // (hour, minute, second, nanosecond) + // Date-time types are always treated as UTC (without timezone info). + // The instant is represented as a (year, month, day, hour, minute, second, nanosecond) tuple. + DbValueDatetime uint8 = 11 + // Unix timestamp (seconds since epoch) + DbValueTimestamp uint8 = 12 + DbValueDbNull uint8 = 13 + DbValueUnsupported uint8 = 14 +) + +// Database values +type DbValue struct { + tag uint8 + value any +} + +func (self DbValue) Tag() uint8 { + return self.tag +} + +func (self DbValue) Boolean() bool { + if self.tag != DbValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self DbValue) Int8() int8 { + if self.tag != DbValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self DbValue) Int16() int16 { + if self.tag != DbValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self DbValue) Int32() int32 { + if self.tag != DbValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self DbValue) Int64() int64 { + if self.tag != DbValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self DbValue) Floating32() float32 { + if self.tag != DbValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self DbValue) Floating64() float64 { + if self.tag != DbValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self DbValue) Str() string { + if self.tag != DbValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self DbValue) Binary() []uint8 { + if self.tag != DbValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} +func (self DbValue) Date() witTypes.Tuple3[int32, uint8, uint8] { + if self.tag != DbValueDate { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple3[int32, uint8, uint8]) +} +func (self DbValue) Time() witTypes.Tuple4[uint8, uint8, uint8, uint32] { + if self.tag != DbValueTime { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple4[uint8, uint8, uint8, uint32]) +} +func (self DbValue) Datetime() witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32] { + if self.tag != DbValueDatetime { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32]) +} +func (self DbValue) Timestamp() int64 { + if self.tag != DbValueTimestamp { + panic("tag mismatch") + } + return self.value.(int64) +} + +func MakeDbValueBoolean(value bool) DbValue { + return DbValue{DbValueBoolean, value} +} +func MakeDbValueInt8(value int8) DbValue { + return DbValue{DbValueInt8, value} +} +func MakeDbValueInt16(value int16) DbValue { + return DbValue{DbValueInt16, value} +} +func MakeDbValueInt32(value int32) DbValue { + return DbValue{DbValueInt32, value} +} +func MakeDbValueInt64(value int64) DbValue { + return DbValue{DbValueInt64, value} +} +func MakeDbValueFloating32(value float32) DbValue { + return DbValue{DbValueFloating32, value} +} +func MakeDbValueFloating64(value float64) DbValue { + return DbValue{DbValueFloating64, value} +} +func MakeDbValueStr(value string) DbValue { + return DbValue{DbValueStr, value} +} +func MakeDbValueBinary(value []uint8) DbValue { + return DbValue{DbValueBinary, value} +} +func MakeDbValueDate(value witTypes.Tuple3[int32, uint8, uint8]) DbValue { + return DbValue{DbValueDate, value} +} +func MakeDbValueTime(value witTypes.Tuple4[uint8, uint8, uint8, uint32]) DbValue { + return DbValue{DbValueTime, value} +} +func MakeDbValueDatetime(value witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32]) DbValue { + return DbValue{DbValueDatetime, value} +} +func MakeDbValueTimestamp(value int64) DbValue { + return DbValue{DbValueTimestamp, value} +} +func MakeDbValueDbNull() DbValue { + return DbValue{DbValueDbNull, nil} +} +func MakeDbValueUnsupported() DbValue { + return DbValue{DbValueUnsupported, nil} +} + +const ( + ParameterValueBoolean uint8 = 0 + ParameterValueInt8 uint8 = 1 + ParameterValueInt16 uint8 = 2 + ParameterValueInt32 uint8 = 3 + ParameterValueInt64 uint8 = 4 + ParameterValueFloating32 uint8 = 5 + ParameterValueFloating64 uint8 = 6 + ParameterValueStr uint8 = 7 + ParameterValueBinary uint8 = 8 + ParameterValueDate uint8 = 9 + // (year, month, day) + ParameterValueTime uint8 = 10 + // (hour, minute, second, nanosecond) + // Date-time types are always treated as UTC (without timezone info). + // The instant is represented as a (year, month, day, hour, minute, second, nanosecond) tuple. + ParameterValueDatetime uint8 = 11 + // Unix timestamp (seconds since epoch) + ParameterValueTimestamp uint8 = 12 + ParameterValueDbNull uint8 = 13 +) + +// Values used in parameterized queries +type ParameterValue struct { + tag uint8 + value any +} + +func (self ParameterValue) Tag() uint8 { + return self.tag +} + +func (self ParameterValue) Boolean() bool { + if self.tag != ParameterValueBoolean { + panic("tag mismatch") + } + return self.value.(bool) +} +func (self ParameterValue) Int8() int8 { + if self.tag != ParameterValueInt8 { + panic("tag mismatch") + } + return self.value.(int8) +} +func (self ParameterValue) Int16() int16 { + if self.tag != ParameterValueInt16 { + panic("tag mismatch") + } + return self.value.(int16) +} +func (self ParameterValue) Int32() int32 { + if self.tag != ParameterValueInt32 { + panic("tag mismatch") + } + return self.value.(int32) +} +func (self ParameterValue) Int64() int64 { + if self.tag != ParameterValueInt64 { + panic("tag mismatch") + } + return self.value.(int64) +} +func (self ParameterValue) Floating32() float32 { + if self.tag != ParameterValueFloating32 { + panic("tag mismatch") + } + return self.value.(float32) +} +func (self ParameterValue) Floating64() float64 { + if self.tag != ParameterValueFloating64 { + panic("tag mismatch") + } + return self.value.(float64) +} +func (self ParameterValue) Str() string { + if self.tag != ParameterValueStr { + panic("tag mismatch") + } + return self.value.(string) +} +func (self ParameterValue) Binary() []uint8 { + if self.tag != ParameterValueBinary { + panic("tag mismatch") + } + return self.value.([]uint8) +} +func (self ParameterValue) Date() witTypes.Tuple3[int32, uint8, uint8] { + if self.tag != ParameterValueDate { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple3[int32, uint8, uint8]) +} +func (self ParameterValue) Time() witTypes.Tuple4[uint8, uint8, uint8, uint32] { + if self.tag != ParameterValueTime { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple4[uint8, uint8, uint8, uint32]) +} +func (self ParameterValue) Datetime() witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32] { + if self.tag != ParameterValueDatetime { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32]) +} +func (self ParameterValue) Timestamp() int64 { + if self.tag != ParameterValueTimestamp { + panic("tag mismatch") + } + return self.value.(int64) +} + +func MakeParameterValueBoolean(value bool) ParameterValue { + return ParameterValue{ParameterValueBoolean, value} +} +func MakeParameterValueInt8(value int8) ParameterValue { + return ParameterValue{ParameterValueInt8, value} +} +func MakeParameterValueInt16(value int16) ParameterValue { + return ParameterValue{ParameterValueInt16, value} +} +func MakeParameterValueInt32(value int32) ParameterValue { + return ParameterValue{ParameterValueInt32, value} +} +func MakeParameterValueInt64(value int64) ParameterValue { + return ParameterValue{ParameterValueInt64, value} +} +func MakeParameterValueFloating32(value float32) ParameterValue { + return ParameterValue{ParameterValueFloating32, value} +} +func MakeParameterValueFloating64(value float64) ParameterValue { + return ParameterValue{ParameterValueFloating64, value} +} +func MakeParameterValueStr(value string) ParameterValue { + return ParameterValue{ParameterValueStr, value} +} +func MakeParameterValueBinary(value []uint8) ParameterValue { + return ParameterValue{ParameterValueBinary, value} +} +func MakeParameterValueDate(value witTypes.Tuple3[int32, uint8, uint8]) ParameterValue { + return ParameterValue{ParameterValueDate, value} +} +func MakeParameterValueTime(value witTypes.Tuple4[uint8, uint8, uint8, uint32]) ParameterValue { + return ParameterValue{ParameterValueTime, value} +} +func MakeParameterValueDatetime(value witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32]) ParameterValue { + return ParameterValue{ParameterValueDatetime, value} +} +func MakeParameterValueTimestamp(value int64) ParameterValue { + return ParameterValue{ParameterValueTimestamp, value} +} +func MakeParameterValueDbNull() ParameterValue { + return ParameterValue{ParameterValueDbNull, nil} +} + +// A database column +type Column struct { + Name string + DataType DbDataType +} + +// A database row +type Row = []DbValue + +// A set of database rows +type RowSet struct { + Columns []Column + Rows [][]DbValue +} + +//go:wasmimport spin:postgres/postgres@3.0.0 [resource-drop]connection +func resourceDropConnection(handle int32) + +// A connection to a postgres database. +type Connection struct { + handle *witRuntime.Handle +} + +func (self *Connection) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Connection) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Connection) Handle() int32 { + return self.handle.Use() +} + +func (self *Connection) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropConnection(handle) + } +} + +func ConnectionFromOwnHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + value := &Connection{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropConnection(handleValue) + } + }, 0) + return value +} + +func ConnectionFromBorrowHandle(handleValue int32) *Connection { + handle := witRuntime.MakeHandle(handleValue) + return &Connection{handle} +} + +//go:wasmimport spin:postgres/postgres@3.0.0 [static]connection.open +func wasm_import_static_connection_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func ConnectionOpen(address string) witTypes.Result[*Connection, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(address)) + pinner.Pin(utf8) + wasm_import_static_connection_open(uintptr(utf8), uint32(len(address)), returnArea) + var result witTypes.Result[*Connection, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Connection, Error](ConnectionFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorConnectionFailed(value) + + case 1: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorBadParameter(value0) + + case 2: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorQueryFailed(value1) + + case 3: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorValueConversionFailed(value2) + + case 4: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value3) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Connection, Error](variant) + default: + panic("unreachable") + } + result4 := result + return result4 + +} + +//go:wasmimport spin:postgres/postgres@3.0.0 [method]connection.query +func wasm_import_method_connection_query(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Query(statement string, params []ParameterValue) witTypes.Result[RowSet, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*24), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*24) + + switch element.Tag() { + case ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case ParameterValueDate: + payload := element.Date() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = (payload).F0 + *(*int8)(unsafe.Add(unsafe.Pointer(base), 12)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 13)) = int8(int32((payload).F2)) + + case ParameterValueTime: + payload := element.Time() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32((payload).F0)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 9)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 10)) = int8(int32((payload).F2)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 12)) = int32((payload).F3) + + case ParameterValueDatetime: + payload := element.Datetime() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = (payload).F0 + *(*int8)(unsafe.Add(unsafe.Pointer(base), 12)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 13)) = int8(int32((payload).F2)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 14)) = int8(int32((payload).F3)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 15)) = int8(int32((payload).F4)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 16)) = int8(int32((payload).F5)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 20)) = int32((payload).F6) + + case ParameterValueTimestamp: + payload := element.Timestamp() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_query((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result13 witTypes.Result[RowSet, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result2 := make([]Column, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result2 = append(result2, Column{value, uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))}) + } + + result6 := make([][]DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4))))), index*(2*4)) + result5 := make([]DbValue, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)))), index*24) + var variant DbValue + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))) { + case 0: + + variant = MakeDbValueBoolean((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))) != 0)) + + case 1: + + variant = MakeDbValueInt8(int8(int8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 2: + + variant = MakeDbValueInt16(int16(int16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))) + + case 3: + + variant = MakeDbValueInt32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 4: + + variant = MakeDbValueInt64(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 5: + + variant = MakeDbValueFloating32(*(*float32)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 6: + + variant = MakeDbValueFloating64(*(*float64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 7: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeDbValueStr(value3) + + case 8: + value4 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4)))) + + variant = MakeDbValueBinary(value4) + + case 9: + + variant = MakeDbValueDate(witTypes.Tuple3[int32, uint8, uint8]{*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 13))))}) + + case 10: + + variant = MakeDbValueTime(witTypes.Tuple4[uint8, uint8, uint8, uint32]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 9)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 10)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 12)))}) + + case 11: + + variant = MakeDbValueDatetime(witTypes.Tuple7[int32, uint8, uint8, uint8, uint8, uint8, uint32]{*(*int32)(unsafe.Add(unsafe.Pointer(base), 8)), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 13)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 14)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 15)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 16)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), 20)))}) + + case 12: + + variant = MakeDbValueTimestamp(*(*int64)(unsafe.Add(unsafe.Pointer(base), 8))) + + case 13: + + variant = MakeDbValueDbNull() + + case 14: + + variant = MakeDbValueUnsupported() + + default: + panic("unreachable") + } + + result5 = append(result5, variant) + } + + result6 = append(result6, result5) + } + + result13 = witTypes.Ok[RowSet, Error](RowSet{result2, result6}) + case 1: + var variant12 Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = MakeErrorConnectionFailed(value7) + + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = MakeErrorBadParameter(value8) + + case 2: + value9 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = MakeErrorQueryFailed(value9) + + case 3: + value10 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = MakeErrorValueConversionFailed(value10) + + case 4: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant12 = MakeErrorOther(value11) + + default: + panic("unreachable") + } + + result13 = witTypes.Err[RowSet, Error](variant12) + default: + panic("unreachable") + } + result14 := result13 + return result14 + +} + +//go:wasmimport spin:postgres/postgres@3.0.0 [method]connection.execute +func wasm_import_method_connection_execute(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Connection) Execute(statement string, params []ParameterValue) witTypes.Result[uint64, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (16 + 2*4), 8)) + utf8 := unsafe.Pointer(unsafe.StringData(statement)) + pinner.Pin(utf8) + slice := params + length := uint32(len(slice)) + result1 := witRuntime.Allocate(pinner, uintptr(length*24), 8) + for index, element := range slice { + base := unsafe.Add(result1, index*24) + + switch element.Tag() { + case ParameterValueBoolean: + payload := element.Boolean() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(0)) + var result int32 + if payload { + result = 1 + } else { + result = 0 + } + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(result) + + case ParameterValueInt8: + payload := element.Int8() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32(payload)) + + case ParameterValueInt16: + payload := element.Int16() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), 8)) = int16(int32(payload)) + + case ParameterValueInt32: + payload := element.Int32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(3)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueInt64: + payload := element.Int64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(4)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueFloating32: + payload := element.Floating32() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(5)) + *(*float32)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueFloating64: + payload := element.Floating64() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(6)) + *(*float64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueStr: + payload := element.Str() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(7)) + utf80 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf80) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(utf80))) + + case ParameterValueBinary: + payload := element.Binary() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(8)) + data := unsafe.Pointer(unsafe.SliceData(payload)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 1*4))) = uint32(uint32(len(payload))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 8)) = uint32(uintptr(uintptr(data))) + + case ParameterValueDate: + payload := element.Date() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(9)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = (payload).F0 + *(*int8)(unsafe.Add(unsafe.Pointer(base), 12)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 13)) = int8(int32((payload).F2)) + + case ParameterValueTime: + payload := element.Time() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(10)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 8)) = int8(int32((payload).F0)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 9)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 10)) = int8(int32((payload).F2)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 12)) = int32((payload).F3) + + case ParameterValueDatetime: + payload := element.Datetime() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(11)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 8)) = (payload).F0 + *(*int8)(unsafe.Add(unsafe.Pointer(base), 12)) = int8(int32((payload).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 13)) = int8(int32((payload).F2)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 14)) = int8(int32((payload).F3)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 15)) = int8(int32((payload).F4)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), 16)) = int8(int32((payload).F5)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 20)) = int32((payload).F6) + + case ParameterValueTimestamp: + payload := element.Timestamp() + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(12)) + *(*int64)(unsafe.Add(unsafe.Pointer(base), 8)) = payload + + case ParameterValueDbNull: + + *(*int8)(unsafe.Add(unsafe.Pointer(base), 0)) = int8(int32(13)) + + default: + panic("unreachable") + } + + } + + wasm_import_method_connection_execute((self).Handle(), uintptr(utf8), uint32(len(statement)), uintptr(result1), length, returnArea) + var result6 witTypes.Result[uint64, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result6 = witTypes.Ok[uint64, Error](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorConnectionFailed(value) + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorBadParameter(value2) + + case 2: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorQueryFailed(value3) + + case 3: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorValueConversionFailed(value4) + + case 4: + value5 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = MakeErrorOther(value5) + + default: + panic("unreachable") + } + + result6 = witTypes.Err[uint64, Error](variant) + default: + panic("unreachable") + } + result7 := result6 + return result7 + +} diff --git a/internal/wasi_cli_0_2_0_environment/wit_bindings.go b/internal/wasi_cli_0_2_0_environment/wit_bindings.go new file mode 100644 index 00000000..821bc125 --- /dev/null +++ b/internal/wasi_cli_0_2_0_environment/wit_bindings.go @@ -0,0 +1,111 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_environment + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:cli/environment@0.2.0 get-environment +func wasm_import_get_environment(arg0 uintptr) + +func GetEnvironment() []witTypes.Tuple2[string, string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_get_environment(returnArea) + result := make([]witTypes.Tuple2[string, string], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0)))), index*(4*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4)))) + + result = append(result, witTypes.Tuple2[string, string]{value, value0}) + } + + result1 := result + return result1 + +} + +//go:wasmimport wasi:cli/environment@0.2.0 get-arguments +func wasm_import_get_arguments(arg0 uintptr) + +func GetArguments() []string { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_get_arguments(returnArea) + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result0 := result + return result0 + +} + +//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd +func wasm_import_initial_cwd(arg0 uintptr) + +func InitialCwd() witTypes.Option[string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_initial_cwd(returnArea) + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + result := option + return result + +} diff --git a/internal/wasi_cli_0_2_0_exit/wit_bindings.go b/internal/wasi_cli_0_2_0_exit/wit_bindings.go new file mode 100644 index 00000000..802c5f5f --- /dev/null +++ b/internal/wasi_cli_0_2_0_exit/wit_bindings.go @@ -0,0 +1,57 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_exit + +import ( + witTypes "go.bytecodealliance.org/pkg/wit/types" +) + +//go:wasmimport wasi:cli/exit@0.2.0 exit +func wasm_import_exit(arg0 int32) + +func Exit(status witTypes.Result[witTypes.Unit, witTypes.Unit]) { + + var option int32 + switch status.Tag() { + case witTypes.ResultOk: + + option = int32(0) + case witTypes.ResultErr: + + option = int32(1) + default: + panic("unreachable") + } + wasm_import_exit(option) + +} diff --git a/internal/wasi_cli_0_2_0_stderr/wit_bindings.go b/internal/wasi_cli_0_2_0_stderr/wit_bindings.go new file mode 100644 index 00000000..181eeba0 --- /dev/null +++ b/internal/wasi_cli_0_2_0_stderr/wit_bindings.go @@ -0,0 +1,49 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_stderr + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" +) + +type OutputStream = wasi_io_0_2_0_streams.OutputStream + +//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr +func wasm_import_get_stderr() int32 + +func GetStderr() *wasi_io_0_2_0_streams.OutputStream { + + result := wasm_import_get_stderr() + return wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_cli_0_2_0_stdin/wit_bindings.go b/internal/wasi_cli_0_2_0_stdin/wit_bindings.go new file mode 100644 index 00000000..2918d3f1 --- /dev/null +++ b/internal/wasi_cli_0_2_0_stdin/wit_bindings.go @@ -0,0 +1,49 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_stdin + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" +) + +type InputStream = wasi_io_0_2_0_streams.InputStream + +//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin +func wasm_import_get_stdin() int32 + +func GetStdin() *wasi_io_0_2_0_streams.InputStream { + + result := wasm_import_get_stdin() + return wasi_io_0_2_0_streams.InputStreamFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_cli_0_2_0_stdout/wit_bindings.go b/internal/wasi_cli_0_2_0_stdout/wit_bindings.go new file mode 100644 index 00000000..e0c2e410 --- /dev/null +++ b/internal/wasi_cli_0_2_0_stdout/wit_bindings.go @@ -0,0 +1,49 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_stdout + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" +) + +type OutputStream = wasi_io_0_2_0_streams.OutputStream + +//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout +func wasm_import_get_stdout() int32 + +func GetStdout() *wasi_io_0_2_0_streams.OutputStream { + + result := wasm_import_get_stdout() + return wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_cli_0_2_0_terminal_input/wit_bindings.go b/internal/wasi_cli_0_2_0_terminal_input/wit_bindings.go new file mode 100644 index 00000000..222c4cd6 --- /dev/null +++ b/internal/wasi_cli_0_2_0_terminal_input/wit_bindings.go @@ -0,0 +1,82 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_terminal_input + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" +) + +//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input +func resourceDropTerminalInput(handle int32) + +// The input side of a terminal. +type TerminalInput struct { + handle *witRuntime.Handle +} + +func (self *TerminalInput) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *TerminalInput) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *TerminalInput) Handle() int32 { + return self.handle.Use() +} + +func (self *TerminalInput) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropTerminalInput(handle) + } +} + +func TerminalInputFromOwnHandle(handleValue int32) *TerminalInput { + handle := witRuntime.MakeHandle(handleValue) + value := &TerminalInput{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropTerminalInput(handleValue) + } + }, 0) + return value +} + +func TerminalInputFromBorrowHandle(handleValue int32) *TerminalInput { + handle := witRuntime.MakeHandle(handleValue) + return &TerminalInput{handle} +} diff --git a/internal/wasi_cli_0_2_0_terminal_output/wit_bindings.go b/internal/wasi_cli_0_2_0_terminal_output/wit_bindings.go new file mode 100644 index 00000000..76bac657 --- /dev/null +++ b/internal/wasi_cli_0_2_0_terminal_output/wit_bindings.go @@ -0,0 +1,82 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_terminal_output + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" +) + +//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output +func resourceDropTerminalOutput(handle int32) + +// The output side of a terminal. +type TerminalOutput struct { + handle *witRuntime.Handle +} + +func (self *TerminalOutput) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *TerminalOutput) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *TerminalOutput) Handle() int32 { + return self.handle.Use() +} + +func (self *TerminalOutput) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropTerminalOutput(handle) + } +} + +func TerminalOutputFromOwnHandle(handleValue int32) *TerminalOutput { + handle := witRuntime.MakeHandle(handleValue) + value := &TerminalOutput{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropTerminalOutput(handleValue) + } + }, 0) + return value +} + +func TerminalOutputFromBorrowHandle(handleValue int32) *TerminalOutput { + handle := witRuntime.MakeHandle(handleValue) + return &TerminalOutput{handle} +} diff --git a/internal/wasi_cli_0_2_0_terminal_stderr/wit_bindings.go b/internal/wasi_cli_0_2_0_terminal_stderr/wit_bindings.go new file mode 100644 index 00000000..e42e0d03 --- /dev/null +++ b/internal/wasi_cli_0_2_0_terminal_stderr/wit_bindings.go @@ -0,0 +1,68 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_terminal_stderr + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_cli_0_2_0_terminal_output" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type TerminalOutput = wasi_cli_0_2_0_terminal_output.TerminalOutput + +//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr +func wasm_import_get_terminal_stderr(arg0 uintptr) + +func GetTerminalStderr() witTypes.Option[*wasi_cli_0_2_0_terminal_output.TerminalOutput] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_get_terminal_stderr(returnArea) + var option witTypes.Option[*wasi_cli_0_2_0_terminal_output.TerminalOutput] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[*wasi_cli_0_2_0_terminal_output.TerminalOutput]() + case 1: + + option = witTypes.Some[*wasi_cli_0_2_0_terminal_output.TerminalOutput](wasi_cli_0_2_0_terminal_output.TerminalOutputFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + default: + panic("unreachable") + } + result := option + return result + +} diff --git a/internal/wasi_cli_0_2_0_terminal_stdin/wit_bindings.go b/internal/wasi_cli_0_2_0_terminal_stdin/wit_bindings.go new file mode 100644 index 00000000..60a61361 --- /dev/null +++ b/internal/wasi_cli_0_2_0_terminal_stdin/wit_bindings.go @@ -0,0 +1,68 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_terminal_stdin + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_cli_0_2_0_terminal_input" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type TerminalInput = wasi_cli_0_2_0_terminal_input.TerminalInput + +//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin +func wasm_import_get_terminal_stdin(arg0 uintptr) + +func GetTerminalStdin() witTypes.Option[*wasi_cli_0_2_0_terminal_input.TerminalInput] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_get_terminal_stdin(returnArea) + var option witTypes.Option[*wasi_cli_0_2_0_terminal_input.TerminalInput] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[*wasi_cli_0_2_0_terminal_input.TerminalInput]() + case 1: + + option = witTypes.Some[*wasi_cli_0_2_0_terminal_input.TerminalInput](wasi_cli_0_2_0_terminal_input.TerminalInputFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + default: + panic("unreachable") + } + result := option + return result + +} diff --git a/internal/wasi_cli_0_2_0_terminal_stdout/wit_bindings.go b/internal/wasi_cli_0_2_0_terminal_stdout/wit_bindings.go new file mode 100644 index 00000000..261a5ec0 --- /dev/null +++ b/internal/wasi_cli_0_2_0_terminal_stdout/wit_bindings.go @@ -0,0 +1,68 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_cli_0_2_0_terminal_stdout + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_cli_0_2_0_terminal_output" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type TerminalOutput = wasi_cli_0_2_0_terminal_output.TerminalOutput + +//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout +func wasm_import_get_terminal_stdout(arg0 uintptr) + +func GetTerminalStdout() witTypes.Option[*wasi_cli_0_2_0_terminal_output.TerminalOutput] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_get_terminal_stdout(returnArea) + var option witTypes.Option[*wasi_cli_0_2_0_terminal_output.TerminalOutput] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[*wasi_cli_0_2_0_terminal_output.TerminalOutput]() + case 1: + + option = witTypes.Some[*wasi_cli_0_2_0_terminal_output.TerminalOutput](wasi_cli_0_2_0_terminal_output.TerminalOutputFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + default: + panic("unreachable") + } + result := option + return result + +} diff --git a/internal/wasi_clocks_0_2_0_monotonic_clock/wit_bindings.go b/internal/wasi_clocks_0_2_0_monotonic_clock/wit_bindings.go new file mode 100644 index 00000000..fce5081a --- /dev/null +++ b/internal/wasi_clocks_0_2_0_monotonic_clock/wit_bindings.go @@ -0,0 +1,87 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_clocks_0_2_0_monotonic_clock + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" +) + +type Pollable = wasi_io_0_2_0_poll.Pollable + +// An instant in time, in nanoseconds. An instant is relative to an +// unspecified initial value, and can only be compared to instances from +// the same monotonic-clock. +type Instant = uint64 + +// A duration of time, in nanoseconds. +type Duration = uint64 + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now +func wasm_import_now() int64 + +func Now() uint64 { + + result := wasm_import_now() + return uint64(result) + +} + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution +func wasm_import_resolution() int64 + +func Resolution() uint64 { + + result := wasm_import_resolution() + return uint64(result) + +} + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant +func wasm_import_subscribe_instant(arg0 int64) int32 + +func SubscribeInstant(when uint64) *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_subscribe_instant(int64(when)) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration +func wasm_import_subscribe_duration(arg0 int64) int32 + +func SubscribeDuration(when uint64) *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_subscribe_duration(int64(when)) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_clocks_0_2_0_wall_clock/wit_bindings.go b/internal/wasi_clocks_0_2_0_wall_clock/wit_bindings.go new file mode 100644 index 00000000..e6810956 --- /dev/null +++ b/internal/wasi_clocks_0_2_0_wall_clock/wit_bindings.go @@ -0,0 +1,73 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_clocks_0_2_0_wall_clock + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" + "unsafe" +) + +// A time and date in seconds plus nanoseconds. +type Datetime struct { + Seconds uint64 + Nanoseconds uint32 +} + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 now +func wasm_import_now(arg0 uintptr) + +func Now() Datetime { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_now(returnArea) + result := Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 0))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))} + return result + +} + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution +func wasm_import_resolution(arg0 uintptr) + +func Resolution() Datetime { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_resolution(returnArea) + result := Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 0))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))} + return result + +} diff --git a/internal/wasi_config_store/wit_bindings.go b/internal/wasi_config_store/wit_bindings.go new file mode 100644 index 00000000..45b93e7c --- /dev/null +++ b/internal/wasi_config_store/wit_bindings.go @@ -0,0 +1,186 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_config_store + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + // This indicates an error from an "upstream" config source. + // As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue buckets, etc), + // the error message is a string. + ErrorUpstream uint8 = 0 + // This indicates an error from an I/O operation. + // As this could be almost _anything_ (such as a file read, network connection, etc), + // the error message is a string. + // Depending on how this ends up being consumed, + // we may consider moving this to use the `wasi:io/error` type instead. + // For simplicity right now in supporting multiple implementations, it is being left as a string. + ErrorIo uint8 = 1 +) + +// An error type that encapsulates the different errors that can occur fetching configuration values. +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Upstream() string { + if self.tag != ErrorUpstream { + panic("tag mismatch") + } + return self.value.(string) +} +func (self Error) Io() string { + if self.tag != ErrorIo { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorUpstream(value string) Error { + return Error{ErrorUpstream, value} +} +func MakeErrorIo(value string) Error { + return Error{ErrorIo, value} +} + +//go:wasmimport wasi:config/store@0.2.0-draft-2024-09-27 get +func wasm_import_get(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Get(key string) witTypes.Result[witTypes.Option[string], Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_get(uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Option[string], Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[string], Error](option) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorUpstream(value0) + + case 1: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value1) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[string], Error](variant) + default: + panic("unreachable") + } + result2 := result + return result2 + +} + +//go:wasmimport wasi:config/store@0.2.0-draft-2024-09-27 get-all +func wasm_import_get_all(arg0 uintptr) + +func GetAll() witTypes.Result[[]witTypes.Tuple2[string, string], Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_get_all(returnArea) + var result3 witTypes.Result[[]witTypes.Tuple2[string, string], Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]witTypes.Tuple2[string, string], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(4*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4)))) + + result = append(result, witTypes.Tuple2[string, string]{value, value0}) + } + + result3 = witTypes.Ok[[]witTypes.Tuple2[string, string], Error](result) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + value1 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorUpstream(value1) + + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorIo(value2) + + default: + panic("unreachable") + } + + result3 = witTypes.Err[[]witTypes.Tuple2[string, string], Error](variant) + default: + panic("unreachable") + } + result4 := result3 + return result4 + +} diff --git a/internal/wasi_filesystem_0_2_0_preopens/wit_bindings.go b/internal/wasi_filesystem_0_2_0_preopens/wit_bindings.go new file mode 100644 index 00000000..15767056 --- /dev/null +++ b/internal/wasi_filesystem_0_2_0_preopens/wit_bindings.go @@ -0,0 +1,65 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_filesystem_0_2_0_preopens + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_filesystem_0_2_0_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Descriptor = wasi_filesystem_0_2_0_types.Descriptor + +//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories +func wasm_import_get_directories(arg0 uintptr) + +func GetDirectories() []witTypes.Tuple2[*wasi_filesystem_0_2_0_types.Descriptor, string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_get_directories(returnArea) + result := make([]witTypes.Tuple2[*wasi_filesystem_0_2_0_types.Descriptor, string], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0)))), index*(3*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))) + + result = append(result, witTypes.Tuple2[*wasi_filesystem_0_2_0_types.Descriptor, string]{wasi_filesystem_0_2_0_types.DescriptorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(base), 0))))), value}) + } + + result0 := result + return result0 + +} diff --git a/internal/wasi_filesystem_0_2_0_types/wit_bindings.go b/internal/wasi_filesystem_0_2_0_types/wit_bindings.go new file mode 100644 index 00000000..0173f6ee --- /dev/null +++ b/internal/wasi_filesystem_0_2_0_types/wit_bindings.go @@ -0,0 +1,1350 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_filesystem_0_2_0_types + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_clocks_0_2_0_wall_clock" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_error" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type InputStream = wasi_io_0_2_0_streams.InputStream +type OutputStream = wasi_io_0_2_0_streams.OutputStream +type Error = wasi_io_0_2_0_error.Error +type Datetime = wasi_clocks_0_2_0_wall_clock.Datetime + +// File size or length of a region within a file. +type Filesize = uint64 + +const ( + // The type of the descriptor or file is unknown or is different from + // any of the other types specified. + DescriptorTypeUnknown uint8 = 0 + // The descriptor refers to a block device inode. + DescriptorTypeBlockDevice uint8 = 1 + // The descriptor refers to a character device inode. + DescriptorTypeCharacterDevice uint8 = 2 + // The descriptor refers to a directory inode. + DescriptorTypeDirectory uint8 = 3 + // The descriptor refers to a named pipe. + DescriptorTypeFifo uint8 = 4 + // The file refers to a symbolic link inode. + DescriptorTypeSymbolicLink uint8 = 5 + // The descriptor refers to a regular file inode. + DescriptorTypeRegularFile uint8 = 6 + // The descriptor refers to a socket. + DescriptorTypeSocket uint8 = 7 +) + +// The type of a filesystem object referenced by a descriptor. +// +// Note: This was called `filetype` in earlier versions of WASI. +type DescriptorType = uint8 + +const ( + // Read mode: Data can be read. + DescriptorFlagsRead uint8 = 1 << 0 + // Write mode: Data can be written to. + DescriptorFlagsWrite uint8 = 1 << 1 + // 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. + DescriptorFlagsFileIntegritySync uint8 = 1 << 2 + // 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. + DescriptorFlagsDataIntegritySync uint8 = 1 << 3 + // Requests that reads be performed at the same level of integrety + // requested for writes. This is similar to `O_RSYNC` in POSIX. + // + // The precise semantics of this operation have not yet been defined for + // WASI. At this time, it should be interpreted as a request, and not a + // requirement. + DescriptorFlagsRequestedWriteSync uint8 = 1 << 4 + // 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. + DescriptorFlagsMutateDirectory uint8 = 1 << 5 +) + +// Descriptor flags. +// +// Note: This was called `fdflags` in earlier versions of WASI. +type DescriptorFlags = uint8 + +const ( + // As long as the resolved path corresponds to a symbolic link, it is + // expanded. + PathFlagsSymlinkFollow uint8 = 1 << 0 +) + +// Flags determining the method of how paths are resolved. +type PathFlags = uint8 + +const ( + // Create file if it does not exist, similar to `O_CREAT` in POSIX. + OpenFlagsCreate uint8 = 1 << 0 + // Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + OpenFlagsDirectory uint8 = 1 << 1 + // Fail if file already exists, similar to `O_EXCL` in POSIX. + OpenFlagsExclusive uint8 = 1 << 2 + // Truncate file to size 0, similar to `O_TRUNC` in POSIX. + OpenFlagsTruncate uint8 = 1 << 3 +) + +// Open flags used by `open-at`. +type OpenFlags = uint8 + +// Number of hard links to an inode. +type LinkCount = uint64 + +// File attributes. +// +// Note: This was called `filestat` in earlier versions of WASI. +type DescriptorStat struct { + // File type. + Type DescriptorType + // Number of hard links to the file. + LinkCount uint64 + // For regular files, the file size in bytes. For symbolic links, the + // length in bytes of the pathname contained in the symbolic link. + Size uint64 + // Last data access timestamp. + // + // If the `option` is none, the platform doesn't maintain an access + // timestamp for this file. + DataAccessTimestamp witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + // Last data modification timestamp. + // + // If the `option` is none, the platform doesn't maintain a + // modification timestamp for this file. + DataModificationTimestamp witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + // Last file status-change timestamp. + // + // If the `option` is none, the platform doesn't maintain a + // status-change timestamp for this file. + StatusChangeTimestamp witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] +} + +const ( + // Leave the timestamp set to its previous value. + NewTimestampNoChange uint8 = 0 + // Set the timestamp to the current time of the system clock associated + // with the filesystem. + NewTimestampNow uint8 = 1 + // Set the timestamp to the given value. + NewTimestampTimestamp uint8 = 2 +) + +// When setting a timestamp, this gives the value to set it to. +type NewTimestamp struct { + tag uint8 + value any +} + +func (self NewTimestamp) Tag() uint8 { + return self.tag +} + +func (self NewTimestamp) Timestamp() wasi_clocks_0_2_0_wall_clock.Datetime { + if self.tag != NewTimestampTimestamp { + panic("tag mismatch") + } + return self.value.(wasi_clocks_0_2_0_wall_clock.Datetime) +} + +func MakeNewTimestampNoChange() NewTimestamp { + return NewTimestamp{NewTimestampNoChange, nil} +} +func MakeNewTimestampNow() NewTimestamp { + return NewTimestamp{NewTimestampNow, nil} +} +func MakeNewTimestampTimestamp(value wasi_clocks_0_2_0_wall_clock.Datetime) NewTimestamp { + return NewTimestamp{NewTimestampTimestamp, value} +} + +// A directory entry. +type DirectoryEntry struct { + // The type of the file referred to by this directory entry. + Type DescriptorType + // The name of the object. + Name string +} + +const ( + // Permission denied, similar to `EACCES` in POSIX. + ErrorCodeAccess uint8 = 0 + // Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + ErrorCodeWouldBlock uint8 = 1 + // Connection already in progress, similar to `EALREADY` in POSIX. + ErrorCodeAlready uint8 = 2 + // Bad descriptor, similar to `EBADF` in POSIX. + ErrorCodeBadDescriptor uint8 = 3 + // Device or resource busy, similar to `EBUSY` in POSIX. + ErrorCodeBusy uint8 = 4 + // Resource deadlock would occur, similar to `EDEADLK` in POSIX. + ErrorCodeDeadlock uint8 = 5 + // Storage quota exceeded, similar to `EDQUOT` in POSIX. + ErrorCodeQuota uint8 = 6 + // File exists, similar to `EEXIST` in POSIX. + ErrorCodeExist uint8 = 7 + // File too large, similar to `EFBIG` in POSIX. + ErrorCodeFileTooLarge uint8 = 8 + // Illegal byte sequence, similar to `EILSEQ` in POSIX. + ErrorCodeIllegalByteSequence uint8 = 9 + // Operation in progress, similar to `EINPROGRESS` in POSIX. + ErrorCodeInProgress uint8 = 10 + // Interrupted function, similar to `EINTR` in POSIX. + ErrorCodeInterrupted uint8 = 11 + // Invalid argument, similar to `EINVAL` in POSIX. + ErrorCodeInvalid uint8 = 12 + // I/O error, similar to `EIO` in POSIX. + ErrorCodeIo uint8 = 13 + // Is a directory, similar to `EISDIR` in POSIX. + ErrorCodeIsDirectory uint8 = 14 + // Too many levels of symbolic links, similar to `ELOOP` in POSIX. + ErrorCodeLoop uint8 = 15 + // Too many links, similar to `EMLINK` in POSIX. + ErrorCodeTooManyLinks uint8 = 16 + // Message too large, similar to `EMSGSIZE` in POSIX. + ErrorCodeMessageSize uint8 = 17 + // Filename too long, similar to `ENAMETOOLONG` in POSIX. + ErrorCodeNameTooLong uint8 = 18 + // No such device, similar to `ENODEV` in POSIX. + ErrorCodeNoDevice uint8 = 19 + // No such file or directory, similar to `ENOENT` in POSIX. + ErrorCodeNoEntry uint8 = 20 + // No locks available, similar to `ENOLCK` in POSIX. + ErrorCodeNoLock uint8 = 21 + // Not enough space, similar to `ENOMEM` in POSIX. + ErrorCodeInsufficientMemory uint8 = 22 + // No space left on device, similar to `ENOSPC` in POSIX. + ErrorCodeInsufficientSpace uint8 = 23 + // Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + ErrorCodeNotDirectory uint8 = 24 + // Directory not empty, similar to `ENOTEMPTY` in POSIX. + ErrorCodeNotEmpty uint8 = 25 + // State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + ErrorCodeNotRecoverable uint8 = 26 + // Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + ErrorCodeUnsupported uint8 = 27 + // Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + ErrorCodeNoTty uint8 = 28 + // No such device or address, similar to `ENXIO` in POSIX. + ErrorCodeNoSuchDevice uint8 = 29 + // Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + ErrorCodeOverflow uint8 = 30 + // Operation not permitted, similar to `EPERM` in POSIX. + ErrorCodeNotPermitted uint8 = 31 + // Broken pipe, similar to `EPIPE` in POSIX. + ErrorCodePipe uint8 = 32 + // Read-only file system, similar to `EROFS` in POSIX. + ErrorCodeReadOnly uint8 = 33 + // Invalid seek, similar to `ESPIPE` in POSIX. + ErrorCodeInvalidSeek uint8 = 34 + // Text file busy, similar to `ETXTBSY` in POSIX. + ErrorCodeTextFileBusy uint8 = 35 + // Cross-device link, similar to `EXDEV` in POSIX. + ErrorCodeCrossDevice uint8 = 36 +) + +// 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. +type ErrorCode = uint8 + +const ( + // The application has no advice to give on its behavior with respect + // to the specified data. + AdviceNormal uint8 = 0 + // The application expects to access the specified data sequentially + // from lower offsets to higher offsets. + AdviceSequential uint8 = 1 + // The application expects to access the specified data in a random + // order. + AdviceRandom uint8 = 2 + // The application expects to access the specified data in the near + // future. + AdviceWillNeed uint8 = 3 + // The application expects that it will not access the specified data + // in the near future. + AdviceDontNeed uint8 = 4 + // The application expects to access the specified data once and then + // not reuse it thereafter. + AdviceNoReuse uint8 = 5 +) + +// File or memory access pattern advisory information. +type Advice = uint8 + +// A 128-bit hash value, split into parts because wasm doesn't have a +// 128-bit integer type. +type MetadataHashValue struct { + // 64 bits of a 128-bit hash value. + Lower uint64 + // Another 64 bits of a 128-bit hash value. + Upper uint64 +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor +func resourceDropDescriptor(handle int32) + +// 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. +type Descriptor struct { + handle *witRuntime.Handle +} + +func (self *Descriptor) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Descriptor) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Descriptor) Handle() int32 { + return self.handle.Use() +} + +func (self *Descriptor) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropDescriptor(handle) + } +} + +func DescriptorFromOwnHandle(handleValue int32) *Descriptor { + handle := witRuntime.MakeHandle(handleValue) + value := &Descriptor{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropDescriptor(handleValue) + } + }, 0) + return value +} + +func DescriptorFromBorrowHandle(handleValue int32) *Descriptor { + handle := witRuntime.MakeHandle(handleValue) + return &Descriptor{handle} +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream +func resourceDropDirectoryEntryStream(handle int32) + +// A stream of directory entries. +type DirectoryEntryStream struct { + handle *witRuntime.Handle +} + +func (self *DirectoryEntryStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *DirectoryEntryStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *DirectoryEntryStream) Handle() int32 { + return self.handle.Use() +} + +func (self *DirectoryEntryStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropDirectoryEntryStream(handle) + } +} + +func DirectoryEntryStreamFromOwnHandle(handleValue int32) *DirectoryEntryStream { + handle := witRuntime.MakeHandle(handleValue) + value := &DirectoryEntryStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropDirectoryEntryStream(handleValue) + } + }, 0) + return value +} + +func DirectoryEntryStreamFromBorrowHandle(handleValue int32) *DirectoryEntryStream { + handle := witRuntime.MakeHandle(handleValue) + return &DirectoryEntryStream{handle} +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream +func wasm_import_method_descriptor_read_via_stream(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *Descriptor) ReadViaStream(offset uint64) witTypes.Result[*wasi_io_0_2_0_streams.InputStream, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_descriptor_read_via_stream((self).Handle(), int64(offset), returnArea) + var result witTypes.Result[*wasi_io_0_2_0_streams.InputStream, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_io_0_2_0_streams.InputStream, ErrorCode](wasi_io_0_2_0_streams.InputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_io_0_2_0_streams.InputStream, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream +func wasm_import_method_descriptor_write_via_stream(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *Descriptor) WriteViaStream(offset uint64) witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_descriptor_write_via_stream((self).Handle(), int64(offset), returnArea) + var result witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_io_0_2_0_streams.OutputStream, ErrorCode](wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_io_0_2_0_streams.OutputStream, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream +func wasm_import_method_descriptor_append_via_stream(arg0 int32, arg1 uintptr) + +func (self *Descriptor) AppendViaStream() witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_descriptor_append_via_stream((self).Handle(), returnArea) + var result witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_io_0_2_0_streams.OutputStream, ErrorCode](wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_io_0_2_0_streams.OutputStream, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise +func wasm_import_method_descriptor_advise(arg0 int32, arg1 int64, arg2 int64, arg3 int32, arg4 uintptr) + +func (self *Descriptor) Advise(offset uint64, length uint64, advice Advice) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_advise((self).Handle(), int64(offset), int64(length), int32(advice), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data +func wasm_import_method_descriptor_sync_data(arg0 int32, arg1 uintptr) + +func (self *Descriptor) SyncData() witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_sync_data((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags +func wasm_import_method_descriptor_get_flags(arg0 int32, arg1 uintptr) + +func (self *Descriptor) GetFlags() witTypes.Result[DescriptorFlags, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_get_flags((self).Handle(), returnArea) + var result witTypes.Result[DescriptorFlags, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[DescriptorFlags, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + case 1: + + result = witTypes.Err[DescriptorFlags, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type +func wasm_import_method_descriptor_get_type(arg0 int32, arg1 uintptr) + +func (self *Descriptor) GetType() witTypes.Result[DescriptorType, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_get_type((self).Handle(), returnArea) + var result witTypes.Result[DescriptorType, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[DescriptorType, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + case 1: + + result = witTypes.Err[DescriptorType, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size +func wasm_import_method_descriptor_set_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *Descriptor) SetSize(size uint64) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_set_size((self).Handle(), int64(size), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times +func wasm_import_method_descriptor_set_times(arg0 int32, arg1 int32, arg2 int64, arg3 int32, arg4 int32, arg5 int64, arg6 int32, arg7 uintptr) + +func (self *Descriptor) SetTimes(dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + var variant int32 + var variant0 int64 + var variant1 int32 + switch dataAccessTimestamp.Tag() { + case NewTimestampNoChange: + + variant = int32(0) + variant0 = 0 + variant1 = 0 + + case NewTimestampNow: + + variant = int32(1) + variant0 = 0 + variant1 = 0 + + case NewTimestampTimestamp: + payload := dataAccessTimestamp.Timestamp() + + variant = int32(2) + variant0 = int64((payload).Seconds) + variant1 = int32((payload).Nanoseconds) + + default: + panic("unreachable") + } + var variant2 int32 + var variant3 int64 + var variant4 int32 + switch dataModificationTimestamp.Tag() { + case NewTimestampNoChange: + + variant2 = int32(0) + variant3 = 0 + variant4 = 0 + + case NewTimestampNow: + + variant2 = int32(1) + variant3 = 0 + variant4 = 0 + + case NewTimestampTimestamp: + payload := dataModificationTimestamp.Timestamp() + + variant2 = int32(2) + variant3 = int64((payload).Seconds) + variant4 = int32((payload).Nanoseconds) + + default: + panic("unreachable") + } + wasm_import_method_descriptor_set_times((self).Handle(), variant, variant0, variant1, variant2, variant3, variant4, returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result5 := result + return result5 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read +func wasm_import_method_descriptor_read(arg0 int32, arg1 int64, arg2 int64, arg3 uintptr) + +func (self *Descriptor) Read(length uint64, offset uint64) witTypes.Result[witTypes.Tuple2[[]uint8, bool], ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_method_descriptor_read((self).Handle(), int64(length), int64(offset), returnArea) + var result witTypes.Result[witTypes.Tuple2[[]uint8, bool], ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[witTypes.Tuple2[[]uint8, bool], ErrorCode](witTypes.Tuple2[[]uint8, bool]{value, (uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) != 0)}) + case 1: + + result = witTypes.Err[witTypes.Tuple2[[]uint8, bool], ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write +func wasm_import_method_descriptor_write(arg0 int32, arg1 uintptr, arg2 uint32, arg3 int64, arg4 uintptr) + +func (self *Descriptor) Write(buffer []uint8, offset uint64) witTypes.Result[uint64, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + data := unsafe.Pointer(unsafe.SliceData(buffer)) + pinner.Pin(data) + wasm_import_method_descriptor_write((self).Handle(), uintptr(data), uint32(len(buffer)), int64(offset), returnArea) + var result witTypes.Result[uint64, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory +func wasm_import_method_descriptor_read_directory(arg0 int32, arg1 uintptr) + +func (self *Descriptor) ReadDirectory() witTypes.Result[*DirectoryEntryStream, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_descriptor_read_directory((self).Handle(), returnArea) + var result witTypes.Result[*DirectoryEntryStream, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*DirectoryEntryStream, ErrorCode](DirectoryEntryStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*DirectoryEntryStream, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync +func wasm_import_method_descriptor_sync(arg0 int32, arg1 uintptr) + +func (self *Descriptor) Sync() witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_descriptor_sync((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at +func wasm_import_method_descriptor_create_directory_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Descriptor) CreateDirectoryAt(path string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_create_directory_at((self).Handle(), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat +func wasm_import_method_descriptor_stat(arg0 int32, arg1 uintptr) + +func (self *Descriptor) Stat() witTypes.Result[DescriptorStat, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 104, 8)) + wasm_import_method_descriptor_stat((self).Handle(), returnArea) + var result witTypes.Result[DescriptorStat, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 48)))}) + default: + panic("unreachable") + } + var option0 witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 56))) { + case 0: + + option0 = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option0 = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 64))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 72)))}) + default: + panic("unreachable") + } + var option1 witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 80))) { + case 0: + + option1 = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option1 = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 88))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 96)))}) + default: + panic("unreachable") + } + + result = witTypes.Ok[DescriptorStat, ErrorCode](DescriptorStat{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 16))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24))), option, option0, option1}) + case 1: + + result = witTypes.Err[DescriptorStat, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result2 := result + return result2 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at +func wasm_import_method_descriptor_stat_at(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func (self *Descriptor) StatAt(pathFlags PathFlags, path string) witTypes.Result[DescriptorStat, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 104, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_stat_at((self).Handle(), int32(pathFlags), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[DescriptorStat, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 48)))}) + default: + panic("unreachable") + } + var option0 witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 56))) { + case 0: + + option0 = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option0 = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 64))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 72)))}) + default: + panic("unreachable") + } + var option1 witTypes.Option[wasi_clocks_0_2_0_wall_clock.Datetime] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 80))) { + case 0: + + option1 = witTypes.None[wasi_clocks_0_2_0_wall_clock.Datetime]() + case 1: + + option1 = witTypes.Some[wasi_clocks_0_2_0_wall_clock.Datetime](wasi_clocks_0_2_0_wall_clock.Datetime{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 88))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 96)))}) + default: + panic("unreachable") + } + + result = witTypes.Ok[DescriptorStat, ErrorCode](DescriptorStat{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 16))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24))), option, option0, option1}) + case 1: + + result = witTypes.Err[DescriptorStat, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result2 := result + return result2 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at +func wasm_import_method_descriptor_set_times_at(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 int32, arg5 int64, arg6 int32, arg7 int32, arg8 int64, arg9 int32, arg10 uintptr) + +func (self *Descriptor) SetTimesAt(pathFlags PathFlags, path string, dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + var variant int32 + var variant0 int64 + var variant1 int32 + switch dataAccessTimestamp.Tag() { + case NewTimestampNoChange: + + variant = int32(0) + variant0 = 0 + variant1 = 0 + + case NewTimestampNow: + + variant = int32(1) + variant0 = 0 + variant1 = 0 + + case NewTimestampTimestamp: + payload := dataAccessTimestamp.Timestamp() + + variant = int32(2) + variant0 = int64((payload).Seconds) + variant1 = int32((payload).Nanoseconds) + + default: + panic("unreachable") + } + var variant2 int32 + var variant3 int64 + var variant4 int32 + switch dataModificationTimestamp.Tag() { + case NewTimestampNoChange: + + variant2 = int32(0) + variant3 = 0 + variant4 = 0 + + case NewTimestampNow: + + variant2 = int32(1) + variant3 = 0 + variant4 = 0 + + case NewTimestampTimestamp: + payload := dataModificationTimestamp.Timestamp() + + variant2 = int32(2) + variant3 = int64((payload).Seconds) + variant4 = int32((payload).Nanoseconds) + + default: + panic("unreachable") + } + wasm_import_method_descriptor_set_times_at((self).Handle(), int32(pathFlags), uintptr(utf8), uint32(len(path)), variant, variant0, variant1, variant2, variant3, variant4, returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result5 := result + return result5 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at +func wasm_import_method_descriptor_link_at(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 int32, arg5 uintptr, arg6 uint32, arg7 uintptr) + +func (self *Descriptor) LinkAt(oldPathFlags PathFlags, oldPath string, newDescriptor *Descriptor, newPath string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(oldPath)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(newPath)) + pinner.Pin(utf80) + wasm_import_method_descriptor_link_at((self).Handle(), int32(oldPathFlags), uintptr(utf8), uint32(len(oldPath)), (newDescriptor).Handle(), uintptr(utf80), uint32(len(newPath)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at +func wasm_import_method_descriptor_open_at(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 int32, arg5 int32, arg6 uintptr) + +func (self *Descriptor) OpenAt(pathFlags PathFlags, path string, openFlags OpenFlags, flags DescriptorFlags) witTypes.Result[*Descriptor, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_open_at((self).Handle(), int32(pathFlags), uintptr(utf8), uint32(len(path)), int32(openFlags), int32(flags), returnArea) + var result witTypes.Result[*Descriptor, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Descriptor, ErrorCode](DescriptorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*Descriptor, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at +func wasm_import_method_descriptor_readlink_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Descriptor) ReadlinkAt(path string) witTypes.Result[string, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_readlink_at((self).Handle(), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[string, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[string, ErrorCode](value) + case 1: + + result = witTypes.Err[string, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at +func wasm_import_method_descriptor_remove_directory_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Descriptor) RemoveDirectoryAt(path string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_remove_directory_at((self).Handle(), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at +func wasm_import_method_descriptor_rename_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 int32, arg4 uintptr, arg5 uint32, arg6 uintptr) + +func (self *Descriptor) RenameAt(oldPath string, newDescriptor *Descriptor, newPath string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(oldPath)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(newPath)) + pinner.Pin(utf80) + wasm_import_method_descriptor_rename_at((self).Handle(), uintptr(utf8), uint32(len(oldPath)), (newDescriptor).Handle(), uintptr(utf80), uint32(len(newPath)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at +func wasm_import_method_descriptor_symlink_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Descriptor) SymlinkAt(oldPath string, newPath string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(oldPath)) + pinner.Pin(utf8) + utf80 := unsafe.Pointer(unsafe.StringData(newPath)) + pinner.Pin(utf80) + wasm_import_method_descriptor_symlink_at((self).Handle(), uintptr(utf8), uint32(len(oldPath)), uintptr(utf80), uint32(len(newPath)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at +func wasm_import_method_descriptor_unlink_file_at(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Descriptor) UnlinkFileAt(path string) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_unlink_file_at((self).Handle(), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object +func wasm_import_method_descriptor_is_same_object(arg0 int32, arg1 int32) int32 + +func (self *Descriptor) IsSameObject(other *Descriptor) bool { + + result := wasm_import_method_descriptor_is_same_object((self).Handle(), (other).Handle()) + return (result != 0) + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash +func wasm_import_method_descriptor_metadata_hash(arg0 int32, arg1 uintptr) + +func (self *Descriptor) MetadataHash() witTypes.Result[MetadataHashValue, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 24, 8)) + wasm_import_method_descriptor_metadata_hash((self).Handle(), returnArea) + var result witTypes.Result[MetadataHashValue, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[MetadataHashValue, ErrorCode](MetadataHashValue{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 16)))}) + case 1: + + result = witTypes.Err[MetadataHashValue, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at +func wasm_import_method_descriptor_metadata_hash_at(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func (self *Descriptor) MetadataHashAt(pathFlags PathFlags, path string) witTypes.Result[MetadataHashValue, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 24, 8)) + utf8 := unsafe.Pointer(unsafe.StringData(path)) + pinner.Pin(utf8) + wasm_import_method_descriptor_metadata_hash_at((self).Handle(), int32(pathFlags), uintptr(utf8), uint32(len(path)), returnArea) + var result witTypes.Result[MetadataHashValue, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[MetadataHashValue, ErrorCode](MetadataHashValue{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 16)))}) + case 1: + + result = witTypes.Err[MetadataHashValue, ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry +func wasm_import_method_directory_entry_stream_read_directory_entry(arg0 int32, arg1 uintptr) + +func (self *DirectoryEntryStream) ReadDirectoryEntry() witTypes.Result[witTypes.Option[DirectoryEntry], ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + wasm_import_method_directory_entry_stream_read_directory_entry((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Option[DirectoryEntry], ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[DirectoryEntry] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[DirectoryEntry]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + + option = witTypes.Some[DirectoryEntry](DirectoryEntry{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4))))), value}) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[DirectoryEntry], ErrorCode](option) + case 1: + + result = witTypes.Err[witTypes.Option[DirectoryEntry], ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code +func wasm_import_filesystem_error_code(arg0 int32, arg1 uintptr) + +func FilesystemErrorCode(err *wasi_io_0_2_0_error.Error) witTypes.Option[ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_filesystem_error_code((err).Handle(), returnArea) + var option witTypes.Option[ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[ErrorCode]() + case 1: + + option = witTypes.Some[ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result := option + return result + +} diff --git a/internal/wasi_http_0_2_0_incoming_handler/wit_bindings.go b/internal/wasi_http_0_2_0_incoming_handler/wit_bindings.go new file mode 100644 index 00000000..a7424149 --- /dev/null +++ b/internal/wasi_http_0_2_0_incoming_handler/wit_bindings.go @@ -0,0 +1,40 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_http_0_2_0_incoming_handler + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" +) + +type IncomingRequest = wasi_http_0_2_0_types.IncomingRequest +type ResponseOutparam = wasi_http_0_2_0_types.ResponseOutparam diff --git a/internal/wasi_http_0_2_0_outgoing_handler/wit_bindings.go b/internal/wasi_http_0_2_0_outgoing_handler/wit_bindings.go new file mode 100644 index 00000000..e75c926a --- /dev/null +++ b/internal/wasi_http_0_2_0_outgoing_handler/wit_bindings.go @@ -0,0 +1,498 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_http_0_2_0_outgoing_handler + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type OutgoingRequest = wasi_http_0_2_0_types.OutgoingRequest +type RequestOptions = wasi_http_0_2_0_types.RequestOptions +type FutureIncomingResponse = wasi_http_0_2_0_types.FutureIncomingResponse +type ErrorCode = wasi_http_0_2_0_types.ErrorCode + +//go:wasmimport wasi:http/outgoing-handler@0.2.0 handle +func wasm_import_handle(arg0 int32, arg1 int32, arg2 int32, arg3 uintptr) + +func Handle(request *wasi_http_0_2_0_types.OutgoingRequest, options witTypes.Option[*wasi_http_0_2_0_types.RequestOptions]) witTypes.Result[*wasi_http_0_2_0_types.FutureIncomingResponse, wasi_http_0_2_0_types.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (24 + 4*4), 8)) + var option int32 + var option0 int32 + switch options.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + case witTypes.OptionSome: + payload := options.Some() + + option = int32(1) + option0 = (payload).TakeHandle() + default: + panic("unreachable") + } + wasm_import_handle((request).TakeHandle(), option, option0, returnArea) + var result witTypes.Result[*wasi_http_0_2_0_types.FutureIncomingResponse, wasi_http_0_2_0_types.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_http_0_2_0_types.FutureIncomingResponse, wasi_http_0_2_0_types.ErrorCode](wasi_http_0_2_0_types.FutureIncomingResponseFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + case 1: + var variant wasi_http_0_2_0_types.ErrorCode + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = wasi_http_0_2_0_types.MakeErrorCodeDnsTimeout() + + case 1: + var option1 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option1 = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option1 = witTypes.Some[string](value) + default: + panic("unreachable") + } + var option2 witTypes.Option[uint16] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option2 = witTypes.None[uint16]() + case 1: + + option2 = witTypes.Some[uint16](uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (18 + 3*4)))))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeDnsError(wasi_http_0_2_0_types.DnsErrorPayload{option1, option2}) + + case 2: + + variant = wasi_http_0_2_0_types.MakeErrorCodeDestinationNotFound() + + case 3: + + variant = wasi_http_0_2_0_types.MakeErrorCodeDestinationUnavailable() + + case 4: + + variant = wasi_http_0_2_0_types.MakeErrorCodeDestinationIpProhibited() + + case 5: + + variant = wasi_http_0_2_0_types.MakeErrorCodeDestinationIpUnroutable() + + case 6: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionRefused() + + case 7: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionTerminated() + + case 8: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionTimeout() + + case 9: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionReadTimeout() + + case 10: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionWriteTimeout() + + case 11: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConnectionLimitReached() + + case 12: + + variant = wasi_http_0_2_0_types.MakeErrorCodeTlsProtocolError() + + case 13: + + variant = wasi_http_0_2_0_types.MakeErrorCodeTlsCertificateError() + + case 14: + var option3 witTypes.Option[uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option3 = witTypes.None[uint8]() + case 1: + + option3 = witTypes.Some[uint8](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 17))))) + default: + panic("unreachable") + } + var option5 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option5 = witTypes.None[string]() + case 1: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option5 = witTypes.Some[string](value4) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeTlsAlertReceived(wasi_http_0_2_0_types.TlsAlertReceivedPayload{option3, option5}) + + case 15: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestDenied() + + case 16: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestLengthRequired() + + case 17: + var option6 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option6 = witTypes.None[uint64]() + case 1: + + option6 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestBodySize(option6) + + case 18: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestMethodInvalid() + + case 19: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestUriInvalid() + + case 20: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestUriTooLong() + + case 21: + var option7 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option7 = witTypes.None[uint32]() + case 1: + + option7 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestHeaderSectionSize(option7) + + case 22: + var option11 witTypes.Option[wasi_http_0_2_0_types.FieldSizePayload] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option11 = witTypes.None[wasi_http_0_2_0_types.FieldSizePayload]() + case 1: + var option9 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option9 = witTypes.None[string]() + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option9 = witTypes.Some[string](value8) + default: + panic("unreachable") + } + var option10 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 4*4)))) { + case 0: + + option10 = witTypes.None[uint32]() + case 1: + + option10 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 4*4))))) + default: + panic("unreachable") + } + + option11 = witTypes.Some[wasi_http_0_2_0_types.FieldSizePayload](wasi_http_0_2_0_types.FieldSizePayload{option9, option10}) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestHeaderSize(option11) + + case 23: + var option12 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option12 = witTypes.None[uint32]() + case 1: + + option12 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestTrailerSectionSize(option12) + + case 24: + var option14 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option14 = witTypes.None[string]() + case 1: + value13 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option14 = witTypes.Some[string](value13) + default: + panic("unreachable") + } + var option15 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option15 = witTypes.None[uint32]() + case 1: + + option15 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpRequestTrailerSize(wasi_http_0_2_0_types.FieldSizePayload{option14, option15}) + + case 25: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseIncomplete() + + case 26: + var option16 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option16 = witTypes.None[uint32]() + case 1: + + option16 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseHeaderSectionSize(option16) + + case 27: + var option18 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option18 = witTypes.None[string]() + case 1: + value17 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option18 = witTypes.Some[string](value17) + default: + panic("unreachable") + } + var option19 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option19 = witTypes.None[uint32]() + case 1: + + option19 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseHeaderSize(wasi_http_0_2_0_types.FieldSizePayload{option18, option19}) + + case 28: + var option20 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option20 = witTypes.None[uint64]() + case 1: + + option20 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseBodySize(option20) + + case 29: + var option21 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option21 = witTypes.None[uint32]() + case 1: + + option21 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseTrailerSectionSize(option21) + + case 30: + var option23 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option23 = witTypes.None[string]() + case 1: + value22 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option23 = witTypes.Some[string](value22) + default: + panic("unreachable") + } + var option24 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option24 = witTypes.None[uint32]() + case 1: + + option24 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseTrailerSize(wasi_http_0_2_0_types.FieldSizePayload{option23, option24}) + + case 31: + var option26 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option26 = witTypes.None[string]() + case 1: + value25 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option26 = witTypes.Some[string](value25) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseTransferCoding(option26) + + case 32: + var option28 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option28 = witTypes.None[string]() + case 1: + value27 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option28 = witTypes.Some[string](value27) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseContentCoding(option28) + + case 33: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpResponseTimeout() + + case 34: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpUpgradeFailed() + + case 35: + + variant = wasi_http_0_2_0_types.MakeErrorCodeHttpProtocolError() + + case 36: + + variant = wasi_http_0_2_0_types.MakeErrorCodeLoopDetected() + + case 37: + + variant = wasi_http_0_2_0_types.MakeErrorCodeConfigurationError() + + case 38: + var option30 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option30 = witTypes.None[string]() + case 1: + value29 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option30 = witTypes.Some[string](value29) + default: + panic("unreachable") + } + + variant = wasi_http_0_2_0_types.MakeErrorCodeInternalError(option30) + + default: + panic("unreachable") + } + + result = witTypes.Err[*wasi_http_0_2_0_types.FutureIncomingResponse, wasi_http_0_2_0_types.ErrorCode](variant) + default: + panic("unreachable") + } + result31 := result + return result31 + +} diff --git a/internal/wasi_http_0_2_0_types/wit_bindings.go b/internal/wasi_http_0_2_0_types/wit_bindings.go new file mode 100644 index 00000000..f703a314 --- /dev/null +++ b/internal/wasi_http_0_2_0_types/wit_bindings.go @@ -0,0 +1,4998 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_http_0_2_0_types + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_error" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Duration = uint64 +type InputStream = wasi_io_0_2_0_streams.InputStream +type OutputStream = wasi_io_0_2_0_streams.OutputStream +type IoError = wasi_io_0_2_0_error.Error +type Pollable = wasi_io_0_2_0_poll.Pollable + +const ( + MethodGet uint8 = 0 + MethodHead uint8 = 1 + MethodPost uint8 = 2 + MethodPut uint8 = 3 + MethodDelete uint8 = 4 + MethodConnect uint8 = 5 + MethodOptions uint8 = 6 + MethodTrace uint8 = 7 + MethodPatch uint8 = 8 + MethodOther uint8 = 9 +) + +// This type corresponds to HTTP standard Methods. +type Method struct { + tag uint8 + value any +} + +func (self Method) Tag() uint8 { + return self.tag +} + +func (self Method) Other() string { + if self.tag != MethodOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeMethodGet() Method { + return Method{MethodGet, nil} +} +func MakeMethodHead() Method { + return Method{MethodHead, nil} +} +func MakeMethodPost() Method { + return Method{MethodPost, nil} +} +func MakeMethodPut() Method { + return Method{MethodPut, nil} +} +func MakeMethodDelete() Method { + return Method{MethodDelete, nil} +} +func MakeMethodConnect() Method { + return Method{MethodConnect, nil} +} +func MakeMethodOptions() Method { + return Method{MethodOptions, nil} +} +func MakeMethodTrace() Method { + return Method{MethodTrace, nil} +} +func MakeMethodPatch() Method { + return Method{MethodPatch, nil} +} +func MakeMethodOther(value string) Method { + return Method{MethodOther, value} +} + +const ( + SchemeHttp uint8 = 0 + SchemeHttps uint8 = 1 + SchemeOther uint8 = 2 +) + +// This type corresponds to HTTP standard Related Schemes. +type Scheme struct { + tag uint8 + value any +} + +func (self Scheme) Tag() uint8 { + return self.tag +} + +func (self Scheme) Other() string { + if self.tag != SchemeOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeSchemeHttp() Scheme { + return Scheme{SchemeHttp, nil} +} +func MakeSchemeHttps() Scheme { + return Scheme{SchemeHttps, nil} +} +func MakeSchemeOther(value string) Scheme { + return Scheme{SchemeOther, value} +} + +// Defines the case payload type for `DNS-error` above: +type DnsErrorPayload struct { + Rcode witTypes.Option[string] + InfoCode witTypes.Option[uint16] +} + +// Defines the case payload type for `TLS-alert-received` above: +type TlsAlertReceivedPayload struct { + AlertId witTypes.Option[uint8] + AlertMessage witTypes.Option[string] +} + +// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: +type FieldSizePayload struct { + FieldName witTypes.Option[string] + FieldSize witTypes.Option[uint32] +} + +const ( + ErrorCodeDnsTimeout uint8 = 0 + ErrorCodeDnsError uint8 = 1 + ErrorCodeDestinationNotFound uint8 = 2 + ErrorCodeDestinationUnavailable uint8 = 3 + ErrorCodeDestinationIpProhibited uint8 = 4 + ErrorCodeDestinationIpUnroutable uint8 = 5 + ErrorCodeConnectionRefused uint8 = 6 + ErrorCodeConnectionTerminated uint8 = 7 + ErrorCodeConnectionTimeout uint8 = 8 + ErrorCodeConnectionReadTimeout uint8 = 9 + ErrorCodeConnectionWriteTimeout uint8 = 10 + ErrorCodeConnectionLimitReached uint8 = 11 + ErrorCodeTlsProtocolError uint8 = 12 + ErrorCodeTlsCertificateError uint8 = 13 + ErrorCodeTlsAlertReceived uint8 = 14 + ErrorCodeHttpRequestDenied uint8 = 15 + ErrorCodeHttpRequestLengthRequired uint8 = 16 + ErrorCodeHttpRequestBodySize uint8 = 17 + ErrorCodeHttpRequestMethodInvalid uint8 = 18 + ErrorCodeHttpRequestUriInvalid uint8 = 19 + ErrorCodeHttpRequestUriTooLong uint8 = 20 + ErrorCodeHttpRequestHeaderSectionSize uint8 = 21 + ErrorCodeHttpRequestHeaderSize uint8 = 22 + ErrorCodeHttpRequestTrailerSectionSize uint8 = 23 + ErrorCodeHttpRequestTrailerSize uint8 = 24 + ErrorCodeHttpResponseIncomplete uint8 = 25 + ErrorCodeHttpResponseHeaderSectionSize uint8 = 26 + ErrorCodeHttpResponseHeaderSize uint8 = 27 + ErrorCodeHttpResponseBodySize uint8 = 28 + ErrorCodeHttpResponseTrailerSectionSize uint8 = 29 + ErrorCodeHttpResponseTrailerSize uint8 = 30 + ErrorCodeHttpResponseTransferCoding uint8 = 31 + ErrorCodeHttpResponseContentCoding uint8 = 32 + ErrorCodeHttpResponseTimeout uint8 = 33 + ErrorCodeHttpUpgradeFailed uint8 = 34 + ErrorCodeHttpProtocolError uint8 = 35 + ErrorCodeLoopDetected uint8 = 36 + ErrorCodeConfigurationError uint8 = 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. + ErrorCodeInternalError uint8 = 38 +) + +// These cases are inspired by the IANA HTTP Proxy Error Types: +// +// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types +type ErrorCode struct { + tag uint8 + value any +} + +func (self ErrorCode) Tag() uint8 { + return self.tag +} + +func (self ErrorCode) DnsError() DnsErrorPayload { + if self.tag != ErrorCodeDnsError { + panic("tag mismatch") + } + return self.value.(DnsErrorPayload) +} +func (self ErrorCode) TlsAlertReceived() TlsAlertReceivedPayload { + if self.tag != ErrorCodeTlsAlertReceived { + panic("tag mismatch") + } + return self.value.(TlsAlertReceivedPayload) +} +func (self ErrorCode) HttpRequestBodySize() witTypes.Option[uint64] { + if self.tag != ErrorCodeHttpRequestBodySize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint64]) +} +func (self ErrorCode) HttpRequestHeaderSectionSize() witTypes.Option[uint32] { + if self.tag != ErrorCodeHttpRequestHeaderSectionSize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint32]) +} +func (self ErrorCode) HttpRequestHeaderSize() witTypes.Option[FieldSizePayload] { + if self.tag != ErrorCodeHttpRequestHeaderSize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[FieldSizePayload]) +} +func (self ErrorCode) HttpRequestTrailerSectionSize() witTypes.Option[uint32] { + if self.tag != ErrorCodeHttpRequestTrailerSectionSize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint32]) +} +func (self ErrorCode) HttpRequestTrailerSize() FieldSizePayload { + if self.tag != ErrorCodeHttpRequestTrailerSize { + panic("tag mismatch") + } + return self.value.(FieldSizePayload) +} +func (self ErrorCode) HttpResponseHeaderSectionSize() witTypes.Option[uint32] { + if self.tag != ErrorCodeHttpResponseHeaderSectionSize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint32]) +} +func (self ErrorCode) HttpResponseHeaderSize() FieldSizePayload { + if self.tag != ErrorCodeHttpResponseHeaderSize { + panic("tag mismatch") + } + return self.value.(FieldSizePayload) +} +func (self ErrorCode) HttpResponseBodySize() witTypes.Option[uint64] { + if self.tag != ErrorCodeHttpResponseBodySize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint64]) +} +func (self ErrorCode) HttpResponseTrailerSectionSize() witTypes.Option[uint32] { + if self.tag != ErrorCodeHttpResponseTrailerSectionSize { + panic("tag mismatch") + } + return self.value.(witTypes.Option[uint32]) +} +func (self ErrorCode) HttpResponseTrailerSize() FieldSizePayload { + if self.tag != ErrorCodeHttpResponseTrailerSize { + panic("tag mismatch") + } + return self.value.(FieldSizePayload) +} +func (self ErrorCode) HttpResponseTransferCoding() witTypes.Option[string] { + if self.tag != ErrorCodeHttpResponseTransferCoding { + panic("tag mismatch") + } + return self.value.(witTypes.Option[string]) +} +func (self ErrorCode) HttpResponseContentCoding() witTypes.Option[string] { + if self.tag != ErrorCodeHttpResponseContentCoding { + panic("tag mismatch") + } + return self.value.(witTypes.Option[string]) +} +func (self ErrorCode) InternalError() witTypes.Option[string] { + if self.tag != ErrorCodeInternalError { + panic("tag mismatch") + } + return self.value.(witTypes.Option[string]) +} + +func MakeErrorCodeDnsTimeout() ErrorCode { + return ErrorCode{ErrorCodeDnsTimeout, nil} +} +func MakeErrorCodeDnsError(value DnsErrorPayload) ErrorCode { + return ErrorCode{ErrorCodeDnsError, value} +} +func MakeErrorCodeDestinationNotFound() ErrorCode { + return ErrorCode{ErrorCodeDestinationNotFound, nil} +} +func MakeErrorCodeDestinationUnavailable() ErrorCode { + return ErrorCode{ErrorCodeDestinationUnavailable, nil} +} +func MakeErrorCodeDestinationIpProhibited() ErrorCode { + return ErrorCode{ErrorCodeDestinationIpProhibited, nil} +} +func MakeErrorCodeDestinationIpUnroutable() ErrorCode { + return ErrorCode{ErrorCodeDestinationIpUnroutable, nil} +} +func MakeErrorCodeConnectionRefused() ErrorCode { + return ErrorCode{ErrorCodeConnectionRefused, nil} +} +func MakeErrorCodeConnectionTerminated() ErrorCode { + return ErrorCode{ErrorCodeConnectionTerminated, nil} +} +func MakeErrorCodeConnectionTimeout() ErrorCode { + return ErrorCode{ErrorCodeConnectionTimeout, nil} +} +func MakeErrorCodeConnectionReadTimeout() ErrorCode { + return ErrorCode{ErrorCodeConnectionReadTimeout, nil} +} +func MakeErrorCodeConnectionWriteTimeout() ErrorCode { + return ErrorCode{ErrorCodeConnectionWriteTimeout, nil} +} +func MakeErrorCodeConnectionLimitReached() ErrorCode { + return ErrorCode{ErrorCodeConnectionLimitReached, nil} +} +func MakeErrorCodeTlsProtocolError() ErrorCode { + return ErrorCode{ErrorCodeTlsProtocolError, nil} +} +func MakeErrorCodeTlsCertificateError() ErrorCode { + return ErrorCode{ErrorCodeTlsCertificateError, nil} +} +func MakeErrorCodeTlsAlertReceived(value TlsAlertReceivedPayload) ErrorCode { + return ErrorCode{ErrorCodeTlsAlertReceived, value} +} +func MakeErrorCodeHttpRequestDenied() ErrorCode { + return ErrorCode{ErrorCodeHttpRequestDenied, nil} +} +func MakeErrorCodeHttpRequestLengthRequired() ErrorCode { + return ErrorCode{ErrorCodeHttpRequestLengthRequired, nil} +} +func MakeErrorCodeHttpRequestBodySize(value witTypes.Option[uint64]) ErrorCode { + return ErrorCode{ErrorCodeHttpRequestBodySize, value} +} +func MakeErrorCodeHttpRequestMethodInvalid() ErrorCode { + return ErrorCode{ErrorCodeHttpRequestMethodInvalid, nil} +} +func MakeErrorCodeHttpRequestUriInvalid() ErrorCode { + return ErrorCode{ErrorCodeHttpRequestUriInvalid, nil} +} +func MakeErrorCodeHttpRequestUriTooLong() ErrorCode { + return ErrorCode{ErrorCodeHttpRequestUriTooLong, nil} +} +func MakeErrorCodeHttpRequestHeaderSectionSize(value witTypes.Option[uint32]) ErrorCode { + return ErrorCode{ErrorCodeHttpRequestHeaderSectionSize, value} +} +func MakeErrorCodeHttpRequestHeaderSize(value witTypes.Option[FieldSizePayload]) ErrorCode { + return ErrorCode{ErrorCodeHttpRequestHeaderSize, value} +} +func MakeErrorCodeHttpRequestTrailerSectionSize(value witTypes.Option[uint32]) ErrorCode { + return ErrorCode{ErrorCodeHttpRequestTrailerSectionSize, value} +} +func MakeErrorCodeHttpRequestTrailerSize(value FieldSizePayload) ErrorCode { + return ErrorCode{ErrorCodeHttpRequestTrailerSize, value} +} +func MakeErrorCodeHttpResponseIncomplete() ErrorCode { + return ErrorCode{ErrorCodeHttpResponseIncomplete, nil} +} +func MakeErrorCodeHttpResponseHeaderSectionSize(value witTypes.Option[uint32]) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseHeaderSectionSize, value} +} +func MakeErrorCodeHttpResponseHeaderSize(value FieldSizePayload) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseHeaderSize, value} +} +func MakeErrorCodeHttpResponseBodySize(value witTypes.Option[uint64]) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseBodySize, value} +} +func MakeErrorCodeHttpResponseTrailerSectionSize(value witTypes.Option[uint32]) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseTrailerSectionSize, value} +} +func MakeErrorCodeHttpResponseTrailerSize(value FieldSizePayload) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseTrailerSize, value} +} +func MakeErrorCodeHttpResponseTransferCoding(value witTypes.Option[string]) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseTransferCoding, value} +} +func MakeErrorCodeHttpResponseContentCoding(value witTypes.Option[string]) ErrorCode { + return ErrorCode{ErrorCodeHttpResponseContentCoding, value} +} +func MakeErrorCodeHttpResponseTimeout() ErrorCode { + return ErrorCode{ErrorCodeHttpResponseTimeout, nil} +} +func MakeErrorCodeHttpUpgradeFailed() ErrorCode { + return ErrorCode{ErrorCodeHttpUpgradeFailed, nil} +} +func MakeErrorCodeHttpProtocolError() ErrorCode { + return ErrorCode{ErrorCodeHttpProtocolError, nil} +} +func MakeErrorCodeLoopDetected() ErrorCode { + return ErrorCode{ErrorCodeLoopDetected, nil} +} +func MakeErrorCodeConfigurationError() ErrorCode { + return ErrorCode{ErrorCodeConfigurationError, nil} +} +func MakeErrorCodeInternalError(value witTypes.Option[string]) ErrorCode { + return ErrorCode{ErrorCodeInternalError, value} +} + +const ( + // This error indicates that a `field-key` or `field-value` was + // syntactically invalid when used with an operation that sets headers in a + // `fields`. + HeaderErrorInvalidSyntax uint8 = 0 + // This error indicates that a forbidden `field-key` was used when trying + // to set a header in a `fields`. + HeaderErrorForbidden uint8 = 1 + // This error indicates that the operation on the `fields` was not + // permitted because the fields are immutable. + HeaderErrorImmutable uint8 = 2 +) + +// This type enumerates the different kinds of errors that may occur when +// setting or appending to a `fields` resource. +type HeaderError struct { + tag uint8 + value any +} + +func (self HeaderError) Tag() uint8 { + return self.tag +} + +func MakeHeaderErrorInvalidSyntax() HeaderError { + return HeaderError{HeaderErrorInvalidSyntax, nil} +} +func MakeHeaderErrorForbidden() HeaderError { + return HeaderError{HeaderErrorForbidden, nil} +} +func MakeHeaderErrorImmutable() HeaderError { + return HeaderError{HeaderErrorImmutable, nil} +} + +// Field keys are always strings. +type FieldKey = string + +// 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. +type FieldValue = []uint8 + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]fields +func resourceDropFields(handle int32) + +// 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 be +// immutable. In an immutable fields, the `set`, `append`, and `delete` +// operations will fail with `header-error.immutable`. +type Fields struct { + handle *witRuntime.Handle +} + +func (self *Fields) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Fields) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Fields) Handle() int32 { + return self.handle.Use() +} + +func (self *Fields) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropFields(handle) + } +} + +func FieldsFromOwnHandle(handleValue int32) *Fields { + handle := witRuntime.MakeHandle(handleValue) + value := &Fields{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropFields(handleValue) + } + }, 0) + return value +} + +func FieldsFromBorrowHandle(handleValue int32) *Fields { + handle := witRuntime.MakeHandle(handleValue) + return &Fields{handle} +} + +// Headers is an alias for Fields. +type Headers = Fields + +// Trailers is an alias for Fields. +type Trailers = Fields + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]incoming-request +func resourceDropIncomingRequest(handle int32) + +// Represents an incoming HTTP Request. +type IncomingRequest struct { + handle *witRuntime.Handle +} + +func (self *IncomingRequest) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *IncomingRequest) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *IncomingRequest) Handle() int32 { + return self.handle.Use() +} + +func (self *IncomingRequest) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropIncomingRequest(handle) + } +} + +func IncomingRequestFromOwnHandle(handleValue int32) *IncomingRequest { + handle := witRuntime.MakeHandle(handleValue) + value := &IncomingRequest{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropIncomingRequest(handleValue) + } + }, 0) + return value +} + +func IncomingRequestFromBorrowHandle(handleValue int32) *IncomingRequest { + handle := witRuntime.MakeHandle(handleValue) + return &IncomingRequest{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]outgoing-request +func resourceDropOutgoingRequest(handle int32) + +// Represents an outgoing HTTP Request. +type OutgoingRequest struct { + handle *witRuntime.Handle +} + +func (self *OutgoingRequest) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *OutgoingRequest) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *OutgoingRequest) Handle() int32 { + return self.handle.Use() +} + +func (self *OutgoingRequest) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropOutgoingRequest(handle) + } +} + +func OutgoingRequestFromOwnHandle(handleValue int32) *OutgoingRequest { + handle := witRuntime.MakeHandle(handleValue) + value := &OutgoingRequest{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropOutgoingRequest(handleValue) + } + }, 0) + return value +} + +func OutgoingRequestFromBorrowHandle(handleValue int32) *OutgoingRequest { + handle := witRuntime.MakeHandle(handleValue) + return &OutgoingRequest{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]request-options +func resourceDropRequestOptions(handle int32) + +// 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`. +type RequestOptions struct { + handle *witRuntime.Handle +} + +func (self *RequestOptions) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *RequestOptions) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *RequestOptions) Handle() int32 { + return self.handle.Use() +} + +func (self *RequestOptions) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropRequestOptions(handle) + } +} + +func RequestOptionsFromOwnHandle(handleValue int32) *RequestOptions { + handle := witRuntime.MakeHandle(handleValue) + value := &RequestOptions{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropRequestOptions(handleValue) + } + }, 0) + return value +} + +func RequestOptionsFromBorrowHandle(handleValue int32) *RequestOptions { + handle := witRuntime.MakeHandle(handleValue) + return &RequestOptions{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]response-outparam +func resourceDropResponseOutparam(handle int32) + +// 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`. +type ResponseOutparam struct { + handle *witRuntime.Handle +} + +func (self *ResponseOutparam) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *ResponseOutparam) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *ResponseOutparam) Handle() int32 { + return self.handle.Use() +} + +func (self *ResponseOutparam) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropResponseOutparam(handle) + } +} + +func ResponseOutparamFromOwnHandle(handleValue int32) *ResponseOutparam { + handle := witRuntime.MakeHandle(handleValue) + value := &ResponseOutparam{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropResponseOutparam(handleValue) + } + }, 0) + return value +} + +func ResponseOutparamFromBorrowHandle(handleValue int32) *ResponseOutparam { + handle := witRuntime.MakeHandle(handleValue) + return &ResponseOutparam{handle} +} + +// This type corresponds to the HTTP standard Status Code. +type StatusCode = uint16 + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]incoming-response +func resourceDropIncomingResponse(handle int32) + +// Represents an incoming HTTP Response. +type IncomingResponse struct { + handle *witRuntime.Handle +} + +func (self *IncomingResponse) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *IncomingResponse) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *IncomingResponse) Handle() int32 { + return self.handle.Use() +} + +func (self *IncomingResponse) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropIncomingResponse(handle) + } +} + +func IncomingResponseFromOwnHandle(handleValue int32) *IncomingResponse { + handle := witRuntime.MakeHandle(handleValue) + value := &IncomingResponse{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropIncomingResponse(handleValue) + } + }, 0) + return value +} + +func IncomingResponseFromBorrowHandle(handleValue int32) *IncomingResponse { + handle := witRuntime.MakeHandle(handleValue) + return &IncomingResponse{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]incoming-body +func resourceDropIncomingBody(handle int32) + +// 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. +type IncomingBody struct { + handle *witRuntime.Handle +} + +func (self *IncomingBody) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *IncomingBody) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *IncomingBody) Handle() int32 { + return self.handle.Use() +} + +func (self *IncomingBody) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropIncomingBody(handle) + } +} + +func IncomingBodyFromOwnHandle(handleValue int32) *IncomingBody { + handle := witRuntime.MakeHandle(handleValue) + value := &IncomingBody{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropIncomingBody(handleValue) + } + }, 0) + return value +} + +func IncomingBodyFromBorrowHandle(handleValue int32) *IncomingBody { + handle := witRuntime.MakeHandle(handleValue) + return &IncomingBody{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]future-trailers +func resourceDropFutureTrailers(handle int32) + +// Represents a future which may eventaully 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. +type FutureTrailers struct { + handle *witRuntime.Handle +} + +func (self *FutureTrailers) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *FutureTrailers) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *FutureTrailers) Handle() int32 { + return self.handle.Use() +} + +func (self *FutureTrailers) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropFutureTrailers(handle) + } +} + +func FutureTrailersFromOwnHandle(handleValue int32) *FutureTrailers { + handle := witRuntime.MakeHandle(handleValue) + value := &FutureTrailers{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropFutureTrailers(handleValue) + } + }, 0) + return value +} + +func FutureTrailersFromBorrowHandle(handleValue int32) *FutureTrailers { + handle := witRuntime.MakeHandle(handleValue) + return &FutureTrailers{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]outgoing-response +func resourceDropOutgoingResponse(handle int32) + +// Represents an outgoing HTTP Response. +type OutgoingResponse struct { + handle *witRuntime.Handle +} + +func (self *OutgoingResponse) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *OutgoingResponse) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *OutgoingResponse) Handle() int32 { + return self.handle.Use() +} + +func (self *OutgoingResponse) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropOutgoingResponse(handle) + } +} + +func OutgoingResponseFromOwnHandle(handleValue int32) *OutgoingResponse { + handle := witRuntime.MakeHandle(handleValue) + value := &OutgoingResponse{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropOutgoingResponse(handleValue) + } + }, 0) + return value +} + +func OutgoingResponseFromBorrowHandle(handleValue int32) *OutgoingResponse { + handle := witRuntime.MakeHandle(handleValue) + return &OutgoingResponse{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]outgoing-body +func resourceDropOutgoingBody(handle int32) + +// 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 occured. The implementation should propogate 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. +type OutgoingBody struct { + handle *witRuntime.Handle +} + +func (self *OutgoingBody) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *OutgoingBody) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *OutgoingBody) Handle() int32 { + return self.handle.Use() +} + +func (self *OutgoingBody) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropOutgoingBody(handle) + } +} + +func OutgoingBodyFromOwnHandle(handleValue int32) *OutgoingBody { + handle := witRuntime.MakeHandle(handleValue) + value := &OutgoingBody{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropOutgoingBody(handleValue) + } + }, 0) + return value +} + +func OutgoingBodyFromBorrowHandle(handleValue int32) *OutgoingBody { + handle := witRuntime.MakeHandle(handleValue) + return &OutgoingBody{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 [resource-drop]future-incoming-response +func resourceDropFutureIncomingResponse(handle int32) + +// Represents a future which may eventaully 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. +type FutureIncomingResponse struct { + handle *witRuntime.Handle +} + +func (self *FutureIncomingResponse) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *FutureIncomingResponse) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *FutureIncomingResponse) Handle() int32 { + return self.handle.Use() +} + +func (self *FutureIncomingResponse) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropFutureIncomingResponse(handle) + } +} + +func FutureIncomingResponseFromOwnHandle(handleValue int32) *FutureIncomingResponse { + handle := witRuntime.MakeHandle(handleValue) + value := &FutureIncomingResponse{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropFutureIncomingResponse(handleValue) + } + }, 0) + return value +} + +func FutureIncomingResponseFromBorrowHandle(handleValue int32) *FutureIncomingResponse { + handle := witRuntime.MakeHandle(handleValue) + return &FutureIncomingResponse{handle} +} + +//go:wasmimport wasi:http/types@0.2.0 http-error-code +func wasm_import_http_error_code(arg0 int32, arg1 uintptr) + +func HttpErrorCode(err *wasi_io_0_2_0_error.Error) witTypes.Option[ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (24 + 4*4), 8)) + wasm_import_http_error_code((err).Handle(), returnArea) + var option29 witTypes.Option[ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option29 = witTypes.None[ErrorCode]() + case 1: + var variant ErrorCode + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeErrorCodeDnsTimeout() + + case 1: + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + var option0 witTypes.Option[uint16] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option0 = witTypes.None[uint16]() + case 1: + + option0 = witTypes.Some[uint16](uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (18 + 3*4)))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeDnsError(DnsErrorPayload{option, option0}) + + case 2: + + variant = MakeErrorCodeDestinationNotFound() + + case 3: + + variant = MakeErrorCodeDestinationUnavailable() + + case 4: + + variant = MakeErrorCodeDestinationIpProhibited() + + case 5: + + variant = MakeErrorCodeDestinationIpUnroutable() + + case 6: + + variant = MakeErrorCodeConnectionRefused() + + case 7: + + variant = MakeErrorCodeConnectionTerminated() + + case 8: + + variant = MakeErrorCodeConnectionTimeout() + + case 9: + + variant = MakeErrorCodeConnectionReadTimeout() + + case 10: + + variant = MakeErrorCodeConnectionWriteTimeout() + + case 11: + + variant = MakeErrorCodeConnectionLimitReached() + + case 12: + + variant = MakeErrorCodeTlsProtocolError() + + case 13: + + variant = MakeErrorCodeTlsCertificateError() + + case 14: + var option1 witTypes.Option[uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option1 = witTypes.None[uint8]() + case 1: + + option1 = witTypes.Some[uint8](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 17))))) + default: + panic("unreachable") + } + var option3 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option3 = witTypes.None[string]() + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option3 = witTypes.Some[string](value2) + default: + panic("unreachable") + } + + variant = MakeErrorCodeTlsAlertReceived(TlsAlertReceivedPayload{option1, option3}) + + case 15: + + variant = MakeErrorCodeHttpRequestDenied() + + case 16: + + variant = MakeErrorCodeHttpRequestLengthRequired() + + case 17: + var option4 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option4 = witTypes.None[uint64]() + case 1: + + option4 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestBodySize(option4) + + case 18: + + variant = MakeErrorCodeHttpRequestMethodInvalid() + + case 19: + + variant = MakeErrorCodeHttpRequestUriInvalid() + + case 20: + + variant = MakeErrorCodeHttpRequestUriTooLong() + + case 21: + var option5 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option5 = witTypes.None[uint32]() + case 1: + + option5 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSectionSize(option5) + + case 22: + var option9 witTypes.Option[FieldSizePayload] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option9 = witTypes.None[FieldSizePayload]() + case 1: + var option7 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option7 = witTypes.None[string]() + case 1: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option7 = witTypes.Some[string](value6) + default: + panic("unreachable") + } + var option8 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 4*4)))) { + case 0: + + option8 = witTypes.None[uint32]() + case 1: + + option8 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 4*4))))) + default: + panic("unreachable") + } + + option9 = witTypes.Some[FieldSizePayload](FieldSizePayload{option7, option8}) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSize(option9) + + case 23: + var option10 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option10 = witTypes.None[uint32]() + case 1: + + option10 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSectionSize(option10) + + case 24: + var option12 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option12 = witTypes.None[string]() + case 1: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option12 = witTypes.Some[string](value11) + default: + panic("unreachable") + } + var option13 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option13 = witTypes.None[uint32]() + case 1: + + option13 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSize(FieldSizePayload{option12, option13}) + + case 25: + + variant = MakeErrorCodeHttpResponseIncomplete() + + case 26: + var option14 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option14 = witTypes.None[uint32]() + case 1: + + option14 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSectionSize(option14) + + case 27: + var option16 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option16 = witTypes.None[string]() + case 1: + value15 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option16 = witTypes.Some[string](value15) + default: + panic("unreachable") + } + var option17 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option17 = witTypes.None[uint32]() + case 1: + + option17 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSize(FieldSizePayload{option16, option17}) + + case 28: + var option18 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option18 = witTypes.None[uint64]() + case 1: + + option18 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseBodySize(option18) + + case 29: + var option19 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option19 = witTypes.None[uint32]() + case 1: + + option19 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSectionSize(option19) + + case 30: + var option21 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option21 = witTypes.None[string]() + case 1: + value20 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option21 = witTypes.Some[string](value20) + default: + panic("unreachable") + } + var option22 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option22 = witTypes.None[uint32]() + case 1: + + option22 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSize(FieldSizePayload{option21, option22}) + + case 31: + var option24 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option24 = witTypes.None[string]() + case 1: + value23 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option24 = witTypes.Some[string](value23) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTransferCoding(option24) + + case 32: + var option26 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option26 = witTypes.None[string]() + case 1: + value25 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option26 = witTypes.Some[string](value25) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseContentCoding(option26) + + case 33: + + variant = MakeErrorCodeHttpResponseTimeout() + + case 34: + + variant = MakeErrorCodeHttpUpgradeFailed() + + case 35: + + variant = MakeErrorCodeHttpProtocolError() + + case 36: + + variant = MakeErrorCodeLoopDetected() + + case 37: + + variant = MakeErrorCodeConfigurationError() + + case 38: + var option28 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option28 = witTypes.None[string]() + case 1: + value27 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option28 = witTypes.Some[string](value27) + default: + panic("unreachable") + } + + variant = MakeErrorCodeInternalError(option28) + + default: + panic("unreachable") + } + + option29 = witTypes.Some[ErrorCode](variant) + default: + panic("unreachable") + } + result := option29 + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [constructor]fields +func wasm_import_constructor_fields() int32 + +func MakeFields() *Fields { + + result := wasm_import_constructor_fields() + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [static]fields.from-list +func wasm_import_static_fields_from_list(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func FieldsFromList(entries []witTypes.Tuple2[string, []uint8]) witTypes.Result[*Fields, HeaderError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + slice := entries + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(4*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(4*4)) + utf8 := unsafe.Pointer(unsafe.StringData((element).F0)) + pinner.Pin(utf8) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len((element).F0))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf8))) + data := unsafe.Pointer(unsafe.SliceData((element).F1)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4))) = uint32(uint32(len((element).F1))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = uint32(uintptr(uintptr(data))) + + } + + wasm_import_static_fields_from_list(uintptr(result), length, returnArea) + var result0 witTypes.Result[*Fields, HeaderError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[*Fields, HeaderError](FieldsFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant HeaderError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeHeaderErrorInvalidSyntax() + + case 1: + + variant = MakeHeaderErrorForbidden() + + case 2: + + variant = MakeHeaderErrorImmutable() + + default: + panic("unreachable") + } + + result0 = witTypes.Err[*Fields, HeaderError](variant) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.get +func wasm_import_method_fields_get(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Fields) Get(name string) [][]uint8 { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + wasm_import_method_fields_get((self).Handle(), uintptr(utf8), uint32(len(name)), returnArea) + result := make([][]uint8, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0)))), index*(2*4)) + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.has +func wasm_import_method_fields_has(arg0 int32, arg1 uintptr, arg2 uint32) int32 + +func (self *Fields) Has(name string) bool { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + result := wasm_import_method_fields_has((self).Handle(), uintptr(utf8), uint32(len(name))) + return (result != 0) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.set +func wasm_import_method_fields_set(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Fields) Set(name string, value [][]uint8) witTypes.Result[witTypes.Unit, HeaderError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + slice := value + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + data := unsafe.Pointer(unsafe.SliceData(element)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(data))) + + } + + wasm_import_method_fields_set((self).Handle(), uintptr(utf8), uint32(len(name)), uintptr(result), length, returnArea) + var result0 witTypes.Result[witTypes.Unit, HeaderError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[witTypes.Unit, HeaderError](witTypes.Unit{}) + case 1: + var variant HeaderError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))) { + case 0: + + variant = MakeHeaderErrorInvalidSyntax() + + case 1: + + variant = MakeHeaderErrorForbidden() + + case 2: + + variant = MakeHeaderErrorImmutable() + + default: + panic("unreachable") + } + + result0 = witTypes.Err[witTypes.Unit, HeaderError](variant) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.delete +func wasm_import_method_fields_delete(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Fields) Delete(name string) witTypes.Result[witTypes.Unit, HeaderError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + wasm_import_method_fields_delete((self).Handle(), uintptr(utf8), uint32(len(name)), returnArea) + var result witTypes.Result[witTypes.Unit, HeaderError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, HeaderError](witTypes.Unit{}) + case 1: + var variant HeaderError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))) { + case 0: + + variant = MakeHeaderErrorInvalidSyntax() + + case 1: + + variant = MakeHeaderErrorForbidden() + + case 2: + + variant = MakeHeaderErrorImmutable() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, HeaderError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.append +func wasm_import_method_fields_append(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Fields) Append(name string, value []uint8) witTypes.Result[witTypes.Unit, HeaderError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_method_fields_append((self).Handle(), uintptr(utf8), uint32(len(name)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, HeaderError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, HeaderError](witTypes.Unit{}) + case 1: + var variant HeaderError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))) { + case 0: + + variant = MakeHeaderErrorInvalidSyntax() + + case 1: + + variant = MakeHeaderErrorForbidden() + + case 2: + + variant = MakeHeaderErrorImmutable() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, HeaderError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.entries +func wasm_import_method_fields_entries(arg0 int32, arg1 uintptr) + +func (self *Fields) Entries() []witTypes.Tuple2[string, []uint8] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_method_fields_entries((self).Handle(), returnArea) + result := make([]witTypes.Tuple2[string, []uint8], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0)))), index*(4*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + value0 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4)))) + + result = append(result, witTypes.Tuple2[string, []uint8]{value, value0}) + } + + result1 := result + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]fields.clone +func wasm_import_method_fields_clone(arg0 int32) int32 + +func (self *Fields) Clone() *Fields { + + result := wasm_import_method_fields_clone((self).Handle()) + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.method +func wasm_import_method_incoming_request_method(arg0 int32, arg1 uintptr) + +func (self *IncomingRequest) Method() Method { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_incoming_request_method((self).Handle(), returnArea) + var variant Method + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + variant = MakeMethodGet() + + case 1: + + variant = MakeMethodHead() + + case 2: + + variant = MakeMethodPost() + + case 3: + + variant = MakeMethodPut() + + case 4: + + variant = MakeMethodDelete() + + case 5: + + variant = MakeMethodConnect() + + case 6: + + variant = MakeMethodOptions() + + case 7: + + variant = MakeMethodTrace() + + case 8: + + variant = MakeMethodPatch() + + case 9: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + variant = MakeMethodOther(value) + + default: + panic("unreachable") + } + result := variant + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.path-with-query +func wasm_import_method_incoming_request_path_with_query(arg0 int32, arg1 uintptr) + +func (self *IncomingRequest) PathWithQuery() witTypes.Option[string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_incoming_request_path_with_query((self).Handle(), returnArea) + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.scheme +func wasm_import_method_incoming_request_scheme(arg0 int32, arg1 uintptr) + +func (self *IncomingRequest) Scheme() witTypes.Option[Scheme] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_method_incoming_request_scheme((self).Handle(), returnArea) + var option witTypes.Option[Scheme] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[Scheme]() + case 1: + var variant Scheme + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeSchemeHttp() + + case 1: + + variant = MakeSchemeHttps() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeSchemeOther(value) + + default: + panic("unreachable") + } + + option = witTypes.Some[Scheme](variant) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.authority +func wasm_import_method_incoming_request_authority(arg0 int32, arg1 uintptr) + +func (self *IncomingRequest) Authority() witTypes.Option[string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_incoming_request_authority((self).Handle(), returnArea) + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.headers +func wasm_import_method_incoming_request_headers(arg0 int32) int32 + +func (self *IncomingRequest) Headers() *Fields { + + result := wasm_import_method_incoming_request_headers((self).Handle()) + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-request.consume +func wasm_import_method_incoming_request_consume(arg0 int32, arg1 uintptr) + +func (self *IncomingRequest) Consume() witTypes.Result[*IncomingBody, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_incoming_request_consume((self).Handle(), returnArea) + var result witTypes.Result[*IncomingBody, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*IncomingBody, witTypes.Unit](IncomingBodyFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*IncomingBody, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [constructor]outgoing-request +func wasm_import_constructor_outgoing_request(arg0 int32) int32 + +func MakeOutgoingRequest(headers *Fields) *OutgoingRequest { + + result := wasm_import_constructor_outgoing_request((headers).TakeHandle()) + return OutgoingRequestFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.body +func wasm_import_method_outgoing_request_body(arg0 int32, arg1 uintptr) + +func (self *OutgoingRequest) Body() witTypes.Result[*OutgoingBody, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_outgoing_request_body((self).Handle(), returnArea) + var result witTypes.Result[*OutgoingBody, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*OutgoingBody, witTypes.Unit](OutgoingBodyFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*OutgoingBody, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.method +func wasm_import_method_outgoing_request_method(arg0 int32, arg1 uintptr) + +func (self *OutgoingRequest) Method() Method { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_outgoing_request_method((self).Handle(), returnArea) + var variant Method + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + variant = MakeMethodGet() + + case 1: + + variant = MakeMethodHead() + + case 2: + + variant = MakeMethodPost() + + case 3: + + variant = MakeMethodPut() + + case 4: + + variant = MakeMethodDelete() + + case 5: + + variant = MakeMethodConnect() + + case 6: + + variant = MakeMethodOptions() + + case 7: + + variant = MakeMethodTrace() + + case 8: + + variant = MakeMethodPatch() + + case 9: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + variant = MakeMethodOther(value) + + default: + panic("unreachable") + } + result := variant + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.set-method +func wasm_import_method_outgoing_request_set_method(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32) int32 + +func (self *OutgoingRequest) SetMethod(method Method) witTypes.Result[witTypes.Unit, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + var variant int32 + var variant0 uintptr + var variant1 uint32 + switch method.Tag() { + case MethodGet: + + variant = int32(0) + variant0 = 0 + variant1 = 0 + + case MethodHead: + + variant = int32(1) + variant0 = 0 + variant1 = 0 + + case MethodPost: + + variant = int32(2) + variant0 = 0 + variant1 = 0 + + case MethodPut: + + variant = int32(3) + variant0 = 0 + variant1 = 0 + + case MethodDelete: + + variant = int32(4) + variant0 = 0 + variant1 = 0 + + case MethodConnect: + + variant = int32(5) + variant0 = 0 + variant1 = 0 + + case MethodOptions: + + variant = int32(6) + variant0 = 0 + variant1 = 0 + + case MethodTrace: + + variant = int32(7) + variant0 = 0 + variant1 = 0 + + case MethodPatch: + + variant = int32(8) + variant0 = 0 + variant1 = 0 + + case MethodOther: + payload := method.Other() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + variant = int32(9) + variant0 = uintptr(utf8) + variant1 = uint32(len(payload)) + + default: + panic("unreachable") + } + result := wasm_import_method_outgoing_request_set_method((self).Handle(), variant, variant0, variant1) + var result2 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result2 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result2 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result2 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.path-with-query +func wasm_import_method_outgoing_request_path_with_query(arg0 int32, arg1 uintptr) + +func (self *OutgoingRequest) PathWithQuery() witTypes.Option[string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_outgoing_request_path_with_query((self).Handle(), returnArea) + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.set-path-with-query +func wasm_import_method_outgoing_request_set_path_with_query(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32) int32 + +func (self *OutgoingRequest) SetPathWithQuery(pathWithQuery witTypes.Option[string]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + var option int32 + var option0 uintptr + var option1 uint32 + switch pathWithQuery.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + option1 = 0 + case witTypes.OptionSome: + payload := pathWithQuery.Some() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + option = int32(1) + option0 = uintptr(utf8) + option1 = uint32(len(payload)) + default: + panic("unreachable") + } + result := wasm_import_method_outgoing_request_set_path_with_query((self).Handle(), option, option0, option1) + var result2 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result2 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result2 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result2 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.scheme +func wasm_import_method_outgoing_request_scheme(arg0 int32, arg1 uintptr) + +func (self *OutgoingRequest) Scheme() witTypes.Option[Scheme] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_method_outgoing_request_scheme((self).Handle(), returnArea) + var option witTypes.Option[Scheme] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[Scheme]() + case 1: + var variant Scheme + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeSchemeHttp() + + case 1: + + variant = MakeSchemeHttps() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeSchemeOther(value) + + default: + panic("unreachable") + } + + option = witTypes.Some[Scheme](variant) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.set-scheme +func wasm_import_method_outgoing_request_set_scheme(arg0 int32, arg1 int32, arg2 int32, arg3 uintptr, arg4 uint32) int32 + +func (self *OutgoingRequest) SetScheme(scheme witTypes.Option[Scheme]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + var option int32 + var option2 int32 + var option3 uintptr + var option4 uint32 + switch scheme.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option2 = 0 + option3 = 0 + option4 = 0 + case witTypes.OptionSome: + payload := scheme.Some() + var variant int32 + var variant0 uintptr + var variant1 uint32 + switch payload.Tag() { + case SchemeHttp: + + variant = int32(0) + variant0 = 0 + variant1 = 0 + + case SchemeHttps: + + variant = int32(1) + variant0 = 0 + variant1 = 0 + + case SchemeOther: + payload := payload.Other() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + variant = int32(2) + variant0 = uintptr(utf8) + variant1 = uint32(len(payload)) + + default: + panic("unreachable") + } + + option = int32(1) + option2 = variant + option3 = variant0 + option4 = variant1 + default: + panic("unreachable") + } + result := wasm_import_method_outgoing_request_set_scheme((self).Handle(), option, option2, option3, option4) + var result5 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result5 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result5 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result5 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.authority +func wasm_import_method_outgoing_request_authority(arg0 int32, arg1 uintptr) + +func (self *OutgoingRequest) Authority() witTypes.Option[string] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_outgoing_request_authority((self).Handle(), returnArea) + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.set-authority +func wasm_import_method_outgoing_request_set_authority(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32) int32 + +func (self *OutgoingRequest) SetAuthority(authority witTypes.Option[string]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + var option int32 + var option0 uintptr + var option1 uint32 + switch authority.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + option1 = 0 + case witTypes.OptionSome: + payload := authority.Some() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + option = int32(1) + option0 = uintptr(utf8) + option1 = uint32(len(payload)) + default: + panic("unreachable") + } + result := wasm_import_method_outgoing_request_set_authority((self).Handle(), option, option0, option1) + var result2 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result2 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result2 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result2 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-request.headers +func wasm_import_method_outgoing_request_headers(arg0 int32) int32 + +func (self *OutgoingRequest) Headers() *Fields { + + result := wasm_import_method_outgoing_request_headers((self).Handle()) + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [constructor]request-options +func wasm_import_constructor_request_options() int32 + +func MakeRequestOptions() *RequestOptions { + + result := wasm_import_constructor_request_options() + return RequestOptionsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.connect-timeout +func wasm_import_method_request_options_connect_timeout(arg0 int32, arg1 uintptr) + +func (self *RequestOptions) ConnectTimeout() witTypes.Option[uint64] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_request_options_connect_timeout((self).Handle(), returnArea) + var option witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[uint64]() + case 1: + + option = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.set-connect-timeout +func wasm_import_method_request_options_set_connect_timeout(arg0 int32, arg1 int32, arg2 int64) int32 + +func (self *RequestOptions) SetConnectTimeout(duration witTypes.Option[uint64]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + + var option int32 + var option0 int64 + switch duration.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + case witTypes.OptionSome: + payload := duration.Some() + + option = int32(1) + option0 = int64(payload) + default: + panic("unreachable") + } + result := wasm_import_method_request_options_set_connect_timeout((self).Handle(), option, option0) + var result1 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result1 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result1 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.first-byte-timeout +func wasm_import_method_request_options_first_byte_timeout(arg0 int32, arg1 uintptr) + +func (self *RequestOptions) FirstByteTimeout() witTypes.Option[uint64] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_request_options_first_byte_timeout((self).Handle(), returnArea) + var option witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[uint64]() + case 1: + + option = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.set-first-byte-timeout +func wasm_import_method_request_options_set_first_byte_timeout(arg0 int32, arg1 int32, arg2 int64) int32 + +func (self *RequestOptions) SetFirstByteTimeout(duration witTypes.Option[uint64]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + + var option int32 + var option0 int64 + switch duration.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + case witTypes.OptionSome: + payload := duration.Some() + + option = int32(1) + option0 = int64(payload) + default: + panic("unreachable") + } + result := wasm_import_method_request_options_set_first_byte_timeout((self).Handle(), option, option0) + var result1 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result1 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result1 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.between-bytes-timeout +func wasm_import_method_request_options_between_bytes_timeout(arg0 int32, arg1 uintptr) + +func (self *RequestOptions) BetweenBytesTimeout() witTypes.Option[uint64] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_request_options_between_bytes_timeout((self).Handle(), returnArea) + var option witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option = witTypes.None[uint64]() + case 1: + + option = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + default: + panic("unreachable") + } + result := option + return result + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]request-options.set-between-bytes-timeout +func wasm_import_method_request_options_set_between_bytes_timeout(arg0 int32, arg1 int32, arg2 int64) int32 + +func (self *RequestOptions) SetBetweenBytesTimeout(duration witTypes.Option[uint64]) witTypes.Result[witTypes.Unit, witTypes.Unit] { + + var option int32 + var option0 int64 + switch duration.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + case witTypes.OptionSome: + payload := duration.Some() + + option = int32(1) + option0 = int64(payload) + default: + panic("unreachable") + } + result := wasm_import_method_request_options_set_between_bytes_timeout((self).Handle(), option, option0) + var result1 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result1 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result1 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result1 + +} + +//go:wasmimport wasi:http/types@0.2.0 [static]response-outparam.set +func wasm_import_static_response_outparam_set(arg0 int32, arg1 int32, arg2 int32, arg3 int32, arg4 int64, arg5 uintptr, arg6 uintptr, arg7 uint32, arg8 int32) + +func ResponseOutparamSet(param *ResponseOutparam, response witTypes.Result[*OutgoingResponse, ErrorCode]) { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + var option70 int32 + var option71 int32 + var option72 int32 + var option73 int64 + var option74 uintptr + var option75 uintptr + var option76 uint32 + var option77 int32 + switch response.Tag() { + case witTypes.ResultOk: + payload := response.Ok() + + option70 = int32(0) + option71 = (payload).TakeHandle() + option72 = 0 + option73 = 0 + option74 = 0 + option75 = 0 + option76 = 0 + option77 = 0 + case witTypes.ResultErr: + payload := response.Err() + var variant int32 + var variant64 int32 + var variant65 int64 + var variant66 uintptr + var variant67 uintptr + var variant68 uint32 + var variant69 int32 + switch payload.Tag() { + case ErrorCodeDnsTimeout: + + variant = int32(0) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeDnsError: + payload := payload.DnsError() + var option int32 + var option0 uintptr + var option1 uint32 + switch (payload).Rcode.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + option1 = 0 + case witTypes.OptionSome: + payload := (payload).Rcode.Some() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + option = int32(1) + option0 = uintptr(utf8) + option1 = uint32(len(payload)) + default: + panic("unreachable") + } + var option2 int32 + var option3 int32 + switch (payload).InfoCode.Tag() { + case witTypes.OptionNone: + + option2 = int32(0) + option3 = 0 + case witTypes.OptionSome: + payload := (payload).InfoCode.Some() + + option2 = int32(1) + option3 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(1) + variant64 = option + variant65 = int64(option0) + variant66 = uintptr(option1) + variant67 = uintptr(option2) + variant68 = uint32(option3) + variant69 = 0 + + case ErrorCodeDestinationNotFound: + + variant = int32(2) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeDestinationUnavailable: + + variant = int32(3) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeDestinationIpProhibited: + + variant = int32(4) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeDestinationIpUnroutable: + + variant = int32(5) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionRefused: + + variant = int32(6) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionTerminated: + + variant = int32(7) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionTimeout: + + variant = int32(8) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionReadTimeout: + + variant = int32(9) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionWriteTimeout: + + variant = int32(10) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConnectionLimitReached: + + variant = int32(11) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeTlsProtocolError: + + variant = int32(12) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeTlsCertificateError: + + variant = int32(13) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeTlsAlertReceived: + payload := payload.TlsAlertReceived() + var option4 int32 + var option5 int32 + switch (payload).AlertId.Tag() { + case witTypes.OptionNone: + + option4 = int32(0) + option5 = 0 + case witTypes.OptionSome: + payload := (payload).AlertId.Some() + + option4 = int32(1) + option5 = int32(payload) + default: + panic("unreachable") + } + var option7 int32 + var option8 uintptr + var option9 uint32 + switch (payload).AlertMessage.Tag() { + case witTypes.OptionNone: + + option7 = int32(0) + option8 = 0 + option9 = 0 + case witTypes.OptionSome: + payload := (payload).AlertMessage.Some() + utf86 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf86) + + option7 = int32(1) + option8 = uintptr(utf86) + option9 = uint32(len(payload)) + default: + panic("unreachable") + } + + variant = int32(14) + variant64 = option4 + variant65 = int64(option5) + variant66 = uintptr(option7) + variant67 = option8 + variant68 = option9 + variant69 = 0 + + case ErrorCodeHttpRequestDenied: + + variant = int32(15) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestLengthRequired: + + variant = int32(16) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestBodySize: + payload := payload.HttpRequestBodySize() + var option10 int32 + var option11 int64 + switch payload.Tag() { + case witTypes.OptionNone: + + option10 = int32(0) + option11 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option10 = int32(1) + option11 = int64(payload) + default: + panic("unreachable") + } + + variant = int32(17) + variant64 = option10 + variant65 = option11 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestMethodInvalid: + + variant = int32(18) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestUriInvalid: + + variant = int32(19) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestUriTooLong: + + variant = int32(20) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestHeaderSectionSize: + payload := payload.HttpRequestHeaderSectionSize() + var option12 int32 + var option13 int32 + switch payload.Tag() { + case witTypes.OptionNone: + + option12 = int32(0) + option13 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option12 = int32(1) + option13 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(21) + variant64 = option12 + variant65 = int64(option13) + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestHeaderSize: + payload := payload.HttpRequestHeaderSize() + var option20 int32 + var option21 int32 + var option22 uintptr + var option23 uint32 + var option24 int32 + var option25 int32 + switch payload.Tag() { + case witTypes.OptionNone: + + option20 = int32(0) + option21 = 0 + option22 = 0 + option23 = 0 + option24 = 0 + option25 = 0 + case witTypes.OptionSome: + payload := payload.Some() + var option15 int32 + var option16 uintptr + var option17 uint32 + switch (payload).FieldName.Tag() { + case witTypes.OptionNone: + + option15 = int32(0) + option16 = 0 + option17 = 0 + case witTypes.OptionSome: + payload := (payload).FieldName.Some() + utf814 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf814) + + option15 = int32(1) + option16 = uintptr(utf814) + option17 = uint32(len(payload)) + default: + panic("unreachable") + } + var option18 int32 + var option19 int32 + switch (payload).FieldSize.Tag() { + case witTypes.OptionNone: + + option18 = int32(0) + option19 = 0 + case witTypes.OptionSome: + payload := (payload).FieldSize.Some() + + option18 = int32(1) + option19 = int32(payload) + default: + panic("unreachable") + } + + option20 = int32(1) + option21 = option15 + option22 = option16 + option23 = option17 + option24 = option18 + option25 = option19 + default: + panic("unreachable") + } + + variant = int32(22) + variant64 = option20 + variant65 = int64(option21) + variant66 = option22 + variant67 = uintptr(option23) + variant68 = uint32(option24) + variant69 = option25 + + case ErrorCodeHttpRequestTrailerSectionSize: + payload := payload.HttpRequestTrailerSectionSize() + var option26 int32 + var option27 int32 + switch payload.Tag() { + case witTypes.OptionNone: + + option26 = int32(0) + option27 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option26 = int32(1) + option27 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(23) + variant64 = option26 + variant65 = int64(option27) + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpRequestTrailerSize: + payload := payload.HttpRequestTrailerSize() + var option29 int32 + var option30 uintptr + var option31 uint32 + switch (payload).FieldName.Tag() { + case witTypes.OptionNone: + + option29 = int32(0) + option30 = 0 + option31 = 0 + case witTypes.OptionSome: + payload := (payload).FieldName.Some() + utf828 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf828) + + option29 = int32(1) + option30 = uintptr(utf828) + option31 = uint32(len(payload)) + default: + panic("unreachable") + } + var option32 int32 + var option33 int32 + switch (payload).FieldSize.Tag() { + case witTypes.OptionNone: + + option32 = int32(0) + option33 = 0 + case witTypes.OptionSome: + payload := (payload).FieldSize.Some() + + option32 = int32(1) + option33 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(24) + variant64 = option29 + variant65 = int64(option30) + variant66 = uintptr(option31) + variant67 = uintptr(option32) + variant68 = uint32(option33) + variant69 = 0 + + case ErrorCodeHttpResponseIncomplete: + + variant = int32(25) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseHeaderSectionSize: + payload := payload.HttpResponseHeaderSectionSize() + var option34 int32 + var option35 int32 + switch payload.Tag() { + case witTypes.OptionNone: + + option34 = int32(0) + option35 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option34 = int32(1) + option35 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(26) + variant64 = option34 + variant65 = int64(option35) + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseHeaderSize: + payload := payload.HttpResponseHeaderSize() + var option37 int32 + var option38 uintptr + var option39 uint32 + switch (payload).FieldName.Tag() { + case witTypes.OptionNone: + + option37 = int32(0) + option38 = 0 + option39 = 0 + case witTypes.OptionSome: + payload := (payload).FieldName.Some() + utf836 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf836) + + option37 = int32(1) + option38 = uintptr(utf836) + option39 = uint32(len(payload)) + default: + panic("unreachable") + } + var option40 int32 + var option41 int32 + switch (payload).FieldSize.Tag() { + case witTypes.OptionNone: + + option40 = int32(0) + option41 = 0 + case witTypes.OptionSome: + payload := (payload).FieldSize.Some() + + option40 = int32(1) + option41 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(27) + variant64 = option37 + variant65 = int64(option38) + variant66 = uintptr(option39) + variant67 = uintptr(option40) + variant68 = uint32(option41) + variant69 = 0 + + case ErrorCodeHttpResponseBodySize: + payload := payload.HttpResponseBodySize() + var option42 int32 + var option43 int64 + switch payload.Tag() { + case witTypes.OptionNone: + + option42 = int32(0) + option43 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option42 = int32(1) + option43 = int64(payload) + default: + panic("unreachable") + } + + variant = int32(28) + variant64 = option42 + variant65 = option43 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseTrailerSectionSize: + payload := payload.HttpResponseTrailerSectionSize() + var option44 int32 + var option45 int32 + switch payload.Tag() { + case witTypes.OptionNone: + + option44 = int32(0) + option45 = 0 + case witTypes.OptionSome: + payload := payload.Some() + + option44 = int32(1) + option45 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(29) + variant64 = option44 + variant65 = int64(option45) + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseTrailerSize: + payload := payload.HttpResponseTrailerSize() + var option47 int32 + var option48 uintptr + var option49 uint32 + switch (payload).FieldName.Tag() { + case witTypes.OptionNone: + + option47 = int32(0) + option48 = 0 + option49 = 0 + case witTypes.OptionSome: + payload := (payload).FieldName.Some() + utf846 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf846) + + option47 = int32(1) + option48 = uintptr(utf846) + option49 = uint32(len(payload)) + default: + panic("unreachable") + } + var option50 int32 + var option51 int32 + switch (payload).FieldSize.Tag() { + case witTypes.OptionNone: + + option50 = int32(0) + option51 = 0 + case witTypes.OptionSome: + payload := (payload).FieldSize.Some() + + option50 = int32(1) + option51 = int32(payload) + default: + panic("unreachable") + } + + variant = int32(30) + variant64 = option47 + variant65 = int64(option48) + variant66 = uintptr(option49) + variant67 = uintptr(option50) + variant68 = uint32(option51) + variant69 = 0 + + case ErrorCodeHttpResponseTransferCoding: + payload := payload.HttpResponseTransferCoding() + var option53 int32 + var option54 uintptr + var option55 uint32 + switch payload.Tag() { + case witTypes.OptionNone: + + option53 = int32(0) + option54 = 0 + option55 = 0 + case witTypes.OptionSome: + payload := payload.Some() + utf852 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf852) + + option53 = int32(1) + option54 = uintptr(utf852) + option55 = uint32(len(payload)) + default: + panic("unreachable") + } + + variant = int32(31) + variant64 = option53 + variant65 = int64(option54) + variant66 = uintptr(option55) + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseContentCoding: + payload := payload.HttpResponseContentCoding() + var option57 int32 + var option58 uintptr + var option59 uint32 + switch payload.Tag() { + case witTypes.OptionNone: + + option57 = int32(0) + option58 = 0 + option59 = 0 + case witTypes.OptionSome: + payload := payload.Some() + utf856 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf856) + + option57 = int32(1) + option58 = uintptr(utf856) + option59 = uint32(len(payload)) + default: + panic("unreachable") + } + + variant = int32(32) + variant64 = option57 + variant65 = int64(option58) + variant66 = uintptr(option59) + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpResponseTimeout: + + variant = int32(33) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpUpgradeFailed: + + variant = int32(34) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeHttpProtocolError: + + variant = int32(35) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeLoopDetected: + + variant = int32(36) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeConfigurationError: + + variant = int32(37) + variant64 = 0 + variant65 = 0 + variant66 = 0 + variant67 = 0 + variant68 = 0 + variant69 = 0 + + case ErrorCodeInternalError: + payload := payload.InternalError() + var option61 int32 + var option62 uintptr + var option63 uint32 + switch payload.Tag() { + case witTypes.OptionNone: + + option61 = int32(0) + option62 = 0 + option63 = 0 + case witTypes.OptionSome: + payload := payload.Some() + utf860 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf860) + + option61 = int32(1) + option62 = uintptr(utf860) + option63 = uint32(len(payload)) + default: + panic("unreachable") + } + + variant = int32(38) + variant64 = option61 + variant65 = int64(option62) + variant66 = uintptr(option63) + variant67 = 0 + variant68 = 0 + variant69 = 0 + + default: + panic("unreachable") + } + + option70 = int32(1) + option71 = variant + option72 = variant64 + option73 = variant65 + option74 = variant66 + option75 = variant67 + option76 = variant68 + option77 = variant69 + default: + panic("unreachable") + } + wasm_import_static_response_outparam_set((param).TakeHandle(), option70, option71, option72, option73, option74, option75, option76, option77) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-response.status +func wasm_import_method_incoming_response_status(arg0 int32) int32 + +func (self *IncomingResponse) Status() uint16 { + + result := wasm_import_method_incoming_response_status((self).Handle()) + return uint16(result) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-response.headers +func wasm_import_method_incoming_response_headers(arg0 int32) int32 + +func (self *IncomingResponse) Headers() *Fields { + + result := wasm_import_method_incoming_response_headers((self).Handle()) + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-response.consume +func wasm_import_method_incoming_response_consume(arg0 int32, arg1 uintptr) + +func (self *IncomingResponse) Consume() witTypes.Result[*IncomingBody, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_incoming_response_consume((self).Handle(), returnArea) + var result witTypes.Result[*IncomingBody, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*IncomingBody, witTypes.Unit](IncomingBodyFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*IncomingBody, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]incoming-body.stream +func wasm_import_method_incoming_body_stream(arg0 int32, arg1 uintptr) + +func (self *IncomingBody) Stream() witTypes.Result[*wasi_io_0_2_0_streams.InputStream, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_incoming_body_stream((self).Handle(), returnArea) + var result witTypes.Result[*wasi_io_0_2_0_streams.InputStream, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_io_0_2_0_streams.InputStream, witTypes.Unit](wasi_io_0_2_0_streams.InputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_io_0_2_0_streams.InputStream, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [static]incoming-body.finish +func wasm_import_static_incoming_body_finish(arg0 int32) int32 + +func IncomingBodyFinish(this *IncomingBody) *FutureTrailers { + + result := wasm_import_static_incoming_body_finish((this).TakeHandle()) + return FutureTrailersFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]future-trailers.subscribe +func wasm_import_method_future_trailers_subscribe(arg0 int32) int32 + +func (self *FutureTrailers) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_future_trailers_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]future-trailers.get +func wasm_import_method_future_trailers_get(arg0 int32, arg1 uintptr) + +func (self *FutureTrailers) Get() witTypes.Option[witTypes.Result[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit]] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (40 + 4*4), 8)) + wasm_import_method_future_trailers_get((self).Handle(), returnArea) + var option31 witTypes.Option[witTypes.Result[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit]] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option31 = witTypes.None[witTypes.Result[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit]]() + case 1: + var result30 witTypes.Result[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + var result witTypes.Result[witTypes.Option[*Fields], ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + var option witTypes.Option[*Fields] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24))) { + case 0: + + option = witTypes.None[*Fields]() + case 1: + + option = witTypes.Some[*Fields](FieldsFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 28)))))) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[*Fields], ErrorCode](option) + case 1: + var variant ErrorCode + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24))) { + case 0: + + variant = MakeErrorCodeDnsTimeout() + + case 1: + var option0 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option0 = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option0 = witTypes.Some[string](value) + default: + panic("unreachable") + } + var option1 witTypes.Option[uint16] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option1 = witTypes.None[uint16]() + case 1: + + option1 = witTypes.Some[uint16](uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (34 + 3*4)))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeDnsError(DnsErrorPayload{option0, option1}) + + case 2: + + variant = MakeErrorCodeDestinationNotFound() + + case 3: + + variant = MakeErrorCodeDestinationUnavailable() + + case 4: + + variant = MakeErrorCodeDestinationIpProhibited() + + case 5: + + variant = MakeErrorCodeDestinationIpUnroutable() + + case 6: + + variant = MakeErrorCodeConnectionRefused() + + case 7: + + variant = MakeErrorCodeConnectionTerminated() + + case 8: + + variant = MakeErrorCodeConnectionTimeout() + + case 9: + + variant = MakeErrorCodeConnectionReadTimeout() + + case 10: + + variant = MakeErrorCodeConnectionWriteTimeout() + + case 11: + + variant = MakeErrorCodeConnectionLimitReached() + + case 12: + + variant = MakeErrorCodeTlsProtocolError() + + case 13: + + variant = MakeErrorCodeTlsCertificateError() + + case 14: + var option2 witTypes.Option[uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option2 = witTypes.None[uint8]() + case 1: + + option2 = witTypes.Some[uint8](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 33))))) + default: + panic("unreachable") + } + var option4 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))) { + case 0: + + option4 = witTypes.None[string]() + case 1: + value3 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) + + option4 = witTypes.Some[string](value3) + default: + panic("unreachable") + } + + variant = MakeErrorCodeTlsAlertReceived(TlsAlertReceivedPayload{option2, option4}) + + case 15: + + variant = MakeErrorCodeHttpRequestDenied() + + case 16: + + variant = MakeErrorCodeHttpRequestLengthRequired() + + case 17: + var option5 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option5 = witTypes.None[uint64]() + case 1: + + option5 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestBodySize(option5) + + case 18: + + variant = MakeErrorCodeHttpRequestMethodInvalid() + + case 19: + + variant = MakeErrorCodeHttpRequestUriInvalid() + + case 20: + + variant = MakeErrorCodeHttpRequestUriTooLong() + + case 21: + var option6 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option6 = witTypes.None[uint32]() + case 1: + + option6 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSectionSize(option6) + + case 22: + var option10 witTypes.Option[FieldSizePayload] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option10 = witTypes.None[FieldSizePayload]() + case 1: + var option8 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))) { + case 0: + + option8 = witTypes.None[string]() + case 1: + value7 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) + + option8 = witTypes.Some[string](value7) + default: + panic("unreachable") + } + var option9 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 4*4)))) { + case 0: + + option9 = witTypes.None[uint32]() + case 1: + + option9 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 4*4))))) + default: + panic("unreachable") + } + + option10 = witTypes.Some[FieldSizePayload](FieldSizePayload{option8, option9}) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSize(option10) + + case 23: + var option11 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option11 = witTypes.None[uint32]() + case 1: + + option11 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSectionSize(option11) + + case 24: + var option13 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option13 = witTypes.None[string]() + case 1: + value12 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option13 = witTypes.Some[string](value12) + default: + panic("unreachable") + } + var option14 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option14 = witTypes.None[uint32]() + case 1: + + option14 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSize(FieldSizePayload{option13, option14}) + + case 25: + + variant = MakeErrorCodeHttpResponseIncomplete() + + case 26: + var option15 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option15 = witTypes.None[uint32]() + case 1: + + option15 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSectionSize(option15) + + case 27: + var option17 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option17 = witTypes.None[string]() + case 1: + value16 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option17 = witTypes.Some[string](value16) + default: + panic("unreachable") + } + var option18 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option18 = witTypes.None[uint32]() + case 1: + + option18 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSize(FieldSizePayload{option17, option18}) + + case 28: + var option19 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option19 = witTypes.None[uint64]() + case 1: + + option19 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseBodySize(option19) + + case 29: + var option20 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option20 = witTypes.None[uint32]() + case 1: + + option20 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSectionSize(option20) + + case 30: + var option22 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option22 = witTypes.None[string]() + case 1: + value21 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option22 = witTypes.Some[string](value21) + default: + panic("unreachable") + } + var option23 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option23 = witTypes.None[uint32]() + case 1: + + option23 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSize(FieldSizePayload{option22, option23}) + + case 31: + var option25 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option25 = witTypes.None[string]() + case 1: + value24 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option25 = witTypes.Some[string](value24) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTransferCoding(option25) + + case 32: + var option27 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option27 = witTypes.None[string]() + case 1: + value26 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option27 = witTypes.Some[string](value26) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseContentCoding(option27) + + case 33: + + variant = MakeErrorCodeHttpResponseTimeout() + + case 34: + + variant = MakeErrorCodeHttpUpgradeFailed() + + case 35: + + variant = MakeErrorCodeHttpProtocolError() + + case 36: + + variant = MakeErrorCodeLoopDetected() + + case 37: + + variant = MakeErrorCodeConfigurationError() + + case 38: + var option29 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option29 = witTypes.None[string]() + case 1: + value28 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option29 = witTypes.Some[string](value28) + default: + panic("unreachable") + } + + variant = MakeErrorCodeInternalError(option29) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[*Fields], ErrorCode](variant) + default: + panic("unreachable") + } + + result30 = witTypes.Ok[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit](result) + case 1: + + result30 = witTypes.Err[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + + option31 = witTypes.Some[witTypes.Result[witTypes.Result[witTypes.Option[*Fields], ErrorCode], witTypes.Unit]](result30) + default: + panic("unreachable") + } + result32 := option31 + return result32 + +} + +//go:wasmimport wasi:http/types@0.2.0 [constructor]outgoing-response +func wasm_import_constructor_outgoing_response(arg0 int32) int32 + +func MakeOutgoingResponse(headers *Fields) *OutgoingResponse { + + result := wasm_import_constructor_outgoing_response((headers).TakeHandle()) + return OutgoingResponseFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-response.status-code +func wasm_import_method_outgoing_response_status_code(arg0 int32) int32 + +func (self *OutgoingResponse) StatusCode() uint16 { + + result := wasm_import_method_outgoing_response_status_code((self).Handle()) + return uint16(result) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-response.set-status-code +func wasm_import_method_outgoing_response_set_status_code(arg0 int32, arg1 int32) int32 + +func (self *OutgoingResponse) SetStatusCode(statusCode uint16) witTypes.Result[witTypes.Unit, witTypes.Unit] { + + result := wasm_import_method_outgoing_response_set_status_code((self).Handle(), int32(statusCode)) + var result0 witTypes.Result[witTypes.Unit, witTypes.Unit] + switch result { + case 0: + + result0 = witTypes.Ok[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + case 1: + + result0 = witTypes.Err[witTypes.Unit, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-response.headers +func wasm_import_method_outgoing_response_headers(arg0 int32) int32 + +func (self *OutgoingResponse) Headers() *Fields { + + result := wasm_import_method_outgoing_response_headers((self).Handle()) + return FieldsFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-response.body +func wasm_import_method_outgoing_response_body(arg0 int32, arg1 uintptr) + +func (self *OutgoingResponse) Body() witTypes.Result[*OutgoingBody, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_outgoing_response_body((self).Handle(), returnArea) + var result witTypes.Result[*OutgoingBody, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*OutgoingBody, witTypes.Unit](OutgoingBodyFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*OutgoingBody, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]outgoing-body.write +func wasm_import_method_outgoing_body_write(arg0 int32, arg1 uintptr) + +func (self *OutgoingBody) Write() witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, witTypes.Unit] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_outgoing_body_write((self).Handle(), returnArea) + var result witTypes.Result[*wasi_io_0_2_0_streams.OutputStream, witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_io_0_2_0_streams.OutputStream, witTypes.Unit](wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_io_0_2_0_streams.OutputStream, witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:http/types@0.2.0 [static]outgoing-body.finish +func wasm_import_static_outgoing_body_finish(arg0 int32, arg1 int32, arg2 int32, arg3 uintptr) + +func OutgoingBodyFinish(this *OutgoingBody, trailers witTypes.Option[*Fields]) witTypes.Result[witTypes.Unit, ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (24 + 4*4), 8)) + var option int32 + var option0 int32 + switch trailers.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + case witTypes.OptionSome: + payload := trailers.Some() + + option = int32(1) + option0 = (payload).TakeHandle() + default: + panic("unreachable") + } + wasm_import_static_outgoing_body_finish((this).TakeHandle(), option, option0, returnArea) + var result witTypes.Result[witTypes.Unit, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, ErrorCode](witTypes.Unit{}) + case 1: + var variant ErrorCode + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeErrorCodeDnsTimeout() + + case 1: + var option1 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option1 = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option1 = witTypes.Some[string](value) + default: + panic("unreachable") + } + var option2 witTypes.Option[uint16] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option2 = witTypes.None[uint16]() + case 1: + + option2 = witTypes.Some[uint16](uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (18 + 3*4)))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeDnsError(DnsErrorPayload{option1, option2}) + + case 2: + + variant = MakeErrorCodeDestinationNotFound() + + case 3: + + variant = MakeErrorCodeDestinationUnavailable() + + case 4: + + variant = MakeErrorCodeDestinationIpProhibited() + + case 5: + + variant = MakeErrorCodeDestinationIpUnroutable() + + case 6: + + variant = MakeErrorCodeConnectionRefused() + + case 7: + + variant = MakeErrorCodeConnectionTerminated() + + case 8: + + variant = MakeErrorCodeConnectionTimeout() + + case 9: + + variant = MakeErrorCodeConnectionReadTimeout() + + case 10: + + variant = MakeErrorCodeConnectionWriteTimeout() + + case 11: + + variant = MakeErrorCodeConnectionLimitReached() + + case 12: + + variant = MakeErrorCodeTlsProtocolError() + + case 13: + + variant = MakeErrorCodeTlsCertificateError() + + case 14: + var option3 witTypes.Option[uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option3 = witTypes.None[uint8]() + case 1: + + option3 = witTypes.Some[uint8](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 17))))) + default: + panic("unreachable") + } + var option5 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option5 = witTypes.None[string]() + case 1: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option5 = witTypes.Some[string](value4) + default: + panic("unreachable") + } + + variant = MakeErrorCodeTlsAlertReceived(TlsAlertReceivedPayload{option3, option5}) + + case 15: + + variant = MakeErrorCodeHttpRequestDenied() + + case 16: + + variant = MakeErrorCodeHttpRequestLengthRequired() + + case 17: + var option6 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option6 = witTypes.None[uint64]() + case 1: + + option6 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestBodySize(option6) + + case 18: + + variant = MakeErrorCodeHttpRequestMethodInvalid() + + case 19: + + variant = MakeErrorCodeHttpRequestUriInvalid() + + case 20: + + variant = MakeErrorCodeHttpRequestUriTooLong() + + case 21: + var option7 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option7 = witTypes.None[uint32]() + case 1: + + option7 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSectionSize(option7) + + case 22: + var option11 witTypes.Option[FieldSizePayload] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option11 = witTypes.None[FieldSizePayload]() + case 1: + var option9 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))) { + case 0: + + option9 = witTypes.None[string]() + case 1: + value8 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) + + option9 = witTypes.Some[string](value8) + default: + panic("unreachable") + } + var option10 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 4*4)))) { + case 0: + + option10 = witTypes.None[uint32]() + case 1: + + option10 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 4*4))))) + default: + panic("unreachable") + } + + option11 = witTypes.Some[FieldSizePayload](FieldSizePayload{option9, option10}) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSize(option11) + + case 23: + var option12 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option12 = witTypes.None[uint32]() + case 1: + + option12 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSectionSize(option12) + + case 24: + var option14 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option14 = witTypes.None[string]() + case 1: + value13 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option14 = witTypes.Some[string](value13) + default: + panic("unreachable") + } + var option15 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option15 = witTypes.None[uint32]() + case 1: + + option15 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSize(FieldSizePayload{option14, option15}) + + case 25: + + variant = MakeErrorCodeHttpResponseIncomplete() + + case 26: + var option16 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option16 = witTypes.None[uint32]() + case 1: + + option16 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSectionSize(option16) + + case 27: + var option18 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option18 = witTypes.None[string]() + case 1: + value17 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option18 = witTypes.Some[string](value17) + default: + panic("unreachable") + } + var option19 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option19 = witTypes.None[uint32]() + case 1: + + option19 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSize(FieldSizePayload{option18, option19}) + + case 28: + var option20 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option20 = witTypes.None[uint64]() + case 1: + + option20 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 24)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseBodySize(option20) + + case 29: + var option21 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option21 = witTypes.None[uint32]() + case 1: + + option21 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSectionSize(option21) + + case 30: + var option23 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option23 = witTypes.None[string]() + case 1: + value22 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option23 = witTypes.Some[string](value22) + default: + panic("unreachable") + } + var option24 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 3*4)))) { + case 0: + + option24 = witTypes.None[uint32]() + case 1: + + option24 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (20 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSize(FieldSizePayload{option23, option24}) + + case 31: + var option26 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option26 = witTypes.None[string]() + case 1: + value25 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option26 = witTypes.Some[string](value25) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTransferCoding(option26) + + case 32: + var option28 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option28 = witTypes.None[string]() + case 1: + value27 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option28 = witTypes.Some[string](value27) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseContentCoding(option28) + + case 33: + + variant = MakeErrorCodeHttpResponseTimeout() + + case 34: + + variant = MakeErrorCodeHttpUpgradeFailed() + + case 35: + + variant = MakeErrorCodeHttpProtocolError() + + case 36: + + variant = MakeErrorCodeLoopDetected() + + case 37: + + variant = MakeErrorCodeConfigurationError() + + case 38: + var option30 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + option30 = witTypes.None[string]() + case 1: + value29 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (16 + 2*4)))) + + option30 = witTypes.Some[string](value29) + default: + panic("unreachable") + } + + variant = MakeErrorCodeInternalError(option30) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, ErrorCode](variant) + default: + panic("unreachable") + } + result31 := result + return result31 + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]future-incoming-response.subscribe +func wasm_import_method_future_incoming_response_subscribe(arg0 int32) int32 + +func (self *FutureIncomingResponse) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_future_incoming_response_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:http/types@0.2.0 [method]future-incoming-response.get +func wasm_import_method_future_incoming_response_get(arg0 int32, arg1 uintptr) + +func (self *FutureIncomingResponse) Get() witTypes.Option[witTypes.Result[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit]] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (40 + 4*4), 8)) + wasm_import_method_future_incoming_response_get((self).Handle(), returnArea) + var option30 witTypes.Option[witTypes.Result[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit]] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + option30 = witTypes.None[witTypes.Result[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit]]() + case 1: + var result29 witTypes.Result[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + var result witTypes.Result[*IncomingResponse, ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16))) { + case 0: + + result = witTypes.Ok[*IncomingResponse, ErrorCode](IncomingResponseFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 24)))))) + case 1: + var variant ErrorCode + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24))) { + case 0: + + variant = MakeErrorCodeDnsTimeout() + + case 1: + var option witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option = witTypes.None[string]() + case 1: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option = witTypes.Some[string](value) + default: + panic("unreachable") + } + var option0 witTypes.Option[uint16] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option0 = witTypes.None[uint16]() + case 1: + + option0 = witTypes.Some[uint16](uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (34 + 3*4)))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeDnsError(DnsErrorPayload{option, option0}) + + case 2: + + variant = MakeErrorCodeDestinationNotFound() + + case 3: + + variant = MakeErrorCodeDestinationUnavailable() + + case 4: + + variant = MakeErrorCodeDestinationIpProhibited() + + case 5: + + variant = MakeErrorCodeDestinationIpUnroutable() + + case 6: + + variant = MakeErrorCodeConnectionRefused() + + case 7: + + variant = MakeErrorCodeConnectionTerminated() + + case 8: + + variant = MakeErrorCodeConnectionTimeout() + + case 9: + + variant = MakeErrorCodeConnectionReadTimeout() + + case 10: + + variant = MakeErrorCodeConnectionWriteTimeout() + + case 11: + + variant = MakeErrorCodeConnectionLimitReached() + + case 12: + + variant = MakeErrorCodeTlsProtocolError() + + case 13: + + variant = MakeErrorCodeTlsCertificateError() + + case 14: + var option1 witTypes.Option[uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option1 = witTypes.None[uint8]() + case 1: + + option1 = witTypes.Some[uint8](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 33))))) + default: + panic("unreachable") + } + var option3 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))) { + case 0: + + option3 = witTypes.None[string]() + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) + + option3 = witTypes.Some[string](value2) + default: + panic("unreachable") + } + + variant = MakeErrorCodeTlsAlertReceived(TlsAlertReceivedPayload{option1, option3}) + + case 15: + + variant = MakeErrorCodeHttpRequestDenied() + + case 16: + + variant = MakeErrorCodeHttpRequestLengthRequired() + + case 17: + var option4 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option4 = witTypes.None[uint64]() + case 1: + + option4 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestBodySize(option4) + + case 18: + + variant = MakeErrorCodeHttpRequestMethodInvalid() + + case 19: + + variant = MakeErrorCodeHttpRequestUriInvalid() + + case 20: + + variant = MakeErrorCodeHttpRequestUriTooLong() + + case 21: + var option5 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option5 = witTypes.None[uint32]() + case 1: + + option5 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSectionSize(option5) + + case 22: + var option9 witTypes.Option[FieldSizePayload] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option9 = witTypes.None[FieldSizePayload]() + case 1: + var option7 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))) { + case 0: + + option7 = witTypes.None[string]() + case 1: + value6 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) + + option7 = witTypes.Some[string](value6) + default: + panic("unreachable") + } + var option8 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 4*4)))) { + case 0: + + option8 = witTypes.None[uint32]() + case 1: + + option8 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 4*4))))) + default: + panic("unreachable") + } + + option9 = witTypes.Some[FieldSizePayload](FieldSizePayload{option7, option8}) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestHeaderSize(option9) + + case 23: + var option10 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option10 = witTypes.None[uint32]() + case 1: + + option10 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSectionSize(option10) + + case 24: + var option12 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option12 = witTypes.None[string]() + case 1: + value11 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option12 = witTypes.Some[string](value11) + default: + panic("unreachable") + } + var option13 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option13 = witTypes.None[uint32]() + case 1: + + option13 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpRequestTrailerSize(FieldSizePayload{option12, option13}) + + case 25: + + variant = MakeErrorCodeHttpResponseIncomplete() + + case 26: + var option14 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option14 = witTypes.None[uint32]() + case 1: + + option14 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSectionSize(option14) + + case 27: + var option16 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option16 = witTypes.None[string]() + case 1: + value15 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option16 = witTypes.Some[string](value15) + default: + panic("unreachable") + } + var option17 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option17 = witTypes.None[uint32]() + case 1: + + option17 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseHeaderSize(FieldSizePayload{option16, option17}) + + case 28: + var option18 witTypes.Option[uint64] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option18 = witTypes.None[uint64]() + case 1: + + option18 = witTypes.Some[uint64](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 40)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseBodySize(option18) + + case 29: + var option19 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option19 = witTypes.None[uint32]() + case 1: + + option19 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 36)))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSectionSize(option19) + + case 30: + var option21 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option21 = witTypes.None[string]() + case 1: + value20 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option21 = witTypes.Some[string](value20) + default: + panic("unreachable") + } + var option22 witTypes.Option[uint32] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 3*4)))) { + case 0: + + option22 = witTypes.None[uint32]() + case 1: + + option22 = witTypes.Some[uint32](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (36 + 3*4))))) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTrailerSize(FieldSizePayload{option21, option22}) + + case 31: + var option24 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option24 = witTypes.None[string]() + case 1: + value23 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option24 = witTypes.Some[string](value23) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseTransferCoding(option24) + + case 32: + var option26 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option26 = witTypes.None[string]() + case 1: + value25 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option26 = witTypes.Some[string](value25) + default: + panic("unreachable") + } + + variant = MakeErrorCodeHttpResponseContentCoding(option26) + + case 33: + + variant = MakeErrorCodeHttpResponseTimeout() + + case 34: + + variant = MakeErrorCodeHttpUpgradeFailed() + + case 35: + + variant = MakeErrorCodeHttpProtocolError() + + case 36: + + variant = MakeErrorCodeLoopDetected() + + case 37: + + variant = MakeErrorCodeConfigurationError() + + case 38: + var option28 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 32))) { + case 0: + + option28 = witTypes.None[string]() + case 1: + value27 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (32 + 2*4)))) + + option28 = witTypes.Some[string](value27) + default: + panic("unreachable") + } + + variant = MakeErrorCodeInternalError(option28) + + default: + panic("unreachable") + } + + result = witTypes.Err[*IncomingResponse, ErrorCode](variant) + default: + panic("unreachable") + } + + result29 = witTypes.Ok[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit](result) + case 1: + + result29 = witTypes.Err[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit](witTypes.Unit{}) + default: + panic("unreachable") + } + + option30 = witTypes.Some[witTypes.Result[witTypes.Result[*IncomingResponse, ErrorCode], witTypes.Unit]](result29) + default: + panic("unreachable") + } + result31 := option30 + return result31 + +} diff --git a/internal/wasi_io_0_2_0_error/wit_bindings.go b/internal/wasi_io_0_2_0_error/wit_bindings.go new file mode 100644 index 00000000..710ed7b0 --- /dev/null +++ b/internal/wasi_io_0_2_0_error/wit_bindings.go @@ -0,0 +1,116 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_io_0_2_0_error + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:io/error@0.2.0 [resource-drop]error +func resourceDropError(handle int32) + +// 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 +// provide functions to further "downcast" this error into more specific +// error information. For example, `error`s returned in streams derived +// from filesystem types to be described using the filesystem's own +// error-code type, using the function +// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter +// `borrow` and returns +// `option`. +// +// The set of functions which can "downcast" an `error` into a more +// concrete type is open. +type Error struct { + handle *witRuntime.Handle +} + +func (self *Error) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Error) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Error) Handle() int32 { + return self.handle.Use() +} + +func (self *Error) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropError(handle) + } +} + +func ErrorFromOwnHandle(handleValue int32) *Error { + handle := witRuntime.MakeHandle(handleValue) + value := &Error{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropError(handleValue) + } + }, 0) + return value +} + +func ErrorFromBorrowHandle(handleValue int32) *Error { + handle := witRuntime.MakeHandle(handleValue) + return &Error{handle} +} + +//go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string +func wasm_import_method_error_to_debug_string(arg0 int32, arg1 uintptr) + +func (self *Error) ToDebugString() string { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_method_error_to_debug_string((self).Handle(), returnArea) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + result := value + return result + +} diff --git a/internal/wasi_io_0_2_0_poll/wit_bindings.go b/internal/wasi_io_0_2_0_poll/wit_bindings.go new file mode 100644 index 00000000..112a5542 --- /dev/null +++ b/internal/wasi_io_0_2_0_poll/wit_bindings.go @@ -0,0 +1,126 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_io_0_2_0_poll + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable +func resourceDropPollable(handle int32) + +// `pollable` represents a single I/O event which may be ready, or not. +type Pollable struct { + handle *witRuntime.Handle +} + +func (self *Pollable) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Pollable) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Pollable) Handle() int32 { + return self.handle.Use() +} + +func (self *Pollable) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropPollable(handle) + } +} + +func PollableFromOwnHandle(handleValue int32) *Pollable { + handle := witRuntime.MakeHandle(handleValue) + value := &Pollable{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropPollable(handleValue) + } + }, 0) + return value +} + +func PollableFromBorrowHandle(handleValue int32) *Pollable { + handle := witRuntime.MakeHandle(handleValue) + return &Pollable{handle} +} + +//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready +func wasm_import_method_pollable_ready(arg0 int32) int32 + +func (self *Pollable) Ready() bool { + + result := wasm_import_method_pollable_ready((self).Handle()) + return (result != 0) + +} + +//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block +func wasm_import_method_pollable_block(arg0 int32) + +func (self *Pollable) Block() { + + wasm_import_method_pollable_block((self).Handle()) + +} + +//go:wasmimport wasi:io/poll@0.2.0 poll +func wasm_import_poll(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Poll(in []*Pollable) []uint32 { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + slice := in + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*4), 4) + for index, element := range slice { + base := unsafe.Add(result, index*4) + *(*int32)(unsafe.Add(unsafe.Pointer(base), 0)) = (element).Handle() + + } + + wasm_import_poll(uintptr(result), length, returnArea) + value := unsafe.Slice((*uint32)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + result0 := value + return result0 + +} diff --git a/internal/wasi_io_0_2_0_streams/wit_bindings.go b/internal/wasi_io_0_2_0_streams/wit_bindings.go new file mode 100644 index 00000000..a0d3be84 --- /dev/null +++ b/internal/wasi_io_0_2_0_streams/wit_bindings.go @@ -0,0 +1,702 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_io_0_2_0_streams + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_error" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Error = wasi_io_0_2_0_error.Error +type Pollable = wasi_io_0_2_0_poll.Pollable + +const ( + // The last operation (a write or flush) failed before completion. + // + // More information is available in the `error` payload. + StreamErrorLastOperationFailed uint8 = 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. + StreamErrorClosed uint8 = 1 +) + +// An error for input-stream and output-stream operations. +type StreamError struct { + tag uint8 + value any +} + +func (self StreamError) Tag() uint8 { + return self.tag +} + +func (self StreamError) LastOperationFailed() *wasi_io_0_2_0_error.Error { + if self.tag != StreamErrorLastOperationFailed { + panic("tag mismatch") + } + return self.value.(*wasi_io_0_2_0_error.Error) +} + +func MakeStreamErrorLastOperationFailed(value *wasi_io_0_2_0_error.Error) StreamError { + return StreamError{StreamErrorLastOperationFailed, value} +} +func MakeStreamErrorClosed() StreamError { + return StreamError{StreamErrorClosed, nil} +} + +//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]input-stream +func resourceDropInputStream(handle int32) + +// 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`. +type InputStream struct { + handle *witRuntime.Handle +} + +func (self *InputStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *InputStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *InputStream) Handle() int32 { + return self.handle.Use() +} + +func (self *InputStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropInputStream(handle) + } +} + +func InputStreamFromOwnHandle(handleValue int32) *InputStream { + handle := witRuntime.MakeHandle(handleValue) + value := &InputStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropInputStream(handleValue) + } + }, 0) + return value +} + +func InputStreamFromBorrowHandle(handleValue int32) *InputStream { + handle := witRuntime.MakeHandle(handleValue) + return &InputStream{handle} +} + +//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]output-stream +func resourceDropOutputStream(handle int32) + +// 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`. +type OutputStream struct { + handle *witRuntime.Handle +} + +func (self *OutputStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *OutputStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *OutputStream) Handle() int32 { + return self.handle.Use() +} + +func (self *OutputStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropOutputStream(handle) + } +} + +func OutputStreamFromOwnHandle(handleValue int32) *OutputStream { + handle := witRuntime.MakeHandle(handleValue) + value := &OutputStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropOutputStream(handleValue) + } + }, 0) + return value +} + +func OutputStreamFromBorrowHandle(handleValue int32) *OutputStream { + handle := witRuntime.MakeHandle(handleValue) + return &OutputStream{handle} +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.read +func wasm_import_method_input_stream_read(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *InputStream) Read(len uint64) witTypes.Result[[]uint8, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_input_stream_read((self).Handle(), int64(len), returnArea) + var result witTypes.Result[[]uint8, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[[]uint8, StreamError](value) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (4 + 1*4))))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[[]uint8, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-read +func wasm_import_method_input_stream_blocking_read(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *InputStream) BlockingRead(len uint64) witTypes.Result[[]uint8, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_input_stream_blocking_read((self).Handle(), int64(len), returnArea) + var result witTypes.Result[[]uint8, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + + result = witTypes.Ok[[]uint8, StreamError](value) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (4 + 1*4))))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[[]uint8, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.skip +func wasm_import_method_input_stream_skip(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *InputStream) Skip(len uint64) witTypes.Result[uint64, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_input_stream_skip((self).Handle(), int64(len), returnArea) + var result witTypes.Result[uint64, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, StreamError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[uint64, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-skip +func wasm_import_method_input_stream_blocking_skip(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *InputStream) BlockingSkip(len uint64) witTypes.Result[uint64, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_input_stream_blocking_skip((self).Handle(), int64(len), returnArea) + var result witTypes.Result[uint64, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, StreamError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[uint64, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.subscribe +func wasm_import_method_input_stream_subscribe(arg0 int32) int32 + +func (self *InputStream) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_input_stream_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.check-write +func wasm_import_method_output_stream_check_write(arg0 int32, arg1 uintptr) + +func (self *OutputStream) CheckWrite() witTypes.Result[uint64, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_output_stream_check_write((self).Handle(), returnArea) + var result witTypes.Result[uint64, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, StreamError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[uint64, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write +func wasm_import_method_output_stream_write(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *OutputStream) Write(contents []uint8) witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + data := unsafe.Pointer(unsafe.SliceData(contents)) + pinner.Pin(data) + wasm_import_method_output_stream_write((self).Handle(), uintptr(data), uint32(len(contents)), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-and-flush +func wasm_import_method_output_stream_blocking_write_and_flush(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *OutputStream) BlockingWriteAndFlush(contents []uint8) witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + data := unsafe.Pointer(unsafe.SliceData(contents)) + pinner.Pin(data) + wasm_import_method_output_stream_blocking_write_and_flush((self).Handle(), uintptr(data), uint32(len(contents)), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.flush +func wasm_import_method_output_stream_flush(arg0 int32, arg1 uintptr) + +func (self *OutputStream) Flush() witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + wasm_import_method_output_stream_flush((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-flush +func wasm_import_method_output_stream_blocking_flush(arg0 int32, arg1 uintptr) + +func (self *OutputStream) BlockingFlush() witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + wasm_import_method_output_stream_blocking_flush((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.subscribe +func wasm_import_method_output_stream_subscribe(arg0 int32) int32 + +func (self *OutputStream) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_output_stream_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write-zeroes +func wasm_import_method_output_stream_write_zeroes(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *OutputStream) WriteZeroes(len uint64) witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + wasm_import_method_output_stream_write_zeroes((self).Handle(), int64(len), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-zeroes-and-flush +func wasm_import_method_output_stream_blocking_write_zeroes_and_flush(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *OutputStream) BlockingWriteZeroesAndFlush(len uint64) witTypes.Result[witTypes.Unit, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + wasm_import_method_output_stream_blocking_write_zeroes_and_flush((self).Handle(), int64(len), returnArea) + var result witTypes.Result[witTypes.Unit, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, StreamError](witTypes.Unit{}) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.splice +func wasm_import_method_output_stream_splice(arg0 int32, arg1 int32, arg2 int64, arg3 uintptr) + +func (self *OutputStream) Splice(src *InputStream, len uint64) witTypes.Result[uint64, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_output_stream_splice((self).Handle(), (src).Handle(), int64(len), returnArea) + var result witTypes.Result[uint64, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, StreamError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[uint64, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-splice +func wasm_import_method_output_stream_blocking_splice(arg0 int32, arg1 int32, arg2 int64, arg3 uintptr) + +func (self *OutputStream) BlockingSplice(src *InputStream, len uint64) witTypes.Result[uint64, StreamError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_output_stream_blocking_splice((self).Handle(), (src).Handle(), int64(len), returnArea) + var result witTypes.Result[uint64, StreamError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, StreamError](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + var variant StreamError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = MakeStreamErrorLastOperationFailed(wasi_io_0_2_0_error.ErrorFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))) + + case 1: + + variant = MakeStreamErrorClosed() + + default: + panic("unreachable") + } + + result = witTypes.Err[uint64, StreamError](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} diff --git a/internal/wasi_keyvalue_atomics/wit_bindings.go b/internal/wasi_keyvalue_atomics/wit_bindings.go new file mode 100644 index 00000000..83749052 --- /dev/null +++ b/internal/wasi_keyvalue_atomics/wit_bindings.go @@ -0,0 +1,330 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_keyvalue_atomics + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_keyvalue_store" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Bucket = wasi_keyvalue_store.Bucket +type Error = wasi_keyvalue_store.Error + +//go:wasmimport wasi:keyvalue/atomics@0.2.0-draft2 [resource-drop]cas +func resourceDropCas(handle int32) + +// A handle to a CAS (compare-and-swap) operation. +type Cas struct { + handle *witRuntime.Handle +} + +func (self *Cas) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Cas) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Cas) Handle() int32 { + return self.handle.Use() +} + +func (self *Cas) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropCas(handle) + } +} + +func CasFromOwnHandle(handleValue int32) *Cas { + handle := witRuntime.MakeHandle(handleValue) + value := &Cas{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropCas(handleValue) + } + }, 0) + return value +} + +func CasFromBorrowHandle(handleValue int32) *Cas { + handle := witRuntime.MakeHandle(handleValue) + return &Cas{handle} +} + +const ( + // A store error occurred when performing the operation + CasErrorStoreError uint8 = 0 + // The CAS operation failed because the value was too old. This returns a new CAS handle + // for easy retries. Implementors MUST return a CAS handle that has been updated to the + // latest version or transaction. + CasErrorCasFailed uint8 = 1 +) + +// The error returned by a CAS operation +type CasError struct { + tag uint8 + value any +} + +func (self CasError) Tag() uint8 { + return self.tag +} + +func (self CasError) StoreError() wasi_keyvalue_store.Error { + if self.tag != CasErrorStoreError { + panic("tag mismatch") + } + return self.value.(wasi_keyvalue_store.Error) +} +func (self CasError) CasFailed() *Cas { + if self.tag != CasErrorCasFailed { + panic("tag mismatch") + } + return self.value.(*Cas) +} + +func MakeCasErrorStoreError(value wasi_keyvalue_store.Error) CasError { + return CasError{CasErrorStoreError, value} +} +func MakeCasErrorCasFailed(value *Cas) CasError { + return CasError{CasErrorCasFailed, value} +} + +//go:wasmimport wasi:keyvalue/atomics@0.2.0-draft2 [static]cas.new +func wasm_import_static_cas_new(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func CasNew(bucket *wasi_keyvalue_store.Bucket, key string) witTypes.Result[*Cas, wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_static_cas_new((bucket).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[*Cas, wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Cas, wasi_keyvalue_store.Error](CasFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Cas, wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:keyvalue/atomics@0.2.0-draft2 [method]cas.current +func wasm_import_method_cas_current(arg0 int32, arg1 uintptr) + +func (self *Cas) Current() witTypes.Result[witTypes.Option[[]uint8], wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + wasm_import_method_cas_current((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Option[[]uint8], wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[[]uint8]() + case 1: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + option = witTypes.Some[[]uint8](value) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[[]uint8], wasi_keyvalue_store.Error](option) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[[]uint8], wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:keyvalue/atomics@0.2.0-draft2 increment +func wasm_import_increment(arg0 int32, arg1 uintptr, arg2 uint32, arg3 int64, arg4 uintptr) + +func Increment(bucket *wasi_keyvalue_store.Bucket, key string, delta int64) witTypes.Result[int64, wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (16 + 2*4), 8)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_increment((bucket).Handle(), uintptr(utf8), uint32(len(key)), delta, returnArea) + var result witTypes.Result[int64, wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[int64, wasi_keyvalue_store.Error](*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8))) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 1*4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (8 + 2*4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[int64, wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:keyvalue/atomics@0.2.0-draft2 swap +func wasm_import_swap(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func Swap(cas *Cas, value []uint8) witTypes.Result[witTypes.Unit, CasError] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (5 * 4), 4)) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_swap((cas).TakeHandle(), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, CasError] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, CasError](witTypes.Unit{}) + case 1: + var variant1 CasError + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value0) + + default: + panic("unreachable") + } + + variant1 = MakeCasErrorStoreError(variant) + + case 1: + + variant1 = MakeCasErrorCasFailed(CasFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4))))))) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, CasError](variant1) + default: + panic("unreachable") + } + result2 := result + return result2 + +} diff --git a/internal/wasi_keyvalue_batch/wit_bindings.go b/internal/wasi_keyvalue_batch/wit_bindings.go new file mode 100644 index 00000000..92ed39e3 --- /dev/null +++ b/internal/wasi_keyvalue_batch/wit_bindings.go @@ -0,0 +1,232 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_keyvalue_batch + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_keyvalue_store" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Bucket = wasi_keyvalue_store.Bucket +type Error = wasi_keyvalue_store.Error + +//go:wasmimport wasi:keyvalue/batch@0.2.0-draft2 get-many +func wasm_import_get_many(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func GetMany(bucket *wasi_keyvalue_store.Bucket, keys []string) witTypes.Result[[]witTypes.Tuple2[string, witTypes.Option[[]uint8]], wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + slice := keys + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf8 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf8) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf8))) + + } + + wasm_import_get_many((bucket).Handle(), uintptr(result), length, returnArea) + var result3 witTypes.Result[[]witTypes.Tuple2[string, witTypes.Option[[]uint8]], wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result1 := make([]witTypes.Tuple2[string, witTypes.Option[[]uint8]], 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(5*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + var option witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))) { + case 0: + + option = witTypes.None[[]uint8]() + case 1: + value0 := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), (4 * 4)))) + + option = witTypes.Some[[]uint8](value0) + default: + panic("unreachable") + } + + result1 = append(result1, witTypes.Tuple2[string, witTypes.Option[[]uint8]]{value, option}) + } + + result3 = witTypes.Ok[[]witTypes.Tuple2[string, witTypes.Option[[]uint8]], wasi_keyvalue_store.Error](result1) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value2) + + default: + panic("unreachable") + } + + result3 = witTypes.Err[[]witTypes.Tuple2[string, witTypes.Option[[]uint8]], wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result4 := result3 + return result4 + +} + +//go:wasmimport wasi:keyvalue/batch@0.2.0-draft2 set-many +func wasm_import_set_many(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func SetMany(bucket *wasi_keyvalue_store.Bucket, keyValues []witTypes.Tuple2[string, []uint8]) witTypes.Result[witTypes.Unit, wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + slice := keyValues + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(4*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(4*4)) + utf8 := unsafe.Pointer(unsafe.StringData((element).F0)) + pinner.Pin(utf8) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len((element).F0))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf8))) + data := unsafe.Pointer(unsafe.SliceData((element).F1)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (3 * 4))) = uint32(uint32(len((element).F1))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = uint32(uintptr(uintptr(data))) + + } + + wasm_import_set_many((bucket).Handle(), uintptr(result), length, returnArea) + var result0 witTypes.Result[witTypes.Unit, wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[witTypes.Unit, wasi_keyvalue_store.Error](witTypes.Unit{}) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value) + + default: + panic("unreachable") + } + + result0 = witTypes.Err[witTypes.Unit, wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:keyvalue/batch@0.2.0-draft2 delete-many +func wasm_import_delete_many(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func DeleteMany(bucket *wasi_keyvalue_store.Bucket, keys []string) witTypes.Result[witTypes.Unit, wasi_keyvalue_store.Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + slice := keys + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(2*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(2*4)) + utf8 := unsafe.Pointer(unsafe.StringData(element)) + pinner.Pin(utf8) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len(element))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(utf8))) + + } + + wasm_import_delete_many((bucket).Handle(), uintptr(result), length, returnArea) + var result0 witTypes.Result[witTypes.Unit, wasi_keyvalue_store.Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[witTypes.Unit, wasi_keyvalue_store.Error](witTypes.Unit{}) + case 1: + var variant wasi_keyvalue_store.Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_keyvalue_store.MakeErrorNoSuchStore() + + case 1: + + variant = wasi_keyvalue_store.MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = wasi_keyvalue_store.MakeErrorOther(value) + + default: + panic("unreachable") + } + + result0 = witTypes.Err[witTypes.Unit, wasi_keyvalue_store.Error](variant) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} diff --git a/internal/wasi_keyvalue_store/wit_bindings.go b/internal/wasi_keyvalue_store/wit_bindings.go new file mode 100644 index 00000000..fff847a1 --- /dev/null +++ b/internal/wasi_keyvalue_store/wit_bindings.go @@ -0,0 +1,466 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_keyvalue_store + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +const ( + // The host does not recognize the store identifier requested. + ErrorNoSuchStore uint8 = 0 + // The requesting component does not have access to the specified store + // (which may or may not exist). + ErrorAccessDenied uint8 = 1 + // Some implementation-specific error has occurred (e.g. I/O) + ErrorOther uint8 = 2 +) + +// The set of errors which may be raised by functions in this package +type Error struct { + tag uint8 + value any +} + +func (self Error) Tag() uint8 { + return self.tag +} + +func (self Error) Other() string { + if self.tag != ErrorOther { + panic("tag mismatch") + } + return self.value.(string) +} + +func MakeErrorNoSuchStore() Error { + return Error{ErrorNoSuchStore, nil} +} +func MakeErrorAccessDenied() Error { + return Error{ErrorAccessDenied, nil} +} +func MakeErrorOther(value string) Error { + return Error{ErrorOther, value} +} + +// A response to a `list-keys` operation. +type KeyResponse struct { + // The list of keys returned by the query. + Keys []string + // The continuation token to use to fetch the next page of keys. If this is `null`, then + // there are no more keys to fetch. + Cursor witTypes.Option[string] +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [resource-drop]bucket +func resourceDropBucket(handle int32) + +// A bucket is a collection of key-value pairs. Each key-value pair is stored as a entry in the +// bucket, and the bucket itself acts as a collection of all these entries. +// +// It is worth noting that the exact terminology for bucket in key-value stores can very +// depending on the specific implementation. For example: +// +// 1. Amazon DynamoDB calls a collection of key-value pairs a table +// 2. Redis has hashes, sets, and sorted sets as different types of collections +// 3. Cassandra calls a collection of key-value pairs a column family +// 4. MongoDB calls a collection of key-value pairs a collection +// 5. Riak calls a collection of key-value pairs a bucket +// 6. Memcached calls a collection of key-value pairs a slab +// 7. Azure Cosmos DB calls a collection of key-value pairs a container +// +// In this interface, we use the term `bucket` to refer to a collection of key-value pairs +type Bucket struct { + handle *witRuntime.Handle +} + +func (self *Bucket) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Bucket) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Bucket) Handle() int32 { + return self.handle.Use() +} + +func (self *Bucket) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropBucket(handle) + } +} + +func BucketFromOwnHandle(handleValue int32) *Bucket { + handle := witRuntime.MakeHandle(handleValue) + value := &Bucket{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropBucket(handleValue) + } + }, 0) + return value +} + +func BucketFromBorrowHandle(handleValue int32) *Bucket { + handle := witRuntime.MakeHandle(handleValue) + return &Bucket{handle} +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 open +func wasm_import_open(arg0 uintptr, arg1 uint32, arg2 uintptr) + +func Open(identifier string) witTypes.Result[*Bucket, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(identifier)) + pinner.Pin(utf8) + wasm_import_open(uintptr(utf8), uint32(len(identifier)), returnArea) + var result witTypes.Result[*Bucket, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*Bucket, Error](BucketFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[*Bucket, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [method]bucket.get +func wasm_import_method_bucket_get(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Bucket) Get(key string) witTypes.Result[witTypes.Option[[]uint8], Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_bucket_get((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Option[[]uint8], Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[[]uint8] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + option = witTypes.None[[]uint8]() + case 1: + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + option = witTypes.Some[[]uint8](value) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[[]uint8], Error](option) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Option[[]uint8], Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [method]bucket.set +func wasm_import_method_bucket_set(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr, arg4 uint32, arg5 uintptr) + +func (self *Bucket) Set(key string, value []uint8) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + data := unsafe.Pointer(unsafe.SliceData(value)) + pinner.Pin(data) + wasm_import_method_bucket_set((self).Handle(), uintptr(utf8), uint32(len(key)), uintptr(data), uint32(len(value)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value0 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value0) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result1 := result + return result1 + +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [method]bucket.delete +func wasm_import_method_bucket_delete(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Bucket) Delete(key string) witTypes.Result[witTypes.Unit, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_bucket_delete((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[witTypes.Unit, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, Error](witTypes.Unit{}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[witTypes.Unit, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [method]bucket.exists +func wasm_import_method_bucket_exists(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *Bucket) Exists(key string) witTypes.Result[bool, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (4 * 4), 4)) + utf8 := unsafe.Pointer(unsafe.StringData(key)) + pinner.Pin(utf8) + wasm_import_method_bucket_exists((self).Handle(), uintptr(utf8), uint32(len(key)), returnArea) + var result witTypes.Result[bool, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[bool, Error]((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) != 0)) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value) + + default: + panic("unreachable") + } + + result = witTypes.Err[bool, Error](variant) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:keyvalue/store@0.2.0-draft2 [method]bucket.list-keys +func wasm_import_method_bucket_list_keys(arg0 int32, arg1 int32, arg2 uintptr, arg3 uint32, arg4 uintptr) + +func (self *Bucket) ListKeys(cursor witTypes.Option[string]) witTypes.Result[KeyResponse, Error] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (6 * 4), 4)) + var option int32 + var option0 uintptr + var option1 uint32 + switch cursor.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option0 = 0 + option1 = 0 + case witTypes.OptionSome: + payload := cursor.Some() + utf8 := unsafe.Pointer(unsafe.StringData(payload)) + pinner.Pin(utf8) + + option = int32(1) + option0 = uintptr(utf8) + option1 = uint32(len(payload)) + default: + panic("unreachable") + } + wasm_import_method_bucket_list_keys((self).Handle(), option, option0, option1, returnArea) + var result5 witTypes.Result[KeyResponse, Error] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]string, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(2*4)) + value := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + + result = append(result, value) + } + + var option3 witTypes.Option[string] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) { + case 0: + + option3 = witTypes.None[string]() + case 1: + value2 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (4 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (5 * 4)))) + + option3 = witTypes.Some[string](value2) + default: + panic("unreachable") + } + + result5 = witTypes.Ok[KeyResponse, Error](KeyResponse{result, option3}) + case 1: + var variant Error + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = MakeErrorNoSuchStore() + + case 1: + + variant = MakeErrorAccessDenied() + + case 2: + value4 := unsafe.String((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (3 * 4)))) + + variant = MakeErrorOther(value4) + + default: + panic("unreachable") + } + + result5 = witTypes.Err[KeyResponse, Error](variant) + default: + panic("unreachable") + } + result6 := result5 + return result6 + +} diff --git a/internal/wasi_random_0_2_0_insecure/wit_bindings.go b/internal/wasi_random_0_2_0_insecure/wit_bindings.go new file mode 100644 index 00000000..a6f368bb --- /dev/null +++ b/internal/wasi_random_0_2_0_insecure/wit_bindings.go @@ -0,0 +1,64 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_random_0_2_0_insecure + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes +func wasm_import_get_insecure_random_bytes(arg0 int64, arg1 uintptr) + +func GetInsecureRandomBytes(len uint64) []uint8 { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_get_insecure_random_bytes(int64(len), returnArea) + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + result := value + return result + +} + +//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64 +func wasm_import_get_insecure_random_u64() int64 + +func GetInsecureRandomU64() uint64 { + + result := wasm_import_get_insecure_random_u64() + return uint64(result) + +} diff --git a/internal/wasi_random_0_2_0_insecure_seed/wit_bindings.go b/internal/wasi_random_0_2_0_insecure_seed/wit_bindings.go new file mode 100644 index 00000000..fe271963 --- /dev/null +++ b/internal/wasi_random_0_2_0_insecure_seed/wit_bindings.go @@ -0,0 +1,55 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_random_0_2_0_insecure_seed + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed +func wasm_import_insecure_seed(arg0 uintptr) + +func InsecureSeed() (uint64, uint64) { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_insecure_seed(returnArea) + result := witTypes.Tuple2[uint64, uint64]{uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 0))), uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))} + tuple := result + return tuple.F0, tuple.F1 + +} diff --git a/internal/wasi_random_0_2_0_random/wit_bindings.go b/internal/wasi_random_0_2_0_random/wit_bindings.go new file mode 100644 index 00000000..49405a54 --- /dev/null +++ b/internal/wasi_random_0_2_0_random/wit_bindings.go @@ -0,0 +1,64 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_random_0_2_0_random + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + "runtime" + "unsafe" +) + +//go:wasmimport wasi:random/random@0.2.0 get-random-bytes +func wasm_import_get_random_bytes(arg0 int64, arg1 uintptr) + +func GetRandomBytes(len uint64) []uint8 { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (2 * 4), 4)) + wasm_import_get_random_bytes(int64(len), returnArea) + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) + result := value + return result + +} + +//go:wasmimport wasi:random/random@0.2.0 get-random-u64 +func wasm_import_get_random_u64() int64 + +func GetRandomU64() uint64 { + + result := wasm_import_get_random_u64() + return uint64(result) + +} diff --git a/internal/wasi_sockets_0_2_0_instance_network/wit_bindings.go b/internal/wasi_sockets_0_2_0_instance_network/wit_bindings.go new file mode 100644 index 00000000..02caf1ba --- /dev/null +++ b/internal/wasi_sockets_0_2_0_instance_network/wit_bindings.go @@ -0,0 +1,49 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_instance_network + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" +) + +type Network = wasi_sockets_0_2_0_network.Network + +//go:wasmimport wasi:sockets/instance-network@0.2.0 instance-network +func wasm_import_instance_network() int32 + +func InstanceNetwork() *wasi_sockets_0_2_0_network.Network { + + result := wasm_import_instance_network() + return wasi_sockets_0_2_0_network.NetworkFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_sockets_0_2_0_ip_name_lookup/wit_bindings.go b/internal/wasi_sockets_0_2_0_ip_name_lookup/wit_bindings.go new file mode 100644 index 00000000..a1fa42c3 --- /dev/null +++ b/internal/wasi_sockets_0_2_0_ip_name_lookup/wit_bindings.go @@ -0,0 +1,176 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_ip_name_lookup + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Pollable = wasi_io_0_2_0_poll.Pollable +type Network = wasi_sockets_0_2_0_network.Network +type ErrorCode = wasi_sockets_0_2_0_network.ErrorCode +type IpAddress = wasi_sockets_0_2_0_network.IpAddress + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [resource-drop]resolve-address-stream +func resourceDropResolveAddressStream(handle int32) + +type ResolveAddressStream struct { + handle *witRuntime.Handle +} + +func (self *ResolveAddressStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *ResolveAddressStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *ResolveAddressStream) Handle() int32 { + return self.handle.Use() +} + +func (self *ResolveAddressStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropResolveAddressStream(handle) + } +} + +func ResolveAddressStreamFromOwnHandle(handleValue int32) *ResolveAddressStream { + handle := witRuntime.MakeHandle(handleValue) + value := &ResolveAddressStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropResolveAddressStream(handleValue) + } + }, 0) + return value +} + +func ResolveAddressStreamFromBorrowHandle(handleValue int32) *ResolveAddressStream { + handle := witRuntime.MakeHandle(handleValue) + return &ResolveAddressStream{handle} +} + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 resolve-addresses +func wasm_import_resolve_addresses(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func ResolveAddresses(network *wasi_sockets_0_2_0_network.Network, name string) witTypes.Result[*ResolveAddressStream, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + utf8 := unsafe.Pointer(unsafe.StringData(name)) + pinner.Pin(utf8) + wasm_import_resolve_addresses((network).Handle(), uintptr(utf8), uint32(len(name)), returnArea) + var result witTypes.Result[*ResolveAddressStream, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*ResolveAddressStream, wasi_sockets_0_2_0_network.ErrorCode](ResolveAddressStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*ResolveAddressStream, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.resolve-next-address +func wasm_import_method_resolve_address_stream_resolve_next_address(arg0 int32, arg1 uintptr) + +func (self *ResolveAddressStream) ResolveNextAddress() witTypes.Result[witTypes.Option[wasi_sockets_0_2_0_network.IpAddress], wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 22, 2)) + wasm_import_method_resolve_address_stream_resolve_next_address((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Option[wasi_sockets_0_2_0_network.IpAddress], wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var option witTypes.Option[wasi_sockets_0_2_0_network.IpAddress] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 2))) { + case 0: + + option = witTypes.None[wasi_sockets_0_2_0_network.IpAddress]() + case 1: + var variant wasi_sockets_0_2_0_network.IpAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpAddressIpv4(witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 6)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 7)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 9))))}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpAddressIpv6(witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 6)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 10)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 14)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 18)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 20))))}) + + default: + panic("unreachable") + } + + option = witTypes.Some[wasi_sockets_0_2_0_network.IpAddress](variant) + default: + panic("unreachable") + } + + result = witTypes.Ok[witTypes.Option[wasi_sockets_0_2_0_network.IpAddress], wasi_sockets_0_2_0_network.ErrorCode](option) + case 1: + + result = witTypes.Err[witTypes.Option[wasi_sockets_0_2_0_network.IpAddress], wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 2))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.subscribe +func wasm_import_method_resolve_address_stream_subscribe(arg0 int32) int32 + +func (self *ResolveAddressStream) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_resolve_address_stream_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_sockets_0_2_0_network/wit_bindings.go b/internal/wasi_sockets_0_2_0_network/wit_bindings.go new file mode 100644 index 00000000..16c7a9f6 --- /dev/null +++ b/internal/wasi_sockets_0_2_0_network/wit_bindings.go @@ -0,0 +1,258 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_network + +import ( + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" +) + +//go:wasmimport wasi:sockets/network@0.2.0 [resource-drop]network +func resourceDropNetwork(handle int32) + +// 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. +type Network struct { + handle *witRuntime.Handle +} + +func (self *Network) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *Network) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *Network) Handle() int32 { + return self.handle.Use() +} + +func (self *Network) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropNetwork(handle) + } +} + +func NetworkFromOwnHandle(handleValue int32) *Network { + handle := witRuntime.MakeHandle(handleValue) + value := &Network{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropNetwork(handleValue) + } + }, 0) + return value +} + +func NetworkFromBorrowHandle(handleValue int32) *Network { + handle := witRuntime.MakeHandle(handleValue) + return &Network{handle} +} + +const ( + // Unknown error + ErrorCodeUnknown uint8 = 0 + // Access denied. + // + // POSIX equivalent: EACCES, EPERM + ErrorCodeAccessDenied uint8 = 1 + // The operation is not supported. + // + // POSIX equivalent: EOPNOTSUPP + ErrorCodeNotSupported uint8 = 2 + // One of the arguments is invalid. + // + // POSIX equivalent: EINVAL + ErrorCodeInvalidArgument uint8 = 3 + // Not enough memory to complete the operation. + // + // POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY + ErrorCodeOutOfMemory uint8 = 4 + // The operation timed out before it could finish completely. + ErrorCodeTimeout uint8 = 5 + // This operation is incompatible with another asynchronous operation that is already in progress. + // + // POSIX equivalent: EALREADY + ErrorCodeConcurrencyConflict uint8 = 6 + // 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. + ErrorCodeNotInProgress uint8 = 7 + // 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. + ErrorCodeWouldBlock uint8 = 8 + // The operation is not valid in the socket's current state. + ErrorCodeInvalidState uint8 = 9 + // A new socket resource could not be created because of a system limit. + ErrorCodeNewSocketLimit uint8 = 10 + // A bind operation failed because the provided address is not an address that the `network` can bind to. + ErrorCodeAddressNotBindable uint8 = 11 + // A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. + ErrorCodeAddressInUse uint8 = 12 + // The remote address is not reachable + ErrorCodeRemoteUnreachable uint8 = 13 + // The TCP connection was forcefully rejected + ErrorCodeConnectionRefused uint8 = 14 + // The TCP connection was reset. + ErrorCodeConnectionReset uint8 = 15 + // A TCP connection was aborted. + ErrorCodeConnectionAborted uint8 = 16 + // The size of a datagram sent to a UDP socket exceeded the maximum + // supported size. + ErrorCodeDatagramTooLarge uint8 = 17 + // Name does not exist or has no suitable associated IP addresses. + ErrorCodeNameUnresolvable uint8 = 18 + // A temporary failure in name resolution occurred. + ErrorCodeTemporaryResolverFailure uint8 = 19 + // A permanent failure in name resolution occurred. + ErrorCodePermanentResolverFailure uint8 = 20 +) + +// 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. +type ErrorCode = uint8 + +const ( + // Similar to `AF_INET` in POSIX. + IpAddressFamilyIpv4 uint8 = 0 + // Similar to `AF_INET6` in POSIX. + IpAddressFamilyIpv6 uint8 = 1 +) + +type IpAddressFamily = uint8 +type Ipv4Address = witTypes.Tuple4[uint8, uint8, uint8, uint8] +type Ipv6Address = witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16] + +const ( + IpAddressIpv4 uint8 = 0 + IpAddressIpv6 uint8 = 1 +) + +type IpAddress struct { + tag uint8 + value any +} + +func (self IpAddress) Tag() uint8 { + return self.tag +} + +func (self IpAddress) Ipv4() witTypes.Tuple4[uint8, uint8, uint8, uint8] { + if self.tag != IpAddressIpv4 { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple4[uint8, uint8, uint8, uint8]) +} +func (self IpAddress) Ipv6() witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16] { + if self.tag != IpAddressIpv6 { + panic("tag mismatch") + } + return self.value.(witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]) +} + +func MakeIpAddressIpv4(value witTypes.Tuple4[uint8, uint8, uint8, uint8]) IpAddress { + return IpAddress{IpAddressIpv4, value} +} +func MakeIpAddressIpv6(value witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]) IpAddress { + return IpAddress{IpAddressIpv6, value} +} + +type Ipv4SocketAddress struct { + // sin_port + Port uint16 + // sin_addr + Address witTypes.Tuple4[uint8, uint8, uint8, uint8] +} + +type Ipv6SocketAddress struct { + // sin6_port + Port uint16 + // sin6_flowinfo + FlowInfo uint32 + // sin6_addr + Address witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16] + // sin6_scope_id + ScopeId uint32 +} + +const ( + IpSocketAddressIpv4 uint8 = 0 + IpSocketAddressIpv6 uint8 = 1 +) + +type IpSocketAddress struct { + tag uint8 + value any +} + +func (self IpSocketAddress) Tag() uint8 { + return self.tag +} + +func (self IpSocketAddress) Ipv4() Ipv4SocketAddress { + if self.tag != IpSocketAddressIpv4 { + panic("tag mismatch") + } + return self.value.(Ipv4SocketAddress) +} +func (self IpSocketAddress) Ipv6() Ipv6SocketAddress { + if self.tag != IpSocketAddressIpv6 { + panic("tag mismatch") + } + return self.value.(Ipv6SocketAddress) +} + +func MakeIpSocketAddressIpv4(value Ipv4SocketAddress) IpSocketAddress { + return IpSocketAddress{IpSocketAddressIpv4, value} +} +func MakeIpSocketAddressIpv6(value Ipv6SocketAddress) IpSocketAddress { + return IpSocketAddress{IpSocketAddressIpv6, value} +} diff --git a/internal/wasi_sockets_0_2_0_tcp/wit_bindings.go b/internal/wasi_sockets_0_2_0_tcp/wit_bindings.go new file mode 100644 index 00000000..90726c9d --- /dev/null +++ b/internal/wasi_sockets_0_2_0_tcp/wit_bindings.go @@ -0,0 +1,910 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_tcp + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_streams" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type InputStream = wasi_io_0_2_0_streams.InputStream +type OutputStream = wasi_io_0_2_0_streams.OutputStream +type Pollable = wasi_io_0_2_0_poll.Pollable +type Duration = uint64 +type Network = wasi_sockets_0_2_0_network.Network +type ErrorCode = wasi_sockets_0_2_0_network.ErrorCode +type IpSocketAddress = wasi_sockets_0_2_0_network.IpSocketAddress +type IpAddressFamily = wasi_sockets_0_2_0_network.IpAddressFamily + +const ( + // Similar to `SHUT_RD` in POSIX. + ShutdownTypeReceive uint8 = 0 + // Similar to `SHUT_WR` in POSIX. + ShutdownTypeSend uint8 = 1 + // Similar to `SHUT_RDWR` in POSIX. + ShutdownTypeBoth uint8 = 2 +) + +type ShutdownType = uint8 + +//go:wasmimport wasi:sockets/tcp@0.2.0 [resource-drop]tcp-socket +func resourceDropTcpSocket(handle int32) + +// 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 a 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. +type TcpSocket struct { + handle *witRuntime.Handle +} + +func (self *TcpSocket) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *TcpSocket) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *TcpSocket) Handle() int32 { + return self.handle.Use() +} + +func (self *TcpSocket) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropTcpSocket(handle) + } +} + +func TcpSocketFromOwnHandle(handleValue int32) *TcpSocket { + handle := witRuntime.MakeHandle(handleValue) + value := &TcpSocket{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropTcpSocket(handleValue) + } + }, 0) + return value +} + +func TcpSocketFromBorrowHandle(handleValue int32) *TcpSocket { + handle := witRuntime.MakeHandle(handleValue) + return &TcpSocket{handle} +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-bind +func wasm_import_method_tcp_socket_start_bind(arg0 int32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 int32, arg6 int32, arg7 int32, arg8 int32, arg9 int32, arg10 int32, arg11 int32, arg12 int32, arg13 int32, arg14 uintptr) + +func (self *TcpSocket) StartBind(network *wasi_sockets_0_2_0_network.Network, localAddress wasi_sockets_0_2_0_network.IpSocketAddress) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + var variant int32 + var variant0 int32 + var variant1 int32 + var variant2 int32 + var variant3 int32 + var variant4 int32 + var variant5 int32 + var variant6 int32 + var variant7 int32 + var variant8 int32 + var variant9 int32 + var variant10 int32 + switch localAddress.Tag() { + case wasi_sockets_0_2_0_network.IpSocketAddressIpv4: + payload := localAddress.Ipv4() + + variant = int32(0) + variant0 = int32((payload).Port) + variant1 = int32(((payload).Address).F0) + variant2 = int32(((payload).Address).F1) + variant3 = int32(((payload).Address).F2) + variant4 = int32(((payload).Address).F3) + variant5 = 0 + variant6 = 0 + variant7 = 0 + variant8 = 0 + variant9 = 0 + variant10 = 0 + + case wasi_sockets_0_2_0_network.IpSocketAddressIpv6: + payload := localAddress.Ipv6() + + variant = int32(1) + variant0 = int32((payload).Port) + variant1 = int32((payload).FlowInfo) + variant2 = int32(((payload).Address).F0) + variant3 = int32(((payload).Address).F1) + variant4 = int32(((payload).Address).F2) + variant5 = int32(((payload).Address).F3) + variant6 = int32(((payload).Address).F4) + variant7 = int32(((payload).Address).F5) + variant8 = int32(((payload).Address).F6) + variant9 = int32(((payload).Address).F7) + variant10 = int32((payload).ScopeId) + + default: + panic("unreachable") + } + wasm_import_method_tcp_socket_start_bind((self).Handle(), (network).Handle(), variant, variant0, variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, variant9, variant10, returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result11 := result + return result11 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-bind +func wasm_import_method_tcp_socket_finish_bind(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) FinishBind() witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_finish_bind((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-connect +func wasm_import_method_tcp_socket_start_connect(arg0 int32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 int32, arg6 int32, arg7 int32, arg8 int32, arg9 int32, arg10 int32, arg11 int32, arg12 int32, arg13 int32, arg14 uintptr) + +func (self *TcpSocket) StartConnect(network *wasi_sockets_0_2_0_network.Network, remoteAddress wasi_sockets_0_2_0_network.IpSocketAddress) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + var variant int32 + var variant0 int32 + var variant1 int32 + var variant2 int32 + var variant3 int32 + var variant4 int32 + var variant5 int32 + var variant6 int32 + var variant7 int32 + var variant8 int32 + var variant9 int32 + var variant10 int32 + switch remoteAddress.Tag() { + case wasi_sockets_0_2_0_network.IpSocketAddressIpv4: + payload := remoteAddress.Ipv4() + + variant = int32(0) + variant0 = int32((payload).Port) + variant1 = int32(((payload).Address).F0) + variant2 = int32(((payload).Address).F1) + variant3 = int32(((payload).Address).F2) + variant4 = int32(((payload).Address).F3) + variant5 = 0 + variant6 = 0 + variant7 = 0 + variant8 = 0 + variant9 = 0 + variant10 = 0 + + case wasi_sockets_0_2_0_network.IpSocketAddressIpv6: + payload := remoteAddress.Ipv6() + + variant = int32(1) + variant0 = int32((payload).Port) + variant1 = int32((payload).FlowInfo) + variant2 = int32(((payload).Address).F0) + variant3 = int32(((payload).Address).F1) + variant4 = int32(((payload).Address).F2) + variant5 = int32(((payload).Address).F3) + variant6 = int32(((payload).Address).F4) + variant7 = int32(((payload).Address).F5) + variant8 = int32(((payload).Address).F6) + variant9 = int32(((payload).Address).F7) + variant10 = int32((payload).ScopeId) + + default: + panic("unreachable") + } + wasm_import_method_tcp_socket_start_connect((self).Handle(), (network).Handle(), variant, variant0, variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, variant9, variant10, returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result11 := result + return result11 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-connect +func wasm_import_method_tcp_socket_finish_connect(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) FinishConnect() witTypes.Result[witTypes.Tuple2[*wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + wasm_import_method_tcp_socket_finish_connect((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Tuple2[*wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Tuple2[*wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode](witTypes.Tuple2[*wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream]{wasi_io_0_2_0_streams.InputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))}) + case 1: + + result = witTypes.Err[witTypes.Tuple2[*wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-listen +func wasm_import_method_tcp_socket_start_listen(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) StartListen() witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_start_listen((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-listen +func wasm_import_method_tcp_socket_finish_listen(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) FinishListen() witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_finish_listen((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.accept +func wasm_import_method_tcp_socket_accept(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) Accept() witTypes.Result[witTypes.Tuple3[*TcpSocket, *wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 4)) + wasm_import_method_tcp_socket_accept((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Tuple3[*TcpSocket, *wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Tuple3[*TcpSocket, *wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode](witTypes.Tuple3[*TcpSocket, *wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream]{TcpSocketFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), wasi_io_0_2_0_streams.InputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))), wasi_io_0_2_0_streams.OutputStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))))}) + case 1: + + result = witTypes.Err[witTypes.Tuple3[*TcpSocket, *wasi_io_0_2_0_streams.InputStream, *wasi_io_0_2_0_streams.OutputStream], wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.local-address +func wasm_import_method_tcp_socket_local_address(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) LocalAddress() witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 36, 4)) + wasm_import_method_tcp_socket_local_address((self).Handle(), returnArea) + var result witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var variant wasi_sockets_0_2_0_network.IpSocketAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv4(wasi_sockets_0_2_0_network.Ipv4SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 10)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 11)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 13))))}}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv6(wasi_sockets_0_2_0_network.Ipv6SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12))), witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 18)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 22)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 26)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 28)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 30))))}, uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 32)))}) + + default: + panic("unreachable") + } + + result = witTypes.Ok[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](variant) + case 1: + + result = witTypes.Err[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.remote-address +func wasm_import_method_tcp_socket_remote_address(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) RemoteAddress() witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 36, 4)) + wasm_import_method_tcp_socket_remote_address((self).Handle(), returnArea) + var result witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var variant wasi_sockets_0_2_0_network.IpSocketAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv4(wasi_sockets_0_2_0_network.Ipv4SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 10)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 11)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 13))))}}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv6(wasi_sockets_0_2_0_network.Ipv6SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12))), witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 18)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 22)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 26)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 28)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 30))))}, uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 32)))}) + + default: + panic("unreachable") + } + + result = witTypes.Ok[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](variant) + case 1: + + result = witTypes.Err[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.is-listening +func wasm_import_method_tcp_socket_is_listening(arg0 int32) int32 + +func (self *TcpSocket) IsListening() bool { + + result := wasm_import_method_tcp_socket_is_listening((self).Handle()) + return (result != 0) + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.address-family +func wasm_import_method_tcp_socket_address_family(arg0 int32) int32 + +func (self *TcpSocket) AddressFamily() wasi_sockets_0_2_0_network.IpAddressFamily { + + result := wasm_import_method_tcp_socket_address_family((self).Handle()) + return uint8(result) + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-listen-backlog-size +func wasm_import_method_tcp_socket_set_listen_backlog_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *TcpSocket) SetListenBacklogSize(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_listen_backlog_size((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-enabled +func wasm_import_method_tcp_socket_keep_alive_enabled(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) KeepAliveEnabled() witTypes.Result[bool, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_keep_alive_enabled((self).Handle(), returnArea) + var result witTypes.Result[bool, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[bool, wasi_sockets_0_2_0_network.ErrorCode]((uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))) != 0)) + case 1: + + result = witTypes.Err[bool, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-enabled +func wasm_import_method_tcp_socket_set_keep_alive_enabled(arg0 int32, arg1 int32, arg2 uintptr) + +func (self *TcpSocket) SetKeepAliveEnabled(value bool) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + var result int32 + if value { + result = 1 + } else { + result = 0 + } + wasm_import_method_tcp_socket_set_keep_alive_enabled((self).Handle(), result, returnArea) + var result0 witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result0 = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-idle-time +func wasm_import_method_tcp_socket_keep_alive_idle_time(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) KeepAliveIdleTime() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_tcp_socket_keep_alive_idle_time((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-idle-time +func wasm_import_method_tcp_socket_set_keep_alive_idle_time(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *TcpSocket) SetKeepAliveIdleTime(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_keep_alive_idle_time((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-interval +func wasm_import_method_tcp_socket_keep_alive_interval(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) KeepAliveInterval() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_tcp_socket_keep_alive_interval((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-interval +func wasm_import_method_tcp_socket_set_keep_alive_interval(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *TcpSocket) SetKeepAliveInterval(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_keep_alive_interval((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-count +func wasm_import_method_tcp_socket_keep_alive_count(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) KeepAliveCount() witTypes.Result[uint32, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_method_tcp_socket_keep_alive_count((self).Handle(), returnArea) + var result witTypes.Result[uint32, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint32, wasi_sockets_0_2_0_network.ErrorCode](uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))) + case 1: + + result = witTypes.Err[uint32, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-count +func wasm_import_method_tcp_socket_set_keep_alive_count(arg0 int32, arg1 int32, arg2 uintptr) + +func (self *TcpSocket) SetKeepAliveCount(value uint32) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_keep_alive_count((self).Handle(), int32(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.hop-limit +func wasm_import_method_tcp_socket_hop_limit(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) HopLimit() witTypes.Result[uint8, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_hop_limit((self).Handle(), returnArea) + var result witTypes.Result[uint8, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint8, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + case 1: + + result = witTypes.Err[uint8, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-hop-limit +func wasm_import_method_tcp_socket_set_hop_limit(arg0 int32, arg1 int32, arg2 uintptr) + +func (self *TcpSocket) SetHopLimit(value uint8) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_hop_limit((self).Handle(), int32(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.receive-buffer-size +func wasm_import_method_tcp_socket_receive_buffer_size(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) ReceiveBufferSize() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_tcp_socket_receive_buffer_size((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-receive-buffer-size +func wasm_import_method_tcp_socket_set_receive_buffer_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *TcpSocket) SetReceiveBufferSize(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_receive_buffer_size((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.send-buffer-size +func wasm_import_method_tcp_socket_send_buffer_size(arg0 int32, arg1 uintptr) + +func (self *TcpSocket) SendBufferSize() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_tcp_socket_send_buffer_size((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-send-buffer-size +func wasm_import_method_tcp_socket_set_send_buffer_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *TcpSocket) SetSendBufferSize(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_set_send_buffer_size((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.subscribe +func wasm_import_method_tcp_socket_subscribe(arg0 int32) int32 + +func (self *TcpSocket) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_tcp_socket_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.shutdown +func wasm_import_method_tcp_socket_shutdown(arg0 int32, arg1 int32, arg2 uintptr) + +func (self *TcpSocket) Shutdown(shutdownType ShutdownType) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_tcp_socket_shutdown((self).Handle(), int32(shutdownType), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} diff --git a/internal/wasi_sockets_0_2_0_tcp_create_socket/wit_bindings.go b/internal/wasi_sockets_0_2_0_tcp_create_socket/wit_bindings.go new file mode 100644 index 00000000..b43187f3 --- /dev/null +++ b/internal/wasi_sockets_0_2_0_tcp_create_socket/wit_bindings.go @@ -0,0 +1,72 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_tcp_create_socket + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_tcp" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Network = wasi_sockets_0_2_0_network.Network +type ErrorCode = wasi_sockets_0_2_0_network.ErrorCode +type IpAddressFamily = wasi_sockets_0_2_0_network.IpAddressFamily +type TcpSocket = wasi_sockets_0_2_0_tcp.TcpSocket + +//go:wasmimport wasi:sockets/tcp-create-socket@0.2.0 create-tcp-socket +func wasm_import_create_tcp_socket(arg0 int32, arg1 uintptr) + +func CreateTcpSocket(addressFamily wasi_sockets_0_2_0_network.IpAddressFamily) witTypes.Result[*wasi_sockets_0_2_0_tcp.TcpSocket, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_create_tcp_socket(int32(addressFamily), returnArea) + var result witTypes.Result[*wasi_sockets_0_2_0_tcp.TcpSocket, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_sockets_0_2_0_tcp.TcpSocket, wasi_sockets_0_2_0_network.ErrorCode](wasi_sockets_0_2_0_tcp.TcpSocketFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_sockets_0_2_0_tcp.TcpSocket, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} diff --git a/internal/wasi_sockets_0_2_0_udp/wit_bindings.go b/internal/wasi_sockets_0_2_0_udp/wit_bindings.go new file mode 100644 index 00000000..4bf25e6e --- /dev/null +++ b/internal/wasi_sockets_0_2_0_udp/wit_bindings.go @@ -0,0 +1,839 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_udp + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_io_0_2_0_poll" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Pollable = wasi_io_0_2_0_poll.Pollable +type Network = wasi_sockets_0_2_0_network.Network +type ErrorCode = wasi_sockets_0_2_0_network.ErrorCode +type IpSocketAddress = wasi_sockets_0_2_0_network.IpSocketAddress +type IpAddressFamily = wasi_sockets_0_2_0_network.IpAddressFamily + +// A received datagram. +type IncomingDatagram struct { + // The payload. + // + // Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + Data []uint8 + // 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`. + RemoteAddress wasi_sockets_0_2_0_network.IpSocketAddress +} + +// A datagram to be sent out. +type OutgoingDatagram struct { + // The payload. + Data []uint8 + // 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`. + RemoteAddress witTypes.Option[wasi_sockets_0_2_0_network.IpSocketAddress] +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]udp-socket +func resourceDropUdpSocket(handle int32) + +// A UDP socket handle. +type UdpSocket struct { + handle *witRuntime.Handle +} + +func (self *UdpSocket) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *UdpSocket) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *UdpSocket) Handle() int32 { + return self.handle.Use() +} + +func (self *UdpSocket) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropUdpSocket(handle) + } +} + +func UdpSocketFromOwnHandle(handleValue int32) *UdpSocket { + handle := witRuntime.MakeHandle(handleValue) + value := &UdpSocket{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropUdpSocket(handleValue) + } + }, 0) + return value +} + +func UdpSocketFromBorrowHandle(handleValue int32) *UdpSocket { + handle := witRuntime.MakeHandle(handleValue) + return &UdpSocket{handle} +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]incoming-datagram-stream +func resourceDropIncomingDatagramStream(handle int32) + +type IncomingDatagramStream struct { + handle *witRuntime.Handle +} + +func (self *IncomingDatagramStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *IncomingDatagramStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *IncomingDatagramStream) Handle() int32 { + return self.handle.Use() +} + +func (self *IncomingDatagramStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropIncomingDatagramStream(handle) + } +} + +func IncomingDatagramStreamFromOwnHandle(handleValue int32) *IncomingDatagramStream { + handle := witRuntime.MakeHandle(handleValue) + value := &IncomingDatagramStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropIncomingDatagramStream(handleValue) + } + }, 0) + return value +} + +func IncomingDatagramStreamFromBorrowHandle(handleValue int32) *IncomingDatagramStream { + handle := witRuntime.MakeHandle(handleValue) + return &IncomingDatagramStream{handle} +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]outgoing-datagram-stream +func resourceDropOutgoingDatagramStream(handle int32) + +type OutgoingDatagramStream struct { + handle *witRuntime.Handle +} + +func (self *OutgoingDatagramStream) TakeHandle() int32 { + return self.handle.Take() +} + +func (self *OutgoingDatagramStream) SetHandle(handle int32) { + self.handle.Set(handle) +} + +func (self *OutgoingDatagramStream) Handle() int32 { + return self.handle.Use() +} + +func (self *OutgoingDatagramStream) Drop() { + handle := self.handle.TakeOrNil() + if handle != 0 { + resourceDropOutgoingDatagramStream(handle) + } +} + +func OutgoingDatagramStreamFromOwnHandle(handleValue int32) *OutgoingDatagramStream { + handle := witRuntime.MakeHandle(handleValue) + value := &OutgoingDatagramStream{handle} + runtime.AddCleanup(value, func(_ int) { + handleValue := handle.TakeOrNil() + if handleValue != 0 { + resourceDropOutgoingDatagramStream(handleValue) + } + }, 0) + return value +} + +func OutgoingDatagramStreamFromBorrowHandle(handleValue int32) *OutgoingDatagramStream { + handle := witRuntime.MakeHandle(handleValue) + return &OutgoingDatagramStream{handle} +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.start-bind +func wasm_import_method_udp_socket_start_bind(arg0 int32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 int32, arg6 int32, arg7 int32, arg8 int32, arg9 int32, arg10 int32, arg11 int32, arg12 int32, arg13 int32, arg14 uintptr) + +func (self *UdpSocket) StartBind(network *wasi_sockets_0_2_0_network.Network, localAddress wasi_sockets_0_2_0_network.IpSocketAddress) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + var variant int32 + var variant0 int32 + var variant1 int32 + var variant2 int32 + var variant3 int32 + var variant4 int32 + var variant5 int32 + var variant6 int32 + var variant7 int32 + var variant8 int32 + var variant9 int32 + var variant10 int32 + switch localAddress.Tag() { + case wasi_sockets_0_2_0_network.IpSocketAddressIpv4: + payload := localAddress.Ipv4() + + variant = int32(0) + variant0 = int32((payload).Port) + variant1 = int32(((payload).Address).F0) + variant2 = int32(((payload).Address).F1) + variant3 = int32(((payload).Address).F2) + variant4 = int32(((payload).Address).F3) + variant5 = 0 + variant6 = 0 + variant7 = 0 + variant8 = 0 + variant9 = 0 + variant10 = 0 + + case wasi_sockets_0_2_0_network.IpSocketAddressIpv6: + payload := localAddress.Ipv6() + + variant = int32(1) + variant0 = int32((payload).Port) + variant1 = int32((payload).FlowInfo) + variant2 = int32(((payload).Address).F0) + variant3 = int32(((payload).Address).F1) + variant4 = int32(((payload).Address).F2) + variant5 = int32(((payload).Address).F3) + variant6 = int32(((payload).Address).F4) + variant7 = int32(((payload).Address).F5) + variant8 = int32(((payload).Address).F6) + variant9 = int32(((payload).Address).F7) + variant10 = int32((payload).ScopeId) + + default: + panic("unreachable") + } + wasm_import_method_udp_socket_start_bind((self).Handle(), (network).Handle(), variant, variant0, variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, variant9, variant10, returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result11 := result + return result11 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.finish-bind +func wasm_import_method_udp_socket_finish_bind(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) FinishBind() witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_udp_socket_finish_bind((self).Handle(), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.stream +func wasm_import_method_udp_socket_stream(arg0 int32, arg1 int32, arg2 int32, arg3 int32, arg4 int32, arg5 int32, arg6 int32, arg7 int32, arg8 int32, arg9 int32, arg10 int32, arg11 int32, arg12 int32, arg13 int32, arg14 uintptr) + +func (self *UdpSocket) Stream(remoteAddress witTypes.Option[wasi_sockets_0_2_0_network.IpSocketAddress]) witTypes.Result[witTypes.Tuple2[*IncomingDatagramStream, *OutgoingDatagramStream], wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 12, 4)) + var option int32 + var option11 int32 + var option12 int32 + var option13 int32 + var option14 int32 + var option15 int32 + var option16 int32 + var option17 int32 + var option18 int32 + var option19 int32 + var option20 int32 + var option21 int32 + var option22 int32 + switch remoteAddress.Tag() { + case witTypes.OptionNone: + + option = int32(0) + option11 = 0 + option12 = 0 + option13 = 0 + option14 = 0 + option15 = 0 + option16 = 0 + option17 = 0 + option18 = 0 + option19 = 0 + option20 = 0 + option21 = 0 + option22 = 0 + case witTypes.OptionSome: + payload := remoteAddress.Some() + var variant int32 + var variant0 int32 + var variant1 int32 + var variant2 int32 + var variant3 int32 + var variant4 int32 + var variant5 int32 + var variant6 int32 + var variant7 int32 + var variant8 int32 + var variant9 int32 + var variant10 int32 + switch payload.Tag() { + case wasi_sockets_0_2_0_network.IpSocketAddressIpv4: + payload := payload.Ipv4() + + variant = int32(0) + variant0 = int32((payload).Port) + variant1 = int32(((payload).Address).F0) + variant2 = int32(((payload).Address).F1) + variant3 = int32(((payload).Address).F2) + variant4 = int32(((payload).Address).F3) + variant5 = 0 + variant6 = 0 + variant7 = 0 + variant8 = 0 + variant9 = 0 + variant10 = 0 + + case wasi_sockets_0_2_0_network.IpSocketAddressIpv6: + payload := payload.Ipv6() + + variant = int32(1) + variant0 = int32((payload).Port) + variant1 = int32((payload).FlowInfo) + variant2 = int32(((payload).Address).F0) + variant3 = int32(((payload).Address).F1) + variant4 = int32(((payload).Address).F2) + variant5 = int32(((payload).Address).F3) + variant6 = int32(((payload).Address).F4) + variant7 = int32(((payload).Address).F5) + variant8 = int32(((payload).Address).F6) + variant9 = int32(((payload).Address).F7) + variant10 = int32((payload).ScopeId) + + default: + panic("unreachable") + } + + option = int32(1) + option11 = variant + option12 = variant0 + option13 = variant1 + option14 = variant2 + option15 = variant3 + option16 = variant4 + option17 = variant5 + option18 = variant6 + option19 = variant7 + option20 = variant8 + option21 = variant9 + option22 = variant10 + default: + panic("unreachable") + } + wasm_import_method_udp_socket_stream((self).Handle(), option, option11, option12, option13, option14, option15, option16, option17, option18, option19, option20, option21, option22, returnArea) + var result witTypes.Result[witTypes.Tuple2[*IncomingDatagramStream, *OutgoingDatagramStream], wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Tuple2[*IncomingDatagramStream, *OutgoingDatagramStream], wasi_sockets_0_2_0_network.ErrorCode](witTypes.Tuple2[*IncomingDatagramStream, *OutgoingDatagramStream]{IncomingDatagramStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))), OutgoingDatagramStreamFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))))}) + case 1: + + result = witTypes.Err[witTypes.Tuple2[*IncomingDatagramStream, *OutgoingDatagramStream], wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result23 := result + return result23 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.local-address +func wasm_import_method_udp_socket_local_address(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) LocalAddress() witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 36, 4)) + wasm_import_method_udp_socket_local_address((self).Handle(), returnArea) + var result witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var variant wasi_sockets_0_2_0_network.IpSocketAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv4(wasi_sockets_0_2_0_network.Ipv4SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 10)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 11)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 13))))}}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv6(wasi_sockets_0_2_0_network.Ipv6SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12))), witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 18)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 22)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 26)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 28)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 30))))}, uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 32)))}) + + default: + panic("unreachable") + } + + result = witTypes.Ok[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](variant) + case 1: + + result = witTypes.Err[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.remote-address +func wasm_import_method_udp_socket_remote_address(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) RemoteAddress() witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 36, 4)) + wasm_import_method_udp_socket_remote_address((self).Handle(), returnArea) + var result witTypes.Result[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + var variant wasi_sockets_0_2_0_network.IpSocketAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv4(wasi_sockets_0_2_0_network.Ipv4SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 10)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 11)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 12)))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 13))))}}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv6(wasi_sockets_0_2_0_network.Ipv6SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8)))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 12))), witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 16)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 18)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 20)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 22)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 24)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 26)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 28)))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 30))))}, uint32(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 32)))}) + + default: + panic("unreachable") + } + + result = witTypes.Ok[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](variant) + case 1: + + result = witTypes.Err[wasi_sockets_0_2_0_network.IpSocketAddress, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.address-family +func wasm_import_method_udp_socket_address_family(arg0 int32) int32 + +func (self *UdpSocket) AddressFamily() wasi_sockets_0_2_0_network.IpAddressFamily { + + result := wasm_import_method_udp_socket_address_family((self).Handle()) + return uint8(result) + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.unicast-hop-limit +func wasm_import_method_udp_socket_unicast_hop_limit(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) UnicastHopLimit() witTypes.Result[uint8, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_udp_socket_unicast_hop_limit((self).Handle(), returnArea) + var result witTypes.Result[uint8, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint8, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + case 1: + + result = witTypes.Err[uint8, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-unicast-hop-limit +func wasm_import_method_udp_socket_set_unicast_hop_limit(arg0 int32, arg1 int32, arg2 uintptr) + +func (self *UdpSocket) SetUnicastHopLimit(value uint8) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_udp_socket_set_unicast_hop_limit((self).Handle(), int32(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.receive-buffer-size +func wasm_import_method_udp_socket_receive_buffer_size(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) ReceiveBufferSize() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_udp_socket_receive_buffer_size((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-receive-buffer-size +func wasm_import_method_udp_socket_set_receive_buffer_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *UdpSocket) SetReceiveBufferSize(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_udp_socket_set_receive_buffer_size((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.send-buffer-size +func wasm_import_method_udp_socket_send_buffer_size(arg0 int32, arg1 uintptr) + +func (self *UdpSocket) SendBufferSize() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_udp_socket_send_buffer_size((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-send-buffer-size +func wasm_import_method_udp_socket_set_send_buffer_size(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *UdpSocket) SetSendBufferSize(value uint64) witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 2, 1)) + wasm_import_method_udp_socket_set_send_buffer_size((self).Handle(), int64(value), returnArea) + var result witTypes.Result[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](witTypes.Unit{}) + case 1: + + result = witTypes.Err[witTypes.Unit, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 1))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.subscribe +func wasm_import_method_udp_socket_subscribe(arg0 int32) int32 + +func (self *UdpSocket) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_udp_socket_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.receive +func wasm_import_method_incoming_datagram_stream_receive(arg0 int32, arg1 int64, arg2 uintptr) + +func (self *IncomingDatagramStream) Receive(maxResults uint64) witTypes.Result[[]IncomingDatagram, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, (3 * 4), 4)) + wasm_import_method_incoming_datagram_stream_receive((self).Handle(), int64(maxResults), returnArea) + var result0 witTypes.Result[[]IncomingDatagram, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + result := make([]IncomingDatagram, 0, *(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))) + for index := 0; index < int(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), (2 * 4)))); index++ { + base := unsafe.Add(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))), index*(32+2*4)) + value := unsafe.Slice((*uint8)(unsafe.Pointer(uintptr(*(*uint32)(unsafe.Add(unsafe.Pointer(base), 0))))), *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4))) + var variant wasi_sockets_0_2_0_network.IpSocketAddress + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (2 * 4)))) { + case 0: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv4(wasi_sockets_0_2_0_network.Ipv4SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (4 + 2*4))))), witTypes.Tuple4[uint8, uint8, uint8, uint8]{uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (6 + 2*4))))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (7 + 2*4))))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (8 + 2*4))))), uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (9 + 2*4)))))}}) + + case 1: + + variant = wasi_sockets_0_2_0_network.MakeIpSocketAddressIpv6(wasi_sockets_0_2_0_network.Ipv6SocketAddress{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (4 + 2*4))))), uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), (8 + 2*4)))), witTypes.Tuple8[uint16, uint16, uint16, uint16, uint16, uint16, uint16, uint16]{uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (12 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (14 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (16 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (18 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (20 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (22 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (24 + 2*4))))), uint16(uint16(*(*uint32)(unsafe.Add(unsafe.Pointer(base), (26 + 2*4)))))}, uint32(*(*int32)(unsafe.Add(unsafe.Pointer(base), (28 + 2*4))))}) + + default: + panic("unreachable") + } + + result = append(result, IncomingDatagram{value, variant}) + } + + result0 = witTypes.Ok[[]IncomingDatagram, wasi_sockets_0_2_0_network.ErrorCode](result) + case 1: + + result0 = witTypes.Err[[]IncomingDatagram, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.subscribe +func wasm_import_method_incoming_datagram_stream_subscribe(arg0 int32) int32 + +func (self *IncomingDatagramStream) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_incoming_datagram_stream_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.check-send +func wasm_import_method_outgoing_datagram_stream_check_send(arg0 int32, arg1 uintptr) + +func (self *OutgoingDatagramStream) CheckSend() witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + wasm_import_method_outgoing_datagram_stream_check_send((self).Handle(), returnArea) + var result witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.send +func wasm_import_method_outgoing_datagram_stream_send(arg0 int32, arg1 uintptr, arg2 uint32, arg3 uintptr) + +func (self *OutgoingDatagramStream) Send(datagrams []OutgoingDatagram) witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 16, 8)) + slice := datagrams + length := uint32(len(slice)) + result := witRuntime.Allocate(pinner, uintptr(length*(32+3*4)), 4) + for index, element := range slice { + base := unsafe.Add(result, index*(32+3*4)) + data := unsafe.Pointer(unsafe.SliceData((element).Data)) + pinner.Pin(data) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 4)) = uint32(uint32(len((element).Data))) + *(*uint32)(unsafe.Add(unsafe.Pointer(base), 0)) = uint32(uintptr(uintptr(data))) + + switch (element).RemoteAddress.Tag() { + case witTypes.OptionNone: + *(*int8)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = int8(int32(0)) + + case witTypes.OptionSome: + payload := (element).RemoteAddress.Some() + *(*int8)(unsafe.Add(unsafe.Pointer(base), (2 * 4))) = int8(int32(1)) + + switch payload.Tag() { + case wasi_sockets_0_2_0_network.IpSocketAddressIpv4: + payload := payload.Ipv4() + *(*int8)(unsafe.Add(unsafe.Pointer(base), (4 + 2*4))) = int8(int32(0)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (8 + 2*4))) = int16(int32((payload).Port)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), (10 + 2*4))) = int8(int32(((payload).Address).F0)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), (11 + 2*4))) = int8(int32(((payload).Address).F1)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), (12 + 2*4))) = int8(int32(((payload).Address).F2)) + *(*int8)(unsafe.Add(unsafe.Pointer(base), (13 + 2*4))) = int8(int32(((payload).Address).F3)) + + case wasi_sockets_0_2_0_network.IpSocketAddressIpv6: + payload := payload.Ipv6() + *(*int8)(unsafe.Add(unsafe.Pointer(base), (4 + 2*4))) = int8(int32(1)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (8 + 2*4))) = int16(int32((payload).Port)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), (12 + 2*4))) = int32((payload).FlowInfo) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (16 + 2*4))) = int16(int32(((payload).Address).F0)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (18 + 2*4))) = int16(int32(((payload).Address).F1)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (20 + 2*4))) = int16(int32(((payload).Address).F2)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (22 + 2*4))) = int16(int32(((payload).Address).F3)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (24 + 2*4))) = int16(int32(((payload).Address).F4)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (26 + 2*4))) = int16(int32(((payload).Address).F5)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (28 + 2*4))) = int16(int32(((payload).Address).F6)) + *(*int16)(unsafe.Add(unsafe.Pointer(base), (30 + 2*4))) = int16(int32(((payload).Address).F7)) + *(*int32)(unsafe.Add(unsafe.Pointer(base), (32 + 2*4))) = int32((payload).ScopeId) + + default: + panic("unreachable") + } + + default: + panic("unreachable") + } + + } + + wasm_import_method_outgoing_datagram_stream_send((self).Handle(), uintptr(result), length, returnArea) + var result0 witTypes.Result[uint64, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result0 = witTypes.Ok[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint64(*(*int64)(unsafe.Add(unsafe.Pointer(returnArea), 8)))) + case 1: + + result0 = witTypes.Err[uint64, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 8))))) + default: + panic("unreachable") + } + result1 := result0 + return result1 + +} + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.subscribe +func wasm_import_method_outgoing_datagram_stream_subscribe(arg0 int32) int32 + +func (self *OutgoingDatagramStream) Subscribe() *wasi_io_0_2_0_poll.Pollable { + + result := wasm_import_method_outgoing_datagram_stream_subscribe((self).Handle()) + return wasi_io_0_2_0_poll.PollableFromOwnHandle(int32(uintptr(result))) + +} diff --git a/internal/wasi_sockets_0_2_0_udp_create_socket/wit_bindings.go b/internal/wasi_sockets_0_2_0_udp_create_socket/wit_bindings.go new file mode 100644 index 00000000..c33872c8 --- /dev/null +++ b/internal/wasi_sockets_0_2_0_udp_create_socket/wit_bindings.go @@ -0,0 +1,72 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wasi_sockets_0_2_0_udp_create_socket + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_network" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_sockets_0_2_0_udp" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +type Network = wasi_sockets_0_2_0_network.Network +type ErrorCode = wasi_sockets_0_2_0_network.ErrorCode +type IpAddressFamily = wasi_sockets_0_2_0_network.IpAddressFamily +type UdpSocket = wasi_sockets_0_2_0_udp.UdpSocket + +//go:wasmimport wasi:sockets/udp-create-socket@0.2.0 create-udp-socket +func wasm_import_create_udp_socket(arg0 int32, arg1 uintptr) + +func CreateUdpSocket(addressFamily wasi_sockets_0_2_0_network.IpAddressFamily) witTypes.Result[*wasi_sockets_0_2_0_udp.UdpSocket, wasi_sockets_0_2_0_network.ErrorCode] { + pinner := &runtime.Pinner{} + defer pinner.Unpin() + + returnArea := uintptr(witRuntime.Allocate(pinner, 8, 4)) + wasm_import_create_udp_socket(int32(addressFamily), returnArea) + var result witTypes.Result[*wasi_sockets_0_2_0_udp.UdpSocket, wasi_sockets_0_2_0_network.ErrorCode] + switch uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 0))) { + case 0: + + result = witTypes.Ok[*wasi_sockets_0_2_0_udp.UdpSocket, wasi_sockets_0_2_0_network.ErrorCode](wasi_sockets_0_2_0_udp.UdpSocketFromOwnHandle(int32(uintptr(*(*int32)(unsafe.Add(unsafe.Pointer(returnArea), 4)))))) + case 1: + + result = witTypes.Err[*wasi_sockets_0_2_0_udp.UdpSocket, wasi_sockets_0_2_0_network.ErrorCode](uint8(uint8(*(*uint32)(unsafe.Add(unsafe.Pointer(returnArea), 4))))) + default: + panic("unreachable") + } + result0 := result + return result0 + +} diff --git a/internal/wit_exports/wit_exports.go b/internal/wit_exports/wit_exports.go new file mode 100644 index 00000000..4b1b650d --- /dev/null +++ b/internal/wit_exports/wit_exports.go @@ -0,0 +1,78 @@ +// Generated by `wit-bindgen` 0.53.1. DO NOT EDIT! +// +// This code was generated from the following packages: +// fermyon:spin +// wasi:io@0.2.0 +// wasi:clocks@0.2.0 +// wasi:random@0.2.0 +// wasi:filesystem@0.2.0 +// wasi:sockets@0.2.0 +// wasi:cli@0.2.0 +// wasi:http@0.2.0 +// wasi:io@0.2.0-rc-2023-10-18 +// wasi:clocks@0.2.0-rc-2023-10-18 +// wasi:random@0.2.0-rc-2023-10-18 +// wasi:filesystem@0.2.0-rc-2023-10-18 +// wasi:sockets@0.2.0-rc-2023-10-18 +// wasi:cli@0.2.0-rc-2023-10-18 +// wasi:http@0.2.0-rc-2023-10-18 +// fermyon:spin@2.0.0 +// wasi:keyvalue@0.2.0-draft2 +// spin:postgres@3.0.0 +// wasi:config@0.2.0-draft-2024-09-27 +// fermyon:spin@3.0.0 +// wasi:io@0.2.0-rc-2023-11-10 +// wasi:clocks@0.2.0-rc-2023-11-10 +// wasi:filesystem@0.2.0-rc-2023-11-10 +// wasi:sockets@0.2.0-rc-2023-11-10 +// wasi:random@0.2.0-rc-2023-11-10 +// wasi:cli@0.2.0-rc-2023-11-10 +// wasi:http@0.2.0-rc-2023-11-10 +// componentize-go:union + +package wit_exports + +import ( + "github.com/spinframework/spin-go-sdk/v3/internal/export_fermyon_spin_inbound_redis" + "github.com/spinframework/spin-go-sdk/v3/internal/export_wasi_http_0_2_0_incoming_handler" + "github.com/spinframework/spin-go-sdk/v3/internal/wasi_http_0_2_0_types" + witRuntime "go.bytecodealliance.org/pkg/wit/runtime" + witTypes "go.bytecodealliance.org/pkg/wit/types" + "runtime" + "unsafe" +) + +var staticPinner = runtime.Pinner{} +var exportReturnArea = uintptr(witRuntime.Allocate(&staticPinner, 2, 1)) +var syncExportPinner = runtime.Pinner{} + +//go:wasmexport wasi:http/incoming-handler@0.2.0#handle +func wasm_export_wasi_http_0_2_0_incoming_handler_handle(arg0 int32, arg1 int32) { + + export_wasi_http_0_2_0_incoming_handler.Handle(wasi_http_0_2_0_types.IncomingRequestFromOwnHandle(int32(uintptr(arg0))), wasi_http_0_2_0_types.ResponseOutparamFromOwnHandle(int32(uintptr(arg1)))) + +} + +//go:wasmexport fermyon:spin/inbound-redis#handle-message +func wasm_export_fermyon_spin_inbound_redis_handle_message(arg0 uintptr, arg1 uint32) uintptr { + + value := unsafe.Slice((*uint8)(unsafe.Pointer(arg0)), arg1) + witRuntime.Unpin() + result := export_fermyon_spin_inbound_redis.HandleMessage(value) + + switch result.Tag() { + case witTypes.ResultOk: + + *(*int8)(unsafe.Add(unsafe.Pointer(exportReturnArea), 0)) = int8(int32(0)) + + case witTypes.ResultErr: + payload := result.Err() + *(*int8)(unsafe.Add(unsafe.Pointer(exportReturnArea), 0)) = int8(int32(1)) + *(*int8)(unsafe.Add(unsafe.Pointer(exportReturnArea), 1)) = int8(int32(payload)) + + default: + panic("unreachable") + } + return exportReturnArea + +} diff --git a/kv/key-value.c b/kv/key-value.c deleted file mode 100644 index bcb03cc8..00000000 --- a/kv/key-value.c +++ /dev/null @@ -1,367 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void key_value_string_set(key_value_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void key_value_string_dup(key_value_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void key_value_string_free(key_value_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void key_value_error_free(key_value_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 5: { - key_value_string_free(&ptr->val.io); - break; - } - } -} -void key_value_expected_store_error_free(key_value_expected_store_error_t *ptr) { - if (!ptr->is_err) { - } else { - key_value_error_free(&ptr->val.err); - } -} -void key_value_list_u8_free(key_value_list_u8_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void key_value_expected_list_u8_error_free(key_value_expected_list_u8_error_t *ptr) { - if (!ptr->is_err) { - key_value_list_u8_free(&ptr->val.ok); - } else { - key_value_error_free(&ptr->val.err); - } -} -void key_value_expected_unit_error_free(key_value_expected_unit_error_t *ptr) { - if (!ptr->is_err) { - } else { - key_value_error_free(&ptr->val.err); - } -} -void key_value_expected_bool_error_free(key_value_expected_bool_error_t *ptr) { - if (!ptr->is_err) { - } else { - key_value_error_free(&ptr->val.err); - } -} -void key_value_list_string_free(key_value_list_string_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - key_value_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void key_value_expected_list_string_error_free(key_value_expected_list_string_error_t *ptr) { - if (!ptr->is_err) { - key_value_list_string_free(&ptr->val.ok); - } else { - key_value_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[16]; -__attribute__((import_module("key-value"), import_name("open"))) -void __wasm_import_key_value_open(int32_t, int32_t, int32_t); -void key_value_open(key_value_string_t *name, key_value_expected_store_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_open((int32_t) (*name).ptr, (int32_t) (*name).len, ptr); - key_value_expected_store_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (uint32_t) (*((int32_t*) (ptr + 4))); - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("get"))) -void __wasm_import_key_value_get(int32_t, int32_t, int32_t, int32_t); -void key_value_get(key_value_store_t store, key_value_string_t *key, key_value_expected_list_u8_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_get((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - key_value_expected_list_u8_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (key_value_list_u8_t) { (uint8_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("set"))) -void __wasm_import_key_value_set(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void key_value_set(key_value_store_t store, key_value_string_t *key, key_value_list_u8_t *value, key_value_expected_unit_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_set((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr); - key_value_expected_unit_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("delete"))) -void __wasm_import_key_value_delete(int32_t, int32_t, int32_t, int32_t); -void key_value_delete(key_value_store_t store, key_value_string_t *key, key_value_expected_unit_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_delete((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - key_value_expected_unit_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("exists"))) -void __wasm_import_key_value_exists(int32_t, int32_t, int32_t, int32_t); -void key_value_exists(key_value_store_t store, key_value_string_t *key, key_value_expected_bool_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_exists((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - key_value_expected_bool_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (int32_t) (*((uint8_t*) (ptr + 4))); - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("get-keys"))) -void __wasm_import_key_value_get_keys(int32_t, int32_t); -void key_value_get_keys(key_value_store_t store, key_value_expected_list_string_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_key_value_get_keys((int32_t) (store), ptr); - key_value_expected_list_string_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (key_value_list_string_t) { (key_value_string_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - key_value_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; - } - case 3: { - break; - } - case 4: { - break; - } - case 5: { - variant.val.io = (key_value_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("key-value"), import_name("close"))) -void __wasm_import_key_value_close(int32_t); -void key_value_close(key_value_store_t store) { - __wasm_import_key_value_close((int32_t) (store)); -} diff --git a/kv/key-value.h b/kv/key-value.h deleted file mode 100644 index 7b78b032..00000000 --- a/kv/key-value.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef __BINDINGS_KEY_VALUE_H -#define __BINDINGS_KEY_VALUE_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } key_value_string_t; - - void key_value_string_set(key_value_string_t *ret, const char *s); - void key_value_string_dup(key_value_string_t *ret, const char *s); - void key_value_string_free(key_value_string_t *ret); - typedef uint32_t key_value_store_t; - typedef struct { - uint8_t tag; - union { - key_value_string_t io; - } val; - } key_value_error_t; - #define KEY_VALUE_ERROR_STORE_TABLE_FULL 0 - #define KEY_VALUE_ERROR_NO_SUCH_STORE 1 - #define KEY_VALUE_ERROR_ACCESS_DENIED 2 - #define KEY_VALUE_ERROR_INVALID_STORE 3 - #define KEY_VALUE_ERROR_NO_SUCH_KEY 4 - #define KEY_VALUE_ERROR_IO 5 - void key_value_error_free(key_value_error_t *ptr); - typedef struct { - bool is_err; - union { - key_value_store_t ok; - key_value_error_t err; - } val; - } key_value_expected_store_error_t; - void key_value_expected_store_error_free(key_value_expected_store_error_t *ptr); - typedef struct { - uint8_t *ptr; - size_t len; - } key_value_list_u8_t; - void key_value_list_u8_free(key_value_list_u8_t *ptr); - typedef struct { - bool is_err; - union { - key_value_list_u8_t ok; - key_value_error_t err; - } val; - } key_value_expected_list_u8_error_t; - void key_value_expected_list_u8_error_free(key_value_expected_list_u8_error_t *ptr); - typedef struct { - bool is_err; - union { - key_value_error_t err; - } val; - } key_value_expected_unit_error_t; - void key_value_expected_unit_error_free(key_value_expected_unit_error_t *ptr); - typedef struct { - bool is_err; - union { - bool ok; - key_value_error_t err; - } val; - } key_value_expected_bool_error_t; - void key_value_expected_bool_error_free(key_value_expected_bool_error_t *ptr); - typedef struct { - key_value_string_t *ptr; - size_t len; - } key_value_list_string_t; - void key_value_list_string_free(key_value_list_string_t *ptr); - typedef struct { - bool is_err; - union { - key_value_list_string_t ok; - key_value_error_t err; - } val; - } key_value_expected_list_string_error_t; - void key_value_expected_list_string_error_free(key_value_expected_list_string_error_t *ptr); - void key_value_open(key_value_string_t *name, key_value_expected_store_error_t *ret0); - void key_value_get(key_value_store_t store, key_value_string_t *key, key_value_expected_list_u8_error_t *ret0); - void key_value_set(key_value_store_t store, key_value_string_t *key, key_value_list_u8_t *value, key_value_expected_unit_error_t *ret0); - void key_value_delete(key_value_store_t store, key_value_string_t *key, key_value_expected_unit_error_t *ret0); - void key_value_exists(key_value_store_t store, key_value_string_t *key, key_value_expected_bool_error_t *ret0); - void key_value_get_keys(key_value_store_t store, key_value_expected_list_string_error_t *ret0); - void key_value_close(key_value_store_t store); - #ifdef __cplusplus -} -#endif -#endif diff --git a/kv/kv.go b/kv/kv.go index c5216600..e45af711 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -1,148 +1,100 @@ -// Package kv provides access to key value stores within Spin -// components. package kv -// #include "key-value.h" -import "C" import ( - "errors" "fmt" - "unsafe" + + keyvalue "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_key_value" ) -// Store is the Key/Value backend storage. type Store struct { - name string - active bool - ptr C.key_value_store_t -} - -// OpenStore creates a new instance of Store and opens a connection. -func OpenStore(name string) (*Store, error) { - s := &Store{name: name} - if err := s.open(); err != nil { - return nil, err - } - return s, nil + store *keyvalue.Store } -// Close terminates the connection to Store. -func (s *Store) Close() { - if s.active { - C.key_value_close(C.uint32_t(s.ptr)) +// Open the store with the label. +func Open(label string) (*Store, error) { + result := keyvalue.StoreOpen(label) + if result.IsErr() { + return nil, errorVariantToError(result.Err()) } - s.active = false -} -// Get retrieves a value from Store. -func (s *Store) Get(key string) ([]byte, error) { - ckey := toCStr(key) - var ret C.key_value_expected_list_u8_error_t - C.key_value_get(C.uint32_t(s.ptr), &ckey, &ret) - if ret.is_err { - return nil, toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) - } - list := (*C.key_value_list_u8_t)(unsafe.Pointer(&ret.val)) - return C.GoBytes(unsafe.Pointer(list.ptr), C.int(list.len)), nil + return &Store{ + store: result.Ok(), + }, nil } -// Delete removes a value from Store. -func (s *Store) Delete(key string) error { - ckey := toCStr(key) - var ret C.key_value_expected_unit_error_t - C.key_value_delete(C.uint32_t(s.ptr), &ckey, &ret) - if ret.is_err { - return toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) - } - return nil +// Open the default store. +// +// This is equivalent to `kv.Open("default")`. +func OpenDefault() (*Store, error) { + return Open("default") } -// Set creates a new key/value in Store. +// Set the key/value pair in store func (s *Store) Set(key string, value []byte) error { - ckey := toCStr(key) - cbytes := toCBytes(value) - var ret C.key_value_expected_unit_error_t - C.key_value_set(C.uint32_t(s.ptr), &ckey, &cbytes, &ret) - if ret.is_err { - return toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) + result := s.store.Set(key, value) + if result.IsErr() { + return errorVariantToError(result.Err()) } + return nil } -// Exists checks if a key exists within Store. -func (s *Store) Exists(key string) (bool, error) { - ckey := toCStr(key) - var ret C.key_value_expected_bool_error_t - C.key_value_exists(C.uint32_t(s.ptr), &ckey, &ret) - if ret.is_err { - return false, toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) +// Get the value of provided key from the store +func (s *Store) Get(key string) ([]byte, error) { + result := s.store.Get(key) + if result.IsErr() { + return nil, errorVariantToError(result.Err()) } - return *(*bool)(unsafe.Pointer(&ret.val)), nil -} -// GetKeys retrieves the list of keys from Store. -func (s *Store) GetKeys() ([]string, error) { - var ret C.key_value_expected_list_string_error_t - C.key_value_get_keys(C.uint32_t(s.ptr), &ret) - if ret.is_err { - return nil, toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) + value := result.Ok() + if value.IsNone() { + return []byte(""), nil } - list := (*C.key_value_list_string_t)(unsafe.Pointer(&ret.val)) - return fromCStrList(list), nil + + return value.Some(), nil } -func (s *Store) open() error { - if s.active { - return nil - } - cname := toCStr(s.name) - var ret C.key_value_expected_store_error_t - C.key_value_open(&cname, &ret) - if ret.is_err { - return toErr((*C.key_value_error_t)(unsafe.Pointer(&ret.val))) +// Delete the given key/value from the store +func (s *Store) Delete(key string) error { + result := s.store.Delete(key) + if result.IsErr() { + return errorVariantToError(result.Err()) } - s.ptr = *(*C.key_value_store_t)(unsafe.Pointer(&ret.val)) - s.active = true + return nil } -func toCBytes(x []byte) C.key_value_list_u8_t { - return C.key_value_list_u8_t{ptr: (*C.uint8_t)(unsafe.Pointer(&x[0])), len: C.size_t(len(x))} -} +// Exists check if a given key exist in the store +func (s *Store) Exists(key string) (bool, error) { + result := s.store.Exists(key) + if result.IsErr() { + return false, errorVariantToError(result.Err()) + } -func toCStr(x string) C.key_value_string_t { - return C.key_value_string_t{ptr: C.CString(x), len: C.size_t(len(x))} + return result.Ok(), nil } -func fromCStrList(list *C.key_value_list_string_t) []string { - var result []string - - listLen := int(list.len) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - str := slice[i] - result = append(result, C.GoStringN(str.ptr, C.int(str.len))) +// GetKets returns all the keys from the store +func (s *Store) GetKeys() ([]string, error) { + result := s.store.GetKeys() + if result.IsErr() { + return nil, errorVariantToError(result.Err()) } - return result + return result.Ok(), nil } -func toErr(err *C.key_value_error_t) error { - switch err.tag { - case 0: - return errors.New("store table full") - case 1: - return errors.New("no such store") - case 2: - return errors.New("access denied") - case 3: - return errors.New("invalid store") - case 4: - return errors.New("no such key") - case 5: - str := (*C.key_value_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("io error: %s", C.GoStringN(str.ptr, C.int(str.len))) +func errorVariantToError(code keyvalue.Error) error { + switch code.Tag() { + case keyvalue.ErrorAccessDenied: + return fmt.Errorf("access denied") + case keyvalue.ErrorNoSuchStore: + return fmt.Errorf("no such store") + case keyvalue.ErrorStoreTableFull: + return fmt.Errorf("store table full") + case keyvalue.ErrorOther: + return fmt.Errorf("%v", code.Other()) default: - return fmt.Errorf("unrecognized error: %v", err.tag) + return fmt.Errorf("no error provided by host implementation") } } diff --git a/kv/testdata/key-value/go.mod b/kv/testdata/key-value/go.mod new file mode 100644 index 00000000..0063085a --- /dev/null +++ b/kv/testdata/key-value/go.mod @@ -0,0 +1,11 @@ +module github.com/spinframework/spin-go-sdk/v3/http/testdata/kv + +go 1.25.5 + +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) + +replace github.com/spinframework/spin-go-sdk/v3 => ../../../ diff --git a/kv/testdata/key-value/go.sum b/kv/testdata/key-value/go.sum new file mode 100644 index 00000000..b5bca15f --- /dev/null +++ b/kv/testdata/key-value/go.sum @@ -0,0 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/kv/testdata/key-value/main.go b/kv/testdata/key-value/main.go new file mode 100644 index 00000000..9ac000e8 --- /dev/null +++ b/kv/testdata/key-value/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/kv" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + store, err := kv.OpenDefault() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + err = store.Set("foo", []byte("bar")) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + value, err := store.Get("foo") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if string(value) != "bar" { + http.Error(w, fmt.Sprintf("expected: %q, got: %q", "bar", value), http.StatusInternalServerError) + return + } + + keys, err := store.GetKeys() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + + _ = json.NewEncoder(w).Encode(keys) + }) +} + +func main() {} diff --git a/kv/testdata/key-value/spin.toml b/kv/testdata/key-value/spin.toml new file mode 100644 index 00000000..16bef71d --- /dev/null +++ b/kv/testdata/key-value/spin.toml @@ -0,0 +1,18 @@ +spin_manifest_version = 2 + +[application] +authors = ["Rajat Jindal "] +description = "A simple Spin application written in Go." +name = "key-value" +version = "1.0.0" + +[[trigger.http]] +route = "/hello" +component = "hello" + +[component.hello] +source = "main.wasm" +key_value_stores = ["default"] +[component.hello.build] +command = "componentize-go build" + diff --git a/llm/internals.go b/llm/internals.go deleted file mode 100644 index 4c644273..00000000 --- a/llm/internals.go +++ /dev/null @@ -1,131 +0,0 @@ -package llm - -// #include "llm.h" -import "C" -import ( - "errors" - "fmt" - "unsafe" -) - -func infer(model, prompt string, params *InferencingParams) (*InferencingResult, error) { - llmModel := toLLMModel(model) - llmPrompt := toLLMString(prompt) - llmParams := toLLMInferencingParams(params) - - var ret C.llm_expected_inferencing_result_error_t - defer C.llm_expected_inferencing_result_error_free(&ret) - - C.llm_infer(&llmModel, &llmPrompt, &llmParams, &ret) - if ret.is_err { - return nil, toErr((*C.llm_error_t)(unsafe.Pointer(&ret.val))) - } - - result := (*C.llm_inferencing_result_t)(unsafe.Pointer(&ret.val)) - - r := &InferencingResult{ - Text: C.GoStringN(result.text.ptr, C.int(result.text.len)), - Usage: &InferencingUsage{ - PromptTokenCount: int(result.usage.prompt_token_count), - GeneratedTokenCount: int(result.usage.generated_token_count), - }, - } - return r, nil -} - -func toErr(err *C.llm_error_t) error { - switch err.tag { - case 0: - return errors.New("model not supported") - case 1: - str := (*C.llm_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("runtime error: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 2: - str := (*C.llm_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("invalid input error: %s", C.GoStringN(str.ptr, C.int(str.len))) - default: - return fmt.Errorf("unrecognized error: %v", err.tag) - } -} - -func toLLMModel(name string) C.llm_inferencing_model_t { - llmString := toLLMString(name) - return *(*C.llm_inferencing_model_t)(unsafe.Pointer(&llmString.ptr)) -} - -func toLLMString(x string) C.llm_string_t { - return C.llm_string_t{ptr: C.CString(x), len: C.size_t(len(x))} -} - -func toLLMInferencingParams(p *InferencingParams) C.llm_option_inferencing_params_t { - if p == nil { - return C.llm_option_inferencing_params_t{is_some: false} - } - llmParams := C.llm_inferencing_params_t{ - max_tokens: C.uint32_t(p.MaxTokens), - repeat_penalty: C.float(p.RepeatPenalty), - repeat_penalty_last_n_token_count: C.uint32_t(p.RepeatPenaltyLastNTokenCount), - temperature: C.float(p.Temperature), - top_k: C.uint32_t(p.TopK), - top_p: C.float(p.TopP), - } - return C.llm_option_inferencing_params_t{is_some: true, val: llmParams} -} - -func generateEmbeddings(model string, text []string) (*EmbeddingsResult, error) { - llmModel := toLLMEmbeddingModel(model) - llmListString := toLLMListString(text) - - var ret C.llm_expected_embeddings_result_error_t - defer C.llm_expected_embeddings_result_error_free(&ret) - - C.llm_generate_embeddings(&llmModel, &llmListString, &ret) - if ret.is_err { - return nil, toErr((*C.llm_error_t)(unsafe.Pointer(&ret.val))) - } - - result := (*C.llm_embeddings_result_t)(unsafe.Pointer(&ret.val)) - - r := &EmbeddingsResult{ - Embeddings: fromLLMListListFloat32(result.embeddings), - Usage: &EmbeddingsUsage{ - PromptTokenCount: int(result.usage.prompt_token_count), - }, - } - return r, nil -} - -func toLLMEmbeddingModel(name string) C.llm_embedding_model_t { - llmString := toLLMString(name) - return *(*C.llm_embedding_model_t)(unsafe.Pointer(&llmString.ptr)) -} - -func toLLMListString(xs []string) C.llm_list_string_t { - cxs := make([]C.llm_string_t, len(xs)) - for i := 0; i < len(xs); i++ { - cxs[i] = toLLMString(xs[i]) - } - return C.llm_list_string_t{ptr: &cxs[0], len: C.size_t(len(cxs))} -} - -func fromLLMListListFloat32(list C.llm_list_list_float32_t) [][]float32 { - listLen := int(list.len) - ret := make([][]float32, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - row := *((*C.llm_list_float32_t)(unsafe.Pointer(&slice[i]))) - ret[i] = fromLLMListFloat32(row) - } - return ret -} - -func fromLLMListFloat32(list C.llm_list_float32_t) []float32 { - listLen := int(list.len) - ret := make([]float32, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - v := *((*C.float)(unsafe.Pointer(&slice[i]))) - ret[i] = float32(v) - } - return ret -} diff --git a/llm/llm.c b/llm/llm.c deleted file mode 100644 index 47420298..00000000 --- a/llm/llm.c +++ /dev/null @@ -1,213 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void llm_string_set(llm_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void llm_string_dup(llm_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void llm_string_free(llm_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void llm_inferencing_model_free(llm_inferencing_model_t *ptr) { - llm_string_free(ptr); -} -void llm_error_free(llm_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - llm_string_free(&ptr->val.runtime_error); - break; - } - case 2: { - llm_string_free(&ptr->val.invalid_input); - break; - } - } -} -void llm_inferencing_result_free(llm_inferencing_result_t *ptr) { - llm_string_free(&ptr->text); -} -void llm_embedding_model_free(llm_embedding_model_t *ptr) { - llm_string_free(ptr); -} -void llm_list_float32_free(llm_list_float32_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 4, 4); -} -void llm_list_list_float32_free(llm_list_list_float32_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - llm_list_float32_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void llm_embeddings_result_free(llm_embeddings_result_t *ptr) { - llm_list_list_float32_free(&ptr->embeddings); -} -void llm_expected_inferencing_result_error_free(llm_expected_inferencing_result_error_t *ptr) { - if (!ptr->is_err) { - llm_inferencing_result_free(&ptr->val.ok); - } else { - llm_error_free(&ptr->val.err); - } -} -void llm_list_string_free(llm_list_string_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - llm_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void llm_expected_embeddings_result_error_free(llm_expected_embeddings_result_error_t *ptr) { - if (!ptr->is_err) { - llm_embeddings_result_free(&ptr->val.ok); - } else { - llm_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[20]; -__attribute__((import_module("llm"), import_name("infer"))) -void __wasm_import_llm_infer(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, float, int32_t, float, int32_t, float, int32_t); -void llm_infer(llm_inferencing_model_t *model, llm_string_t *prompt, llm_option_inferencing_params_t *params, llm_expected_inferencing_result_error_t *ret0) { - int32_t option; - int32_t option1; - float option2; - int32_t option3; - float option4; - int32_t option5; - float option6; - - if ((*params).is_some) { - const llm_inferencing_params_t *payload0 = &(*params).val; - option = 1; - option1 = (int32_t) ((*payload0).max_tokens); - option2 = (*payload0).repeat_penalty; - option3 = (int32_t) ((*payload0).repeat_penalty_last_n_token_count); - option4 = (*payload0).temperature; - option5 = (int32_t) ((*payload0).top_k); - option6 = (*payload0).top_p; - - } else { - option = 0; - option1 = 0; - option2 = 0; - option3 = 0; - option4 = 0; - option5 = 0; - option6 = 0; - - } - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_llm_infer((int32_t) (*model).ptr, (int32_t) (*model).len, (int32_t) (*prompt).ptr, (int32_t) (*prompt).len, option, option1, option2, option3, option4, option5, option6, ptr); - llm_expected_inferencing_result_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (llm_inferencing_result_t) { - (llm_string_t) { (char*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }, - (llm_inferencing_usage_t) { - (uint32_t) (*((int32_t*) (ptr + 12))), - (uint32_t) (*((int32_t*) (ptr + 16))), - }, - }; - break; - } - case 1: { - expected.is_err = true; - llm_error_t variant; - variant.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant.tag) { - case 0: { - break; - } - case 1: { - variant.val.runtime_error = (llm_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant.val.invalid_input = (llm_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("llm"), import_name("generate-embeddings"))) -void __wasm_import_llm_generate_embeddings(int32_t, int32_t, int32_t, int32_t, int32_t); -void llm_generate_embeddings(llm_embedding_model_t *model, llm_list_string_t *text, llm_expected_embeddings_result_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_llm_generate_embeddings((int32_t) (*model).ptr, (int32_t) (*model).len, (int32_t) (*text).ptr, (int32_t) (*text).len, ptr); - llm_expected_embeddings_result_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (llm_embeddings_result_t) { - (llm_list_list_float32_t) { (llm_list_float32_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }, - (llm_embeddings_usage_t) { - (uint32_t) (*((int32_t*) (ptr + 12))), - }, - }; - break; - } - case 1: { - expected.is_err = true; - llm_error_t variant; - variant.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant.tag) { - case 0: { - break; - } - case 1: { - variant.val.runtime_error = (llm_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant.val.invalid_input = (llm_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} diff --git a/llm/llm.go b/llm/llm.go index 292c9068..decd0981 100644 --- a/llm/llm.go +++ b/llm/llm.go @@ -1,56 +1,67 @@ -// Package llm provides the interface to use Large Language Models in Spin. package llm -// InferenceParams is the optional request parameters. +import ( + "fmt" + + llm "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_llm" + wit "go.bytecodealliance.org/pkg/wit/types" +) + +// The model use for inferencing +const ( + Llama2Chat InferencingModel = "llama2-chat" + CodellamaInstruct InferencingModel = "codellama-instruct" +) + type InferencingParams struct { - // MaxTokens is the maximum tokens that should be inferred. - // Default: 100 + // The maximum tokens that should be inferred. // // Note: the backing implementation may return less tokens. - MaxTokens int32 - // RepeatPenalty is the amount the model should avoid repeating tokens. - // Default: 1.1 - RepeatPenalty float32 - // RepeatPenaltyLastNTokenCount the number of tokens the model should - // apply the repeat penalty to. - // Default: 64 - RepeatPenaltyLastNTokenCount int32 - // Temperature is the randomness with which the next token is selected. - // Default: 0.8 - Temperature float32 - // TopK is the number of possible next tokens the model will choose from. - // Default: 40 - TopK int32 - // TopP is the probability total of next tokens the model will choose - // from. - // Default: 0.9 - TopP float32 + MaxTokens uint32 `json:"max-tokens"` + + // The amount the model should avoid repeating tokens. + RepeatPenalty float32 `json:"repeat-penalty"` + + // The number of tokens the model should apply the repeat penalty to. + RepeatPenaltyLastNTokenCount uint32 `json:"repeat-penalty-last-n-token-count"` + + // The randomness with which the next token is selected. + Temperature float32 `json:"temperature"` + + // The number of possible next tokens the model will choose from. + TopK uint32 `json:"top-k"` + + // The probability total of next tokens the model will choose from. + TopP float32 `json:"top-p"` } -// InferencingResult is the result of an inference. type InferencingResult struct { - // Text is the text generated by the model. - Text string - // Usage is information about the inferencing request. - Usage *InferencingUsage + // The text generated by the model + // TODO: this should be a stream + Text string `json:"text"` + + // Usage information about the inferencing request + Usage InferencingUsage `json:"usage"` } -// InferencingUsage represents information related to the inferencing result. +// Usage information related to the inferencing result type InferencingUsage struct { - // PromptTokenCount is the number of tokens in the prompt. - PromptTokenCount int - // GeneratedTokenCount is the number of tokens generated by the - // inferencing operation. - GeneratedTokenCount int -} + // TODO: It's not clear whether this is important. + // _ cm.HostLayout `json:"-"` -// Infer performs inferencing using the provided model and prompt with the -// given optional parameters. -func Infer(model, prompt string, params *InferencingParams) (*InferencingResult, error) { - return infer(model, prompt, params) + // Number of tokens in the prompt + PromptTokenCount uint32 `json:"prompt-token-count"` + + // Number of tokens generated by the inferencing operation + GeneratedTokenCount uint32 `json:"generated-token-count"` } -// EmbeddingsResult of generating embeddings. +// A Large Language Model. +type InferencingModel string + +// The model used for generating embeddings +type EmbeddingModel string + type EmbeddingsResult struct { // Embeddings are the embeddings generated by the request. Embeddings [][]float32 @@ -58,13 +69,69 @@ type EmbeddingsResult struct { Usage *EmbeddingsUsage } -// Embeddings is usage related to an embeddings generation request. type EmbeddingsUsage struct { // PromptTokenCount is number of tokens in the prompt. PromptTokenCount int } +// Infer performs inferencing using the provided model and prompt with the +// given optional parameters. +func Infer(model string, prompt string, params *InferencingParams) (InferencingResult, error) { + iparams := wit.None[llm.InferencingParams]() + if params != nil { + iparams = wit.Some(llm.InferencingParams{ + MaxTokens: params.MaxTokens, + RepeatPenalty: params.RepeatPenalty, + RepeatPenaltyLastNTokenCount: params.RepeatPenaltyLastNTokenCount, + Temperature: params.Temperature, + TopK: params.TopK, + TopP: params.TopP, + }) + } + + result := llm.Infer(llm.InferencingModel(model), prompt, iparams) + if result.IsErr() { + return InferencingResult{}, errorVariantToError(result.Err()) + } + + return InferencingResult{ + Text: result.Ok().Text, + Usage: InferencingUsage{ + PromptTokenCount: result.Ok().Usage.PromptTokenCount, + GeneratedTokenCount: result.Ok().Usage.GeneratedTokenCount, + }, + }, nil +} + // GenerateEmbeddings generates the embeddings for the supplied list of text. -func GenerateEmbeddings(model string, text []string) (*EmbeddingsResult, error) { - return generateEmbeddings(model, text) +func GenerateEmbeddings(model EmbeddingModel, text []string) (*EmbeddingsResult, error) { + result := llm.GenerateEmbeddings(llm.EmbeddingModel(model), text) + if result.IsErr() { + return &EmbeddingsResult{}, errorVariantToError(result.Err()) + } + + embeddings := [][]float32{} + for _, l := range result.Ok().Embeddings { + embeddings = append(embeddings, l) + } + + return &EmbeddingsResult{ + Embeddings: embeddings, + Usage: &EmbeddingsUsage{ + PromptTokenCount: int(result.Ok().Usage.PromptTokenCount), + }, + }, nil +} + +func errorVariantToError(err llm.Error) error { + switch err.Tag() { + case llm.ErrorModelNotSupported: + return fmt.Errorf("model not supported") + case llm.ErrorRuntimeError: + return fmt.Errorf("runtime error %s", err.RuntimeError()) + case llm.ErrorInvalidInput: + return fmt.Errorf("invalid input %s", err.InvalidInput()) + default: + return fmt.Errorf("no error provided by host implementation") + } } diff --git a/llm/llm.h b/llm/llm.h deleted file mode 100644 index 57c5a49f..00000000 --- a/llm/llm.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef __BINDINGS_LLM_H -#define __BINDINGS_LLM_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } llm_string_t; - - void llm_string_set(llm_string_t *ret, const char *s); - void llm_string_dup(llm_string_t *ret, const char *s); - void llm_string_free(llm_string_t *ret); - // A Large Language Model. - typedef llm_string_t llm_inferencing_model_t; - void llm_inferencing_model_free(llm_inferencing_model_t *ptr); - // Inference request parameters - typedef struct { - uint32_t max_tokens; - float repeat_penalty; - uint32_t repeat_penalty_last_n_token_count; - float temperature; - uint32_t top_k; - float top_p; - } llm_inferencing_params_t; - // The set of errors which may be raised by functions in this interface - typedef struct { - uint8_t tag; - union { - llm_string_t runtime_error; - llm_string_t invalid_input; - } val; - } llm_error_t; - #define LLM_ERROR_MODEL_NOT_SUPPORTED 0 - #define LLM_ERROR_RUNTIME_ERROR 1 - #define LLM_ERROR_INVALID_INPUT 2 - void llm_error_free(llm_error_t *ptr); - // Usage information related to the inferencing result - typedef struct { - uint32_t prompt_token_count; - uint32_t generated_token_count; - } llm_inferencing_usage_t; - // An inferencing result - typedef struct { - llm_string_t text; - llm_inferencing_usage_t usage; - } llm_inferencing_result_t; - void llm_inferencing_result_free(llm_inferencing_result_t *ptr); - // The model used for generating embeddings - typedef llm_string_t llm_embedding_model_t; - void llm_embedding_model_free(llm_embedding_model_t *ptr); - typedef struct { - float *ptr; - size_t len; - } llm_list_float32_t; - void llm_list_float32_free(llm_list_float32_t *ptr); - typedef struct { - llm_list_float32_t *ptr; - size_t len; - } llm_list_list_float32_t; - void llm_list_list_float32_free(llm_list_list_float32_t *ptr); - // Usage related to an embeddings generation request - typedef struct { - uint32_t prompt_token_count; - } llm_embeddings_usage_t; - // Result of generating embeddings - typedef struct { - llm_list_list_float32_t embeddings; - llm_embeddings_usage_t usage; - } llm_embeddings_result_t; - void llm_embeddings_result_free(llm_embeddings_result_t *ptr); - typedef struct { - bool is_some; - llm_inferencing_params_t val; - } llm_option_inferencing_params_t; - typedef struct { - bool is_err; - union { - llm_inferencing_result_t ok; - llm_error_t err; - } val; - } llm_expected_inferencing_result_error_t; - void llm_expected_inferencing_result_error_free(llm_expected_inferencing_result_error_t *ptr); - typedef struct { - llm_string_t *ptr; - size_t len; - } llm_list_string_t; - void llm_list_string_free(llm_list_string_t *ptr); - typedef struct { - bool is_err; - union { - llm_embeddings_result_t ok; - llm_error_t err; - } val; - } llm_expected_embeddings_result_error_t; - void llm_expected_embeddings_result_error_free(llm_expected_embeddings_result_error_t *ptr); - void llm_infer(llm_inferencing_model_t *model, llm_string_t *prompt, llm_option_inferencing_params_t *params, llm_expected_inferencing_result_error_t *ret0); - void llm_generate_embeddings(llm_embedding_model_t *model, llm_list_string_t *text, llm_expected_embeddings_result_error_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/mqtt/mqtt.go b/mqtt/mqtt.go new file mode 100644 index 00000000..0430e011 --- /dev/null +++ b/mqtt/mqtt.go @@ -0,0 +1,49 @@ +package mqtt + +import ( + "fmt" + + mqtt "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_mqtt" +) + +type Connection struct { + conn mqtt.Connection +} + +// OpenConnection initializes an MQTT connection +func OpenConnection(address, username, password string, keepAliveIntervalInSecs uint64) (Connection, error) { + result := mqtt.ConnectionOpen(address, username, password, keepAliveIntervalInSecs) + if result.IsErr() { + return Connection{}, toError(result.Err()) + } + + return Connection{conn: *result.Ok()}, nil +} + +// Publish publishes an MQTT message +func (c *Connection) Publish(topic string, payload []byte, qos QoS) error { + result := c.conn.Publish(topic, mqtt.Payload(payload), mqtt.Qos(qos)) + if result.IsErr() { + return toError(result.Err()) + } + + return nil +} + +// QoS for publishing Mqtt messages +type QoS = mqtt.Qos + +const ( + QosAtMostOnce = mqtt.QosAtMostOnce + QosAtLeastOnce = mqtt.QosAtLeastOnce + QosExactlyOnce = mqtt.QosExactlyOnce +) + +func toError(err mqtt.Error) error { + switch err.Tag() { + case mqtt.ErrorConnectionFailed: + return fmt.Errorf("connection-failed: %s", err.ConnectionFailed()) + default: + return fmt.Errorf("%s", err.Other()) + } +} diff --git a/mysql/internals.go b/mysql/internals.go deleted file mode 100644 index 9b033310..00000000 --- a/mysql/internals.go +++ /dev/null @@ -1,325 +0,0 @@ -package mysql - -// #include "outbound-mysql.h" -// #include -import "C" -import ( - "errors" - "fmt" - "reflect" - "unsafe" -) - -func execute(address string, statement string, args []any) error { - var ret C.outbound_mysql_expected_unit_mysql_error_t - defer C.outbound_mysql_expected_unit_mysql_error_free(&ret) - - mysqlAddress := outboundMysqlStr(address) - mysqlStatement := outboundMysqlStr(statement) - params := toOutboundMysqlParameterListValue(args) - - C.outbound_mysql_execute(&mysqlAddress, &mysqlStatement, ¶ms, &ret) - - if ret.is_err { - spinErr := (*C.outbound_mysql_mysql_error_t)(unsafe.Pointer(&ret.val)) - return toErr(spinErr) - } - - return nil -} - -func query(address string, statement string, args []any) (*rows, error) { - var ret C.outbound_mysql_expected_row_set_mysql_error_t - defer C.outbound_mysql_expected_row_set_mysql_error_free(&ret) - - mysqlAddress := outboundMysqlStr(address) - mysqlStatement := outboundMysqlStr(statement) - params := toOutboundMysqlParameterListValue(args) - - C.outbound_mysql_query(&mysqlAddress, &mysqlStatement, ¶ms, &ret) - - if ret.is_err { - spinErr := (*C.outbound_mysql_mysql_error_t)(unsafe.Pointer(&ret.val)) - return nil, toErr(spinErr) - } - - qr := (*C.outbound_mysql_row_set_t)(unsafe.Pointer(&ret.val)) - - columns, columnType := fromOutboundMysqlListColoum(qr.columns) - - rs, err := fromOutboundMysqlListRow(qr.rows) - if err != nil { - return nil, err - } - - result := &rows{ - columns: columns, - columnType: columnType, - rows: rs, - len: int(qr.rows.len), - } - - return result, nil -} - -func fromOutboundMysqlListRow(list C.outbound_mysql_list_row_t) ([][]any, error) { - var err error - listLen := int(list.len) - ret := make([][]any, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - row := *((*C.outbound_mysql_row_t)(unsafe.Pointer(&slice[i]))) - ret[i], err = fromOutboundMysqlRow(row) - if err != nil { - return nil, err - } - } - return ret, nil - -} - -func fromOutboundMysqlRow(row C.outbound_mysql_row_t) ([]any, error) { - var err error - rowLen := int(row.len) - ret := make([]any, rowLen) - slice := unsafe.Slice(row.ptr, rowLen) - for i := 0; i < rowLen; i++ { - value := *((*C.outbound_mysql_db_value_t)(unsafe.Pointer(&slice[i]))) - ret[i], err = fromOutboundMysqlDbValue(value) - if err != nil { - return nil, err - } - } - return ret, err -} - -func fromOutboundMysqlListColoum(list C.outbound_mysql_list_column_t) ([]string, []uint8) { - coloumLen := int(list.len) - ret := make([]string, coloumLen) - retType := make([]uint8, coloumLen) - slice := unsafe.Slice(list.ptr, coloumLen) - for i := 0; i < coloumLen; i++ { - column := *((*C.outbound_mysql_column_t)(unsafe.Pointer(&slice[i]))) - ret[i], retType[i] = fromOutboundMysqlDbColumn(column) - } - return ret, retType -} - -func fromOutboundMysqlDbColumn(c C.outbound_mysql_column_t) (string, uint8) { - return C.GoStringN(c.name.ptr, C.int(c.name.len)), uint8(*(*C.uint8_t)(unsafe.Pointer(&c.data_type))) -} - -func outboundMysqlStr(x string) C.outbound_mysql_string_t { - return C.outbound_mysql_string_t{ptr: C.CString(x), len: C.size_t(len(x))} -} - -func toOutboundMysqlParameterListValue(xv []any) C.outbound_mysql_list_parameter_value_t { - if len(xv) == 0 { - return C.outbound_mysql_list_parameter_value_t{} - } - cxv := make([]C.outbound_mysql_parameter_value_t, len(xv)) - for i := 0; i < len(xv); i++ { - cxv[i] = toOutboundMysqlParameterValue(xv[i]) - } - return C.outbound_mysql_list_parameter_value_t{ptr: &cxv[0], len: C.size_t(len(cxv))} -} - -const ( - dbValueBoolean uint8 = iota - dbValueInt8 - dbValueInt16 - dbValueInt32 - dbValueInt64 - dbValueUint8 - dbValueUint16 - dbValueUint32 - dbValueUint64 - dbValueFloat32 - dbValueFloat64 - dbValueStr - dbValueBinary - dbValueNull - dbValueUnsupported -) - -func fromOutboundMysqlDbValue(x C.outbound_mysql_db_value_t) (any, error) { - switch x.tag { - case dbValueBoolean: - return *(*bool)(unsafe.Pointer(&x.val)), nil - case dbValueInt8: - return int8(*(*C.int8_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt16: - return int16(*(*C.int16_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt32: - return int32(*(*C.int32_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt64: - return int64(*(*C.int64_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint8: - return uint8(*(*C.uint8_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint16: - return uint16(*(*C.uint16_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint32: - return uint32(*(*C.uint32_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint64: - return uint64(*(*C.uint64_t)(unsafe.Pointer(&x.val))), nil - case dbValueFloat32: - return float32(*(*C.float)(unsafe.Pointer(&x.val))), nil - case dbValueFloat64: - return float64(*(*C.double)(unsafe.Pointer(&x.val))), nil - case dbValueBinary: - blob := (*C.outbound_mysql_list_u8_t)(unsafe.Pointer(&x.val)) - return C.GoBytes(unsafe.Pointer(blob.ptr), C.int(blob.len)), nil - case dbValueStr: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&x.val)) - return C.GoStringN(str.ptr, C.int(str.len)), nil - case dbValueNull: - return nil, nil - case dbValueUnsupported: - return nil, errors.New("db return value type unsupported") - } - return nil, errors.New("db return value unknown type") -} - -const ( - paramValueBoolean uint8 = iota - paramValueInt8 - paramValueInt16 - paramValueInt32 - paramValueInt64 - paramValueUint8 - paramValueUint16 - paramValueUint32 - paramValueUint64 - paramValueFloat32 - paramValueFloat64 - paramValueStr - paramValueBinary - paramValueNull - paramValueUnspported -) - -func toOutboundMysqlParameterValue(x any) C.outbound_mysql_parameter_value_t { - var ret C.outbound_mysql_parameter_value_t - switch v := x.(type) { - case bool: - *(*bool)(unsafe.Pointer(&ret.val)) = bool(v) - ret.tag = paramValueBoolean - case int8: - *(*C.int8_t)(unsafe.Pointer(&ret.val)) = int8(v) - ret.tag = paramValueInt8 - case int16: - *(*C.int16_t)(unsafe.Pointer(&ret.val)) = int16(v) - ret.tag = paramValueInt16 - case int32: - *(*C.int32_t)(unsafe.Pointer(&ret.val)) = int32(v) - ret.tag = paramValueInt32 - case int64: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = int64(v) - ret.tag = paramValueInt64 - case int: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = int64(v) - ret.tag = paramValueInt64 - case uint8: - *(*C.uint8_t)(unsafe.Pointer(&ret.val)) = uint8(v) - ret.tag = paramValueUint8 - case uint16: - *(*C.uint16_t)(unsafe.Pointer(&ret.val)) = uint16(v) - ret.tag = paramValueUint16 - case uint32: - *(*C.uint32_t)(unsafe.Pointer(&ret.val)) = uint32(v) - ret.tag = paramValueUint32 - case uint64: - *(*C.uint64_t)(unsafe.Pointer(&ret.val)) = uint64(v) - ret.tag = paramValueUint64 - case float32: - *(*C.float)(unsafe.Pointer(&ret.val)) = float32(v) - ret.tag = paramValueFloat32 - case float64: - *(*C.double)(unsafe.Pointer(&ret.val)) = float64(v) - ret.tag = paramValueFloat64 - case string: - str := outboundMysqlStr(v) - *(*C.outbound_mysql_string_t)(unsafe.Pointer(&ret.val)) = str - ret.tag = paramValueStr - case []byte: - blob := C.outbound_mysql_list_u8_t{ptr: &v[0], len: C.size_t(len(v))} - *(*C.outbound_mysql_list_u8_t)(unsafe.Pointer(&ret.val)) = blob - ret.tag = paramValueBinary - case nil: - ret.tag = paramValueNull - default: - ret.tag = paramValueUnspported - } - return ret -} - -func toErr(err *C.outbound_mysql_mysql_error_t) error { - switch err.tag { - case 0: - return nil - case 1: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("connection failed: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 2: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("bad parameter: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 3: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("query failed: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 4: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf(fmt.Sprintf("value conversion failed: %s", C.GoStringN(str.ptr, C.int(str.len)))) - case 5: - str := (*C.outbound_mysql_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf(fmt.Sprintf("other error: %s", C.GoStringN(str.ptr, C.int(str.len)))) - default: - return fmt.Errorf("unrecognized error: %v", err.tag) - } -} - -const ( - dbDataTypeBoolean uint8 = iota - dbDataTypeInt8 - dbDataTypeInt16 - dbDataTypeInt32 - dbDataTypeInt64 - dbDataTypeUint8 - dbDataTypeUint16 - dbDataTypeUint32 - dbDataTypeUint64 - dbDataTypeFloating32 - dbDataTypeFloating64 - dbDataTypeStr - dbDataTypeBinary - dbDataTypeOther -) - -func colTypeToReflectType(typ uint8) reflect.Type { - switch typ { - case dbDataTypeBoolean: - return reflect.TypeOf(false) - case dbDataTypeInt8: - return reflect.TypeOf(int8(0)) - case dbDataTypeInt16: - return reflect.TypeOf(int16(0)) - case dbDataTypeInt32: - return reflect.TypeOf(int32(0)) - case dbDataTypeInt64: - return reflect.TypeOf(int64(0)) - case dbDataTypeUint8: - return reflect.TypeOf(uint8(0)) - case dbDataTypeUint16: - return reflect.TypeOf(uint16(0)) - case dbDataTypeUint32: - return reflect.TypeOf(uint32(0)) - case dbDataTypeUint64: - return reflect.TypeOf(uint64(0)) - case dbDataTypeStr: - return reflect.TypeOf("") - case dbDataTypeBinary: - return reflect.TypeOf(new([]byte)) - case dbDataTypeOther: - return reflect.TypeOf(new(any)).Elem() - } - panic("invalid db column type of " + string(typ)) -} diff --git a/mysql/mysql.go b/mysql/mysql.go index 72b78ddc..d3a65e02 100644 --- a/mysql/mysql.go +++ b/mysql/mysql.go @@ -8,106 +8,62 @@ import ( "io" "reflect" - spindb "github.com/spinframework/spin-go-sdk/v2/internal/db" + spindb "github.com/spinframework/spin-go-sdk/v3/internal/db" + mysql "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_mysql" + rdbmstypes "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_rdbms_types" ) // Open returns a new connection to the database. -func Open(address string) *sql.DB { - return sql.OpenDB(&connector{address}) +func Open(name string) *sql.DB { + return sql.OpenDB(&connector{name: name}) } -// connector implements driver.Connector. -type connector struct { - address string -} - -// Connect returns a connection to the database. -func (d *connector) Connect(_ context.Context) (driver.Conn, error) { - return d.Open(d.address) -} - -// Driver returns the underlying Driver of the Connector. -func (d *connector) Driver() driver.Driver { - return d -} - -// Open returns a new connection to the database. -func (d *connector) Open(address string) (driver.Conn, error) { - return &conn{address: address}, nil -} - -// conn implements driver.Conn type conn struct { - address string -} - -var _ driver.Conn = (*conn)(nil) - -// Prepare returns a prepared statement, bound to this connection. -func (c *conn) Prepare(query string) (driver.Stmt, error) { - return &stmt{c: c, query: query}, nil + spinConn mysql.Connection } func (c *conn) Close() error { return nil } +func (c *conn) Prepare(query string) (driver.Stmt, error) { + return &stmt{conn: c, query: query}, nil +} + func (c *conn) Begin() (driver.Tx, error) { return nil, errors.New("transactions are unsupported by this driver") } -type stmt struct { - c *conn - query string +type connector struct { + conn *conn + name string } -var _ driver.Stmt = (*stmt)(nil) -var _ driver.ColumnConverter = (*stmt)(nil) - -// Close closes the statement. -func (s *stmt) Close() error { - return nil +func (d *connector) Connect(_ context.Context) (driver.Conn, error) { + if d.conn != nil { + return d.conn, nil + } + return d.Open(d.name) } -// NumInput returns the number of placeholder parameters. -func (s *stmt) NumInput() int { - // Golang sql won't sanity check argument counts before Query. - return -1 +func (d *connector) Driver() driver.Driver { + return d } -// Query executes a query that may return rows, such as a SELECT. -func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] +func (d *connector) Open(name string) (driver.Conn, error) { + results := mysql.ConnectionOpen(name) + if results.IsErr() { + return nil, toError(results.Err()) } - return query(s.c.address, s.query, params) + d.conn = &conn{spinConn: *results.Ok()} + return d.conn, nil } -// Exec executes a query that doesn't return rows, such as an INSERT or -// UPDATE. -func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] +func (d *connector) Close() error { + if d.conn != nil { + d.conn.Close() } - err := execute(s.c.address, s.query, params) - return &result{}, err -} - -// ColumnConverter returns GlobalParameterConverter to prevent using driver.DefaultParameterConverter. -func (s *stmt) ColumnConverter(_ int) driver.ValueConverter { - return spindb.GlobalParameterConverter -} - -type result struct{} - -func (r result) LastInsertId() (int64, error) { - return -1, errors.New("LastInsertId is unsupported by this driver") -} - -func (r result) RowsAffected() (int64, error) { - return -1, errors.New("RowsAffected is unsupported by this driver") + return nil } type rows struct { @@ -171,3 +127,211 @@ func (r *rows) NextResultSet() error { func (r *rows) ColumnTypeScanType(index int) reflect.Type { return colTypeToReflectType(r.columnType[index]) } + +type stmt struct { + conn *conn + query string +} + +var _ driver.Stmt = (*stmt)(nil) +var _ driver.ColumnConverter = (*stmt)(nil) + +// Close closes the statement. +func (s *stmt) Close() error { + return nil +} + +// NumInput returns the number of placeholder parameters. +func (s *stmt) NumInput() int { + // Golang sql won't sanity check argument counts before Query. + return -1 +} + +// Exec executes a query that doesn't return rows, such as an INSERT or +// UPDATE. +func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { + wasiParams := make([]mysql.ParameterValue, len(args)) + for i, v := range args { + wasiParams[i] = toWasiParameterValue(v) + } + + queryResult := s.conn.spinConn.Execute(s.query, wasiParams) + if queryResult.IsErr() { + return &result{}, toError(queryResult.Err()) + } + + return &result{}, nil +} + +// Query executes a query that may return rows, such as a SELECT. +func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { + wasiParams := make([]mysql.ParameterValue, len(args)) + for i, v := range args { + wasiParams[i] = toWasiParameterValue(v) + } + + results := s.conn.spinConn.Query(s.query, wasiParams) + if results.IsErr() { + return nil, toError(results.Err()) + } + + rowLen := len(results.Ok().Rows) + allRows := make([][]any, rowLen) + for rowNum, row := range results.Ok().Rows { + allRows[rowNum] = toRow(row) + } + + cols := results.Ok().Columns + colNames := make([]string, len(cols)) + colTypes := make([]uint8, len(cols)) + for i, c := range cols { + colNames[i] = c.Name + colTypes[i] = uint8(c.DataType) + } + + rows := &rows{ + columns: colNames, + columnType: colTypes, + rows: allRows, + len: int(rowLen), + } + return rows, nil +} + +func toWasiParameterValue(x any) mysql.ParameterValue { + switch v := x.(type) { + case bool: + return rdbmstypes.MakeParameterValueBoolean(v) + case int8: + return rdbmstypes.MakeParameterValueInt8(v) + case int16: + return rdbmstypes.MakeParameterValueInt16(v) + case int32: + return rdbmstypes.MakeParameterValueInt32(v) + case int64: + return rdbmstypes.MakeParameterValueInt64(v) + case int: + return rdbmstypes.MakeParameterValueInt64(int64(v)) + case uint8: + return rdbmstypes.MakeParameterValueUint8(v) + case uint16: + return rdbmstypes.MakeParameterValueUint16(v) + case uint32: + return rdbmstypes.MakeParameterValueUint32(v) + case uint64: + return rdbmstypes.MakeParameterValueUint64(v) + case float32: + return rdbmstypes.MakeParameterValueFloating32(v) + case float64: + return rdbmstypes.MakeParameterValueFloating64(v) + case string: + return rdbmstypes.MakeParameterValueStr(v) + case []byte: + return rdbmstypes.MakeParameterValueBinary(v) + case nil: + return rdbmstypes.MakeParameterValueDbNull() + default: + panic("unknown value type") + } +} + +func toError(err mysql.Error) error { + switch err.Tag() { + case rdbmstypes.ErrorBadParameter: + return errors.New(err.BadParameter()) + case rdbmstypes.ErrorConnectionFailed: + return errors.New(err.ConnectionFailed()) + case rdbmstypes.ErrorQueryFailed: + return errors.New(err.QueryFailed()) + case rdbmstypes.ErrorValueConversionFailed: + return errors.New(err.ValueConversionFailed()) + default: + // TODO: not sure if using "Other" as the default is appropriate + return errors.New(err.Other()) + } +} + +func toRow(row []rdbmstypes.DbValue) []any { + result := make([]any, len(row)) + for i, v := range row { + switch v.Tag() { + case rdbmstypes.DbValueBoolean: + result[i] = v.Boolean() + case rdbmstypes.DbValueInt8: + result[i] = v.Int8() + case rdbmstypes.DbValueInt16: + result[i] = v.Int16() + case rdbmstypes.DbValueInt32: + result[i] = v.Int32() + case rdbmstypes.DbValueInt64: + result[i] = v.Int64() + case rdbmstypes.DbValueUint8: + result[i] = v.Uint8() + case rdbmstypes.DbValueUint16: + result[i] = v.Uint16() + case rdbmstypes.DbValueUint32: + result[i] = v.Uint32() + case rdbmstypes.DbValueUint64: + result[i] = v.Uint64() + case rdbmstypes.DbValueFloating32: + result[i] = v.Floating32() + case rdbmstypes.DbValueFloating64: + result[i] = v.Floating64() + case rdbmstypes.DbValueStr: + result[i] = v.Str() + case rdbmstypes.DbValueBinary: + result[i] = v.Binary() + case rdbmstypes.DbValueDbNull: + result[i] = nil + default: + panic("unknown value type") + } + } + + return result +} + +// ColumnConverter returns GlobalParameterConverter to prevent using driver.DefaultParameterConverter. +func (s *stmt) ColumnConverter(_ int) driver.ValueConverter { + return spindb.GlobalParameterConverter +} + +type result struct{} + +func (r result) LastInsertId() (int64, error) { + return -1, errors.New("LastInsertId is unsupported by this driver") +} + +func (r result) RowsAffected() (int64, error) { + return -1, errors.New("RowsAffected is unsupported by this driver") +} + +func colTypeToReflectType(typ uint8) reflect.Type { + switch typ { + case uint8(rdbmstypes.DbDataTypeBoolean): + return reflect.TypeOf(false) + case uint8(rdbmstypes.DbDataTypeInt8): + return reflect.TypeOf(int8(0)) + case uint8(rdbmstypes.DbDataTypeInt16): + return reflect.TypeOf(int16(0)) + case uint8(rdbmstypes.DbDataTypeInt32): + return reflect.TypeOf(int32(0)) + case uint8(rdbmstypes.DbDataTypeInt64): + return reflect.TypeOf(int64(0)) + case uint8(rdbmstypes.DbDataTypeUint8): + return reflect.TypeOf(uint8(0)) + case uint8(rdbmstypes.DbDataTypeUint16): + return reflect.TypeOf(uint16(0)) + case uint8(rdbmstypes.DbDataTypeUint32): + return reflect.TypeOf(uint32(0)) + case uint8(rdbmstypes.DbDataTypeUint64): + return reflect.TypeOf(uint64(0)) + case uint8(rdbmstypes.DbDataTypeStr): + return reflect.TypeOf("") + case uint8(rdbmstypes.DbDataTypeBinary): + return reflect.TypeOf(new([]byte)) + case uint8(rdbmstypes.DbDataTypeOther): + return reflect.TypeOf(new(any)).Elem() + } + panic("invalid db column type of " + string(typ)) +} diff --git a/mysql/outbound-mysql.c b/mysql/outbound-mysql.c deleted file mode 100644 index f83753f2..00000000 --- a/mysql/outbound-mysql.c +++ /dev/null @@ -1,243 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void outbound_mysql_string_set(outbound_mysql_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void outbound_mysql_string_dup(outbound_mysql_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void outbound_mysql_string_free(outbound_mysql_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void outbound_mysql_mysql_error_free(outbound_mysql_mysql_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - outbound_mysql_string_free(&ptr->val.connection_failed); - break; - } - case 2: { - outbound_mysql_string_free(&ptr->val.bad_parameter); - break; - } - case 3: { - outbound_mysql_string_free(&ptr->val.query_failed); - break; - } - case 4: { - outbound_mysql_string_free(&ptr->val.value_conversion_failed); - break; - } - case 5: { - outbound_mysql_string_free(&ptr->val.other_error); - break; - } - } -} -void outbound_mysql_column_free(outbound_mysql_column_t *ptr) { - outbound_mysql_string_free(&ptr->name); -} -void outbound_mysql_list_u8_free(outbound_mysql_list_u8_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void outbound_mysql_db_value_free(outbound_mysql_db_value_t *ptr) { - switch ((int32_t) ptr->tag) { - case 11: { - outbound_mysql_string_free(&ptr->val.str); - break; - } - case 12: { - outbound_mysql_list_u8_free(&ptr->val.binary); - break; - } - } -} -void outbound_mysql_parameter_value_free(outbound_mysql_parameter_value_t *ptr) { - switch ((int32_t) ptr->tag) { - case 11: { - outbound_mysql_string_free(&ptr->val.str); - break; - } - case 12: { - outbound_mysql_list_u8_free(&ptr->val.binary); - break; - } - } -} -void outbound_mysql_row_free(outbound_mysql_row_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_mysql_db_value_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void outbound_mysql_list_column_free(outbound_mysql_list_column_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_mysql_column_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 12, 4); -} -void outbound_mysql_list_row_free(outbound_mysql_list_row_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_mysql_row_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void outbound_mysql_row_set_free(outbound_mysql_row_set_t *ptr) { - outbound_mysql_list_column_free(&ptr->columns); - outbound_mysql_list_row_free(&ptr->rows); -} -void outbound_mysql_list_parameter_value_free(outbound_mysql_list_parameter_value_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_mysql_parameter_value_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void outbound_mysql_expected_row_set_mysql_error_free(outbound_mysql_expected_row_set_mysql_error_t *ptr) { - if (!ptr->is_err) { - outbound_mysql_row_set_free(&ptr->val.ok); - } else { - outbound_mysql_mysql_error_free(&ptr->val.err); - } -} -void outbound_mysql_expected_unit_mysql_error_free(outbound_mysql_expected_unit_mysql_error_t *ptr) { - if (!ptr->is_err) { - } else { - outbound_mysql_mysql_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[20]; -__attribute__((import_module("outbound-mysql"), import_name("query"))) -void __wasm_import_outbound_mysql_query(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void outbound_mysql_query(outbound_mysql_string_t *address, outbound_mysql_string_t *statement, outbound_mysql_list_parameter_value_t *params, outbound_mysql_expected_row_set_mysql_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_mysql_query((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*statement).ptr, (int32_t) (*statement).len, (int32_t) (*params).ptr, (int32_t) (*params).len, ptr); - outbound_mysql_expected_row_set_mysql_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (outbound_mysql_row_set_t) { - (outbound_mysql_list_column_t) { (outbound_mysql_column_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }, - (outbound_mysql_list_row_t) { (outbound_mysql_row_t*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }, - }; - break; - } - case 1: { - expected.is_err = true; - outbound_mysql_mysql_error_t variant13; - variant13.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant13.tag) { - case 0: { - break; - } - case 1: { - variant13.val.connection_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant13.val.bad_parameter = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 3: { - variant13.val.query_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 4: { - variant13.val.value_conversion_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 5: { - variant13.val.other_error = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant13; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("outbound-mysql"), import_name("execute"))) -void __wasm_import_outbound_mysql_execute(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void outbound_mysql_execute(outbound_mysql_string_t *address, outbound_mysql_string_t *statement, outbound_mysql_list_parameter_value_t *params, outbound_mysql_expected_unit_mysql_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_mysql_execute((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*statement).ptr, (int32_t) (*statement).len, (int32_t) (*params).ptr, (int32_t) (*params).len, ptr); - outbound_mysql_expected_unit_mysql_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - - break; - } - case 1: { - expected.is_err = true; - outbound_mysql_mysql_error_t variant; - variant.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant.tag) { - case 0: { - break; - } - case 1: { - variant.val.connection_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant.val.bad_parameter = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 3: { - variant.val.query_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 4: { - variant.val.value_conversion_failed = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 5: { - variant.val.other_error = (outbound_mysql_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} diff --git a/mysql/outbound-mysql.h b/mysql/outbound-mysql.h deleted file mode 100644 index 2615ff71..00000000 --- a/mysql/outbound-mysql.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef __BINDINGS_OUTBOUND_MYSQL_H -#define __BINDINGS_OUTBOUND_MYSQL_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef struct { - char *ptr; - size_t len; -} outbound_mysql_string_t; - -void outbound_mysql_string_set(outbound_mysql_string_t *ret, const char *s); -void outbound_mysql_string_dup(outbound_mysql_string_t *ret, const char *s); -void outbound_mysql_string_free(outbound_mysql_string_t *ret); -typedef struct { - uint8_t tag; - union { - outbound_mysql_string_t connection_failed; - outbound_mysql_string_t bad_parameter; - outbound_mysql_string_t query_failed; - outbound_mysql_string_t value_conversion_failed; - outbound_mysql_string_t other_error; - } val; -} outbound_mysql_mysql_error_t; -#define OUTBOUND_MYSQL_MYSQL_ERROR_SUCCESS 0 -#define OUTBOUND_MYSQL_MYSQL_ERROR_CONNECTION_FAILED 1 -#define OUTBOUND_MYSQL_MYSQL_ERROR_BAD_PARAMETER 2 -#define OUTBOUND_MYSQL_MYSQL_ERROR_QUERY_FAILED 3 -#define OUTBOUND_MYSQL_MYSQL_ERROR_VALUE_CONVERSION_FAILED 4 -#define OUTBOUND_MYSQL_MYSQL_ERROR_OTHER_ERROR 5 -void outbound_mysql_mysql_error_free(outbound_mysql_mysql_error_t *ptr); -typedef uint8_t outbound_mysql_db_data_type_t; -#define OUTBOUND_MYSQL_DB_DATA_TYPE_BOOLEAN 0 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_INT8 1 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_INT16 2 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_INT32 3 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_INT64 4 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_UINT8 5 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_UINT16 6 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_UINT32 7 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_UINT64 8 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_FLOATING32 9 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_FLOATING64 10 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_STR 11 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_BINARY 12 -#define OUTBOUND_MYSQL_DB_DATA_TYPE_OTHER 13 -typedef struct { - outbound_mysql_string_t name; - outbound_mysql_db_data_type_t data_type; -} outbound_mysql_column_t; -void outbound_mysql_column_free(outbound_mysql_column_t *ptr); -typedef struct { - uint8_t *ptr; - size_t len; -} outbound_mysql_list_u8_t; -void outbound_mysql_list_u8_free(outbound_mysql_list_u8_t *ptr); -typedef struct { - uint8_t tag; - union { - bool boolean; - int8_t int8; - int16_t int16; - int32_t int32; - int64_t int64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float floating32; - double floating64; - outbound_mysql_string_t str; - outbound_mysql_list_u8_t binary; - } val; -} outbound_mysql_db_value_t; -#define OUTBOUND_MYSQL_DB_VALUE_BOOLEAN 0 -#define OUTBOUND_MYSQL_DB_VALUE_INT8 1 -#define OUTBOUND_MYSQL_DB_VALUE_INT16 2 -#define OUTBOUND_MYSQL_DB_VALUE_INT32 3 -#define OUTBOUND_MYSQL_DB_VALUE_INT64 4 -#define OUTBOUND_MYSQL_DB_VALUE_UINT8 5 -#define OUTBOUND_MYSQL_DB_VALUE_UINT16 6 -#define OUTBOUND_MYSQL_DB_VALUE_UINT32 7 -#define OUTBOUND_MYSQL_DB_VALUE_UINT64 8 -#define OUTBOUND_MYSQL_DB_VALUE_FLOATING32 9 -#define OUTBOUND_MYSQL_DB_VALUE_FLOATING64 10 -#define OUTBOUND_MYSQL_DB_VALUE_STR 11 -#define OUTBOUND_MYSQL_DB_VALUE_BINARY 12 -#define OUTBOUND_MYSQL_DB_VALUE_DB_NULL 13 -#define OUTBOUND_MYSQL_DB_VALUE_UNSUPPORTED 14 -void outbound_mysql_db_value_free(outbound_mysql_db_value_t *ptr); -typedef struct { - uint8_t tag; - union { - bool boolean; - int8_t int8; - int16_t int16; - int32_t int32; - int64_t int64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float floating32; - double floating64; - outbound_mysql_string_t str; - outbound_mysql_list_u8_t binary; - } val; -} outbound_mysql_parameter_value_t; -#define OUTBOUND_MYSQL_PARAMETER_VALUE_BOOLEAN 0 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_INT8 1 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_INT16 2 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_INT32 3 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_INT64 4 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_UINT8 5 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_UINT16 6 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_UINT32 7 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_UINT64 8 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_FLOATING32 9 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_FLOATING64 10 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_STR 11 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_BINARY 12 -#define OUTBOUND_MYSQL_PARAMETER_VALUE_DB_NULL 13 -void outbound_mysql_parameter_value_free(outbound_mysql_parameter_value_t *ptr); -typedef struct { - outbound_mysql_db_value_t *ptr; - size_t len; -} outbound_mysql_row_t; -void outbound_mysql_row_free(outbound_mysql_row_t *ptr); -typedef struct { - outbound_mysql_column_t *ptr; - size_t len; -} outbound_mysql_list_column_t; -void outbound_mysql_list_column_free(outbound_mysql_list_column_t *ptr); -typedef struct { - outbound_mysql_row_t *ptr; - size_t len; -} outbound_mysql_list_row_t; -void outbound_mysql_list_row_free(outbound_mysql_list_row_t *ptr); -typedef struct { - outbound_mysql_list_column_t columns; - outbound_mysql_list_row_t rows; -} outbound_mysql_row_set_t; -void outbound_mysql_row_set_free(outbound_mysql_row_set_t *ptr); -typedef struct { - outbound_mysql_parameter_value_t *ptr; - size_t len; -} outbound_mysql_list_parameter_value_t; -void outbound_mysql_list_parameter_value_free( - outbound_mysql_list_parameter_value_t *ptr); -typedef struct { - bool is_err; - union { - outbound_mysql_row_set_t ok; - outbound_mysql_mysql_error_t err; - } val; -} outbound_mysql_expected_row_set_mysql_error_t; -void outbound_mysql_expected_row_set_mysql_error_free( - outbound_mysql_expected_row_set_mysql_error_t *ptr); -typedef struct { - bool is_err; - union { - outbound_mysql_mysql_error_t err; - } val; -} outbound_mysql_expected_unit_mysql_error_t; -void outbound_mysql_expected_unit_mysql_error_free( - outbound_mysql_expected_unit_mysql_error_t *ptr); -void outbound_mysql_query(outbound_mysql_string_t *address, - outbound_mysql_string_t *statement, - outbound_mysql_list_parameter_value_t *params, - outbound_mysql_expected_row_set_mysql_error_t *ret0); -void outbound_mysql_execute(outbound_mysql_string_t *address, - outbound_mysql_string_t *statement, - outbound_mysql_list_parameter_value_t *params, - outbound_mysql_expected_unit_mysql_error_t *ret0); -#ifdef __cplusplus -} -#endif -#endif diff --git a/pg/internals.go b/pg/internals.go deleted file mode 100644 index 959626ea..00000000 --- a/pg/internals.go +++ /dev/null @@ -1,325 +0,0 @@ -package pg - -// #include "outbound-pg.h" -// #include -import "C" - -import ( - "errors" - "fmt" - "reflect" - "unsafe" -) - -func execute(address string, statement string, args []any) (uint64, error) { - var ret C.outbound_pg_expected_u64_pg_error_t - defer C.outbound_pg_expected_u64_pg_error_free(&ret) - - pgAddress := outboundPgStr(address) - pgStatement := outboundPgStr(statement) - params := toOutboundPgParameterListValue(args) - - C.outbound_pg_execute(&pgAddress, &pgStatement, ¶ms, &ret) - - if ret.is_err { - spinErr := (*C.outbound_pg_pg_error_t)(unsafe.Pointer(&ret.val)) - return 0, toErr(spinErr) - } - return uint64(*(*C.uint64_t)(unsafe.Pointer(&ret.val))), nil -} - -func query(address string, statement string, args []any) (*rows, error) { - var ret C.outbound_pg_expected_row_set_pg_error_t - defer C.outbound_pg_expected_row_set_pg_error_free(&ret) - - pgAddress := outboundPgStr(address) - pgStatement := outboundPgStr(statement) - params := toOutboundPgParameterListValue(args) - - C.outbound_pg_query(&pgAddress, &pgStatement, ¶ms, &ret) - - if ret.is_err { - spinErr := (*C.outbound_pg_pg_error_t)(unsafe.Pointer(&ret.val)) - return nil, toErr(spinErr) - } - - qr := (*C.outbound_pg_row_set_t)(unsafe.Pointer(&ret.val)) - - columns, columnType := fromOutboundPgListColoum(qr.columns) - - rs, err := fromOutboundPgListRow(qr.rows) - if err != nil { - return nil, err - } - - result := &rows{ - columns: columns, - columnType: columnType, - rows: rs, - len: int(qr.rows.len), - } - - return result, nil -} - -func fromOutboundPgListRow(list C.outbound_pg_list_row_t) ([][]any, error) { - var err error - listLen := int(list.len) - ret := make([][]any, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - row := *((*C.outbound_pg_row_t)(unsafe.Pointer(&slice[i]))) - ret[i], err = fromOutboundPgRow(row) - if err != nil { - return nil, err - } - } - return ret, nil - -} - -func fromOutboundPgRow(row C.outbound_pg_row_t) ([]any, error) { - var err error - rowLen := int(row.len) - ret := make([]any, rowLen) - slice := unsafe.Slice(row.ptr, rowLen) - for i := 0; i < rowLen; i++ { - value := *((*C.outbound_pg_db_value_t)(unsafe.Pointer(&slice[i]))) - ret[i], err = fromOutboundPgDbValue(value) - if err != nil { - return nil, err - } - } - return ret, err -} - -func fromOutboundPgListColoum(list C.outbound_pg_list_column_t) ([]string, []uint8) { - coloumLen := int(list.len) - ret := make([]string, coloumLen) - retType := make([]uint8, coloumLen) - slice := unsafe.Slice(list.ptr, coloumLen) - for i := 0; i < coloumLen; i++ { - column := *((*C.outbound_pg_column_t)(unsafe.Pointer(&slice[i]))) - ret[i], retType[i] = fromOutboundPgDbColumn(column) - } - return ret, retType -} - -func fromOutboundPgDbColumn(c C.outbound_pg_column_t) (string, uint8) { - return C.GoStringN(c.name.ptr, C.int(c.name.len)), uint8(*(*C.uint8_t)(unsafe.Pointer(&c.data_type))) -} - -func toOutboundPgParameterListValue(xv []any) C.outbound_pg_list_parameter_value_t { - if len(xv) == 0 { - return C.outbound_pg_list_parameter_value_t{} - } - cxv := make([]C.outbound_pg_parameter_value_t, len(xv)) - for i := 0; i < len(xv); i++ { - cxv[i] = toOutboundPgParameterValue(xv[i]) - } - return C.outbound_pg_list_parameter_value_t{ptr: &cxv[0], len: C.size_t(len(cxv))} -} - -func outboundPgStr(x string) C.outbound_pg_string_t { - return C.outbound_pg_string_t{ptr: C.CString(x), len: C.size_t(len(x))} -} - -func toErr(err *C.outbound_pg_pg_error_t) error { - switch err.tag { - case 0: - return nil - case 1: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("connection failed: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 2: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("bad parameter: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 3: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf("query failed: %s", C.GoStringN(str.ptr, C.int(str.len))) - case 4: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf(fmt.Sprintf("value conversion failed: %s", C.GoStringN(str.ptr, C.int(str.len)))) - case 5: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&err.val)) - return fmt.Errorf(fmt.Sprintf("other error: %s", C.GoStringN(str.ptr, C.int(str.len)))) - default: - return fmt.Errorf("unrecognized error: %v", err.tag) - } -} - -const ( - dbValueBoolean uint8 = iota - dbValueInt8 - dbValueInt16 - dbValueInt32 - dbValueInt64 - dbValueUint8 - dbValueUint16 - dbValueUint32 - dbValueUint64 - dbValueFloat32 - dbValueFloat64 - dbValueStr - dbValueBinary - dbValueNull - dbValueUnsupported -) - -func fromOutboundPgDbValue(x C.outbound_pg_db_value_t) (any, error) { - switch x.tag { - case dbValueBoolean: - return *(*bool)(unsafe.Pointer(&x.val)), nil - case dbValueInt8: - return int8(*(*C.int8_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt16: - return int16(*(*C.int16_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt32: - return int32(*(*C.int32_t)(unsafe.Pointer(&x.val))), nil - case dbValueInt64: - return int64(*(*C.int64_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint8: - return uint8(*(*C.uint8_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint16: - return uint16(*(*C.uint16_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint32: - return uint32(*(*C.uint32_t)(unsafe.Pointer(&x.val))), nil - case dbValueUint64: - return uint64(*(*C.uint64_t)(unsafe.Pointer(&x.val))), nil - case dbValueFloat32: - return float32(*(*C.float)(unsafe.Pointer(&x.val))), nil - case dbValueFloat64: - return float64(*(*C.double)(unsafe.Pointer(&x.val))), nil - case dbValueBinary: - blob := (*C.outbound_pg_list_u8_t)(unsafe.Pointer(&x.val)) - return C.GoBytes(unsafe.Pointer(blob.ptr), C.int(blob.len)), nil - case dbValueStr: - str := (*C.outbound_pg_string_t)(unsafe.Pointer(&x.val)) - return C.GoStringN(str.ptr, C.int(str.len)), nil - case dbValueNull: - return nil, nil - case dbValueUnsupported: - return nil, errors.New("db return value type unsupported") - } - return nil, errors.New("db return value unknown type") -} - -const ( - paramValueBoolean uint8 = iota - paramValueInt8 - paramValueInt16 - paramValueInt32 - paramValueInt64 - paramValueUint8 - paramValueUint16 - paramValueUint32 - paramValueUint64 - paramValueFloat32 - paramValueFloat64 - paramValueStr - paramValueBinary - paramValueNull - paramValueUnspported -) - -func toOutboundPgParameterValue(x any) C.outbound_pg_parameter_value_t { - var ret C.outbound_pg_parameter_value_t - switch v := x.(type) { - case bool: - *(*bool)(unsafe.Pointer(&ret.val)) = bool(v) - ret.tag = paramValueBoolean - case int8: - *(*C.int8_t)(unsafe.Pointer(&ret.val)) = int8(v) - ret.tag = paramValueInt8 - case int16: - *(*C.int16_t)(unsafe.Pointer(&ret.val)) = int16(v) - ret.tag = paramValueInt16 - case int32: - *(*C.int32_t)(unsafe.Pointer(&ret.val)) = int32(v) - ret.tag = paramValueInt32 - case int64: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = int64(v) - ret.tag = paramValueInt64 - case int: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = int64(v) - ret.tag = paramValueInt64 - case uint8: - *(*C.uint8_t)(unsafe.Pointer(&ret.val)) = uint8(v) - ret.tag = paramValueUint8 - case uint16: - *(*C.uint16_t)(unsafe.Pointer(&ret.val)) = uint16(v) - ret.tag = paramValueUint16 - case uint32: - *(*C.uint32_t)(unsafe.Pointer(&ret.val)) = uint32(v) - ret.tag = paramValueUint32 - case uint64: - *(*C.uint64_t)(unsafe.Pointer(&ret.val)) = uint64(v) - ret.tag = paramValueUint64 - case float32: - *(*C.float)(unsafe.Pointer(&ret.val)) = float32(v) - ret.tag = paramValueFloat32 - case float64: - *(*C.double)(unsafe.Pointer(&ret.val)) = float64(v) - ret.tag = paramValueFloat64 - case string: - str := outboundPgStr(v) - *(*C.outbound_pg_string_t)(unsafe.Pointer(&ret.val)) = str - ret.tag = paramValueStr - case []byte: - blob := C.outbound_pg_list_u8_t{ptr: &v[0], len: C.size_t(len(v))} - *(*C.outbound_pg_list_u8_t)(unsafe.Pointer(&ret.val)) = blob - ret.tag = paramValueBinary - case nil: - ret.tag = paramValueNull - default: - ret.tag = paramValueUnspported - } - return ret -} - -const ( - dbDataTypeBoolean uint8 = iota - dbDataTypeInt8 - dbDataTypeInt16 - dbDataTypeInt32 - dbDataTypeInt64 - dbDataTypeUint8 - dbDataTypeUint16 - dbDataTypeUint32 - dbDataTypeUint64 - dbDataTypeFloating32 - dbDataTypeFloating64 - dbDataTypeStr - dbDataTypeBinary - dbDataTypeOther -) - -func colTypeToReflectType(typ uint8) reflect.Type { - switch typ { - case dbDataTypeBoolean: - return reflect.TypeOf(false) - case dbDataTypeInt8: - return reflect.TypeOf(int8(0)) - case dbDataTypeInt16: - return reflect.TypeOf(int16(0)) - case dbDataTypeInt32: - return reflect.TypeOf(int32(0)) - case dbDataTypeInt64: - return reflect.TypeOf(int64(0)) - case dbDataTypeUint8: - return reflect.TypeOf(uint8(0)) - case dbDataTypeUint16: - return reflect.TypeOf(uint16(0)) - case dbDataTypeUint32: - return reflect.TypeOf(uint32(0)) - case dbDataTypeUint64: - return reflect.TypeOf(uint64(0)) - case dbDataTypeStr: - return reflect.TypeOf("") - case dbDataTypeBinary: - return reflect.TypeOf(new([]byte)) - case dbDataTypeOther: - return reflect.TypeOf(new(any)).Elem() - } - panic("invalid db column type of " + string(typ)) -} diff --git a/pg/outbound-pg.c b/pg/outbound-pg.c deleted file mode 100644 index 151867af..00000000 --- a/pg/outbound-pg.c +++ /dev/null @@ -1,243 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void outbound_pg_string_set(outbound_pg_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void outbound_pg_string_dup(outbound_pg_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void outbound_pg_string_free(outbound_pg_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void outbound_pg_pg_error_free(outbound_pg_pg_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - outbound_pg_string_free(&ptr->val.connection_failed); - break; - } - case 2: { - outbound_pg_string_free(&ptr->val.bad_parameter); - break; - } - case 3: { - outbound_pg_string_free(&ptr->val.query_failed); - break; - } - case 4: { - outbound_pg_string_free(&ptr->val.value_conversion_failed); - break; - } - case 5: { - outbound_pg_string_free(&ptr->val.other_error); - break; - } - } -} -void outbound_pg_column_free(outbound_pg_column_t *ptr) { - outbound_pg_string_free(&ptr->name); -} -void outbound_pg_list_u8_free(outbound_pg_list_u8_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void outbound_pg_db_value_free(outbound_pg_db_value_t *ptr) { - switch ((int32_t) ptr->tag) { - case 11: { - outbound_pg_string_free(&ptr->val.str); - break; - } - case 12: { - outbound_pg_list_u8_free(&ptr->val.binary); - break; - } - } -} -void outbound_pg_parameter_value_free(outbound_pg_parameter_value_t *ptr) { - switch ((int32_t) ptr->tag) { - case 11: { - outbound_pg_string_free(&ptr->val.str); - break; - } - case 12: { - outbound_pg_list_u8_free(&ptr->val.binary); - break; - } - } -} -void outbound_pg_row_free(outbound_pg_row_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_pg_db_value_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void outbound_pg_list_column_free(outbound_pg_list_column_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_pg_column_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 12, 4); -} -void outbound_pg_list_row_free(outbound_pg_list_row_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_pg_row_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void outbound_pg_row_set_free(outbound_pg_row_set_t *ptr) { - outbound_pg_list_column_free(&ptr->columns); - outbound_pg_list_row_free(&ptr->rows); -} -void outbound_pg_list_parameter_value_free(outbound_pg_list_parameter_value_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_pg_parameter_value_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void outbound_pg_expected_row_set_pg_error_free(outbound_pg_expected_row_set_pg_error_t *ptr) { - if (!ptr->is_err) { - outbound_pg_row_set_free(&ptr->val.ok); - } else { - outbound_pg_pg_error_free(&ptr->val.err); - } -} -void outbound_pg_expected_u64_pg_error_free(outbound_pg_expected_u64_pg_error_t *ptr) { - if (!ptr->is_err) { - } else { - outbound_pg_pg_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(8))) -static uint8_t RET_AREA[20]; -__attribute__((import_module("outbound-pg"), import_name("query"))) -void __wasm_import_outbound_pg_query(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void outbound_pg_query(outbound_pg_string_t *address, outbound_pg_string_t *statement, outbound_pg_list_parameter_value_t *params, outbound_pg_expected_row_set_pg_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_pg_query((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*statement).ptr, (int32_t) (*statement).len, (int32_t) (*params).ptr, (int32_t) (*params).len, ptr); - outbound_pg_expected_row_set_pg_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (outbound_pg_row_set_t) { - (outbound_pg_list_column_t) { (outbound_pg_column_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }, - (outbound_pg_list_row_t) { (outbound_pg_row_t*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }, - }; - break; - } - case 1: { - expected.is_err = true; - outbound_pg_pg_error_t variant13; - variant13.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant13.tag) { - case 0: { - break; - } - case 1: { - variant13.val.connection_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant13.val.bad_parameter = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 3: { - variant13.val.query_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 4: { - variant13.val.value_conversion_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 5: { - variant13.val.other_error = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant13; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("outbound-pg"), import_name("execute"))) -void __wasm_import_outbound_pg_execute(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void outbound_pg_execute(outbound_pg_string_t *address, outbound_pg_string_t *statement, outbound_pg_list_parameter_value_t *params, outbound_pg_expected_u64_pg_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_pg_execute((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*statement).ptr, (int32_t) (*statement).len, (int32_t) (*params).ptr, (int32_t) (*params).len, ptr); - outbound_pg_expected_u64_pg_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (uint64_t) (*((int64_t*) (ptr + 8))); - break; - } - case 1: { - expected.is_err = true; - outbound_pg_pg_error_t variant; - variant.tag = (int32_t) (*((uint8_t*) (ptr + 8))); - switch ((int32_t) variant.tag) { - case 0: { - break; - } - case 1: { - variant.val.connection_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - case 2: { - variant.val.bad_parameter = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - case 3: { - variant.val.query_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - case 4: { - variant.val.value_conversion_failed = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - case 5: { - variant.val.other_error = (outbound_pg_string_t) { (char*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} diff --git a/pg/outbound-pg.h b/pg/outbound-pg.h deleted file mode 100644 index 4284e161..00000000 --- a/pg/outbound-pg.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef __BINDINGS_OUTBOUND_PG_H -#define __BINDINGS_OUTBOUND_PG_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } outbound_pg_string_t; - - void outbound_pg_string_set(outbound_pg_string_t *ret, const char *s); - void outbound_pg_string_dup(outbound_pg_string_t *ret, const char *s); - void outbound_pg_string_free(outbound_pg_string_t *ret); - typedef struct { - uint8_t tag; - union { - outbound_pg_string_t connection_failed; - outbound_pg_string_t bad_parameter; - outbound_pg_string_t query_failed; - outbound_pg_string_t value_conversion_failed; - outbound_pg_string_t other_error; - } val; - } outbound_pg_pg_error_t; - #define OUTBOUND_PG_PG_ERROR_SUCCESS 0 - #define OUTBOUND_PG_PG_ERROR_CONNECTION_FAILED 1 - #define OUTBOUND_PG_PG_ERROR_BAD_PARAMETER 2 - #define OUTBOUND_PG_PG_ERROR_QUERY_FAILED 3 - #define OUTBOUND_PG_PG_ERROR_VALUE_CONVERSION_FAILED 4 - #define OUTBOUND_PG_PG_ERROR_OTHER_ERROR 5 - void outbound_pg_pg_error_free(outbound_pg_pg_error_t *ptr); - typedef uint8_t outbound_pg_db_data_type_t; - #define OUTBOUND_PG_DB_DATA_TYPE_BOOLEAN 0 - #define OUTBOUND_PG_DB_DATA_TYPE_INT8 1 - #define OUTBOUND_PG_DB_DATA_TYPE_INT16 2 - #define OUTBOUND_PG_DB_DATA_TYPE_INT32 3 - #define OUTBOUND_PG_DB_DATA_TYPE_INT64 4 - #define OUTBOUND_PG_DB_DATA_TYPE_UINT8 5 - #define OUTBOUND_PG_DB_DATA_TYPE_UINT16 6 - #define OUTBOUND_PG_DB_DATA_TYPE_UINT32 7 - #define OUTBOUND_PG_DB_DATA_TYPE_UINT64 8 - #define OUTBOUND_PG_DB_DATA_TYPE_FLOATING32 9 - #define OUTBOUND_PG_DB_DATA_TYPE_FLOATING64 10 - #define OUTBOUND_PG_DB_DATA_TYPE_STR 11 - #define OUTBOUND_PG_DB_DATA_TYPE_BINARY 12 - #define OUTBOUND_PG_DB_DATA_TYPE_OTHER 13 - typedef struct { - outbound_pg_string_t name; - outbound_pg_db_data_type_t data_type; - } outbound_pg_column_t; - void outbound_pg_column_free(outbound_pg_column_t *ptr); - typedef struct { - uint8_t *ptr; - size_t len; - } outbound_pg_list_u8_t; - void outbound_pg_list_u8_free(outbound_pg_list_u8_t *ptr); - typedef struct { - uint8_t tag; - union { - bool boolean; - int8_t int8; - int16_t int16; - int32_t int32; - int64_t int64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float floating32; - double floating64; - outbound_pg_string_t str; - outbound_pg_list_u8_t binary; - } val; - } outbound_pg_db_value_t; - #define OUTBOUND_PG_DB_VALUE_BOOLEAN 0 - #define OUTBOUND_PG_DB_VALUE_INT8 1 - #define OUTBOUND_PG_DB_VALUE_INT16 2 - #define OUTBOUND_PG_DB_VALUE_INT32 3 - #define OUTBOUND_PG_DB_VALUE_INT64 4 - #define OUTBOUND_PG_DB_VALUE_UINT8 5 - #define OUTBOUND_PG_DB_VALUE_UINT16 6 - #define OUTBOUND_PG_DB_VALUE_UINT32 7 - #define OUTBOUND_PG_DB_VALUE_UINT64 8 - #define OUTBOUND_PG_DB_VALUE_FLOATING32 9 - #define OUTBOUND_PG_DB_VALUE_FLOATING64 10 - #define OUTBOUND_PG_DB_VALUE_STR 11 - #define OUTBOUND_PG_DB_VALUE_BINARY 12 - #define OUTBOUND_PG_DB_VALUE_DB_NULL 13 - #define OUTBOUND_PG_DB_VALUE_UNSUPPORTED 14 - void outbound_pg_db_value_free(outbound_pg_db_value_t *ptr); - typedef struct { - uint8_t tag; - union { - bool boolean; - int8_t int8; - int16_t int16; - int32_t int32; - int64_t int64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float floating32; - double floating64; - outbound_pg_string_t str; - outbound_pg_list_u8_t binary; - } val; - } outbound_pg_parameter_value_t; - #define OUTBOUND_PG_PARAMETER_VALUE_BOOLEAN 0 - #define OUTBOUND_PG_PARAMETER_VALUE_INT8 1 - #define OUTBOUND_PG_PARAMETER_VALUE_INT16 2 - #define OUTBOUND_PG_PARAMETER_VALUE_INT32 3 - #define OUTBOUND_PG_PARAMETER_VALUE_INT64 4 - #define OUTBOUND_PG_PARAMETER_VALUE_UINT8 5 - #define OUTBOUND_PG_PARAMETER_VALUE_UINT16 6 - #define OUTBOUND_PG_PARAMETER_VALUE_UINT32 7 - #define OUTBOUND_PG_PARAMETER_VALUE_UINT64 8 - #define OUTBOUND_PG_PARAMETER_VALUE_FLOATING32 9 - #define OUTBOUND_PG_PARAMETER_VALUE_FLOATING64 10 - #define OUTBOUND_PG_PARAMETER_VALUE_STR 11 - #define OUTBOUND_PG_PARAMETER_VALUE_BINARY 12 - #define OUTBOUND_PG_PARAMETER_VALUE_DB_NULL 13 - void outbound_pg_parameter_value_free(outbound_pg_parameter_value_t *ptr); - typedef struct { - outbound_pg_db_value_t *ptr; - size_t len; - } outbound_pg_row_t; - void outbound_pg_row_free(outbound_pg_row_t *ptr); - typedef struct { - outbound_pg_column_t *ptr; - size_t len; - } outbound_pg_list_column_t; - void outbound_pg_list_column_free(outbound_pg_list_column_t *ptr); - typedef struct { - outbound_pg_row_t *ptr; - size_t len; - } outbound_pg_list_row_t; - void outbound_pg_list_row_free(outbound_pg_list_row_t *ptr); - typedef struct { - outbound_pg_list_column_t columns; - outbound_pg_list_row_t rows; - } outbound_pg_row_set_t; - void outbound_pg_row_set_free(outbound_pg_row_set_t *ptr); - typedef struct { - outbound_pg_parameter_value_t *ptr; - size_t len; - } outbound_pg_list_parameter_value_t; - void outbound_pg_list_parameter_value_free(outbound_pg_list_parameter_value_t *ptr); - typedef struct { - bool is_err; - union { - outbound_pg_row_set_t ok; - outbound_pg_pg_error_t err; - } val; - } outbound_pg_expected_row_set_pg_error_t; - void outbound_pg_expected_row_set_pg_error_free(outbound_pg_expected_row_set_pg_error_t *ptr); - typedef struct { - bool is_err; - union { - uint64_t ok; - outbound_pg_pg_error_t err; - } val; - } outbound_pg_expected_u64_pg_error_t; - void outbound_pg_expected_u64_pg_error_free(outbound_pg_expected_u64_pg_error_t *ptr); - void outbound_pg_query(outbound_pg_string_t *address, outbound_pg_string_t *statement, outbound_pg_list_parameter_value_t *params, outbound_pg_expected_row_set_pg_error_t *ret0); - void outbound_pg_execute(outbound_pg_string_t *address, outbound_pg_string_t *statement, outbound_pg_list_parameter_value_t *params, outbound_pg_expected_u64_pg_error_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/pg/pg.go b/pg/pg.go index 956f1883..002f4f3b 100644 --- a/pg/pg.go +++ b/pg/pg.go @@ -8,22 +8,28 @@ import ( "io" "reflect" - spindb "github.com/spinframework/spin-go-sdk/v2/internal/db" + spindb "github.com/spinframework/spin-go-sdk/v3/internal/db" + pg "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_postgres" + rdbmstypes "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_rdbms_types" ) // Open returns a new connection to the database. -func Open(address string) *sql.DB { - return sql.OpenDB(&connector{address}) +func Open(name string) *sql.DB { + return sql.OpenDB(&connector{name: name}) } // connector implements driver.Connector. type connector struct { - address string + conn *conn + name string } // Connect returns a connection to the database. func (d *connector) Connect(_ context.Context) (driver.Conn, error) { - return d.Open(d.address) + if d.conn != nil { + return d.conn, nil + } + return d.Open(d.name) } // Driver returns the underlying Driver of the Connector. @@ -32,20 +38,25 @@ func (d *connector) Driver() driver.Driver { } // Open returns a new connection to the database. -func (d *connector) Open(address string) (driver.Conn, error) { - return &conn{address: address}, nil +func (d *connector) Open(name string) (driver.Conn, error) { + results := pg.ConnectionOpen(name) + if results.IsErr() { + return nil, toError(results.Err()) + } + d.conn = &conn{spinConn: *results.Ok()} + return d.conn, nil } // conn implements driver.Conn type conn struct { - address string + spinConn pg.Connection } var _ driver.Conn = (*conn)(nil) // Prepare returns a prepared statement, bound to this connection. func (c *conn) Prepare(query string) (driver.Stmt, error) { - return &stmt{c: c, query: query}, nil + return &stmt{conn: c, query: query}, nil } func (c *conn) Close() error { @@ -57,7 +68,7 @@ func (c *conn) Begin() (driver.Tx, error) { } type stmt struct { - c *conn + conn *conn query string } @@ -77,22 +88,53 @@ func (s *stmt) NumInput() int { // Query executes a query that may return rows, such as a SELECT. func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] + rdbmsParams := make([]pg.ParameterValue, len(args)) + for i, v := range args { + rdbmsParams[i] = toRdbmsParameterValue(v) + } + + results := s.conn.spinConn.Query(s.query, rdbmsParams) + if results.IsErr() { + return nil, toError(results.Err()) } - return query(s.c.address, s.query, params) + + rowLen := len(results.Ok().Rows) + allRows := make([][]any, rowLen) + for rowNum, row := range results.Ok().Rows { + allRows[rowNum] = toRow(row) + } + + cols := results.Ok().Columns + colNames := make([]string, len(cols)) + colTypes := make([]uint8, len(cols)) + for i, c := range cols { + colNames[i] = c.Name + colTypes[i] = uint8(c.DataType) + } + + rows := &rows{ + columns: colNames, + columnType: colTypes, + rows: allRows, + len: int(rowLen), + } + return rows, nil } // Exec executes a query that doesn't return rows, such as an INSERT or // UPDATE. func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] + rdbmsParams := make([]pg.ParameterValue, len(args)) + for i, v := range args { + rdbmsParams[i] = toRdbmsParameterValue(v) } - n, err := execute(s.c.address, s.query, params) - return &result{rowsAffected: int64(n)}, err + + queryResult := s.conn.spinConn.Execute(s.query, rdbmsParams) + if queryResult.IsErr() { + return &result{}, toError(queryResult.Err()) + } + + return &result{}, nil } // ColumnConverter returns GlobalParameterConverter to prevent using driver.DefaultParameterConverter. @@ -173,3 +215,126 @@ func (r *rows) NextResultSet() error { func (r *rows) ColumnTypeScanType(index int) reflect.Type { return colTypeToReflectType(r.columnType[index]) } + +func toRdbmsParameterValue(x any) pg.ParameterValue { + switch v := x.(type) { + case bool: + return rdbmstypes.MakeParameterValueBoolean(v) + case int8: + return rdbmstypes.MakeParameterValueInt8(v) + case int16: + return rdbmstypes.MakeParameterValueInt16(v) + case int32: + return rdbmstypes.MakeParameterValueInt32(v) + case int64: + return rdbmstypes.MakeParameterValueInt64(v) + case int: + return rdbmstypes.MakeParameterValueInt64(int64(v)) + case uint8: + return rdbmstypes.MakeParameterValueUint8(v) + case uint16: + return rdbmstypes.MakeParameterValueUint16(v) + case uint32: + return rdbmstypes.MakeParameterValueUint32(v) + case uint64: + return rdbmstypes.MakeParameterValueUint64(v) + case float32: + return rdbmstypes.MakeParameterValueFloating32(v) + case float64: + return rdbmstypes.MakeParameterValueFloating64(v) + case string: + return rdbmstypes.MakeParameterValueStr(v) + case []byte: + return rdbmstypes.MakeParameterValueBinary(v) + case nil: + return rdbmstypes.MakeParameterValueDbNull() + default: + panic("unknown value type") + } +} + +func toError(err pg.Error) error { + switch err.Tag() { + case rdbmstypes.ErrorBadParameter: + return errors.New(err.BadParameter()) + case rdbmstypes.ErrorConnectionFailed: + return errors.New(err.ConnectionFailed()) + case rdbmstypes.ErrorQueryFailed: + return errors.New(err.QueryFailed()) + case rdbmstypes.ErrorValueConversionFailed: + return errors.New(err.ValueConversionFailed()) + default: + // TODO: not sure if using "Other" as the default is appropriate + return errors.New(err.Other()) + } +} + +func toRow(row []rdbmstypes.DbValue) []any { + result := make([]any, len(row)) + for i, v := range row { + switch v.Tag() { + case rdbmstypes.DbValueBoolean: + result[i] = v.Boolean() + case rdbmstypes.DbValueInt8: + result[i] = v.Int8() + case rdbmstypes.DbValueInt16: + result[i] = v.Int16() + case rdbmstypes.DbValueInt32: + result[i] = v.Int32() + case rdbmstypes.DbValueInt64: + result[i] = v.Int64() + case rdbmstypes.DbValueUint8: + result[i] = v.Uint8() + case rdbmstypes.DbValueUint16: + result[i] = v.Uint16() + case rdbmstypes.DbValueUint32: + result[i] = v.Uint32() + case rdbmstypes.DbValueUint64: + result[i] = v.Uint64() + case rdbmstypes.DbValueFloating32: + result[i] = v.Floating32() + case rdbmstypes.DbValueFloating64: + result[i] = v.Floating64() + case rdbmstypes.DbValueStr: + result[i] = v.Str() + case rdbmstypes.DbValueBinary: + result[i] = v.Binary() + case rdbmstypes.DbValueDbNull: + result[i] = nil + default: + panic("unknown value type") + } + } + + return result +} + +func colTypeToReflectType(typ uint8) reflect.Type { + switch typ { + case uint8(rdbmstypes.DbDataTypeBoolean): + return reflect.TypeOf(false) + case uint8(rdbmstypes.DbDataTypeInt8): + return reflect.TypeOf(int8(0)) + case uint8(rdbmstypes.DbDataTypeInt16): + return reflect.TypeOf(int16(0)) + case uint8(rdbmstypes.DbDataTypeInt32): + return reflect.TypeOf(int32(0)) + case uint8(rdbmstypes.DbDataTypeInt64): + return reflect.TypeOf(int64(0)) + case uint8(rdbmstypes.DbDataTypeUint8): + return reflect.TypeOf(uint8(0)) + case uint8(rdbmstypes.DbDataTypeUint16): + return reflect.TypeOf(uint16(0)) + case uint8(rdbmstypes.DbDataTypeUint32): + return reflect.TypeOf(uint32(0)) + case uint8(rdbmstypes.DbDataTypeUint64): + return reflect.TypeOf(uint64(0)) + case uint8(rdbmstypes.DbDataTypeStr): + return reflect.TypeOf("") + case uint8(rdbmstypes.DbDataTypeBinary): + return reflect.TypeOf(new([]byte)) + case uint8(rdbmstypes.DbDataTypeOther): + return reflect.TypeOf(new(any)).Elem() + } + panic("invalid db column type of " + string(typ)) +} diff --git a/readme.md b/readme.md deleted file mode 100644 index dc34f3e7..00000000 --- a/readme.md +++ /dev/null @@ -1,21 +0,0 @@ -# The (Tiny)Go SDK for Spin - -This package contains an SDK that facilitates building Spin components in -(Tiny)Go. It allows building HTTP components that target the Spin -executor. - -```go -import ( - "fmt" - spinhttp "github.com/spinframework/spin-go-sdk/v2/http" -) - -func init() { - // call the Handle function - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Hello, Fermyon!") - }) -} - -func main() {} -``` diff --git a/redis/internals.go b/redis/internals.go deleted file mode 100644 index 4b71ab63..00000000 --- a/redis/internals.go +++ /dev/null @@ -1,241 +0,0 @@ -package redis - -// #include "outbound-redis.h" -// #include "spin-redis.h" -// #include -import "C" -import ( - "errors" - "fmt" - "unsafe" -) - -// argumentKind represents a type of a argument for executing a Redis command. -type argumentKind uint8 - -const ( - argumentKindInt argumentKind = iota - argumentKindBinary -) - -// argument represents an argument for a Redis command. -type argument struct { - kind argumentKind - val any -} - -func createParameter(x any) (*argument, error) { - var p argument - switch v := x.(type) { - case int: - p.kind = argumentKindInt - p.val = int64(v) - case int32: - p.kind = argumentKindInt - p.val = int64(v) - case int64: - p.kind = argumentKindInt - p.val = v - case string: - p.kind = argumentKindBinary - p.val = []byte(v) - case []byte: - p.kind = argumentKindBinary - p.val = v - default: - return &p, fmt.Errorf("unsupported parameter type: %T", x) - } - return &p, nil -} - -//export spin_redis_handle_redis_message -func handleRedisMessage(payload *C.spin_redis_payload_t) C.spin_redis_error_t { - bytes := C.GoBytes(unsafe.Pointer(payload.ptr), C.int(payload.len)) - if err := handler(bytes); err != nil { - return C.uint8_t(1) - - } - return C.uint8_t(0) -} - -func publish(addr, channel string, payload []byte) error { - caddr := redisStr(addr) - cchannel := redisStr(channel) - cpayload := C.outbound_redis_payload_t{ptr: &payload[0], len: C.size_t(len(payload))} - - err := C.outbound_redis_publish(&caddr, &cchannel, &cpayload) - return toErr(err) -} - -func get(addr, key string) ([]byte, error) { - caddr := redisStr(addr) - ckey := redisStr(key) - - var cpayload C.outbound_redis_payload_t - - err := C.outbound_redis_get(&caddr, &ckey, &cpayload) - payload := C.GoBytes(unsafe.Pointer(cpayload.ptr), C.int(cpayload.len)) - return payload, toErr(err) -} - -func set(addr, key string, payload []byte) error { - caddr := redisStr(addr) - ckey := redisStr(key) - cpayload := C.outbound_redis_payload_t{ptr: &payload[0], len: C.size_t(len(payload))} - - err := C.outbound_redis_set(&caddr, &ckey, &cpayload) - return toErr(err) -} - -func incr(addr, key string) (int64, error) { - caddr := redisStr(addr) - ckey := redisStr(key) - - var cpayload C.int64_t - - err := C.outbound_redis_incr(&caddr, &ckey, &cpayload) - return int64(cpayload), toErr(err) -} - -func del(addr string, keys []string) (int64, error) { - caddr := redisStr(addr) - ckeys := redisListStr(keys) - - var cpayload C.int64_t - - err := C.outbound_redis_del(&caddr, &ckeys, &cpayload) - return int64(cpayload), toErr(err) -} - -func sadd(addr, key string, values []string) (int64, error) { - caddr := redisStr(addr) - ckey := redisStr(key) - cvalues := redisListStr(values) - - var cpayload C.int64_t - - err := C.outbound_redis_sadd(&caddr, &ckey, &cvalues, &cpayload) - return int64(cpayload), toErr(err) -} - -func smembers(addr, key string) ([]string, error) { - caddr := redisStr(addr) - ckey := redisStr(key) - - var cpayload C.outbound_redis_list_string_t - - err := C.outbound_redis_smembers(&caddr, &ckey, &cpayload) - return fromRedisListStr(&cpayload), toErr(err) -} - -func srem(addr, key string, values []string) (int64, error) { - caddr := redisStr(addr) - ckey := redisStr(key) - cvalues := redisListStr(values) - - var cpayload C.int64_t - - err := C.outbound_redis_srem(&caddr, &ckey, &cvalues, &cpayload) - return int64(cpayload), toErr(err) -} - -func execute(addr, command string, arguments []*argument) ([]*Result, error) { - caddr := redisStr(addr) - ccommand := redisStr(command) - carguments := redisListParameter(arguments) - - var cpayload C.outbound_redis_list_redis_result_t - - err := C.outbound_redis_execute(&caddr, &ccommand, &carguments, &cpayload) - return fromRedisListResult(&cpayload), toErr(err) -} - -func redisStr(x string) C.outbound_redis_string_t { - return C.outbound_redis_string_t{ptr: C.CString(x), len: C.size_t(len(x))} -} - -func redisListStr(xs []string) C.outbound_redis_list_string_t { - if len(xs) == 0 { - return C.outbound_redis_list_string_t{} - } - cxs := make([]C.outbound_redis_string_t, 0, len(xs)) - for i := 0; i < len(xs); i++ { - cxs = append(cxs, redisStr(xs[i])) - } - return C.outbound_redis_list_string_t{ptr: &cxs[0], len: C.size_t(len(cxs))} -} - -func fromRedisListStr(list *C.outbound_redis_list_string_t) []string { - listLen := int(list.len) - result := make([]string, 0, listLen) - - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - str := slice[i] - result = append(result, C.GoStringN(str.ptr, C.int(str.len))) - } - return result -} - -func redisParameter(x *argument) C.outbound_redis_redis_parameter_t { - var ret C.outbound_redis_redis_parameter_t - switch x.kind { - case argumentKindInt: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = x.val.(int64) - case argumentKindBinary: - value := x.val.([]byte) - payload := C.outbound_redis_payload_t{ptr: &value[0], len: C.size_t(len(value))} - *(*C.outbound_redis_payload_t)(unsafe.Pointer(&ret.val)) = payload - } - ret.tag = C.uint8_t(x.kind) - return ret -} - -func redisListParameter(xs []*argument) C.outbound_redis_list_redis_parameter_t { - if len(xs) == 0 { - return C.outbound_redis_list_redis_parameter_t{} - } - - cxs := make([]C.outbound_redis_redis_parameter_t, 0, len(xs)) - for i := 0; i < len(xs); i++ { - cxs = append(cxs, redisParameter(xs[i])) - } - return C.outbound_redis_list_redis_parameter_t{ptr: &cxs[0], len: C.size_t(len(cxs))} -} - -func fromRedisResult(result *C.outbound_redis_redis_result_t) *Result { - var val any - switch ResultKind(result.tag) { - case ResultKindNil: - val = nil - case ResultKindStatus: - str := (*C.outbound_redis_string_t)(unsafe.Pointer(&result.val)) - val = C.GoStringN(str.ptr, C.int(str.len)) - case ResultKindInt64: - val = int64(*(*C.int64_t)(unsafe.Pointer(&result.val))) - case ResultKindBinary: - payload := (*C.outbound_redis_payload_t)(unsafe.Pointer(&result.val)) - val = C.GoBytes(unsafe.Pointer(payload.ptr), C.int(payload.len)) - } - - return &Result{Kind: ResultKind(result.tag), Val: val} -} - -func fromRedisListResult(list *C.outbound_redis_list_redis_result_t) []*Result { - listLen := int(list.len) - result := make([]*Result, 0, listLen) - - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - result = append(result, fromRedisResult(&slice[i])) - } - - return result -} - -func toErr(code C.uint8_t) error { - if code == 1 { - return errors.New("internal server error") - } - return nil -} diff --git a/redis/internals_test.go b/redis/internals_test.go deleted file mode 100644 index 191fa6ee..00000000 --- a/redis/internals_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package redis - -import ( - "reflect" - "testing" -) - -func TestCreateParameter(t *testing.T) { - tests := []struct { - in any - want argumentKind - }{ - {in: "a", want: argumentKindBinary}, - {in: []byte("b"), want: argumentKindBinary}, - {in: 1, want: argumentKindInt}, - {in: int64(2), want: argumentKindInt}, - {in: int32(3), want: argumentKindInt}, - } - - for _, tc := range tests { - p, err := createParameter(tc.in) - if err != nil { - t.Error(err) - } - if p.kind != tc.want { - t.Errorf("want %s, got %s", tc.want, p.kind) - } - } -} - -func TestRedisListString(t *testing.T) { - list := []string{"a", "b", "c"} - - rlist := redisListStr(list) - got := fromRedisListStr(&rlist) - - if !reflect.DeepEqual(list, got) { - t.Errorf("want %s, got %s", list, got) - } -} diff --git a/redis/outbound-redis.c b/redis/outbound-redis.c deleted file mode 100644 index 40feb726..00000000 --- a/redis/outbound-redis.c +++ /dev/null @@ -1,320 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void outbound_redis_string_set(outbound_redis_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void outbound_redis_string_dup(outbound_redis_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void outbound_redis_string_free(outbound_redis_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void outbound_redis_payload_free(outbound_redis_payload_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void outbound_redis_redis_parameter_free(outbound_redis_redis_parameter_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - outbound_redis_payload_free(&ptr->val.binary); - break; - } - } -} -void outbound_redis_redis_result_free(outbound_redis_redis_result_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - outbound_redis_string_free(&ptr->val.status); - break; - } - case 3: { - outbound_redis_payload_free(&ptr->val.binary); - break; - } - } -} -typedef struct { - bool is_err; - union { - outbound_redis_error_t err; - } val; -} outbound_redis_expected_unit_error_t; -typedef struct { - bool is_err; - union { - outbound_redis_payload_t ok; - outbound_redis_error_t err; - } val; -} outbound_redis_expected_payload_error_t; -typedef struct { - bool is_err; - union { - int64_t ok; - outbound_redis_error_t err; - } val; -} outbound_redis_expected_s64_error_t; -void outbound_redis_list_string_free(outbound_redis_list_string_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_redis_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -typedef struct { - bool is_err; - union { - outbound_redis_list_string_t ok; - outbound_redis_error_t err; - } val; -} outbound_redis_expected_list_string_error_t; -void outbound_redis_list_redis_parameter_free(outbound_redis_list_redis_parameter_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_redis_redis_parameter_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void outbound_redis_list_redis_result_free(outbound_redis_list_redis_result_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - outbound_redis_redis_result_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -typedef struct { - bool is_err; - union { - outbound_redis_list_redis_result_t ok; - outbound_redis_error_t err; - } val; -} outbound_redis_expected_list_redis_result_error_t; - -__attribute__((aligned(8))) -static uint8_t RET_AREA[16]; -__attribute__((import_module("outbound-redis"), import_name("publish"))) -void __wasm_import_outbound_redis_publish(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_publish(outbound_redis_string_t *address, outbound_redis_string_t *channel, outbound_redis_payload_t *payload) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_publish((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*channel).ptr, (int32_t) (*channel).len, (int32_t) (*payload).ptr, (int32_t) (*payload).len, ptr); - outbound_redis_expected_unit_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 1))); - break; - } - }return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("get"))) -void __wasm_import_outbound_redis_get(int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_get(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_payload_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_get((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - outbound_redis_expected_payload_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (outbound_redis_payload_t) { (uint8_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 4))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("set"))) -void __wasm_import_outbound_redis_set(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_set(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_payload_t *value) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_set((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr); - outbound_redis_expected_unit_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 1))); - break; - } - }return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("incr"))) -void __wasm_import_outbound_redis_incr(int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_incr(outbound_redis_string_t *address, outbound_redis_string_t *key, int64_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_incr((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - outbound_redis_expected_s64_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = *((int64_t*) (ptr + 8)); - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 8))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("del"))) -void __wasm_import_outbound_redis_del(int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_del(outbound_redis_string_t *address, outbound_redis_list_string_t *keys, int64_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_del((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*keys).ptr, (int32_t) (*keys).len, ptr); - outbound_redis_expected_s64_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = *((int64_t*) (ptr + 8)); - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 8))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("sadd"))) -void __wasm_import_outbound_redis_sadd(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_sadd(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *values, int64_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_sadd((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, (int32_t) (*values).ptr, (int32_t) (*values).len, ptr); - outbound_redis_expected_s64_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = *((int64_t*) (ptr + 8)); - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 8))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("smembers"))) -void __wasm_import_outbound_redis_smembers(int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_smembers(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_smembers((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - outbound_redis_expected_list_string_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (outbound_redis_list_string_t) { (outbound_redis_string_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 4))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("srem"))) -void __wasm_import_outbound_redis_srem(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_srem(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *values, int64_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_srem((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*key).ptr, (int32_t) (*key).len, (int32_t) (*values).ptr, (int32_t) (*values).len, ptr); - outbound_redis_expected_s64_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = *((int64_t*) (ptr + 8)); - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 8))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} -__attribute__((import_module("outbound-redis"), import_name("execute"))) -void __wasm_import_outbound_redis_execute(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -outbound_redis_error_t outbound_redis_execute(outbound_redis_string_t *address, outbound_redis_string_t *command, outbound_redis_list_redis_parameter_t *arguments, outbound_redis_list_redis_result_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_outbound_redis_execute((int32_t) (*address).ptr, (int32_t) (*address).len, (int32_t) (*command).ptr, (int32_t) (*command).len, (int32_t) (*arguments).ptr, (int32_t) (*arguments).len, ptr); - outbound_redis_expected_list_redis_result_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (outbound_redis_list_redis_result_t) { (outbound_redis_redis_result_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - - expected.val.err = (int32_t) (*((uint8_t*) (ptr + 4))); - break; - } - }*ret0 = expected.val.ok; - return expected.is_err ? expected.val.err : -1; -} diff --git a/redis/outbound-redis.h b/redis/outbound-redis.h deleted file mode 100644 index 4281bd97..00000000 --- a/redis/outbound-redis.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __BINDINGS_OUTBOUND_REDIS_H -#define __BINDINGS_OUTBOUND_REDIS_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } outbound_redis_string_t; - - void outbound_redis_string_set(outbound_redis_string_t *ret, const char *s); - void outbound_redis_string_dup(outbound_redis_string_t *ret, const char *s); - void outbound_redis_string_free(outbound_redis_string_t *ret); - typedef uint8_t outbound_redis_error_t; - #define OUTBOUND_REDIS_ERROR_SUCCESS 0 - #define OUTBOUND_REDIS_ERROR_ERROR 1 - typedef struct { - uint8_t *ptr; - size_t len; - } outbound_redis_payload_t; - void outbound_redis_payload_free(outbound_redis_payload_t *ptr); - typedef struct { - uint8_t tag; - union { - int64_t int64; - outbound_redis_payload_t binary; - } val; - } outbound_redis_redis_parameter_t; - #define OUTBOUND_REDIS_REDIS_PARAMETER_INT64 0 - #define OUTBOUND_REDIS_REDIS_PARAMETER_BINARY 1 - void outbound_redis_redis_parameter_free(outbound_redis_redis_parameter_t *ptr); - typedef struct { - uint8_t tag; - union { - outbound_redis_string_t status; - int64_t int64; - outbound_redis_payload_t binary; - } val; - } outbound_redis_redis_result_t; - #define OUTBOUND_REDIS_REDIS_RESULT_NIL 0 - #define OUTBOUND_REDIS_REDIS_RESULT_STATUS 1 - #define OUTBOUND_REDIS_REDIS_RESULT_INT64 2 - #define OUTBOUND_REDIS_REDIS_RESULT_BINARY 3 - void outbound_redis_redis_result_free(outbound_redis_redis_result_t *ptr); - typedef struct { - outbound_redis_string_t *ptr; - size_t len; - } outbound_redis_list_string_t; - void outbound_redis_list_string_free(outbound_redis_list_string_t *ptr); - typedef struct { - outbound_redis_redis_parameter_t *ptr; - size_t len; - } outbound_redis_list_redis_parameter_t; - void outbound_redis_list_redis_parameter_free(outbound_redis_list_redis_parameter_t *ptr); - typedef struct { - outbound_redis_redis_result_t *ptr; - size_t len; - } outbound_redis_list_redis_result_t; - void outbound_redis_list_redis_result_free(outbound_redis_list_redis_result_t *ptr); - outbound_redis_error_t outbound_redis_publish(outbound_redis_string_t *address, outbound_redis_string_t *channel, outbound_redis_payload_t *payload); - outbound_redis_error_t outbound_redis_get(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_payload_t *ret0); - outbound_redis_error_t outbound_redis_set(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_payload_t *value); - outbound_redis_error_t outbound_redis_incr(outbound_redis_string_t *address, outbound_redis_string_t *key, int64_t *ret0); - outbound_redis_error_t outbound_redis_del(outbound_redis_string_t *address, outbound_redis_list_string_t *keys, int64_t *ret0); - outbound_redis_error_t outbound_redis_sadd(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *values, int64_t *ret0); - outbound_redis_error_t outbound_redis_smembers(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *ret0); - outbound_redis_error_t outbound_redis_srem(outbound_redis_string_t *address, outbound_redis_string_t *key, outbound_redis_list_string_t *values, int64_t *ret0); - outbound_redis_error_t outbound_redis_execute(outbound_redis_string_t *address, outbound_redis_string_t *command, outbound_redis_list_redis_parameter_t *arguments, outbound_redis_list_redis_result_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/redis/redis.go b/redis/redis.go index a5b03736..56ac1bea 100644 --- a/redis/redis.go +++ b/redis/redis.go @@ -1,89 +1,134 @@ -// Package redis provides the handler function for the Redis trigger, as well -// as access to Redis within Spin components. +// Package redis provides access to Redis within Spin components, as well as a +// handler for inbound Redis messages. + package redis import ( - "errors" "fmt" - "os" -) -// handler is the function that will be called by the Redis trigger in Spin. -var handler = defaultHandler - -// defaultHandler is a placeholder for returning a useful error to stdout when -// the handler is not set. -var defaultHandler = func(payload []byte) error { - fmt.Fprintln(os.Stderr, "redis handler undefined") - return nil -} + incominghandler "github.com/spinframework/spin-go-sdk/v3/internal/export_fermyon_spin_inbound_redis" + redis "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_redis" + redis_types "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_redis_types" + _ "github.com/spinframework/spin-go-sdk/v3/internal/wit_exports" + wit "go.bytecodealliance.org/pkg/wit/types" +) -// Handle sets the handler function for redis. -// It must be set in an init() function. -func Handle(fn func(payload []byte) error) { - handler = fn +func Handle(handle func(message []byte) error) { + incominghandler.Exports.Handle = func(message []byte) wit.Result[wit.Unit, redis_types.Error] { + err := handle(message) + if err == nil { + return wit.Err[wit.Unit, redis_types.Error](redis_types.ErrorError) + } else { + return wit.Ok[wit.Unit, redis_types.Error](wit.Unit{}) + } + } } // Client is a Redis client. type Client struct { - addr string + conn redis.Connection } // NewClient returns a Redis client. -func NewClient(address string) *Client { - return &Client{addr: address} +func NewClient(address string) (Client, error) { + result := redis.ConnectionOpen(address) + if result.IsErr() { + return Client{}, toError(result.Err()) + } + + return Client{conn: *result.Ok()}, nil } // Publish a Redis message to the specified channel. func (c *Client) Publish(channel string, payload []byte) error { - if len(payload) == 0 { - return errors.New("payload is empty") + result := c.conn.Publish(channel, redis.Payload(payload)) + if result.IsErr() { + return toError(result.Err()) } - return publish(c.addr, channel, payload) + + return nil } -// Get the value of a key. An error is returned if the value stored at key is -// not a string. +// Get the value of a key. func (c *Client) Get(key string) ([]byte, error) { - return get(c.addr, key) + result := c.conn.Get(key) + if result.IsErr() { + return nil, toError(result.Err()) + } + + if result.Ok().IsNone() { + return nil, nil + } + + return result.Ok().Some(), nil } -// Set key to value. If key alreads holds a value, it is overwritten. +// Set key to value. +// +// If key already holds a value, it is overwritten. func (c *Client) Set(key string, payload []byte) error { - if len(payload) == 0 { - return errors.New("payload is empty") + result := c.conn.Set(key, redis.Payload(payload)) + if result.IsErr() { + return toError(result.Err()) } - return set(c.addr, key, payload) + + return nil } -// Incr increments the number stored at key by one. If the key does not exist, -// it is set to 0 before performing the operation. An error is returned if -// the key contains a value of the wrong type or contains a string that can not -// be represented as integer. +// Increments the number stored at key by one. +// +// If the key does not exist, it is set to 0 before performing the operation. +// An `error::type-error` is returned if the key contains a value of the wrong type +// or contains a string that can not be represented as integer. func (c *Client) Incr(key string) (int64, error) { - return incr(c.addr, key) + result := c.conn.Incr(key) + if result.IsErr() { + return 0, toError(result.Err()) + } + + return result.Ok(), nil } -// Del removes the specified keys. A key is ignored if it does not exist. -func (c *Client) Del(keys ...string) (int64, error) { - return del(c.addr, keys) +// Removes the specified keys. +// +// A key is ignored if it does not exist. Returns the number of keys deleted. +func (c *Client) Del(keys ...string) (uint32, error) { + result := c.conn.Del(keys) + if result.IsErr() { + return 0, toError(result.Err()) + } + + return result.Ok(), nil } -// Sadd adds the specified values to the set for the specified key, creating -// it if it does not already exist. -func (c *Client) Sadd(key string, values ...string) (int64, error) { - return sadd(c.addr, key, values) +// Add the specified `values` to the set named `key`, returning the number of newly-added values. +func (c *Client) Sadd(key string, values ...string) (uint32, error) { + result := c.conn.Sadd(key, values) + if result.IsErr() { + return 0, toError(result.Err()) + } + + return result.Ok(), nil } -// Smembers gets the elements of the set for the specified key. +// Retrieve the contents of the set named `key`. func (c *Client) Smembers(key string) ([]string, error) { - return smembers(c.addr, key) + result := c.conn.Smembers(key) + if result.IsErr() { + return nil, toError(result.Err()) + } + + return result.Ok(), nil } -// Srem removes the specified elements from the set for the specified key. -// This has no effect if the key does not exist. -func (c *Client) Srem(key string, values ...string) (int64, error) { - return srem(c.addr, key, values) +// Remove the specified `values` from the set named `key`, returning the number of newly-removed values. +func (c *Client) Srem(key string, values ...string) (uint32, error) { + result := c.conn.Srem(key, values) + if result.IsErr() { + return 0, toError(result.Err()) + } + + return result.Ok(), nil } // ResultKind represents a result type returned from executing a Redis command. @@ -127,7 +172,7 @@ type Result struct { // // Arguments must be string, []byte, int, int64, or int32. func (c *Client) Execute(command string, arguments ...any) ([]*Result, error) { - var params []*argument + var params []redis.RedisParameter for _, a := range arguments { p, err := createParameter(a) if err != nil { @@ -135,5 +180,62 @@ func (c *Client) Execute(command string, arguments ...any) ([]*Result, error) { } params = append(params, p) } - return execute(c.addr, command, params) + + result := c.conn.Execute(command, params) + if result.IsErr() { + return nil, toError(result.Err()) + } + + var results []*Result + for _, r := range result.Ok() { + results = append(results, toResult(r)) + } + + return results, nil +} + +func createParameter(x any) (redis.RedisParameter, error) { + switch v := x.(type) { + case int: + return redis.MakeRedisParameterInt64(int64(v)), nil + case int64: + return redis.MakeRedisParameterInt64(v), nil + case int32: + return redis.MakeRedisParameterInt64(int64(v)), nil + case []byte: + return redis.MakeRedisParameterBinary(redis.Payload(v)), nil + case string: + return redis.MakeRedisParameterBinary(redis.Payload(v)), nil + default: + return redis.RedisParameter{}, fmt.Errorf("invalid type %T; must be string, []byte, int, int64, or int32", v) + } +} + +func toResult(param redis.RedisResult) *Result { + switch param.Tag() { + case redis.RedisResultStatus: + return &Result{ + Kind: ResultKindStatus, + Val: param.Status(), + } + case redis.RedisResultInt64: + return &Result{ + Kind: ResultKindInt64, + Val: param.Int64(), + } + case redis.RedisResultBinary: + return &Result{ + Kind: ResultKindBinary, + Val: param.Binary(), + } + default: + return &Result{ + Kind: ResultKindNil, + Val: nil, + } + } +} + +func toError(e redis.Error) error { + return fmt.Errorf("%v", e.Other()) } diff --git a/redis/spin-redis.c b/redis/spin-redis.c deleted file mode 100644 index 665d4ebd..00000000 --- a/redis/spin-redis.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void spin_redis_string_set(spin_redis_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void spin_redis_string_dup(spin_redis_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void spin_redis_string_free(spin_redis_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void spin_redis_payload_free(spin_redis_payload_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void spin_redis_redis_parameter_free(spin_redis_redis_parameter_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - spin_redis_payload_free(&ptr->val.binary); - break; - } - } -} -void spin_redis_redis_result_free(spin_redis_redis_result_t *ptr) { - switch ((int32_t) ptr->tag) { - case 1: { - spin_redis_string_free(&ptr->val.status); - break; - } - case 3: { - spin_redis_payload_free(&ptr->val.binary); - break; - } - } -} -typedef struct { - bool is_err; - union { - spin_redis_error_t err; - } val; -} spin_redis_expected_unit_error_t; - -__attribute__((aligned(1))) -static uint8_t RET_AREA[2]; -__attribute__((export_name("handle-redis-message"))) -int32_t __wasm_export_spin_redis_handle_redis_message(int32_t arg, int32_t arg0) { - spin_redis_payload_t arg1 = (spin_redis_payload_t) { (uint8_t*)(arg), (size_t)(arg0) }; - spin_redis_error_t ret = spin_redis_handle_redis_message(&arg1); - - spin_redis_expected_unit_error_t ret2; - if (ret <= 2) { - ret2.is_err = true; - ret2.val.err = ret; - } else { - ret2.is_err = false; - - } - int32_t ptr = (int32_t) &RET_AREA; - - if ((ret2).is_err) { - const spin_redis_error_t *payload3 = &(ret2).val.err; - *((int8_t*)(ptr + 0)) = 1; - *((int8_t*)(ptr + 1)) = (int32_t) *payload3; - - } else { - - *((int8_t*)(ptr + 0)) = 0; - - } - return ptr; -} diff --git a/redis/spin-redis.h b/redis/spin-redis.h deleted file mode 100644 index 9f73ba40..00000000 --- a/redis/spin-redis.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __BINDINGS_SPIN_REDIS_H -#define __BINDINGS_SPIN_REDIS_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } spin_redis_string_t; - - void spin_redis_string_set(spin_redis_string_t *ret, const char *s); - void spin_redis_string_dup(spin_redis_string_t *ret, const char *s); - void spin_redis_string_free(spin_redis_string_t *ret); - typedef uint8_t spin_redis_error_t; - #define SPIN_REDIS_ERROR_SUCCESS 0 - #define SPIN_REDIS_ERROR_ERROR 1 - typedef struct { - uint8_t *ptr; - size_t len; - } spin_redis_payload_t; - void spin_redis_payload_free(spin_redis_payload_t *ptr); - typedef struct { - uint8_t tag; - union { - int64_t int64; - spin_redis_payload_t binary; - } val; - } spin_redis_redis_parameter_t; - #define SPIN_REDIS_REDIS_PARAMETER_INT64 0 - #define SPIN_REDIS_REDIS_PARAMETER_BINARY 1 - void spin_redis_redis_parameter_free(spin_redis_redis_parameter_t *ptr); - typedef struct { - uint8_t tag; - union { - spin_redis_string_t status; - int64_t int64; - spin_redis_payload_t binary; - } val; - } spin_redis_redis_result_t; - #define SPIN_REDIS_REDIS_RESULT_NIL 0 - #define SPIN_REDIS_REDIS_RESULT_STATUS 1 - #define SPIN_REDIS_REDIS_RESULT_INT64 2 - #define SPIN_REDIS_REDIS_RESULT_BINARY 3 - void spin_redis_redis_result_free(spin_redis_redis_result_t *ptr); - spin_redis_error_t spin_redis_handle_redis_message(spin_redis_payload_t *message); - #ifdef __cplusplus -} -#endif -#endif diff --git a/sdk_version/sdk-version-go-template.c b/sdk_version/sdk-version-go-template.c deleted file mode 100644 index ebddb4b1..00000000 --- a/sdk_version/sdk-version-go-template.c +++ /dev/null @@ -1,14 +0,0 @@ -__attribute__((weak, export_name("spin-sdk-version-{{VERSION}}"))) -void __spin_sdk_version(void) { - -} - -__attribute__((weak, export_name("spin-sdk-language-go"))) -void __spin_sdk_language(void) { - -} - -__attribute__((weak, export_name("spin-sdk-commit-{{COMMIT}}"))) -void __spin_sdk_commit(void) { - -} diff --git a/sqlite/internals.go b/sqlite/internals.go deleted file mode 100644 index 441710f3..00000000 --- a/sqlite/internals.go +++ /dev/null @@ -1,169 +0,0 @@ -package sqlite - -// #include "sqlite.h" -import "C" -import ( - "errors" - "fmt" - "unsafe" -) - -func open(name string) (*conn, error) { - var dbname C.sqlite_string_t - var ret C.sqlite_expected_connection_error_t - - dbname = sqliteStr(name) - C.sqlite_open(&dbname, &ret) - - if ret.is_err { - return nil, toErr((*C.sqlite_error_t)(unsafe.Pointer(&ret.val))) - } - - sqliteConn := *((*C.sqlite_connection_t)(unsafe.Pointer(&ret.val))) - return &conn{_ptr: sqliteConn}, nil -} - -func (db *conn) close() { - C.sqlite_close(db._ptr) -} - -func (db *conn) execute(statement string, args []any) (*rows, error) { - var ret C.sqlite_expected_query_result_error_t - defer C.sqlite_expected_query_result_error_free(&ret) - - sqliteStatement := sqliteStr(statement) - params := toSqliteListValue(args) - - C.sqlite_execute(db._ptr, &sqliteStatement, ¶ms, &ret) - - if ret.is_err { - spinErr := (*C.sqlite_error_t)(unsafe.Pointer(&ret.val)) - return nil, toErr(spinErr) - } - - qr := (*C.sqlite_query_result_t)(unsafe.Pointer(&ret.val)) - - result := &rows{ - columns: fromSqliteListString(qr.columns), - rows: fromSqliteListRowResult(qr.rows), - len: int(qr.rows.len), - } - - return result, nil -} - -func fromSqliteListRowResult(list C.sqlite_list_row_result_t) [][]any { - listLen := int(list.len) - ret := make([][]any, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - row := *((*C.sqlite_list_value_t)(unsafe.Pointer(&slice[i]))) - ret[i] = fromSqliteListValue(row) - } - return ret - -} - -func fromSqliteListString(list C.sqlite_list_string_t) []string { - listLen := int(list.len) - ret := make([]string, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - str := slice[i] - ret[i] = C.GoStringN(str.ptr, C.int(str.len)) - } - return ret -} - -func fromSqliteListValue(list C.sqlite_list_value_t) []any { - listLen := int(list.len) - ret := make([]any, listLen) - slice := unsafe.Slice(list.ptr, listLen) - for i := 0; i < listLen; i++ { - ret[i] = fromSqliteValue(slice[i]) - } - return ret -} - -func toSqliteListValue(xv []any) C.sqlite_list_value_t { - if len(xv) == 0 { - return C.sqlite_list_value_t{} - } - cxv := make([]C.sqlite_value_t, len(xv)) - for i := 0; i < len(xv); i++ { - cxv[i] = toSqliteValue(xv[i]) - } - return C.sqlite_list_value_t{ptr: &cxv[0], len: C.size_t(len(cxv))} -} - -const ( - valueInt uint8 = iota - valueReal - valueText - valueBlob - valueNull -) - -func toSqliteValue(x any) C.sqlite_value_t { - var ret C.sqlite_value_t - switch v := x.(type) { - case int: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = int64(v) - ret.tag = valueInt - case int64: - *(*C.int64_t)(unsafe.Pointer(&ret.val)) = v - ret.tag = valueInt - case float64: - *(*C.double)(unsafe.Pointer(&ret.val)) = v - ret.tag = valueReal - case string: - str := sqliteStr(v) - *(*C.sqlite_string_t)(unsafe.Pointer(&ret.val)) = str - ret.tag = valueText - case []byte: - blob := C.sqlite_list_u8_t{ptr: &v[0], len: C.size_t(len(v))} - *(*C.sqlite_list_u8_t)(unsafe.Pointer(&ret.val)) = blob - ret.tag = valueBlob - default: - ret.tag = valueNull - } - return ret -} - -func fromSqliteValue(x C.sqlite_value_t) any { - switch x.tag { - case valueInt: - return int64(*(*C.int64_t)(unsafe.Pointer(&x.val))) - case valueReal: - return float64(*(*C.double)(unsafe.Pointer(&x.val))) - case valueBlob: - blob := (*C.sqlite_list_u8_t)(unsafe.Pointer(&x.val)) - return C.GoBytes(unsafe.Pointer(blob.ptr), C.int(blob.len)) - case valueText: - str := (*C.sqlite_string_t)(unsafe.Pointer(&x.val)) - return C.GoStringN(str.ptr, C.int(str.len)) - } - return nil -} - -func sqliteStr(x string) C.sqlite_string_t { - return C.sqlite_string_t{ptr: C.CString(x), len: C.size_t(len(x))} -} - -func toErr(err *C.sqlite_error_t) error { - switch err.tag { - case 0: - return errors.New("no such database") - case 1: - return errors.New("access denied") - case 2: - return errors.New("invalid connection") - case 3: - return errors.New("database full") - case 4: - str := (*C.sqlite_string_t)(unsafe.Pointer(&err.val)) - return errors.New(fmt.Sprintf("io error: %s", C.GoStringN(str.ptr, C.int(str.len)))) - default: - return errors.New(fmt.Sprintf("unrecognized error: %v", err.tag)) - } -} diff --git a/sqlite/internals_test.go b/sqlite/internals_test.go deleted file mode 100644 index 7e85bb05..00000000 --- a/sqlite/internals_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package sqlite - -import ( - "reflect" - "testing" -) - -func TestValue(t *testing.T) { - tests := []any{ - int64(1234), - 3.14, - "foo", - []byte("bar"), - nil, - } - - for _, tc := range tests { - got := fromSqliteValue(toSqliteValue(tc)) - if !reflect.DeepEqual(tc, got) { - t.Errorf("want %T(%#v), got %T(%#v)", tc, tc, got, got) - } - } -} - -func TestValueList(t *testing.T) { - tc := []any{ - int64(1234), - 3.14, - "foo", - []byte("bar"), - nil, - } - - got := fromSqliteListValue(toSqliteListValue(tc)) - if !reflect.DeepEqual(tc, got) { - t.Errorf("want %v, got %v", tc, got) - } -} diff --git a/sqlite/sqlite.c b/sqlite/sqlite.c deleted file mode 100644 index 62e08af8..00000000 --- a/sqlite/sqlite.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void sqlite_string_set(sqlite_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void sqlite_string_dup(sqlite_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void sqlite_string_free(sqlite_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void sqlite_error_free(sqlite_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 4: { - sqlite_string_free(&ptr->val.io); - break; - } - } -} -void sqlite_list_string_free(sqlite_list_string_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - sqlite_string_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void sqlite_list_u8_free(sqlite_list_u8_t *ptr) { - canonical_abi_free(ptr->ptr, ptr->len * 1, 1); -} -void sqlite_value_free(sqlite_value_t *ptr) { - switch ((int32_t) ptr->tag) { - case 2: { - sqlite_string_free(&ptr->val.text); - break; - } - case 3: { - sqlite_list_u8_free(&ptr->val.blob); - break; - } - } -} -void sqlite_list_value_free(sqlite_list_value_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - sqlite_value_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 16, 8); -} -void sqlite_row_result_free(sqlite_row_result_t *ptr) { - sqlite_list_value_free(&ptr->values); -} -void sqlite_list_row_result_free(sqlite_list_row_result_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - sqlite_row_result_free(&ptr->ptr[i]); - } - canonical_abi_free(ptr->ptr, ptr->len * 8, 4); -} -void sqlite_query_result_free(sqlite_query_result_t *ptr) { - sqlite_list_string_free(&ptr->columns); - sqlite_list_row_result_free(&ptr->rows); -} -void sqlite_expected_connection_error_free(sqlite_expected_connection_error_t *ptr) { - if (!ptr->is_err) { - } else { - sqlite_error_free(&ptr->val.err); - } -} -void sqlite_expected_query_result_error_free(sqlite_expected_query_result_error_t *ptr) { - if (!ptr->is_err) { - sqlite_query_result_free(&ptr->val.ok); - } else { - sqlite_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[20]; -__attribute__((import_module("sqlite"), import_name("open"))) -void __wasm_import_sqlite_open(int32_t, int32_t, int32_t); -void sqlite_open(sqlite_string_t *name, sqlite_expected_connection_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_sqlite_open((int32_t) (*name).ptr, (int32_t) (*name).len, ptr); - sqlite_expected_connection_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (uint32_t) (*((int32_t*) (ptr + 4))); - break; - } - case 1: { - expected.is_err = true; - sqlite_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; - } - case 3: { - break; - } - case 4: { - variant.val.io = (sqlite_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("sqlite"), import_name("execute"))) -void __wasm_import_sqlite_execute(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t); -void sqlite_execute(sqlite_connection_t conn, sqlite_string_t *statement, sqlite_list_value_t *parameters, sqlite_expected_query_result_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_sqlite_execute((int32_t) (conn), (int32_t) (*statement).ptr, (int32_t) (*statement).len, (int32_t) (*parameters).ptr, (int32_t) (*parameters).len, ptr); - sqlite_expected_query_result_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (sqlite_query_result_t) { - (sqlite_list_string_t) { (sqlite_string_t*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }, - (sqlite_list_row_result_t) { (sqlite_row_result_t*)(*((int32_t*) (ptr + 12))), (size_t)(*((int32_t*) (ptr + 16))) }, - }; - break; - } - case 1: { - expected.is_err = true; - sqlite_error_t variant4; - variant4.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant4.tag) { - case 0: { - break; - } - case 1: { - break; - } - case 2: { - break; - } - case 3: { - break; - } - case 4: { - variant4.val.io = (sqlite_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant4; - break; - } - }*ret0 = expected; -} -__attribute__((import_module("sqlite"), import_name("close"))) -void __wasm_import_sqlite_close(int32_t); -void sqlite_close(sqlite_connection_t conn) { - __wasm_import_sqlite_close((int32_t) (conn)); -} diff --git a/sqlite/sqlite.go b/sqlite/sqlite.go index 5f783baa..5b7ea938 100644 --- a/sqlite/sqlite.go +++ b/sqlite/sqlite.go @@ -7,7 +7,8 @@ import ( "errors" "io" - spindb "github.com/spinframework/spin-go-sdk/v2/internal/db" + spindb "github.com/spinframework/spin-go-sdk/v3/internal/db" + sqlite "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_sqlite" ) // Open returns a new connection to the database. @@ -17,18 +18,17 @@ func Open(name string) *sql.DB { // conn represents a database connection. type conn struct { - _ptr uint32 + spinConn sqlite.Connection } // Close the connection. func (c *conn) Close() error { - c.close() return nil } // Prepare returns a prepared statement, bound to this connection. func (c *conn) Prepare(query string) (driver.Stmt, error) { - return &stmt{c: c, query: query}, nil + return &stmt{conn: c, query: query}, nil } // Begin isn't supported. @@ -58,14 +58,12 @@ func (d *connector) Driver() driver.Driver { // Open returns a new connection to the database. func (d *connector) Open(name string) (driver.Conn, error) { - conn, err := open(name) - if err != nil { - return nil, err + results := sqlite.ConnectionOpen(name) + if results.IsErr() { + return nil, toError(results.Err()) } - - d.conn = conn - - return conn, err + d.conn = &conn{spinConn: *results.Ok()} + return d.conn, nil } // Close closes the connection to the database. @@ -132,7 +130,7 @@ func (r *rows) NextResultSet() error { } type stmt struct { - c *conn + conn *conn query string } @@ -152,22 +150,50 @@ func (s *stmt) NumInput() int { // Query executes a query that may return rows, such as a SELECT. func (s *stmt) Query(args []driver.Value) (driver.Rows, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] + sqliteParams := make([]sqlite.Value, len(args)) + for i, v := range args { + sqliteParams[i] = toSqliteValue(v) + } + + results := s.conn.spinConn.Execute(s.query, sqliteParams) + if results.IsErr() { + return nil, toError(results.Err()) + } + + rowLen := len(results.Ok().Rows) + allRows := make([][]any, rowLen) + for rowNum, row := range results.Ok().Rows { + allRows[rowNum] = toRow(row.Values) } - return s.c.execute(s.query, params) + + cols := results.Ok().Columns + colNames := make([]string, len(cols)) + for i, c := range cols { + colNames[i] = c + } + + rows := &rows{ + columns: colNames, + rows: allRows, + len: int(rowLen), + } + return rows, nil } // Exec executes a query that doesn't return rows, such as an INSERT or // UPDATE. func (s *stmt) Exec(args []driver.Value) (driver.Result, error) { - params := make([]any, len(args)) - for i := range args { - params[i] = args[i] + sqliteParams := make([]sqlite.Value, len(args)) + for i, v := range args { + sqliteParams[i] = toSqliteValue(v) + } + + queryResult := s.conn.spinConn.Execute(s.query, sqliteParams) + if queryResult.IsErr() { + return &result{}, toError(queryResult.Err()) } - _, err := s.c.execute(s.query, params) - return &result{}, err + + return &result{}, nil } // ColumnConverter returns GlobalParameterConverter to prevent using driver.DefaultParameterConverter. @@ -184,3 +210,77 @@ func (r result) LastInsertId() (int64, error) { func (r result) RowsAffected() (int64, error) { return -1, errors.New("RowsAffected is unsupported by this driver") } + +func toSqliteValue(x any) sqlite.Value { + switch v := x.(type) { + case int8: + return sqlite.MakeValueInteger(int64(v)) + case int16: + return sqlite.MakeValueInteger(int64(v)) + case int32: + return sqlite.MakeValueInteger(int64(v)) + case int64: + return sqlite.MakeValueInteger(v) + case int: + return sqlite.MakeValueInteger(int64(v)) + case uint8: + return sqlite.MakeValueInteger(int64(v)) + case uint16: + return sqlite.MakeValueInteger(int64(v)) + case uint32: + return sqlite.MakeValueInteger(int64(v)) + case uint64: + return sqlite.MakeValueInteger(int64(v)) + case float32: + return sqlite.MakeValueReal(float64(v)) + case float64: + return sqlite.MakeValueReal(v) + case string: + return sqlite.MakeValueText(v) + case []byte: + return sqlite.MakeValueBlob(v) + case nil: + return sqlite.MakeValueNull() + default: + panic("unknown value type") + } +} + +func toError(err sqlite.Error) error { + switch err.Tag() { + case sqlite.ErrorNoSuchDatabase: + return errors.New("no such database") + case sqlite.ErrorAccessDenied: + return errors.New("access denied") + case sqlite.ErrorInvalidConnection: + return errors.New("invalid connection") + case sqlite.ErrorDatabaseFull: + return errors.New("database full") + case sqlite.ErrorIo: + return errors.New(err.Io()) + default: + panic("unreachable code") + } +} + +func toRow(row []sqlite.Value) []any { + result := make([]any, len(row)) + for i, v := range row { + switch v.Tag() { + case sqlite.ValueInteger: + result[i] = v.Integer() + case sqlite.ValueReal: + result[i] = v.Real() + case sqlite.ValueText: + result[i] = v.Text() + case sqlite.ValueBlob: + result[i] = v.Blob() + case sqlite.ValueNull: + result[i] = nil + default: + panic("unreachable code") + } + } + + return result +} diff --git a/sqlite/sqlite.h b/sqlite/sqlite.h deleted file mode 100644 index 7d2e0cd2..00000000 --- a/sqlite/sqlite.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __BINDINGS_SQLITE_H -#define __BINDINGS_SQLITE_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } sqlite_string_t; - - void sqlite_string_set(sqlite_string_t *ret, const char *s); - void sqlite_string_dup(sqlite_string_t *ret, const char *s); - void sqlite_string_free(sqlite_string_t *ret); - typedef uint32_t sqlite_connection_t; - typedef struct { - uint8_t tag; - union { - sqlite_string_t io; - } val; - } sqlite_error_t; - #define SQLITE_ERROR_NO_SUCH_DATABASE 0 - #define SQLITE_ERROR_ACCESS_DENIED 1 - #define SQLITE_ERROR_INVALID_CONNECTION 2 - #define SQLITE_ERROR_DATABASE_FULL 3 - #define SQLITE_ERROR_IO 4 - void sqlite_error_free(sqlite_error_t *ptr); - typedef struct { - sqlite_string_t *ptr; - size_t len; - } sqlite_list_string_t; - void sqlite_list_string_free(sqlite_list_string_t *ptr); - typedef struct { - uint8_t *ptr; - size_t len; - } sqlite_list_u8_t; - void sqlite_list_u8_free(sqlite_list_u8_t *ptr); - typedef struct { - uint8_t tag; - union { - int64_t integer; - double real; - sqlite_string_t text; - sqlite_list_u8_t blob; - } val; - } sqlite_value_t; - #define SQLITE_VALUE_INTEGER 0 - #define SQLITE_VALUE_REAL 1 - #define SQLITE_VALUE_TEXT 2 - #define SQLITE_VALUE_BLOB 3 - #define SQLITE_VALUE_NULL 4 - void sqlite_value_free(sqlite_value_t *ptr); - typedef struct { - sqlite_value_t *ptr; - size_t len; - } sqlite_list_value_t; - void sqlite_list_value_free(sqlite_list_value_t *ptr); - typedef struct { - sqlite_list_value_t values; - } sqlite_row_result_t; - void sqlite_row_result_free(sqlite_row_result_t *ptr); - typedef struct { - sqlite_row_result_t *ptr; - size_t len; - } sqlite_list_row_result_t; - void sqlite_list_row_result_free(sqlite_list_row_result_t *ptr); - typedef struct { - sqlite_list_string_t columns; - sqlite_list_row_result_t rows; - } sqlite_query_result_t; - void sqlite_query_result_free(sqlite_query_result_t *ptr); - typedef struct { - bool is_err; - union { - sqlite_connection_t ok; - sqlite_error_t err; - } val; - } sqlite_expected_connection_error_t; - void sqlite_expected_connection_error_free(sqlite_expected_connection_error_t *ptr); - typedef struct { - bool is_err; - union { - sqlite_query_result_t ok; - sqlite_error_t err; - } val; - } sqlite_expected_query_result_error_t; - void sqlite_expected_query_result_error_free(sqlite_expected_query_result_error_t *ptr); - void sqlite_open(sqlite_string_t *name, sqlite_expected_connection_error_t *ret0); - void sqlite_execute(sqlite_connection_t conn, sqlite_string_t *statement, sqlite_list_value_t *parameters, sqlite_expected_query_result_error_t *ret0); - void sqlite_close(sqlite_connection_t conn); - #ifdef __cplusplus -} -#endif -#endif diff --git a/variables/internals.go b/variables/internals.go deleted file mode 100644 index 97ab580b..00000000 --- a/variables/internals.go +++ /dev/null @@ -1,42 +0,0 @@ -package variables - -// #cgo CFLAGS: -Wno-unused-parameter -Wno-switch-bool -// #include -// #include -import "C" -import ( - "errors" - "unsafe" -) - -func get(key string) (string, error) { - var spinResponse C.spin_config_expected_string_error_t - - spinKey := C.spin_config_string_t{ptr: C.CString(key), len: C.size_t(len(key))} - defer func() { - C.spin_config_expected_string_error_free(&spinResponse) - C.spin_config_string_free(&spinKey) - }() - - C.spin_config_get_config(&spinKey, &spinResponse) - - if spinResponse.is_err { // error response from spin - spinErr := (*C.spin_config_error_t)(unsafe.Pointer(&spinResponse.val)) - return "", toError(spinErr) - } - - ok := (*spinString)(unsafe.Pointer(&spinResponse.val)) - return ok.String(), nil -} - -func toError(err *C.spin_config_error_t) error { - spinErr := (*spinString)(unsafe.Pointer(&err.val)) - return errors.New(spinErr.String()) -} - -type spinString C.spin_config_string_t - -// String returns the spinString as a go string. -func (ss spinString) String() string { - return C.GoStringN(ss.ptr, C.int(ss.len)) -} diff --git a/variables/spin-config.c b/variables/spin-config.c deleted file mode 100644 index b2d1ab02..00000000 --- a/variables/spin-config.c +++ /dev/null @@ -1,117 +0,0 @@ -#include -#include - -__attribute__((weak, export_name("canonical_abi_realloc"))) -void *canonical_abi_realloc( -void *ptr, -size_t orig_size, -size_t align, -size_t new_size -) { - if (new_size == 0) - return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) - abort(); - return ret; -} - -__attribute__((weak, export_name("canonical_abi_free"))) -void canonical_abi_free( -void *ptr, -size_t size, -size_t align -) { - if (size == 0) - return; - free(ptr); -} -#include - -void spin_config_string_set(spin_config_string_t *ret, const char *s) { - ret->ptr = (char*) s; - ret->len = strlen(s); -} - -void spin_config_string_dup(spin_config_string_t *ret, const char *s) { - ret->len = strlen(s); - ret->ptr = canonical_abi_realloc(NULL, 0, 1, ret->len); - memcpy(ret->ptr, s, ret->len); -} - -void spin_config_string_free(spin_config_string_t *ret) { - canonical_abi_free(ret->ptr, ret->len, 1); - ret->ptr = NULL; - ret->len = 0; -} -void spin_config_error_free(spin_config_error_t *ptr) { - switch ((int32_t) ptr->tag) { - case 0: { - spin_config_string_free(&ptr->val.provider); - break; - } - case 1: { - spin_config_string_free(&ptr->val.invalid_key); - break; - } - case 2: { - spin_config_string_free(&ptr->val.invalid_schema); - break; - } - case 3: { - spin_config_string_free(&ptr->val.other); - break; - } - } -} -void spin_config_expected_string_error_free(spin_config_expected_string_error_t *ptr) { - if (!ptr->is_err) { - spin_config_string_free(&ptr->val.ok); - } else { - spin_config_error_free(&ptr->val.err); - } -} - -__attribute__((aligned(4))) -static uint8_t RET_AREA[16]; -__attribute__((import_module("spin-config"), import_name("get-config"))) -void __wasm_import_spin_config_get_config(int32_t, int32_t, int32_t); -void spin_config_get_config(spin_config_string_t *key, spin_config_expected_string_error_t *ret0) { - int32_t ptr = (int32_t) &RET_AREA; - __wasm_import_spin_config_get_config((int32_t) (*key).ptr, (int32_t) (*key).len, ptr); - spin_config_expected_string_error_t expected; - switch ((int32_t) (*((uint8_t*) (ptr + 0)))) { - case 0: { - expected.is_err = false; - - expected.val.ok = (spin_config_string_t) { (char*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) }; - break; - } - case 1: { - expected.is_err = true; - spin_config_error_t variant; - variant.tag = (int32_t) (*((uint8_t*) (ptr + 4))); - switch ((int32_t) variant.tag) { - case 0: { - variant.val.provider = (spin_config_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 1: { - variant.val.invalid_key = (spin_config_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 2: { - variant.val.invalid_schema = (spin_config_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - case 3: { - variant.val.other = (spin_config_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) }; - break; - } - } - - expected.val.err = variant; - break; - } - }*ret0 = expected; -} diff --git a/variables/spin-config.h b/variables/spin-config.h deleted file mode 100644 index 46be58d4..00000000 --- a/variables/spin-config.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __BINDINGS_SPIN_CONFIG_H -#define __BINDINGS_SPIN_CONFIG_H -#ifdef __cplusplus -extern "C" -{ - #endif - - #include - #include - - typedef struct { - char *ptr; - size_t len; - } spin_config_string_t; - - void spin_config_string_set(spin_config_string_t *ret, const char *s); - void spin_config_string_dup(spin_config_string_t *ret, const char *s); - void spin_config_string_free(spin_config_string_t *ret); - typedef struct { - uint8_t tag; - union { - spin_config_string_t provider; - spin_config_string_t invalid_key; - spin_config_string_t invalid_schema; - spin_config_string_t other; - } val; - } spin_config_error_t; - #define SPIN_CONFIG_ERROR_PROVIDER 0 - #define SPIN_CONFIG_ERROR_INVALID_KEY 1 - #define SPIN_CONFIG_ERROR_INVALID_SCHEMA 2 - #define SPIN_CONFIG_ERROR_OTHER 3 - void spin_config_error_free(spin_config_error_t *ptr); - typedef struct { - bool is_err; - union { - spin_config_string_t ok; - spin_config_error_t err; - } val; - } spin_config_expected_string_error_t; - void spin_config_expected_string_error_free(spin_config_expected_string_error_t *ptr); - void spin_config_get_config(spin_config_string_t *key, spin_config_expected_string_error_t *ret0); - #ifdef __cplusplus -} -#endif -#endif diff --git a/variables/testdata/variables/go.mod b/variables/testdata/variables/go.mod new file mode 100644 index 00000000..fa6b0b8f --- /dev/null +++ b/variables/testdata/variables/go.mod @@ -0,0 +1,11 @@ +module github.com/spinframework/spin-go-sdk/v3/examples/variables + +go 1.25.5 + +require ( + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/pkg v0.2.1 +) + +replace github.com/spinframework/spin-go-sdk/v3 => ../../../ diff --git a/variables/testdata/variables/go.sum b/variables/testdata/variables/go.sum new file mode 100644 index 00000000..b5bca15f --- /dev/null +++ b/variables/testdata/variables/go.sum @@ -0,0 +1,6 @@ +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0 h1:fbwpkAmU6eZnDQpBHrdQwPXi5atE0KSfjU8zwFkClnw= +github.com/bytecodealliance/wit-bindgen/crates/go/src/package v0.51.0/go.mod h1:MUXxhOBN0hAtqHjc9/9XAEiXcGhcwYL6PeDXkKwVZN0= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +go.bytecodealliance.org/pkg v0.2.1 h1:TdRagooIcCW3UmlKqVO4cDR3GNDyfDnbiBzGI6TOvyg= +go.bytecodealliance.org/pkg v0.2.1/go.mod h1:OjA+V8g3uUFixeCKFfamm6sYhTJdg8fvwEdJ2GO0GSk= diff --git a/variables/testdata/variables/main.go b/variables/testdata/variables/main.go new file mode 100644 index 00000000..b59196de --- /dev/null +++ b/variables/testdata/variables/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "net/http" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + "github.com/spinframework/spin-go-sdk/v3/variables" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + // Get variable value `message` defined in spin.toml. + val, err := variables.Get("message") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + fmt.Fprintln(w, "message: ", val) + }) +} + +func main() {} diff --git a/variables/testdata/variables/spin.toml b/variables/testdata/variables/spin.toml new file mode 100644 index 00000000..759589e3 --- /dev/null +++ b/variables/testdata/variables/spin.toml @@ -0,0 +1,23 @@ +spin_manifest_version = 2 + +[application] +name = "variables-example" +authors = ["Fermyon Engineering "] +description = "A simple Spin application written in Go." +version = "1.0.0" + +[variables] +object = { default = "teapot" } + +[[trigger.http]] +route = "/..." +component = "variables" + +[component.variables] +source = "main.wasm" +[component.variables.variables] +message = "I'm a {{object}}" + +[component.variables.build] +command = "componentize-go build" + diff --git a/variables/variables.go b/variables/variables.go index 5a669a14..8d70b792 100644 --- a/variables/variables.go +++ b/variables/variables.go @@ -1,8 +1,34 @@ package variables +import ( + "fmt" + + variables "github.com/spinframework/spin-go-sdk/v3/internal/fermyon_spin_2_0_0_variables" +) + // Get an application variable value for the current component. // // The name must match one defined in in the component manifest. func Get(key string) (string, error) { - return get(key) + result := variables.Get(key) + if result.IsErr() { + return "", errorVariantToError(result.Err()) + } + + return result.Ok(), nil +} + +func errorVariantToError(err variables.Error) error { + switch err.Tag() { + case variables.ErrorInvalidName: + return fmt.Errorf("%v", err.InvalidName()) + case variables.ErrorProvider: + return fmt.Errorf("%v", err.Provider()) + case variables.ErrorUndefined: + return fmt.Errorf("%v", err.Undefined()) + case variables.ErrorOther: + return fmt.Errorf("%v", err.Other()) + default: + return fmt.Errorf("no error provided by host implementation") + } } diff --git a/wit/deps/cli-2023-10-18/command.wit b/wit/deps/cli-2023-10-18/command.wit new file mode 100644 index 00000000..d7ea2d91 --- /dev/null +++ b/wit/deps/cli-2023-10-18/command.wit @@ -0,0 +1,7 @@ +package wasi:cli@0.2.0-rc-2023-10-18; + +world command { + include reactor; + + export run; +} diff --git a/wit/deps/cli-2023-10-18/environment.wit b/wit/deps/cli-2023-10-18/environment.wit new file mode 100644 index 00000000..70065233 --- /dev/null +++ b/wit/deps/cli-2023-10-18/environment.wit @@ -0,0 +1,18 @@ +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} diff --git a/wit/deps/cli-2023-10-18/exit.wit b/wit/deps/cli-2023-10-18/exit.wit new file mode 100644 index 00000000..d0c2b82a --- /dev/null +++ b/wit/deps/cli-2023-10-18/exit.wit @@ -0,0 +1,4 @@ +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} diff --git a/wit/deps/cli-2023-10-18/reactor.wit b/wit/deps/cli-2023-10-18/reactor.wit new file mode 100644 index 00000000..904b9946 --- /dev/null +++ b/wit/deps/cli-2023-10-18/reactor.wit @@ -0,0 +1,32 @@ +package wasi:cli@0.2.0-rc-2023-10-18; + +world reactor { + import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/timezone@0.2.0-rc-2023-10-18; + import wasi:filesystem/types@0.2.0-rc-2023-10-18; + import wasi:filesystem/preopens@0.2.0-rc-2023-10-18; + import wasi:sockets/instance-network@0.2.0-rc-2023-10-18; + import wasi:sockets/ip-name-lookup@0.2.0-rc-2023-10-18; + import wasi:sockets/network@0.2.0-rc-2023-10-18; + import wasi:sockets/tcp-create-socket@0.2.0-rc-2023-10-18; + import wasi:sockets/tcp@0.2.0-rc-2023-10-18; + import wasi:sockets/udp-create-socket@0.2.0-rc-2023-10-18; + import wasi:sockets/udp@0.2.0-rc-2023-10-18; + import wasi:random/random@0.2.0-rc-2023-10-18; + import wasi:random/insecure@0.2.0-rc-2023-10-18; + import wasi:random/insecure-seed@0.2.0-rc-2023-10-18; + import wasi:io/poll@0.2.0-rc-2023-10-18; + import wasi:io/streams@0.2.0-rc-2023-10-18; + + import environment; + import exit; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; +} diff --git a/wit/deps/cli-2023-10-18/run.wit b/wit/deps/cli-2023-10-18/run.wit new file mode 100644 index 00000000..a70ee8c0 --- /dev/null +++ b/wit/deps/cli-2023-10-18/run.wit @@ -0,0 +1,4 @@ +interface run { + /// Run the program. + run: func() -> result; +} diff --git a/wit/deps/cli-2023-10-18/stdio.wit b/wit/deps/cli-2023-10-18/stdio.wit new file mode 100644 index 00000000..513ca92d --- /dev/null +++ b/wit/deps/cli-2023-10-18/stdio.wit @@ -0,0 +1,17 @@ +interface stdin { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; + + get-stderr: func() -> output-stream; +} diff --git a/wit/deps/cli-2023-10-18/terminal.wit b/wit/deps/cli-2023-10-18/terminal.wit new file mode 100644 index 00000000..47495769 --- /dev/null +++ b/wit/deps/cli-2023-10-18/terminal.wit @@ -0,0 +1,47 @@ +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; + + // In the future, this may include functions for disabling echoing, + // disabling input buffering so that keyboard events are sent through + // immediately, querying supported features, and so on. +} + +interface terminal-output { + /// The output side of a terminal. + resource 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. +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} diff --git a/wit/deps/cli-2023-11-10/command.wit b/wit/deps/cli-2023-11-10/command.wit new file mode 100644 index 00000000..74811d32 --- /dev/null +++ b/wit/deps/cli-2023-11-10/command.wit @@ -0,0 +1,7 @@ +package wasi:cli@0.2.0-rc-2023-11-10; + +world command { + include reactor; + + export run; +} diff --git a/wit/deps/cli-2023-11-10/environment.wit b/wit/deps/cli-2023-11-10/environment.wit new file mode 100644 index 00000000..70065233 --- /dev/null +++ b/wit/deps/cli-2023-11-10/environment.wit @@ -0,0 +1,18 @@ +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} diff --git a/wit/deps/cli-2023-11-10/exit.wit b/wit/deps/cli-2023-11-10/exit.wit new file mode 100644 index 00000000..d0c2b82a --- /dev/null +++ b/wit/deps/cli-2023-11-10/exit.wit @@ -0,0 +1,4 @@ +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} diff --git a/wit/deps/cli-2023-11-10/reactor.wit b/wit/deps/cli-2023-11-10/reactor.wit new file mode 100644 index 00000000..eafa2fd4 --- /dev/null +++ b/wit/deps/cli-2023-11-10/reactor.wit @@ -0,0 +1,31 @@ +package wasi:cli@0.2.0-rc-2023-11-10; + +world reactor { + import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10; + import wasi:filesystem/types@0.2.0-rc-2023-11-10; + import wasi:filesystem/preopens@0.2.0-rc-2023-11-10; + import wasi:sockets/instance-network@0.2.0-rc-2023-11-10; + import wasi:sockets/ip-name-lookup@0.2.0-rc-2023-11-10; + import wasi:sockets/network@0.2.0-rc-2023-11-10; + import wasi:sockets/tcp-create-socket@0.2.0-rc-2023-11-10; + import wasi:sockets/tcp@0.2.0-rc-2023-11-10; + import wasi:sockets/udp-create-socket@0.2.0-rc-2023-11-10; + import wasi:sockets/udp@0.2.0-rc-2023-11-10; + import wasi:random/random@0.2.0-rc-2023-11-10; + import wasi:random/insecure@0.2.0-rc-2023-11-10; + import wasi:random/insecure-seed@0.2.0-rc-2023-11-10; + import wasi:io/poll@0.2.0-rc-2023-11-10; + import wasi:io/streams@0.2.0-rc-2023-11-10; + + import environment; + import exit; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; +} diff --git a/wit/deps/cli-2023-11-10/run.wit b/wit/deps/cli-2023-11-10/run.wit new file mode 100644 index 00000000..a70ee8c0 --- /dev/null +++ b/wit/deps/cli-2023-11-10/run.wit @@ -0,0 +1,4 @@ +interface run { + /// Run the program. + run: func() -> result; +} diff --git a/wit/deps/cli-2023-11-10/stdio.wit b/wit/deps/cli-2023-11-10/stdio.wit new file mode 100644 index 00000000..1b653b6e --- /dev/null +++ b/wit/deps/cli-2023-11-10/stdio.wit @@ -0,0 +1,17 @@ +interface stdin { + use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream}; + + get-stderr: func() -> output-stream; +} diff --git a/wit/deps/cli-2023-11-10/terminal.wit b/wit/deps/cli-2023-11-10/terminal.wit new file mode 100644 index 00000000..47495769 --- /dev/null +++ b/wit/deps/cli-2023-11-10/terminal.wit @@ -0,0 +1,47 @@ +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; + + // In the future, this may include functions for disabling echoing, + // disabling input buffering so that keyboard events are sent through + // immediately, querying supported features, and so on. +} + +interface terminal-output { + /// The output side of a terminal. + resource 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. +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} diff --git a/wit/deps/cli/command.wit b/wit/deps/cli/command.wit new file mode 100644 index 00000000..d8005bd3 --- /dev/null +++ b/wit/deps/cli/command.wit @@ -0,0 +1,7 @@ +package wasi:cli@0.2.0; + +world command { + include imports; + + export run; +} diff --git a/wit/deps/cli/environment.wit b/wit/deps/cli/environment.wit new file mode 100644 index 00000000..70065233 --- /dev/null +++ b/wit/deps/cli/environment.wit @@ -0,0 +1,18 @@ +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} diff --git a/wit/deps/cli/exit.wit b/wit/deps/cli/exit.wit new file mode 100644 index 00000000..d0c2b82a --- /dev/null +++ b/wit/deps/cli/exit.wit @@ -0,0 +1,4 @@ +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} diff --git a/wit/deps/cli/imports.wit b/wit/deps/cli/imports.wit new file mode 100644 index 00000000..083b84a0 --- /dev/null +++ b/wit/deps/cli/imports.wit @@ -0,0 +1,20 @@ +package wasi:cli@0.2.0; + +world imports { + include wasi:clocks/imports@0.2.0; + include wasi:filesystem/imports@0.2.0; + include wasi:sockets/imports@0.2.0; + include wasi:random/imports@0.2.0; + include wasi:io/imports@0.2.0; + + import environment; + import exit; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; +} diff --git a/wit/deps/cli/run.wit b/wit/deps/cli/run.wit new file mode 100644 index 00000000..a70ee8c0 --- /dev/null +++ b/wit/deps/cli/run.wit @@ -0,0 +1,4 @@ +interface run { + /// Run the program. + run: func() -> result; +} diff --git a/wit/deps/cli/stdio.wit b/wit/deps/cli/stdio.wit new file mode 100644 index 00000000..31ef35b5 --- /dev/null +++ b/wit/deps/cli/stdio.wit @@ -0,0 +1,17 @@ +interface stdin { + use wasi:io/streams@0.2.0.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stderr: func() -> output-stream; +} diff --git a/wit/deps/cli/terminal.wit b/wit/deps/cli/terminal.wit new file mode 100644 index 00000000..38c724ef --- /dev/null +++ b/wit/deps/cli/terminal.wit @@ -0,0 +1,49 @@ +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +interface terminal-output { + /// The output side of a terminal. + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} diff --git a/wit/deps/clocks-2023-10-18/monotonic-clock.wit b/wit/deps/clocks-2023-10-18/monotonic-clock.wit new file mode 100644 index 00000000..c0ecb529 --- /dev/null +++ b/wit/deps/clocks-2023-10-18/monotonic-clock.wit @@ -0,0 +1,32 @@ +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +/// +/// It is intended for measuring elapsed time. +interface monotonic-clock { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + + /// A timestamp in nanoseconds. + type instant = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; + + /// Query the resolution of the clock. + resolution: func() -> instant; + + /// Create a `pollable` which will resolve once the specified time has been + /// reached. + subscribe: func( + when: instant, + absolute: bool + ) -> pollable; +} diff --git a/wit/deps/clocks-2023-10-18/timezone.wit b/wit/deps/clocks-2023-10-18/timezone.wit new file mode 100644 index 00000000..e717e7b8 --- /dev/null +++ b/wit/deps/clocks-2023-10-18/timezone.wit @@ -0,0 +1,48 @@ +interface timezone { + use wall-clock.{datetime}; + + /// 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. + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + utc-offset: func(when: datetime) -> s32; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + 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, + } +} diff --git a/wit/deps/clocks-2023-10-18/wall-clock.wit b/wit/deps/clocks-2023-10-18/wall-clock.wit new file mode 100644 index 00000000..c3956496 --- /dev/null +++ b/wit/deps/clocks-2023-10-18/wall-clock.wit @@ -0,0 +1,41 @@ +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; +} diff --git a/wit/deps/clocks-2023-10-18/world.wit b/wit/deps/clocks-2023-10-18/world.wit new file mode 100644 index 00000000..cdfb51d9 --- /dev/null +++ b/wit/deps/clocks-2023-10-18/world.wit @@ -0,0 +1,7 @@ +package wasi:clocks@0.2.0-rc-2023-10-18; + +world imports { + import monotonic-clock; + import wall-clock; + import timezone; +} diff --git a/wit/deps/clocks-2023-11-10/monotonic-clock.wit b/wit/deps/clocks-2023-11-10/monotonic-clock.wit new file mode 100644 index 00000000..09ef32c3 --- /dev/null +++ b/wit/deps/clocks-2023-11-10/monotonic-clock.wit @@ -0,0 +1,45 @@ +package wasi:clocks@0.2.0-rc-2023-11-10; +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +/// +/// It is intended for measuring elapsed time. +interface monotonic-clock { + use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + type instant = u64; + + /// A duration of time, in nanoseconds. + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// occured. + subscribe-instant: func( + when: instant, + ) -> pollable; + + /// Create a `pollable` which will resolve once the given duration has + /// elapsed, starting at the time at which this function was called. + /// occured. + subscribe-duration: func( + when: duration, + ) -> pollable; +} diff --git a/wit/deps/clocks-2023-11-10/wall-clock.wit b/wit/deps/clocks-2023-11-10/wall-clock.wit new file mode 100644 index 00000000..8abb9a0c --- /dev/null +++ b/wit/deps/clocks-2023-11-10/wall-clock.wit @@ -0,0 +1,42 @@ +package wasi:clocks@0.2.0-rc-2023-11-10; +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; +} diff --git a/wit/deps/clocks-2023-11-10/world.wit b/wit/deps/clocks-2023-11-10/world.wit new file mode 100644 index 00000000..8fa080f0 --- /dev/null +++ b/wit/deps/clocks-2023-11-10/world.wit @@ -0,0 +1,6 @@ +package wasi:clocks@0.2.0-rc-2023-11-10; + +world imports { + import monotonic-clock; + import wall-clock; +} diff --git a/wit/deps/clocks/monotonic-clock.wit b/wit/deps/clocks/monotonic-clock.wit new file mode 100644 index 00000000..4e4dc3a1 --- /dev/null +++ b/wit/deps/clocks/monotonic-clock.wit @@ -0,0 +1,45 @@ +package wasi:clocks@0.2.0; +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +/// +/// It is intended for measuring elapsed time. +interface monotonic-clock { + use wasi:io/poll@0.2.0.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + type instant = u64; + + /// A duration of time, in nanoseconds. + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// occured. + subscribe-instant: func( + when: instant, + ) -> pollable; + + /// Create a `pollable` which will resolve once the given duration has + /// elapsed, starting at the time at which this function was called. + /// occured. + subscribe-duration: func( + when: duration, + ) -> pollable; +} diff --git a/wit/deps/clocks/wall-clock.wit b/wit/deps/clocks/wall-clock.wit new file mode 100644 index 00000000..440ca0f3 --- /dev/null +++ b/wit/deps/clocks/wall-clock.wit @@ -0,0 +1,42 @@ +package wasi:clocks@0.2.0; +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; +} diff --git a/wit/deps/clocks/world.wit b/wit/deps/clocks/world.wit new file mode 100644 index 00000000..c0224572 --- /dev/null +++ b/wit/deps/clocks/world.wit @@ -0,0 +1,6 @@ +package wasi:clocks@0.2.0; + +world imports { + import monotonic-clock; + import wall-clock; +} diff --git a/wit/deps/filesystem-2023-10-18/preopens.wit b/wit/deps/filesystem-2023-10-18/preopens.wit new file mode 100644 index 00000000..3f787ac3 --- /dev/null +++ b/wit/deps/filesystem-2023-10-18/preopens.wit @@ -0,0 +1,6 @@ +interface preopens { + use types.{descriptor}; + + /// Return the set of preopened directories, and their path. + get-directories: func() -> list>; +} diff --git a/wit/deps/filesystem-2023-10-18/types.wit b/wit/deps/filesystem-2023-10-18/types.wit new file mode 100644 index 00000000..af361354 --- /dev/null +++ b/wit/deps/filesystem-2023-10-18/types.wit @@ -0,0 +1,810 @@ +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +interface types { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0-rc-2023-10-18.{datetime}; + + /// File size or length of a region within a file. + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrety + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Permissions mode used by `open-at`, `change-file-permissions-at`, and + /// similar. + flags modes { + /// True if the resource is considered readable by the containing + /// filesystem. + readable, + /// True if the resource is considered writable by the containing + /// filesystem. + writable, + /// True if the resource is considered executable by the containing + /// filesystem. This does not apply to directories. + executable, + } + + /// Access type used by `access-at`. + variant access-type { + /// Test for readability, writeability, or executability. + access(modes), + + /// Test whether the path exists. + exists, + } + + /// Number of hard links to an inode. + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + read-via-stream: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + write-via-stream: func( + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in in POSIX. + append-via-stream: func() -> result; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + read: func( + /// The maximum number of bytes to read. + length: filesize, + /// The offset within the file at which to read. + offset: filesize, + ) -> result, bool>, error-code>; + + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + write: func( + /// Data to write + buffer: list, + /// The offset within the file at which to write. + offset: filesize, + ) -> result; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Note: This is similar to `linkat` in POSIX. + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// The returned descriptor is not guaranteed to be the lowest-numbered + /// descriptor not currently open/ it is randomized to prevent applications + /// from depending on making assumptions about indexes, since this is + /// error-prone in multi-threaded contexts. The returned descriptor is + /// guaranteed to be less than 2**31. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + /// Permissions to use when creating a new file. + modes: modes + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Check accessibility of a filesystem path. + /// + /// Check whether the given filesystem path names an object which is + /// readable, writable, or executable, or whether it exists. + /// + /// This does not a guarantee that subsequent accesses will succeed, as + /// filesystem permissions may be modified asynchronously by external + /// entities. + /// + /// Note: This is similar to `faccessat` with the `AT_EACCESS` flag in POSIX. + access-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to check. + path: string, + /// The type of check to perform. + %type: access-type + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Change the permissions of a filesystem object that is not a directory. + /// + /// Note that the ultimate meanings of these permissions is + /// filesystem-specific. + /// + /// Note: This is similar to `fchmodat` in POSIX. + change-file-permissions-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to operate on. + path: string, + /// The new permissions for the filesystem object. + modes: modes, + ) -> result<_, error-code>; + + /// Change the permissions of a directory. + /// + /// Note that the ultimate meanings of these permissions is + /// filesystem-specific. + /// + /// Unlike in POSIX, the `executable` flag is not reinterpreted as a "search" + /// flag. `read` on a directory implies readability and searchability, and + /// `execute` is not valid for directories. + /// + /// Note: This is similar to `fchmodat` in POSIX. + change-directory-permissions-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to operate on. + path: string, + /// The new permissions for the directory. + modes: modes, + ) -> result<_, error-code>; + + /// Request a shared advisory lock for an open file. + /// + /// This requests a *shared* lock; more than one shared lock can be held for + /// a file at the same time. + /// + /// If the open file has an exclusive lock, this function downgrades the lock + /// to a shared lock. If it has a shared lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified how shared locks interact with locks acquired by + /// non-WASI programs. + /// + /// This function blocks until the lock can be acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_SH)` in Unix. + lock-shared: func() -> result<_, error-code>; + + /// Request an exclusive advisory lock for an open file. + /// + /// This requests an *exclusive* lock; no other locks may be held for the + /// file while an exclusive lock is held. + /// + /// If the open file has a shared lock and there are no exclusive locks held + /// for the file, this function upgrades the lock to an exclusive lock. If the + /// open file already has an exclusive lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified whether this function succeeds if the file descriptor + /// is not opened for writing. It is unspecified how exclusive locks interact + /// with locks acquired by non-WASI programs. + /// + /// This function blocks until the lock can be acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_EX)` in Unix. + lock-exclusive: func() -> result<_, error-code>; + + /// Request a shared advisory lock for an open file. + /// + /// This requests a *shared* lock; more than one shared lock can be held for + /// a file at the same time. + /// + /// If the open file has an exclusive lock, this function downgrades the lock + /// to a shared lock. If it has a shared lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified how shared locks interact with locks acquired by + /// non-WASI programs. + /// + /// This function returns `error-code::would-block` if the lock cannot be + /// acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_SH | LOCK_NB)` in Unix. + try-lock-shared: func() -> result<_, error-code>; + + /// Request an exclusive advisory lock for an open file. + /// + /// This requests an *exclusive* lock; no other locks may be held for the + /// file while an exclusive lock is held. + /// + /// If the open file has a shared lock and there are no exclusive locks held + /// for the file, this function upgrades the lock to an exclusive lock. If the + /// open file already has an exclusive lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified whether this function succeeds if the file descriptor + /// is not opened for writing. It is unspecified how exclusive locks interact + /// with locks acquired by non-WASI programs. + /// + /// This function returns `error-code::would-block` if the lock cannot be + /// acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_EX | LOCK_NB)` in Unix. + try-lock-exclusive: func() -> result<_, error-code>; + + /// Release a shared or exclusive lock on an open file. + /// + /// Note: This is similar to `flock(fd, LOCK_UN)` in Unix. + unlock: func() -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encourated to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + read-directory-entry: func() -> result, 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. + filesystem-error-code: func(err: borrow) -> option; +} diff --git a/wit/deps/filesystem-2023-10-18/world.wit b/wit/deps/filesystem-2023-10-18/world.wit new file mode 100644 index 00000000..3f953f89 --- /dev/null +++ b/wit/deps/filesystem-2023-10-18/world.wit @@ -0,0 +1,6 @@ +package wasi:filesystem@0.2.0-rc-2023-10-18; + +world imports { + import types; + import preopens; +} diff --git a/wit/deps/filesystem-2023-11-10/preopens.wit b/wit/deps/filesystem-2023-11-10/preopens.wit new file mode 100644 index 00000000..95ec6784 --- /dev/null +++ b/wit/deps/filesystem-2023-11-10/preopens.wit @@ -0,0 +1,8 @@ +package wasi:filesystem@0.2.0-rc-2023-11-10; + +interface preopens { + use types.{descriptor}; + + /// Return the set of preopened directories, and their path. + get-directories: func() -> list>; +} diff --git a/wit/deps/filesystem-2023-11-10/types.wit b/wit/deps/filesystem-2023-11-10/types.wit new file mode 100644 index 00000000..059722ab --- /dev/null +++ b/wit/deps/filesystem-2023-11-10/types.wit @@ -0,0 +1,634 @@ +package wasi:filesystem@0.2.0-rc-2023-11-10; +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +interface types { + use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0-rc-2023-11-10.{datetime}; + + /// File size or length of a region within a file. + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrety + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + read-via-stream: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + write-via-stream: func( + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in in POSIX. + append-via-stream: func() -> result; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + read: func( + /// The maximum number of bytes to read. + length: filesize, + /// The offset within the file at which to read. + offset: filesize, + ) -> result, bool>, error-code>; + + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + write: func( + /// Data to write + buffer: list, + /// The offset within the file at which to write. + offset: filesize, + ) -> result; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Note: This is similar to `linkat` in POSIX. + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// The returned descriptor is not guaranteed to be the lowest-numbered + /// descriptor not currently open/ it is randomized to prevent applications + /// from depending on making assumptions about indexes, since this is + /// error-prone in multi-threaded contexts. The returned descriptor is + /// guaranteed to be less than 2**31. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encourated to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + read-directory-entry: func() -> result, 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. + filesystem-error-code: func(err: borrow) -> option; +} diff --git a/wit/deps/filesystem-2023-11-10/world.wit b/wit/deps/filesystem-2023-11-10/world.wit new file mode 100644 index 00000000..285e0bae --- /dev/null +++ b/wit/deps/filesystem-2023-11-10/world.wit @@ -0,0 +1,6 @@ +package wasi:filesystem@0.2.0-rc-2023-11-10; + +world imports { + import types; + import preopens; +} diff --git a/wit/deps/filesystem/preopens.wit b/wit/deps/filesystem/preopens.wit new file mode 100644 index 00000000..da801f6d --- /dev/null +++ b/wit/deps/filesystem/preopens.wit @@ -0,0 +1,8 @@ +package wasi:filesystem@0.2.0; + +interface preopens { + use types.{descriptor}; + + /// Return the set of preopened directories, and their path. + get-directories: func() -> list>; +} diff --git a/wit/deps/filesystem/types.wit b/wit/deps/filesystem/types.wit new file mode 100644 index 00000000..11108fcd --- /dev/null +++ b/wit/deps/filesystem/types.wit @@ -0,0 +1,634 @@ +package wasi:filesystem@0.2.0; +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +interface types { + use wasi:io/streams@0.2.0.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0.{datetime}; + + /// File size or length of a region within a file. + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrety + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Number of hard links to an inode. + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + read-via-stream: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + write-via-stream: func( + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in in POSIX. + append-via-stream: func() -> result; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + read: func( + /// The maximum number of bytes to read. + length: filesize, + /// The offset within the file at which to read. + offset: filesize, + ) -> result, bool>, error-code>; + + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + write: func( + /// Data to write + buffer: list, + /// The offset within the file at which to write. + offset: filesize, + ) -> result; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Note: This is similar to `linkat` in POSIX. + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// The returned descriptor is not guaranteed to be the lowest-numbered + /// descriptor not currently open/ it is randomized to prevent applications + /// from depending on making assumptions about indexes, since this is + /// error-prone in multi-threaded contexts. The returned descriptor is + /// guaranteed to be less than 2**31. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encourated to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + read-directory-entry: func() -> result, 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. + filesystem-error-code: func(err: borrow) -> option; +} diff --git a/wit/deps/filesystem/world.wit b/wit/deps/filesystem/world.wit new file mode 100644 index 00000000..663f5792 --- /dev/null +++ b/wit/deps/filesystem/world.wit @@ -0,0 +1,6 @@ +package wasi:filesystem@0.2.0; + +world imports { + import types; + import preopens; +} diff --git a/wit/deps/http-2023-10-18/incoming-handler.wit b/wit/deps/http-2023-10-18/incoming-handler.wit new file mode 100644 index 00000000..6968d633 --- /dev/null +++ b/wit/deps/http-2023-10-18/incoming-handler.wit @@ -0,0 +1,24 @@ +// The `wasi:http/incoming-handler` interface is meant to be exported by +// components and called by the host in response to a new incoming HTTP +// response. +// +// NOTE: in Preview3, this interface will be merged with +// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface +// that takes a `request` parameter and returns a `response` result. +// +interface incoming-handler { + use types.{incoming-request, response-outparam}; + + // The `handle` function takes an outparam instead of returning its response + // so that the component may stream its response while streaming any other + // request or response bodies. The callee MUST write a response to the + // `response-outparam` and then finish the response before returning. The `handle` + // function is allowed to continue execution after finishing the response's + // output stream. While this post-response execution is taken off the + // critical path, since there is no return value, there is no way to report + // its success or failure. + handle: func( + request: incoming-request, + response-out: response-outparam + ); +} diff --git a/wit/deps/http-2023-10-18/outgoing-handler.wit b/wit/deps/http-2023-10-18/outgoing-handler.wit new file mode 100644 index 00000000..286e2833 --- /dev/null +++ b/wit/deps/http-2023-10-18/outgoing-handler.wit @@ -0,0 +1,20 @@ +// The `wasi:http/outgoing-handler` interface is meant to be imported by +// components and implemented by the host. +// +// NOTE: in Preview3, this interface will be merged with +// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface +// that takes a `request` parameter and returns a `response` result. +// +interface outgoing-handler { + use types.{outgoing-request, request-options, future-incoming-response, error}; + + // The parameter and result types of the `handle` function allow the caller + // to concurrently stream the bodies of the outgoing request and the incoming + // response. + // Consumes the outgoing-request. Gives an error if the outgoing-request + // is invalid or cannot be satisfied by this handler. + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff --git a/wit/deps/http-2023-10-18/proxy.wit b/wit/deps/http-2023-10-18/proxy.wit new file mode 100644 index 00000000..dde0659d --- /dev/null +++ b/wit/deps/http-2023-10-18/proxy.wit @@ -0,0 +1,34 @@ +package wasi:http@0.2.0-rc-2023-10-18; + +// 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. +world proxy { + // HTTP proxies have access to time and randomness. + import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/timezone@0.2.0-rc-2023-10-18; + import wasi:random/random@0.2.0-rc-2023-10-18; + + // Proxies have standard output and error streams which are expected to + // terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.2.0-rc-2023-10-18; + import wasi:cli/stderr@0.2.0-rc-2023-10-18; + + // TODO: this is a temporary workaround until component tooling is able to + // gracefully handle the absence of stdin. Hosts must return an eof stream + // for this import, which is what wasi-libc + tooling will do automatically + // when this import is properly removed. + import wasi:cli/stdin@0.2.0-rc-2023-10-18; + + // This is the default handler to use when user code simply wants to make an + // HTTP request (e.g., via `fetch()`). + import outgoing-handler; + + // The host delivers incoming HTTP requests to a component by calling the + // `handle` function of this exported interface. A host may arbitrarily reuse + // or not reuse component instance when delivering incoming HTTP requests and + // thus a component must be able to handle 0..N calls to `handle`. + export incoming-handler; +} diff --git a/wit/deps/http-2023-10-18/types.wit b/wit/deps/http-2023-10-18/types.wit new file mode 100644 index 00000000..2471f046 --- /dev/null +++ b/wit/deps/http-2023-10-18/types.wit @@ -0,0 +1,208 @@ +/// The `wasi:http/types` interface is meant to be imported by components to +/// define the HTTP resource types and operations used by the component's +/// imported and exported interfaces. +interface types { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream}; + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + + // This type corresponds to HTTP standard Methods. + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + variant scheme { + HTTP, + HTTPS, + other(string) + } + + // TODO: perhaps better align with HTTP semantics? + /// This type enumerates the different kinds of errors that may occur when + /// initially returning a response. + variant error { + invalid-url(string), + timeout-error(string), + protocol-error(string), + unexpected-error(string) + } + + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. + resource fields { + // Multiple values for a header are multiple entries in the list with the + // same key. + constructor(entries: list>>); + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + get: func(name: string) -> list>; + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + set: func(name: string, value: list>); + delete: func(name: string); + append: func(name: string, value: list); + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + entries: func() -> list>>; + + // Deep copy of all contents in a fields. + clone: func() -> fields; + } + + type headers = fields; + type trailers = fields; + + /// The following block defines the `incoming-request` and `outgoing-request` + /// resource types that correspond to HTTP standard Requests. + /// + /// The `consume` and `write` methods may only be called once (and + /// return failure thereafter). + resource incoming-request { + method: func() -> method; + + path-with-query: func() -> option; + + scheme: func() -> option; + + authority: func() -> option; + + headers: func() -> /* child */ headers; + + /// Returns the input-stream child at most once. + /// + /// If called more than once, subsequent calls return an error. + consume: func() -> result; + } + + resource outgoing-request { + constructor( + method: method, + path-with-query: option, + scheme: option, + authority: option, + headers: borrow + ); + + /// Will return the outgoing-body child at most once. + /// + /// If called more than once, subsequent calls return an error. + write: func() -> result< /* child */ outgoing-body>; + } + + /// Additional optional parameters that can be set when making a request. + record request-options { + // The following timeouts are specific to the HTTP protocol and work + // independently of the overall timeouts passed to `io.poll.poll-list`. + + /// The timeout for the initial connect. + connect-timeout-ms: option, + + /// The timeout for receiving the first byte of the response body. + first-byte-timeout-ms: option, + + /// The timeout for receiving the next chunk of bytes in the response body + /// stream. + between-bytes-timeout-ms: option + } + + /// The following block defines a special resource type used by the + /// `wasi:http/incoming-handler` interface. When resource types are added, this + /// block can be replaced by a proper `resource response-outparam { ... }` + /// definition. Later, with Preview3, the need for an outparam goes away entirely + /// (the `wasi:http/handler` interface used for both incoming and outgoing can + /// simply return a `stream`). + resource response-outparam { + set: static func(param: response-outparam, response: result); + } + + // This type corresponds to the HTTP standard Status Code. + type status-code = u16; + + /// The following block defines the `incoming-response` and `outgoing-response` + /// resource types that correspond to HTTP standard Responses. + /// + /// The `consume` and `write` methods may only be called once (and return failure thereafter). + resource incoming-response { + status: func() -> status-code; + + headers: func() -> /* child */ headers; + + // May be called at most once. returns error if called additional times. + // TODO: make incoming-request-consume work the same way, giving a child + // incoming-body. + consume: func() -> result; + } + + resource incoming-body { + // returned input-stream is a child - the implementation may trap if + // incoming-body is dropped (or consumed by call to + // incoming-body-finish) before the input-stream is dropped. + // May be called at most once. returns error if called additional times. + %stream: func() -> result; + + // takes ownership of incoming-body. this will trap if the + // incoming-body-stream child is still alive! + finish: static func(this: incoming-body) -> + /* transitive child of the incoming-response of incoming-body */ future-trailers; + } + + resource future-trailers { + /// Pollable that resolves when the body has been fully read, and the trailers + /// are ready to be consumed. + subscribe: func() -> /* child */ pollable; + + /// Retrieve reference to trailers, if they are ready. + get: func() -> option>; + } + + resource outgoing-response { + constructor(status-code: status-code, headers: borrow); + + /// Will give the child outgoing-response at most once. subsequent calls will + /// return an error. + write: func() -> result; + } + + resource outgoing-body { + /// Will give the child output-stream at most once. subsequent calls will + /// return an error. + 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. + finish: static func(this: outgoing-body, trailers: option); + } + + /// The following block defines a special resource type used by the + /// `wasi:http/outgoing-handler` interface to emulate + /// `future>` in advance of Preview3. Given a + /// `future-incoming-response`, the client can call the non-blocking `get` + /// method to get the result if it is available. If the result is not available, + /// the client can call `listen` to get a `pollable` that can be passed to + /// `wasi:io/poll.poll-list`. + resource future-incoming-response { + /// option indicates readiness. + /// outer result indicates you are allowed to get the + /// incoming-response-or-error at most once. subsequent calls after ready + /// will return an error here. + /// inner result indicates whether the incoming-response was available, or an + /// error occured. + get: func() -> option>>; + + subscribe: func() -> /* child */ pollable; + } +} diff --git a/wit/deps/http-2023-11-10/handler.wit b/wit/deps/http-2023-11-10/handler.wit new file mode 100644 index 00000000..a34a0649 --- /dev/null +++ b/wit/deps/http-2023-11-10/handler.wit @@ -0,0 +1,43 @@ +/// This interface defines a handler of incoming HTTP Requests. It should +/// be exported by components which can respond to HTTP Requests. +interface incoming-handler { + 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. + 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. +interface outgoing-handler { + 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`. + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff --git a/wit/deps/http-2023-11-10/proxy.wit b/wit/deps/http-2023-11-10/proxy.wit new file mode 100644 index 00000000..453f5905 --- /dev/null +++ b/wit/deps/http-2023-11-10/proxy.wit @@ -0,0 +1,33 @@ +package wasi:http@0.2.0-rc-2023-11-10; + +/// 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. +world proxy { + /// HTTP proxies have access to time and randomness. + import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10; + import wasi:random/random@0.2.0-rc-2023-11-10; + + /// Proxies have standard output and error streams which are expected to + /// terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.2.0-rc-2023-11-10; + import wasi:cli/stderr@0.2.0-rc-2023-11-10; + + /// TODO: this is a temporary workaround until component tooling is able to + /// gracefully handle the absence of stdin. Hosts must return an eof stream + /// for this import, which is what wasi-libc + tooling will do automatically + /// when this import is properly removed. + import wasi:cli/stdin@0.2.0-rc-2023-11-10; + + /// This is the default handler to use when user code simply wants to make an + /// HTTP request (e.g., via `fetch()`). + import outgoing-handler; + + /// The host delivers incoming HTTP requests to a component by calling the + /// `handle` function of this exported interface. A host may arbitrarily reuse + /// or not reuse component instance when delivering incoming HTTP requests and + /// thus a component must be able to handle 0..N calls to `handle`. + export incoming-handler; +} diff --git a/wit/deps/http-2023-11-10/types.wit b/wit/deps/http-2023-11-10/types.wit new file mode 100644 index 00000000..1dd4214c --- /dev/null +++ b/wit/deps/http-2023-11-10/types.wit @@ -0,0 +1,559 @@ +/// 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. +interface types { + use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration}; + use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream}; + use wasi:io/error@0.2.0-rc-2023-11-10.{error as io-error}; + use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; + + /// This type corresponds to HTTP standard Methods. + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + variant scheme { + HTTP, + HTTPS, + other(string) + } + + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types + 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) + } + + /// Defines the case payload type for `DNS-error` above: + record DNS-error-payload { + rcode: option, + info-code: option + } + + /// Defines the case payload type for `TLS-alert-received` above: + record TLS-alert-received-payload { + alert-id: option, + alert-message: option + } + + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + record field-size-payload { + field-name: option, + field-size: 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. + http-error-code: func(err: borrow) -> option; + + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + variant header-error { + /// This error indicates that a `field-key` 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-key` 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. + type field-key = string; + + /// 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. + 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 be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + resource fields { + + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + constructor(); + + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + /// + /// The tuple is a pair of the field key, represented as a string, and + /// Value, represented as a list of bytes. In a valid Fields, all keys + /// and values are valid UTF-8 strings. However, values are not always + /// well-formed, so they are represented as a raw list of bytes. + /// + /// An error result will be returned if any header or value was + /// syntactically invalid, or if a header was forbidden. + from-list: static func( + entries: list> + ) -> result; + + /// Get all of the values corresponding to a key. + get: func(name: field-key) -> list; + + /// Set all of the values for a key. Clears any existing values for that + /// key, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + set: func(name: field-key, value: list) -> result<_, header-error>; + + /// Delete all values for a key. Does nothing if no values for the key + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + delete: func(name: field-key) -> result<_, header-error>; + + /// Append a value for a key. Does not change or delete any existing + /// values for that key. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + append: func(name: field-key, value: field-value) -> result<_, header-error>; + + /// Retrieve the full set of keys and values in the Fields. Like the + /// constructor, the list represents each key-value pair. + /// + /// The outer list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + entries: func() -> list>; + + /// Make a deep copy of the Fields. Equivelant in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + clone: func() -> fields; + } + + /// Headers is an alias for Fields. + type headers = fields; + + /// Trailers is an alias for Fields. + type trailers = fields; + + /// Represents an incoming HTTP Request. + resource incoming-request { + + /// Returns the method of the incoming request. + method: func() -> method; + + /// Returns the path with query parameters from the request, as a string. + path-with-query: func() -> option; + + /// Returns the protocol scheme from the request. + scheme: func() -> option; + + /// Returns the authority from the request, if it was present. + 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. + headers: func() -> headers; + + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + consume: func() -> result; + } + + /// Represents an outgoing HTTP Request. + 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`. + 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. + body: func() -> result; + + /// Get the Method for the Request. + 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. + 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. + 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. + 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. + 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. + set-scheme: func(scheme: option) -> result; + + /// Get the HTTP Authority for the Request. 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. + authority: func() -> option; + /// Set the HTTP Authority for the Request. 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. + 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 transfered to + /// another component by e.g. `outgoing-handler.handle`. + headers: func() -> headers; + } + + /// Parameters for making an HTTP Request. Each of these parameters is an + /// optional timeout, with the unit in milliseconds, 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`. + resource request-options { + /// Construct a default `request-options` value. + constructor(); + + /// The timeout for the initial connect to the HTTP Server. + connect-timeout-ms: func() -> option; + + /// Set the timeout for the initial connect to the HTTP Server. An error + /// return value indicates that this timeout is not supported. + set-connect-timeout-ms: func(ms: option) -> result; + + /// The timeout for receiving the first byte of the Response body. + first-byte-timeout-ms: 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. + set-first-byte-timeout-ms: func(ms: option) -> result; + + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + between-bytes-timeout-ms: 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. + set-between-bytes-timeout-ms: func(ms: 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`. + resource response-outparam { + + /// 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. + set: static func( + param: response-outparam, + response: result, + ); + } + + /// This type corresponds to the HTTP standard Status Code. + type status-code = u16; + + /// Represents an incoming HTTP Response. + resource incoming-response { + + /// Returns the status code from the incoming response. + 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. + headers: func() -> headers; + + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + 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. + 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. + %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. + finish: static func(this: incoming-body) -> future-trailers; + } + + /// Represents a future which may eventaully 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. + resource future-trailers { + + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + subscribe: func() -> pollable; + + /// Returns the contents of the trailers, or an error which occured, + /// 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 `result` represents that either the HTTP Request or Response body, + /// as well as any trailers, were received successfully, or that an error + /// occured 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. + get: func() -> option, error-code>>; + } + + /// Represents an outgoing HTTP Response. + 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. + constructor(headers: headers); + + /// Get the HTTP Status Code for the Response. + 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. + 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 transfered to + /// another component by e.g. `outgoing-handler.handle`. + 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. + 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 occured. The implementation should propogate 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. + 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. + 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. + finish: static func( + this: outgoing-body, + trailers: option + ) -> result<_, error-code>; + } + + /// Represents a future which may eventaully 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. + resource future-incoming-response { + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + 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 recieved successfully, or that an error + /// occured. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + get: func() -> option>>; + + } +} diff --git a/wit/deps/http/handler.wit b/wit/deps/http/handler.wit new file mode 100644 index 00000000..a34a0649 --- /dev/null +++ b/wit/deps/http/handler.wit @@ -0,0 +1,43 @@ +/// This interface defines a handler of incoming HTTP Requests. It should +/// be exported by components which can respond to HTTP Requests. +interface incoming-handler { + 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. + 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. +interface outgoing-handler { + 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`. + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff --git a/wit/deps/http/proxy.wit b/wit/deps/http/proxy.wit new file mode 100644 index 00000000..687c24d2 --- /dev/null +++ b/wit/deps/http/proxy.wit @@ -0,0 +1,32 @@ +package wasi:http@0.2.0; + +/// 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. +world proxy { + /// HTTP proxies have access to time and randomness. + include wasi:clocks/imports@0.2.0; + import wasi:random/random@0.2.0; + + /// Proxies have standard output and error streams which are expected to + /// terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.2.0; + import wasi:cli/stderr@0.2.0; + + /// TODO: this is a temporary workaround until component tooling is able to + /// gracefully handle the absence of stdin. Hosts must return an eof stream + /// for this import, which is what wasi-libc + tooling will do automatically + /// when this import is properly removed. + import wasi:cli/stdin@0.2.0; + + /// This is the default handler to use when user code simply wants to make an + /// HTTP request (e.g., via `fetch()`). + import outgoing-handler; + + /// The host delivers incoming HTTP requests to a component by calling the + /// `handle` function of this exported interface. A host may arbitrarily reuse + /// or not reuse component instance when delivering incoming HTTP requests and + /// thus a component must be able to handle 0..N calls to `handle`. + export incoming-handler; +} diff --git a/wit/deps/http/types.wit b/wit/deps/http/types.wit new file mode 100644 index 00000000..755ac6a6 --- /dev/null +++ b/wit/deps/http/types.wit @@ -0,0 +1,570 @@ +/// 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. +interface types { + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use wasi:io/streams@0.2.0.{input-stream, output-stream}; + use wasi:io/error@0.2.0.{error as io-error}; + use wasi:io/poll@0.2.0.{pollable}; + + /// This type corresponds to HTTP standard Methods. + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + variant scheme { + HTTP, + HTTPS, + other(string) + } + + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types + 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) + } + + /// Defines the case payload type for `DNS-error` above: + record DNS-error-payload { + rcode: option, + info-code: option + } + + /// Defines the case payload type for `TLS-alert-received` above: + record TLS-alert-received-payload { + alert-id: option, + alert-message: option + } + + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + record field-size-payload { + field-name: option, + field-size: 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. + http-error-code: func(err: borrow) -> option; + + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + variant header-error { + /// This error indicates that a `field-key` 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-key` 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. + type field-key = string; + + /// 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. + 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 be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + resource fields { + + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + constructor(); + + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + /// + /// The tuple is a pair of the field key, represented as a string, and + /// Value, represented as a list of bytes. In a valid Fields, all keys + /// and values are valid UTF-8 strings. However, values are not always + /// well-formed, so they are represented as a raw list of bytes. + /// + /// An error result will be returned if any header or value was + /// syntactically invalid, or if a header was forbidden. + from-list: static func( + entries: list> + ) -> result; + + /// Get all of the values corresponding to a key. If the key is not present + /// in this `fields`, an empty list is returned. However, if the key is + /// present but empty, this is represented by a list with one or more + /// empty field-values present. + get: func(name: field-key) -> list; + + /// Returns `true` when the key is present in this `fields`. If the key is + /// syntactically invalid, `false` is returned. + has: func(name: field-key) -> bool; + + /// Set all of the values for a key. Clears any existing values for that + /// key, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + set: func(name: field-key, value: list) -> result<_, header-error>; + + /// Delete all values for a key. Does nothing if no values for the key + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + delete: func(name: field-key) -> result<_, header-error>; + + /// Append a value for a key. Does not change or delete any existing + /// values for that key. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + append: func(name: field-key, value: field-value) -> result<_, header-error>; + + /// Retrieve the full set of keys and values in the Fields. Like the + /// constructor, the list represents each key-value pair. + /// + /// The outer list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + entries: func() -> list>; + + /// Make a deep copy of the Fields. Equivelant in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + clone: func() -> fields; + } + + /// Headers is an alias for Fields. + type headers = fields; + + /// Trailers is an alias for Fields. + type trailers = fields; + + /// Represents an incoming HTTP Request. + resource incoming-request { + + /// Returns the method of the incoming request. + method: func() -> method; + + /// Returns the path with query parameters from the request, as a string. + path-with-query: func() -> option; + + /// Returns the protocol scheme from the request. + scheme: func() -> option; + + /// Returns the authority from the request, if it was present. + 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. + headers: func() -> headers; + + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + consume: func() -> result; + } + + /// Represents an outgoing HTTP Request. + 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`. + 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. + body: func() -> result; + + /// Get the Method for the Request. + 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. + 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. + 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. + 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. + 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. + set-scheme: func(scheme: option) -> result; + + /// Get the HTTP Authority for the Request. 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. + authority: func() -> option; + /// Set the HTTP Authority for the Request. 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. + 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 transfered to + /// another component by e.g. `outgoing-handler.handle`. + 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`. + resource request-options { + /// Construct a default `request-options` value. + constructor(); + + /// The timeout for the initial connect to the HTTP Server. + 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. + set-connect-timeout: func(duration: option) -> result; + + /// The timeout for receiving the first byte of the Response body. + 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. + set-first-byte-timeout: func(duration: option) -> result; + + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + 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. + 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`. + resource response-outparam { + + /// 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. + set: static func( + param: response-outparam, + response: result, + ); + } + + /// This type corresponds to the HTTP standard Status Code. + type status-code = u16; + + /// Represents an incoming HTTP Response. + resource incoming-response { + + /// Returns the status code from the incoming response. + 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. + headers: func() -> headers; + + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + 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. + 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. + %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. + finish: static func(this: incoming-body) -> future-trailers; + } + + /// Represents a future which may eventaully 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. + resource future-trailers { + + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + subscribe: func() -> pollable; + + /// Returns the contents of the trailers, or an error which occured, + /// 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 occured 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. + get: func() -> option, error-code>>>; + } + + /// Represents an outgoing HTTP Response. + 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. + constructor(headers: headers); + + /// Get the HTTP Status Code for the Response. + 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. + 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 transfered to + /// another component by e.g. `outgoing-handler.handle`. + 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. + 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 occured. The implementation should propogate 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. + 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. + 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. + finish: static func( + this: outgoing-body, + trailers: option + ) -> result<_, error-code>; + } + + /// Represents a future which may eventaully 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. + resource future-incoming-response { + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + 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 recieved successfully, or that an error + /// occured. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + get: func() -> option>>; + + } +} diff --git a/wit/deps/io-2023-10-18/poll.wit b/wit/deps/io-2023-10-18/poll.wit new file mode 100644 index 00000000..74835e6a --- /dev/null +++ b/wit/deps/io-2023-10-18/poll.wit @@ -0,0 +1,32 @@ +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +interface poll { + /// A "pollable" handle. + resource pollable; + + /// 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. + /// + /// If the list contains more elements than can be indexed with a `u32` + /// value, this function traps. + /// + /// 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 reaedy for I/O. + poll-list: func(in: list>) -> list; + + /// Poll for completion on a single pollable. + /// + /// This function is similar to `poll-list`, but operates on only a single + /// pollable. When it returns, the handle is ready for I/O. + poll-one: func(in: borrow); +} diff --git a/wit/deps/io-2023-10-18/streams.wit b/wit/deps/io-2023-10-18/streams.wit new file mode 100644 index 00000000..c9600b70 --- /dev/null +++ b/wit/deps/io-2023-10-18/streams.wit @@ -0,0 +1,287 @@ +/// 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. +interface streams { + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + 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 + } + + /// Contextual error information about the last failure that happened on + /// a read, write, or flush from an `input-stream` or `output-stream`. + /// + /// This type is returned through the `stream-error` type whenever an + /// operation on a stream directly fails or an error is discovered + /// after-the-fact, for example when a write's failure shows up through a + /// later `flush` or `check-write`. + /// + /// Interfaces such as `wasi:filesystem/types` provide functionality to + /// further "downcast" this error into interface-specific error information. + resource error { + /// Returns a string that's suitable to assist humans in debugging this + /// error. + /// + /// The returned string will change across platforms and hosts which + /// means that parsing it, for example, would be a + /// platform-compatibility hazard. + to-debug-string: func() -> string; + } + + /// 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`. + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a `stream-status` which, indicates whether further + /// reads are expected to produce data. The returned list will contain up to + /// `len` bytes; it may return fewer than requested, but not more. An + /// empty list and `stream-status:open` indicates no more data is + /// available at this time, and that the pollable given by `subscribe` + /// will be ready when more data is available. + /// + /// Once a stream has reached the end, subsequent calls to `read` or + /// `skip` will always report `stream-status:ended` rather than producing more + /// data. + /// + /// When the caller gives a `len` of 0, it represents a request to read 0 + /// bytes. This read should always succeed and return an empty list and + /// the current `stream-status`. + /// + /// 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. + read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, identical to `read`. + blocking-read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Skip bytes from a stream. + /// + /// This is similar to the `read` function, but avoids copying the + /// bytes into the instance. + /// + /// Once a stream has reached the end, subsequent calls to read or + /// `skip` will always report end-of-stream rather than producing more + /// data. + /// + /// This function returns the number of bytes skipped, along with a + /// `stream-status` indicating whether the end of the stream was + /// reached. The returned value will be at most `len`; it may be less. + skip: func( + /// The maximum number of bytes to skip. + 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`. + blocking-skip: func( + /// The maximum number of bytes to skip. + 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. + 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`. + 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. + check-write: func() -> result; + + /// Perform a write. This function never blocks. + /// + /// 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. + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + 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. + flush: func() -> result<_, stream-error>; + + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + 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 occured. 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. + 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. + write-zeroes: func( + /// The number of zero-bytes to write + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-zeroes-and-flush: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Read from one stream and write to another. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + /// + /// Unlike other I/O functions, this function blocks until all the data + /// read from the input stream has been written to the output stream. + splice: func( + /// The stream to read from + src: input-stream, + /// The number of bytes to splice + len: u64, + ) -> result; + + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until at least + /// one byte can be read. + blocking-splice: func( + /// The stream to read from + src: input-stream, + /// The number of bytes to splice + len: u64, + ) -> result; + + /// Forward the entire contents of an input stream to an output stream. + /// + /// This function repeatedly reads from the input stream and writes + /// the data to the output stream, until the end of the input stream + /// is reached, or an error is encountered. + /// + /// Unlike other I/O functions, this function blocks until the end + /// of the input stream is seen and all the data has been written to + /// the output stream. + /// + /// This function returns the number of bytes transferred, and the status of + /// the output stream. + forward: func( + /// The stream to read from + src: input-stream + ) -> result; + } +} diff --git a/wit/deps/io-2023-10-18/world.wit b/wit/deps/io-2023-10-18/world.wit new file mode 100644 index 00000000..a0bcd312 --- /dev/null +++ b/wit/deps/io-2023-10-18/world.wit @@ -0,0 +1 @@ +package wasi:io@0.2.0-rc-2023-10-18; diff --git a/wit/deps/io-2023-11-10/error.wit b/wit/deps/io-2023-11-10/error.wit new file mode 100644 index 00000000..31918acb --- /dev/null +++ b/wit/deps/io-2023-11-10/error.wit @@ -0,0 +1,34 @@ +package wasi:io@0.2.0-rc-2023-11-10; + + +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 + /// provide functions to further "downcast" this error into more specific + /// error information. For example, `error`s returned in streams derived + /// from filesystem types to be described using the filesystem's own + /// error-code type, using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter + /// `borrow` and returns + /// `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + 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. + to-debug-string: func() -> string; + } +} diff --git a/wit/deps/io-2023-11-10/poll.wit b/wit/deps/io-2023-11-10/poll.wit new file mode 100644 index 00000000..bddde3c1 --- /dev/null +++ b/wit/deps/io-2023-11-10/poll.wit @@ -0,0 +1,41 @@ +package wasi:io@0.2.0-rc-2023-11-10; + +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +interface poll { + /// `pollable` epresents a single I/O event which may be ready, or not. + resource pollable { + + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + 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. + 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. + /// + /// If the list contains more elements than can be indexed with a `u32` + /// value, this function traps. + /// + /// 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 reaedy for I/O. + poll: func(in: list>) -> list; +} diff --git a/wit/deps/io-2023-11-10/streams.wit b/wit/deps/io-2023-11-10/streams.wit new file mode 100644 index 00000000..e7e1b689 --- /dev/null +++ b/wit/deps/io-2023-11-10/streams.wit @@ -0,0 +1,251 @@ +package wasi:io@0.2.0-rc-2023-11-10; + +/// 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. +interface streams { + use error.{error}; + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + 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`. + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// 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. + read: func( + /// The maximum number of bytes to read + 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`. + blocking-read: func( + /// The maximum number of bytes to read + 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. + skip: func( + /// The maximum number of bytes to skip. + 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`. + blocking-skip: func( + /// The maximum number of bytes to skip. + 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. + 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`. + 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. + check-write: func() -> result; + + /// Perform a write. This function never blocks. + /// + /// 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. + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + 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. + flush: func() -> result<_, stream-error>; + + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + 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 occured. 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. + 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. + write-zeroes: func( + /// The number of zero-bytes to write + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-zeroes-and-flush: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivelant 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`. + splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + 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`. + blocking-splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + len: u64, + ) -> result; + } +} diff --git a/wit/deps/io-2023-11-10/world.wit b/wit/deps/io-2023-11-10/world.wit new file mode 100644 index 00000000..8243da2e --- /dev/null +++ b/wit/deps/io-2023-11-10/world.wit @@ -0,0 +1,6 @@ +package wasi:io@0.2.0-rc-2023-11-10; + +world imports { + import streams; + import poll; +} diff --git a/wit/deps/io/error.wit b/wit/deps/io/error.wit new file mode 100644 index 00000000..22e5b648 --- /dev/null +++ b/wit/deps/io/error.wit @@ -0,0 +1,34 @@ +package wasi:io@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 + /// provide functions to further "downcast" this error into more specific + /// error information. For example, `error`s returned in streams derived + /// from filesystem types to be described using the filesystem's own + /// error-code type, using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter + /// `borrow` and returns + /// `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + 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. + to-debug-string: func() -> string; + } +} diff --git a/wit/deps/io/poll.wit b/wit/deps/io/poll.wit new file mode 100644 index 00000000..ddc67f8b --- /dev/null +++ b/wit/deps/io/poll.wit @@ -0,0 +1,41 @@ +package wasi:io@0.2.0; + +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +interface poll { + /// `pollable` represents a single I/O event which may be ready, or not. + resource pollable { + + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + 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. + 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. + /// + /// If the list contains more elements than can be indexed with a `u32` + /// value, this function traps. + /// + /// 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 reaedy for I/O. + poll: func(in: list>) -> list; +} diff --git a/wit/deps/io/streams.wit b/wit/deps/io/streams.wit new file mode 100644 index 00000000..6d2f871e --- /dev/null +++ b/wit/deps/io/streams.wit @@ -0,0 +1,262 @@ +package wasi:io@0.2.0; + +/// 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. +interface streams { + use error.{error}; + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + 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`. + 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. + read: func( + /// The maximum number of bytes to read + 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`. + blocking-read: func( + /// The maximum number of bytes to read + 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. + skip: func( + /// The maximum number of bytes to skip. + 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`. + blocking-skip: func( + /// The maximum number of bytes to skip. + 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. + 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`. + 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. + 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. + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + 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. + flush: func() -> result<_, stream-error>; + + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + 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 occured. 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. + 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. + write-zeroes: func( + /// The number of zero-bytes to write + 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. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-zeroes-and-flush: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivelant 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`. + splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + 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`. + blocking-splice: func( + /// The stream to read from + src: borrow, + /// The number of bytes to splice + len: u64, + ) -> result; + } +} diff --git a/wit/deps/io/world.wit b/wit/deps/io/world.wit new file mode 100644 index 00000000..5f0b43fe --- /dev/null +++ b/wit/deps/io/world.wit @@ -0,0 +1,6 @@ +package wasi:io@0.2.0; + +world imports { + import streams; + import poll; +} diff --git a/wit/deps/keyvalue-2024-10-17/atomic.wit b/wit/deps/keyvalue-2024-10-17/atomic.wit new file mode 100644 index 00000000..4a02c580 --- /dev/null +++ b/wit/deps/keyvalue-2024-10-17/atomic.wit @@ -0,0 +1,46 @@ +/// A keyvalue interface that provides atomic operations. +/// +/// Atomic operations are single, indivisible operations. When a fault causes an atomic operation to +/// fail, it will appear to the invoker of the atomic operation that the action either completed +/// successfully or did nothing at all. +/// +/// Please note that this interface is bare functions that take a reference to a bucket. This is to +/// get around the current lack of a way to "extend" a resource with additional methods inside of +/// wit. Future version of the interface will instead extend these methods on the base `bucket` +/// resource. +interface atomics { + use store.{bucket, error}; + + /// The error returned by a CAS operation + variant cas-error { + /// A store error occurred when performing the operation + store-error(error), + /// The CAS operation failed because the value was too old. This returns a new CAS handle + /// for easy retries. Implementors MUST return a CAS handle that has been updated to the + /// latest version or transaction. + cas-failed(cas), + } + + /// A handle to a CAS (compare-and-swap) operation. + resource cas { + /// Construct a new CAS operation. Implementors can map the underlying functionality + /// (transactions, versions, etc) as desired. + new: static func(bucket: borrow, key: string) -> result; + /// Get the current value of the key (if it exists). This allows for avoiding reads if all + /// that is needed to ensure the atomicity of the operation + current: func() -> result>, error>; + } + + /// Atomically increment the value associated with the key in the store by the given delta. It + /// returns the new value. + /// + /// If the key does not exist in the store, it creates a new key-value pair with the value set + /// to the given delta. + /// + /// If any other error occurs, it returns an `Err(error)`. + increment: func(bucket: borrow, key: string, delta: s64) -> result; + + /// Perform the swap on a CAS operation. This consumes the CAS handle and returns an error if + /// the CAS operation failed. + swap: func(cas: cas, value: list) -> result<_, cas-error>; +} diff --git a/wit/deps/keyvalue-2024-10-17/batch.wit b/wit/deps/keyvalue-2024-10-17/batch.wit new file mode 100644 index 00000000..6d6e8735 --- /dev/null +++ b/wit/deps/keyvalue-2024-10-17/batch.wit @@ -0,0 +1,63 @@ +/// A keyvalue interface that provides batch operations. +/// +/// A batch operation is an operation that operates on multiple keys at once. +/// +/// Batch operations are useful for reducing network round-trip time. For example, if you want to +/// get the values associated with 100 keys, you can either do 100 get operations or you can do 1 +/// batch get operation. The batch operation is faster because it only needs to make 1 network call +/// instead of 100. +/// +/// A batch operation does not guarantee atomicity, meaning that if the batch operation fails, some +/// of the keys may have been modified and some may not. +/// +/// This interface does has the same consistency guarantees as the `store` interface, meaning that +/// you should be able to "read your writes." +/// +/// Please note that this interface is bare functions that take a reference to a bucket. This is to +/// get around the current lack of a way to "extend" a resource with additional methods inside of +/// wit. Future version of the interface will instead extend these methods on the base `bucket` +/// resource. +interface batch { + use store.{bucket, error}; + + /// Get the key-value pairs associated with the keys in the store. It returns a list of + /// key-value pairs. + /// + /// If any of the keys do not exist in the store, it returns a `none` value for that pair in the + /// list. + /// + /// MAY show an out-of-date value if there are concurrent writes to the store. + /// + /// If any other error occurs, it returns an `Err(error)`. + get-many: func(bucket: borrow, keys: list) -> result>>>, error>; + + /// Set the values associated with the keys in the store. If the key already exists in the + /// store, it overwrites the value. + /// + /// Note that the key-value pairs are not guaranteed to be set in the order they are provided. + /// + /// If any of the keys do not exist in the store, it creates a new key-value pair. + /// + /// If any other error occurs, it returns an `Err(error)`. When an error occurs, it does not + /// rollback the key-value pairs that were already set. Thus, this batch operation does not + /// guarantee atomicity, implying that some key-value pairs could be set while others might + /// fail. + /// + /// Other concurrent operations may also be able to see the partial results. + set-many: func(bucket: borrow, key-values: list>>) -> result<_, error>; + + /// Delete the key-value pairs associated with the keys in the store. + /// + /// Note that the key-value pairs are not guaranteed to be deleted in the order they are + /// provided. + /// + /// If any of the keys do not exist in the store, it skips the key. + /// + /// If any other error occurs, it returns an `Err(error)`. When an error occurs, it does not + /// rollback the key-value pairs that were already deleted. Thus, this batch operation does not + /// guarantee atomicity, implying that some key-value pairs could be deleted while others might + /// fail. + /// + /// Other concurrent operations may also be able to see the partial results. + delete-many: func(bucket: borrow, keys: list) -> result<_, error>; +} diff --git a/wit/deps/keyvalue-2024-10-17/store.wit b/wit/deps/keyvalue-2024-10-17/store.wit new file mode 100644 index 00000000..c7fef411 --- /dev/null +++ b/wit/deps/keyvalue-2024-10-17/store.wit @@ -0,0 +1,122 @@ +/// A keyvalue interface that provides eventually consistent key-value operations. +/// +/// Each of these operations acts on a single key-value pair. +/// +/// The value in the key-value pair is defined as a `u8` byte array and the intention is that it is +/// the common denominator for all data types defined by different key-value stores to handle data, +/// ensuring compatibility between different key-value stores. Note: the clients will be expecting +/// serialization/deserialization overhead to be handled by the key-value store. The value could be +/// a serialized object from JSON, HTML or vendor-specific data types like AWS S3 objects. +/// +/// Data consistency in a key value store refers to the guarantee that once a write operation +/// completes, all subsequent read operations will return the value that was written. +/// +/// Any implementation of this interface must have enough consistency to guarantee "reading your +/// writes." In particular, this means that the client should never get a value that is older than +/// the one it wrote, but it MAY get a newer value if one was written around the same time. These +/// guarantees only apply to the same client (which will likely be provided by the host or an +/// external capability of some kind). In this context a "client" is referring to the caller or +/// guest that is consuming this interface. Once a write request is committed by a specific client, +/// all subsequent read requests by the same client will reflect that write or any subsequent +/// writes. Another client running in a different context may or may not immediately see the result +/// due to the replication lag. As an example of all of this, if a value at a given key is A, and +/// the client writes B, then immediately reads, it should get B. If something else writes C in +/// quick succession, then the client may get C. However, a client running in a separate context may +/// still see A or B +interface store { + /// The set of errors which may be raised by functions in this package + variant error { + /// The host does not recognize the store identifier requested. + no-such-store, + + /// The requesting component does not have access to the specified store + /// (which may or may not exist). + access-denied, + + /// Some implementation-specific error has occurred (e.g. I/O) + other(string) + } + + /// A response to a `list-keys` operation. + record key-response { + /// The list of keys returned by the query. + keys: list, + /// The continuation token to use to fetch the next page of keys. If this is `null`, then + /// there are no more keys to fetch. + cursor: option + } + + /// Get the bucket with the specified identifier. + /// + /// `identifier` must refer to a bucket provided by the host. + /// + /// `error::no-such-store` will be raised if the `identifier` is not recognized. + open: func(identifier: string) -> result; + + /// A bucket is a collection of key-value pairs. Each key-value pair is stored as a entry in the + /// bucket, and the bucket itself acts as a collection of all these entries. + /// + /// It is worth noting that the exact terminology for bucket in key-value stores can very + /// depending on the specific implementation. For example: + /// + /// 1. Amazon DynamoDB calls a collection of key-value pairs a table + /// 2. Redis has hashes, sets, and sorted sets as different types of collections + /// 3. Cassandra calls a collection of key-value pairs a column family + /// 4. MongoDB calls a collection of key-value pairs a collection + /// 5. Riak calls a collection of key-value pairs a bucket + /// 6. Memcached calls a collection of key-value pairs a slab + /// 7. Azure Cosmos DB calls a collection of key-value pairs a container + /// + /// In this interface, we use the term `bucket` to refer to a collection of key-value pairs + resource bucket { + /// Get the value associated with the specified `key` + /// + /// The value is returned as an option. If the key-value pair exists in the + /// store, it returns `Ok(value)`. If the key does not exist in the + /// store, it returns `Ok(none)`. + /// + /// If any other error occurs, it returns an `Err(error)`. + get: func(key: string) -> result>, error>; + + /// Set the value associated with the key in the store. If the key already + /// exists in the store, it overwrites the value. + /// + /// If the key does not exist in the store, it creates a new key-value pair. + /// + /// If any other error occurs, it returns an `Err(error)`. + set: func(key: string, value: list) -> result<_, error>; + + /// Delete the key-value pair associated with the key in the store. + /// + /// If the key does not exist in the store, it does nothing. + /// + /// If any other error occurs, it returns an `Err(error)`. + delete: func(key: string) -> result<_, error>; + + /// Check if the key exists in the store. + /// + /// If the key exists in the store, it returns `Ok(true)`. If the key does + /// not exist in the store, it returns `Ok(false)`. + /// + /// If any other error occurs, it returns an `Err(error)`. + exists: func(key: string) -> result; + + /// Get all the keys in the store with an optional cursor (for use in pagination). It + /// returns a list of keys. Please note that for most KeyValue implementations, this is a + /// can be a very expensive operation and so it should be used judiciously. Implementations + /// can return any number of keys in a single response, but they should never attempt to + /// send more data than is reasonable (i.e. on a small edge device, this may only be a few + /// KB, while on a large machine this could be several MB). Any response should also return + /// a cursor that can be used to fetch the next page of keys. See the `key-response` record + /// for more information. + /// + /// Note that the keys are not guaranteed to be returned in any particular order. + /// + /// If the store is empty, it returns an empty list. + /// + /// MAY show an out-of-date list of keys if there are concurrent writes to the store. + /// + /// If any error occurs, it returns an `Err(error)`. + list-keys: func(cursor: option) -> result; + } +} diff --git a/wit/deps/keyvalue-2024-10-17/watch.wit b/wit/deps/keyvalue-2024-10-17/watch.wit new file mode 100644 index 00000000..92991196 --- /dev/null +++ b/wit/deps/keyvalue-2024-10-17/watch.wit @@ -0,0 +1,16 @@ +/// A keyvalue interface that provides watch operations. +/// +/// This interface is used to provide event-driven mechanisms to handle +/// keyvalue changes. +interface watcher { + /// A keyvalue interface that provides handle-watch operations. + use store.{bucket}; + + /// Handle the `set` event for the given bucket and key. It includes a reference to the `bucket` + /// that can be used to interact with the store. + on-set: func(bucket: bucket, key: string, value: list); + + /// Handle the `delete` event for the given bucket and key. It includes a reference to the + /// `bucket` that can be used to interact with the store. + on-delete: func(bucket: bucket, key: string); +} diff --git a/wit/deps/keyvalue-2024-10-17/world.wit b/wit/deps/keyvalue-2024-10-17/world.wit new file mode 100644 index 00000000..e8fb821a --- /dev/null +++ b/wit/deps/keyvalue-2024-10-17/world.wit @@ -0,0 +1,26 @@ +package wasi:keyvalue@0.2.0-draft2; + +/// The `wasi:keyvalue/imports` world provides common APIs for interacting with key-value stores. +/// Components targeting this world will be able to do: +/// +/// 1. CRUD (create, read, update, delete) operations on key-value stores. +/// 2. Atomic `increment` and CAS (compare-and-swap) operations. +/// 3. Batch operations that can reduce the number of round trips to the network. +world imports { + /// The `store` capability allows the component to perform eventually consistent operations on + /// the key-value store. + import store; + + /// The `atomic` capability allows the component to perform atomic / `increment` and CAS + /// (compare-and-swap) operations. + import atomics; + + /// The `batch` capability allows the component to perform eventually consistent batch + /// operations that can reduce the number of round trips to the network. + import batch; +} + +world watch-service { + include imports; + export watcher; +} diff --git a/wit/deps/random-2023-10-18/insecure-seed.wit b/wit/deps/random-2023-10-18/insecure-seed.wit new file mode 100644 index 00000000..139aed15 --- /dev/null +++ b/wit/deps/random-2023-10-18/insecure-seed.wit @@ -0,0 +1,24 @@ +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + insecure-seed: func() -> tuple; +} diff --git a/wit/deps/random-2023-10-18/insecure.wit b/wit/deps/random-2023-10-18/insecure.wit new file mode 100644 index 00000000..2ffd223c --- /dev/null +++ b/wit/deps/random-2023-10-18/insecure.wit @@ -0,0 +1,21 @@ +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-insecure-random-u64: func() -> u64; +} diff --git a/wit/deps/random-2023-10-18/random.wit b/wit/deps/random-2023-10-18/random.wit new file mode 100644 index 00000000..2c3c6a85 --- /dev/null +++ b/wit/deps/random-2023-10-18/random.wit @@ -0,0 +1,25 @@ +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-random-u64: func() -> u64; +} diff --git a/wit/deps/random-2023-10-18/world.wit b/wit/deps/random-2023-10-18/world.wit new file mode 100644 index 00000000..dcbff938 --- /dev/null +++ b/wit/deps/random-2023-10-18/world.wit @@ -0,0 +1,7 @@ +package wasi:random@0.2.0-rc-2023-10-18; + +world imports { + import random; + import insecure; + import insecure-seed; +} diff --git a/wit/deps/random-2023-11-10/insecure-seed.wit b/wit/deps/random-2023-11-10/insecure-seed.wit new file mode 100644 index 00000000..f76e87da --- /dev/null +++ b/wit/deps/random-2023-11-10/insecure-seed.wit @@ -0,0 +1,25 @@ +package wasi:random@0.2.0-rc-2023-11-10; +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + insecure-seed: func() -> tuple; +} diff --git a/wit/deps/random-2023-11-10/insecure.wit b/wit/deps/random-2023-11-10/insecure.wit new file mode 100644 index 00000000..ec7b9973 --- /dev/null +++ b/wit/deps/random-2023-11-10/insecure.wit @@ -0,0 +1,22 @@ +package wasi:random@0.2.0-rc-2023-11-10; +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-insecure-random-u64: func() -> u64; +} diff --git a/wit/deps/random-2023-11-10/random.wit b/wit/deps/random-2023-11-10/random.wit new file mode 100644 index 00000000..7a7dfa27 --- /dev/null +++ b/wit/deps/random-2023-11-10/random.wit @@ -0,0 +1,26 @@ +package wasi:random@0.2.0-rc-2023-11-10; +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-random-u64: func() -> u64; +} diff --git a/wit/deps/random-2023-11-10/world.wit b/wit/deps/random-2023-11-10/world.wit new file mode 100644 index 00000000..49e5743b --- /dev/null +++ b/wit/deps/random-2023-11-10/world.wit @@ -0,0 +1,7 @@ +package wasi:random@0.2.0-rc-2023-11-10; + +world imports { + import random; + import insecure; + import insecure-seed; +} diff --git a/wit/deps/random/insecure-seed.wit b/wit/deps/random/insecure-seed.wit new file mode 100644 index 00000000..47210ac6 --- /dev/null +++ b/wit/deps/random/insecure-seed.wit @@ -0,0 +1,25 @@ +package wasi:random@0.2.0; +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + insecure-seed: func() -> tuple; +} diff --git a/wit/deps/random/insecure.wit b/wit/deps/random/insecure.wit new file mode 100644 index 00000000..c58f4ee8 --- /dev/null +++ b/wit/deps/random/insecure.wit @@ -0,0 +1,22 @@ +package wasi:random@0.2.0; +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-insecure-random-u64: func() -> u64; +} diff --git a/wit/deps/random/random.wit b/wit/deps/random/random.wit new file mode 100644 index 00000000..0c017f09 --- /dev/null +++ b/wit/deps/random/random.wit @@ -0,0 +1,26 @@ +package wasi:random@0.2.0; +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +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. + 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`. + get-random-u64: func() -> u64; +} diff --git a/wit/deps/random/world.wit b/wit/deps/random/world.wit new file mode 100644 index 00000000..3da34914 --- /dev/null +++ b/wit/deps/random/world.wit @@ -0,0 +1,7 @@ +package wasi:random@0.2.0; + +world imports { + import random; + import insecure; + import insecure-seed; +} diff --git a/wit/deps/sockets-2023-10-18/instance-network.wit b/wit/deps/sockets-2023-10-18/instance-network.wit new file mode 100644 index 00000000..14e4479e --- /dev/null +++ b/wit/deps/sockets-2023-10-18/instance-network.wit @@ -0,0 +1,9 @@ + +/// This interface provides a value-export of the default network handle.. +interface instance-network { + use network.{network}; + + /// Get a handle to the default network. + instance-network: func() -> network; + +} diff --git a/wit/deps/sockets-2023-10-18/ip-name-lookup.wit b/wit/deps/sockets-2023-10-18/ip-name-lookup.wit new file mode 100644 index 00000000..f2dab32f --- /dev/null +++ b/wit/deps/sockets-2023-10-18/ip-name-lookup.wit @@ -0,0 +1,61 @@ + +interface ip-name-lookup { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-address, ip-address-family}; + + + /// Resolve an internet host name to a list of IP addresses. + /// + /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. + /// + /// # Parameters + /// - `name`: The name to look up. IP addresses are not allowed. Unicode domain names are automatically converted + /// to ASCII using IDNA encoding. + /// - `address-family`: If provided, limit the results to addresses of this specific address family. + /// - `include-unavailable`: When set to true, this function will also return addresses of which the runtime + /// thinks (or knows) can't be connected to at the moment. For example, this will return IPv6 addresses on + /// systems without an active IPv6 interface. Notes: + /// - Even when no public IPv6 interfaces are present or active, names like "localhost" can still resolve to an IPv6 address. + /// - Whatever is "available" or "unavailable" is volatile and can change everytime a network cable is unplugged. + /// + /// 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. + /// + /// At the moment, the stream never completes successfully with 0 items. Ie. the first call + /// to `resolve-next-address` never returns `ok(none)`. This may change in the future. + /// + /// # Typical errors + /// - `invalid-argument`: `name` is a syntactically invalid domain name. + /// - `invalid-argument`: `name` is an IP address. + /// - `not-supported`: The specified `address-family` is not supported. (EAI_FAMILY) + /// + /// # References: + /// - + /// - + /// - + /// - + resolve-addresses: func(network: borrow, name: string, address-family: option, include-unavailable: bool) -> result; + + 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) + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets-2023-10-18/network.wit b/wit/deps/sockets-2023-10-18/network.wit new file mode 100644 index 00000000..fc516047 --- /dev/null +++ b/wit/deps/sockets-2023-10-18/network.wit @@ -0,0 +1,146 @@ + +interface network { + /// 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. + 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. + enum error-code { + // ### GENERAL ERRORS ### + + /// 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, + + + + // ### TCP & UDP SOCKET ERRORS ### + + /// 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, + + + // ### TCP SOCKET ERRORS ### + + /// The connection was forcefully rejected + connection-refused, + + /// The connection was reset. + connection-reset, + + /// A connection was aborted. + connection-aborted, + + // ### UDP SOCKET ERRORS ### + datagram-too-large, + + + // ### NAME LOOKUP ERRORS ### + + /// 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, + } + + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + type ipv4-address = tuple; + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, // sin_port + address: ipv4-address, // sin_addr + } + + record ipv6-socket-address { + port: u16, // sin6_port + flow-info: u32, // sin6_flowinfo + address: ipv6-address, // sin6_addr + scope-id: u32, // sin6_scope_id + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + +} diff --git a/wit/deps/sockets-2023-10-18/tcp-create-socket.wit b/wit/deps/sockets-2023-10-18/tcp-create-socket.wit new file mode 100644 index 00000000..a9a33738 --- /dev/null +++ b/wit/deps/sockets-2023-10-18/tcp-create-socket.wit @@ -0,0 +1,26 @@ + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + use tcp.{tcp-socket}; + + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// + /// 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`/`listen`/`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 + /// - + /// - + /// - + /// - + create-tcp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets-2023-10-18/tcp.wit b/wit/deps/sockets-2023-10-18/tcp.wit new file mode 100644 index 00000000..448f629e --- /dev/null +++ b/wit/deps/sockets-2023-10-18/tcp.wit @@ -0,0 +1,268 @@ + +interface tcp { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream}; + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + 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 handle. + 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. + /// + /// When a socket is not explicitly bound, the first invocation to a listen or connect operation will + /// implicitly bind the socket. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` 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, but the socket has `ipv6-only` enabled. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the Connection state + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// POSIX mentions: + /// > If connect() fails, the state of the socket is unspecified. Conforming applications should + /// > close the file descriptor and create a new socket before attempting to reconnect. + /// + /// WASI prescribes the following behavior: + /// - If `connect` fails because an input/state validation error, the socket should remain usable. + /// - If a connection was actually attempted but failed, the socket should become unusable for further network communication. + /// Besides `drop`, any method after such a failure may return an error. + /// + /// # Typical `start` 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, but the socket has `ipv6-only` enabled. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 Connection state. (EISCONN) + /// - `invalid-state`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows) + /// + /// # Typical `finish` errors + /// - `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) + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result, error-code>; + + /// Start listening for new connections. + /// + /// Transitions the socket into the Listener state. + /// + /// Unlike POSIX: + /// - this function is async. This enables interactive WASI hosts to inject permission prompts. + /// - the socket must already be explicitly bound. + /// + /// # Typical `start` errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the Listener state. + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-listen: func() -> result<_, error-code>; + finish-listen: func() -> result<_, error-code>; + + /// Accept a new client socket. + /// + /// The returned socket is bound and in the Connection state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `ipv6-only` + /// - `keep-alive` + /// - `no-delay` + /// - `unicast-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 Listener 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 + /// - + /// - + /// - + /// - + 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 + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> result<_, error-code>; + + /// Hints the desired listen queue size. Implementations are free to ignore this. + /// + /// # Typical errors + /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. + /// - `invalid-state`: (set) The socket is already in the Connection state. + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + + /// Equivalent to the SO_KEEPALIVE socket option. + keep-alive: func() -> result; + set-keep-alive: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the TCP_NODELAY socket option. + /// + /// The default value is `false`. + no-delay: func() -> result; + set-no-delay: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. + /// In other words, after setting a value, reading the same setting back may return a different value. + /// + /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of + /// actual data to be sent/received by the application, because the kernel might also use the buffer space + /// for internal metadata structures. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + + /// Initiate a graceful shutdown. + /// + /// - receive: the socket is not expecting to receive any more data from the peer. All subsequent read + /// operations on the `input-stream` associated with this socket will return an End Of Stream indication. + /// Any data still in the receive queue at time of calling `shutdown` will be discarded. + /// - send: the socket is not expecting to send any more data to the peer. All subsequent write + /// operations on the `output-stream` associated with this socket will return an error. + /// - both: same effect as receive & send combined. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the Connection state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} diff --git a/wit/deps/sockets-2023-10-18/udp-create-socket.wit b/wit/deps/sockets-2023-10-18/udp-create-socket.wit new file mode 100644 index 00000000..e026359f --- /dev/null +++ b/wit/deps/sockets-2023-10-18/udp-create-socket.wit @@ -0,0 +1,26 @@ + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + use udp.{udp-socket}; + + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// + /// 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: + /// - + /// - + /// - + /// - + create-udp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets-2023-10-18/udp.wit b/wit/deps/sockets-2023-10-18/udp.wit new file mode 100644 index 00000000..91a8c6c4 --- /dev/null +++ b/wit/deps/sockets-2023-10-18/udp.wit @@ -0,0 +1,213 @@ + +interface udp { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + + record datagram { + data: list, // Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + remote-address: ip-socket-address, + + /// Possible future additions: + /// local-address: ip-socket-address, // IP_PKTINFO / IP_RECVDSTADDR / IPV6_PKTINFO + /// local-interface: u32, // IP_PKTINFO / IP_RECVIF + /// ttl: u8, // IP_RECVTTL + /// dscp: u6, // IP_RECVTOS + /// ecn: u2, // IP_RECVTOS + } + + + + /// A UDP socket handle. + 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 TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// When a socket is not explicitly bound, the first invocation to connect will implicitly bind the socket. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Set the destination address. + /// + /// The local-address is updated based on the best network path to `remote-address`. + /// + /// When a destination address is set: + /// - all receive operations will only return datagrams sent from the provided `remote-address`. + /// - the `send` function can only be used to send to this destination. + /// + /// Note that this function does not generate any network traffic and the peer is not aware of this "connection". + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 already bound to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result<_, error-code>; + + /// 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. + /// If `max-results` is 0, this function returns successfully with an empty list. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. (EINVAL) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) + /// - `would-block`: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + receive: func(max-results: u64) -> result, error-code>; + + /// 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 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)`. + /// + /// The remote address option is required. To send a message to the "connected" peer, + /// call `remote-address` to get their address. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 the `datagram.remote-address` does not match the address passed to `connect`. (EISCONN) + /// - `invalid-state`: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind. + /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) + /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) + /// - `would-block`: The send buffer is currently full. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + send: func(datagrams: list) -> result; + + /// 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 + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the address set with `connect`. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. + /// In other words, after setting a value, reading the same setting back may return a different value. + /// + /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of + /// actual data to be sent/received by the application, because the kernel might also use the buffer space + /// for internal metadata structures. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets-2023-10-18/world.wit b/wit/deps/sockets-2023-10-18/world.wit new file mode 100644 index 00000000..d16530c3 --- /dev/null +++ b/wit/deps/sockets-2023-10-18/world.wit @@ -0,0 +1,11 @@ +package wasi:sockets@0.2.0-rc-2023-10-18; + +world imports { + import instance-network; + import network; + import udp; + import udp-create-socket; + import tcp; + import tcp-create-socket; + import ip-name-lookup; +} diff --git a/wit/deps/sockets-2023-11-10/instance-network.wit b/wit/deps/sockets-2023-11-10/instance-network.wit new file mode 100644 index 00000000..e455d0ff --- /dev/null +++ b/wit/deps/sockets-2023-11-10/instance-network.wit @@ -0,0 +1,9 @@ + +/// This interface provides a value-export of the default network handle.. +interface instance-network { + use network.{network}; + + /// Get a handle to the default network. + instance-network: func() -> network; + +} diff --git a/wit/deps/sockets-2023-11-10/ip-name-lookup.wit b/wit/deps/sockets-2023-11-10/ip-name-lookup.wit new file mode 100644 index 00000000..931ccf7e --- /dev/null +++ b/wit/deps/sockets-2023-11-10/ip-name-lookup.wit @@ -0,0 +1,51 @@ + +interface ip-name-lookup { + use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; + use network.{network, error-code, ip-address}; + + + /// 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: + /// - + /// - + /// - + /// - + resolve-addresses: func(network: borrow, name: string) -> result; + + 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) + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets-2023-11-10/network.wit b/wit/deps/sockets-2023-11-10/network.wit new file mode 100644 index 00000000..6bb07cd6 --- /dev/null +++ b/wit/deps/sockets-2023-11-10/network.wit @@ -0,0 +1,147 @@ + +interface network { + /// 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. + 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. + enum error-code { + // ### GENERAL ERRORS ### + + /// 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, + + + + // ### TCP & UDP SOCKET ERRORS ### + + /// 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, + + + // ### TCP SOCKET ERRORS ### + + /// The connection was forcefully rejected + connection-refused, + + /// The connection was reset. + connection-reset, + + /// A connection was aborted. + connection-aborted, + + + // ### UDP SOCKET ERRORS ### + datagram-too-large, + + + // ### NAME LOOKUP ERRORS ### + + /// 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, + } + + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + type ipv4-address = tuple; + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, // sin_port + address: ipv4-address, // sin_addr + } + + record ipv6-socket-address { + port: u16, // sin6_port + flow-info: u32, // sin6_flowinfo + address: ipv6-address, // sin6_addr + scope-id: u32, // sin6_scope_id + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + +} diff --git a/wit/deps/sockets-2023-11-10/tcp-create-socket.wit b/wit/deps/sockets-2023-11-10/tcp-create-socket.wit new file mode 100644 index 00000000..768a07c8 --- /dev/null +++ b/wit/deps/sockets-2023-11-10/tcp-create-socket.wit @@ -0,0 +1,26 @@ + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + use tcp.{tcp-socket}; + + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// + /// 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`/`listen`/`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 + /// - + /// - + /// - + /// - + create-tcp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets-2023-11-10/tcp.wit b/wit/deps/sockets-2023-11-10/tcp.wit new file mode 100644 index 00000000..b01b65e6 --- /dev/null +++ b/wit/deps/sockets-2023-11-10/tcp.wit @@ -0,0 +1,321 @@ + +interface tcp { + use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream}; + use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; + use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + 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 handle. + 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. + /// + /// When a socket is not explicitly bound, the first invocation to a listen or connect operation will + /// implicitly bind the socket. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` 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, but the socket has `ipv6-only` enabled. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the Connection state + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// POSIX mentions: + /// > If connect() fails, the state of the socket is unspecified. Conforming applications should + /// > close the file descriptor and create a new socket before attempting to reconnect. + /// + /// WASI prescribes the following behavior: + /// - If `connect` fails because an input/state validation error, the socket should remain usable. + /// - If a connection was actually attempted but failed, the socket should become unusable for further network communication. + /// Besides `drop`, any method after such a failure may return an error. + /// + /// # Typical `start` 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, but the socket has `ipv6-only` enabled. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 Connection state. (EISCONN) + /// - `invalid-state`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows) + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result, error-code>; + + /// Start listening for new connections. + /// + /// Transitions the socket into the Listener state. + /// + /// Unlike POSIX: + /// - this function is async. This enables interactive WASI hosts to inject permission prompts. + /// - the socket must already be explicitly bound. + /// + /// # Typical `start` errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the Listener state. + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-listen: func() -> result<_, error-code>; + finish-listen: func() -> result<_, error-code>; + + /// Accept a new client socket. + /// + /// The returned socket is bound and in the Connection state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `ipv6-only` + /// - `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 Listener 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 + /// - + /// - + /// - + /// - + 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 + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether the socket is listening for new connections. + /// + /// Equivalent to the SO_ACCEPTCONN socket option. + is-listening: func() -> bool; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> result<_, error-code>; + + /// 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 already in the Connection state. + 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. + keep-alive-enabled: func() -> result; + 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. + keep-alive-idle-time: func() -> result; + 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. + keep-alive-interval: func() -> result; + 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. + keep-alive-count: func() -> result; + 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. + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + hop-limit: func() -> result; + 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. + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + + /// Initiate a graceful shutdown. + /// + /// - receive: the socket is not expecting to receive any more data from the peer. All subsequent read + /// operations on the `input-stream` associated with this socket will return an End Of Stream indication. + /// Any data still in the receive queue at time of calling `shutdown` will be discarded. + /// - send: the socket is not expecting to send any more data to the peer. All subsequent write + /// operations on the `output-stream` associated with this socket will return an error. + /// - both: same effect as receive & send combined. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the Connection state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} diff --git a/wit/deps/sockets-2023-11-10/udp-create-socket.wit b/wit/deps/sockets-2023-11-10/udp-create-socket.wit new file mode 100644 index 00000000..cc58234d --- /dev/null +++ b/wit/deps/sockets-2023-11-10/udp-create-socket.wit @@ -0,0 +1,26 @@ + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + use udp.{udp-socket}; + + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// + /// 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: + /// - + /// - + /// - + /// - + create-udp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets-2023-11-10/udp.wit b/wit/deps/sockets-2023-11-10/udp.wit new file mode 100644 index 00000000..c8dafadf --- /dev/null +++ b/wit/deps/sockets-2023-11-10/udp.wit @@ -0,0 +1,277 @@ + +interface udp { + use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + /// A received datagram. + 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. + 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. + 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. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `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) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + 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`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 + /// - + /// - + /// - + /// - + %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 + /// - + /// - + /// - + /// - + 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 + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> 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. + unicast-hop-limit: func() -> result; + 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. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } + + 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 + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } + + 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`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `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 + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets-2023-11-10/world.wit b/wit/deps/sockets-2023-11-10/world.wit new file mode 100644 index 00000000..49ad8d3d --- /dev/null +++ b/wit/deps/sockets-2023-11-10/world.wit @@ -0,0 +1,11 @@ +package wasi:sockets@0.2.0-rc-2023-11-10; + +world imports { + import instance-network; + import network; + import udp; + import udp-create-socket; + import tcp; + import tcp-create-socket; + import ip-name-lookup; +} diff --git a/wit/deps/sockets/instance-network.wit b/wit/deps/sockets/instance-network.wit new file mode 100644 index 00000000..e455d0ff --- /dev/null +++ b/wit/deps/sockets/instance-network.wit @@ -0,0 +1,9 @@ + +/// This interface provides a value-export of the default network handle.. +interface instance-network { + use network.{network}; + + /// Get a handle to the default network. + instance-network: func() -> network; + +} diff --git a/wit/deps/sockets/ip-name-lookup.wit b/wit/deps/sockets/ip-name-lookup.wit new file mode 100644 index 00000000..8e639ec5 --- /dev/null +++ b/wit/deps/sockets/ip-name-lookup.wit @@ -0,0 +1,51 @@ + +interface ip-name-lookup { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-address}; + + + /// 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: + /// - + /// - + /// - + /// - + resolve-addresses: func(network: borrow, name: string) -> result; + + 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) + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets/network.wit b/wit/deps/sockets/network.wit new file mode 100644 index 00000000..9cadf065 --- /dev/null +++ b/wit/deps/sockets/network.wit @@ -0,0 +1,145 @@ + +interface network { + /// 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. + 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. + 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, + } + + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + type ipv4-address = tuple; + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + /// sin_port + port: u16, + /// sin_addr + address: ipv4-address, + } + + record ipv6-socket-address { + /// sin6_port + port: u16, + /// sin6_flowinfo + flow-info: u32, + /// sin6_addr + address: ipv6-address, + /// sin6_scope_id + scope-id: u32, + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + +} diff --git a/wit/deps/sockets/tcp-create-socket.wit b/wit/deps/sockets/tcp-create-socket.wit new file mode 100644 index 00000000..c7ddf1f2 --- /dev/null +++ b/wit/deps/sockets/tcp-create-socket.wit @@ -0,0 +1,27 @@ + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + 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 + /// - + /// - + /// - + /// - + create-tcp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets/tcp.wit b/wit/deps/sockets/tcp.wit new file mode 100644 index 00000000..5902b9ee --- /dev/null +++ b/wit/deps/sockets/tcp.wit @@ -0,0 +1,353 @@ + +interface tcp { + use wasi:io/streams@0.2.0.{input-stream, output-stream}; + use wasi:io/poll@0.2.0.{pollable}; + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + 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 a 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. + 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 + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the `connection` 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 + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + 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 + /// - + /// - + /// - + /// - + start-listen: func() -> result<_, error-code>; + 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 + /// - + /// - + /// - + /// - + 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 + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether the socket is in the `listening` state. + /// + /// Equivalent to the SO_ACCEPTCONN socket option. + is-listening: func() -> bool; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + 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. + 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. + keep-alive-enabled: func() -> result; + 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. + keep-alive-idle-time: func() -> result; + 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. + keep-alive-interval: func() -> result; + 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. + keep-alive-count: func() -> result; + 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. + hop-limit: func() -> result; + 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. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 a more information. + /// + /// Note: this function is here for WASI Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + 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 a 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 + /// - + /// - + /// - + /// - + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} diff --git a/wit/deps/sockets/udp-create-socket.wit b/wit/deps/sockets/udp-create-socket.wit new file mode 100644 index 00000000..0482d1fe --- /dev/null +++ b/wit/deps/sockets/udp-create-socket.wit @@ -0,0 +1,27 @@ + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + 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: + /// - + /// - + /// - + /// - + create-udp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/wit/deps/sockets/udp.wit b/wit/deps/sockets/udp.wit new file mode 100644 index 00000000..d987a0a9 --- /dev/null +++ b/wit/deps/sockets/udp.wit @@ -0,0 +1,266 @@ + +interface udp { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + /// A received datagram. + 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. + 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. + 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 + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + 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 + /// - + /// - + /// - + /// - + %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 + /// - + /// - + /// - + /// - + 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 + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + 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. + unicast-hop-limit: func() -> result; + 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. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } + + 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 + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } + + 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 + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + 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 Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/wit/deps/sockets/world.wit b/wit/deps/sockets/world.wit new file mode 100644 index 00000000..f8bb92ae --- /dev/null +++ b/wit/deps/sockets/world.wit @@ -0,0 +1,11 @@ +package wasi:sockets@0.2.0; + +world imports { + import instance-network; + import network; + import udp; + import udp-create-socket; + import tcp; + import tcp-create-socket; + import ip-name-lookup; +} diff --git a/wit/deps/spin-postgres@3.0.0/postgres.wit b/wit/deps/spin-postgres@3.0.0/postgres.wit new file mode 100644 index 00000000..55833229 --- /dev/null +++ b/wit/deps/spin-postgres@3.0.0/postgres.wit @@ -0,0 +1,100 @@ +package spin:postgres@3.0.0; + +interface postgres { + /// Errors related to interacting with a database. + variant error { + connection-failed(string), + bad-parameter(string), + query-failed(string), + value-conversion-failed(string), + other(string) + } + + /// Data types for a database column + enum db-data-type { + boolean, + int8, + int16, + int32, + int64, + floating32, + floating64, + str, + binary, + date, + time, + datetime, + timestamp, + other, + } + + /// Database values + variant db-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + date(tuple), // (year, month, day) + time(tuple), // (hour, minute, second, nanosecond) + /// Date-time types are always treated as UTC (without timezone info). + /// The instant is represented as a (year, month, day, hour, minute, second, nanosecond) tuple. + datetime(tuple), + /// Unix timestamp (seconds since epoch) + timestamp(s64), + db-null, + unsupported, + } + + /// Values used in parameterized queries + variant parameter-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + date(tuple), // (year, month, day) + time(tuple), // (hour, minute, second, nanosecond) + /// Date-time types are always treated as UTC (without timezone info). + /// The instant is represented as a (year, month, day, hour, minute, second, nanosecond) tuple. + datetime(tuple), + /// Unix timestamp (seconds since epoch) + timestamp(s64), + db-null, + } + + /// A database column + record column { + name: string, + data-type: db-data-type, + } + + /// A database row + type row = list; + + /// A set of database rows + record row-set { + columns: list, + rows: list, + } + + /// A connection to a postgres database. + resource connection { + /// Open a connection to the Postgres instance at `address`. + open: static func(address: string) -> result; + + /// Query the database. + query: func(statement: string, params: list) -> result; + + /// Execute command to the database. + execute: func(statement: string, params: list) -> result; + } +} diff --git a/wit/deps/spin@2.0.0/key-value.wit b/wit/deps/spin@2.0.0/key-value.wit new file mode 100644 index 00000000..7ba4ed94 --- /dev/null +++ b/wit/deps/spin@2.0.0/key-value.wit @@ -0,0 +1,47 @@ +interface key-value { + /// An open key-value store + resource store { + /// Open the store with the specified label. + /// + /// `label` must refer to a store allowed in the spin.toml manifest. + /// + /// `error::no-such-store` will be raised if the `label` is not recognized. + open: static func(label: string) -> result; + + /// Get the value associated with the specified `key` + /// + /// Returns `ok(none)` if the key does not exist. + get: func(key: string) -> result>, error>; + + /// Set the `value` associated with the specified `key` overwriting any existing value. + set: func(key: string, value: list) -> result<_, error>; + + /// Delete the tuple with the specified `key` + /// + /// No error is raised if a tuple did not previously exist for `key`. + delete: func(key: string) -> result<_, error>; + + /// Return whether a tuple exists for the specified `key` + exists: func(key: string) -> result; + + /// Return a list of all the keys + get-keys: func() -> result, error>; + } + + /// The set of errors which may be raised by functions in this interface + variant error { + /// Too many stores have been opened simultaneously. Closing one or more + /// stores prior to retrying may address this. + store-table-full, + + /// The host does not recognize the store label requested. + no-such-store, + + /// The requesting component does not have access to the specified store + /// (which may or may not exist). + access-denied, + + /// Some implementation-specific error has occurred (e.g. I/O) + other(string) + } +} diff --git a/wit/deps/spin@2.0.0/llm.wit b/wit/deps/spin@2.0.0/llm.wit new file mode 100644 index 00000000..bcb59b86 --- /dev/null +++ b/wit/deps/spin@2.0.0/llm.wit @@ -0,0 +1,70 @@ +// A WASI interface dedicated to performing inferencing for Large Language Models. +interface llm { + /// A Large Language Model. + type inferencing-model = string; + + /// Inference request parameters + record inferencing-params { + /// The maximum tokens that should be inferred. + /// + /// Note: the backing implementation may return less tokens. + max-tokens: u32, + /// The amount the model should avoid repeating tokens. + repeat-penalty: f32, + /// The number of tokens the model should apply the repeat penalty to. + repeat-penalty-last-n-token-count: u32, + /// The randomness with which the next token is selected. + temperature: f32, + /// The number of possible next tokens the model will choose from. + top-k: u32, + /// The probability total of next tokens the model will choose from. + top-p: f32 + } + + /// The set of errors which may be raised by functions in this interface + variant error { + model-not-supported, + runtime-error(string), + invalid-input(string) + } + + /// An inferencing result + record inferencing-result { + /// The text generated by the model + // TODO: this should be a stream + text: string, + /// Usage information about the inferencing request + usage: inferencing-usage + } + + /// Usage information related to the inferencing result + record inferencing-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + /// Number of tokens generated by the inferencing operation + generated-token-count: u32 + } + + /// Perform inferencing using the provided model and prompt with the given optional params + infer: func(model: inferencing-model, prompt: string, params: option) -> result; + + /// The model used for generating embeddings + type embedding-model = string; + + /// Generate embeddings for the supplied list of text + generate-embeddings: func(model: embedding-model, text: list) -> result; + + /// Result of generating embeddings + record embeddings-result { + /// The embeddings generated by the request + embeddings: list>, + /// Usage related to the embeddings generation request + usage: embeddings-usage + } + + /// Usage related to an embeddings generation request + record embeddings-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + } +} diff --git a/wit/deps/spin@2.0.0/mqtt.wit b/wit/deps/spin@2.0.0/mqtt.wit new file mode 100644 index 00000000..32f04fb5 --- /dev/null +++ b/wit/deps/spin@2.0.0/mqtt.wit @@ -0,0 +1,31 @@ +interface mqtt { + /// Errors related to interacting with Mqtt + variant error { + /// An invalid address string + invalid-address, + /// There are too many open connections + too-many-connections, + /// Connection failure e.g. address not allowed. + connection-failed(string), + /// Some other error occurred + other(string), + } + + /// QoS for publishing Mqtt messages + enum qos { + at-most-once, + at-least-once, + exactly-once, + } + + resource connection { + /// Open a connection to the Mqtt instance at `address`. + open: static func(address: string, username: string, password: string, keep-alive-interval-in-secs: u64) -> result; + + /// Publish an Mqtt message to the specified `topic`. + publish: func(topic: string, payload: payload, qos: qos) -> result<_, error>; + } + + /// The message payload. + type payload = list; +} diff --git a/wit/deps/spin@2.0.0/mysql.wit b/wit/deps/spin@2.0.0/mysql.wit new file mode 100644 index 00000000..446cf89e --- /dev/null +++ b/wit/deps/spin@2.0.0/mysql.wit @@ -0,0 +1,15 @@ +interface mysql { + use rdbms-types.{parameter-value, row-set, error}; + + /// A connection to a MySQL database. + resource connection { + /// Open a connection to the MySQL instance at `address`. + open: static func(address: string) -> result; + + /// query the database: select + query: func(statement: string, params: list) -> result; + + /// execute command to the database: insert, update, delete + execute: func(statement: string, params: list) -> result<_, error>; + } +} diff --git a/wit/deps/spin@2.0.0/postgres.wit b/wit/deps/spin@2.0.0/postgres.wit new file mode 100644 index 00000000..ebe1ec6a --- /dev/null +++ b/wit/deps/spin@2.0.0/postgres.wit @@ -0,0 +1,15 @@ +interface postgres { + use rdbms-types.{parameter-value, row-set, error}; + + /// A connection to a postgres database. + resource connection { + /// Open a connection to the Postgres instance at `address`. + open: static func(address: string) -> result; + + /// Query the database. + query: func(statement: string, params: list) -> result; + + /// Execute command to the database. + execute: func(statement: string, params: list) -> result; + } +} diff --git a/wit/deps/spin@2.0.0/rdbms-types.wit b/wit/deps/spin@2.0.0/rdbms-types.wit new file mode 100644 index 00000000..aff2e960 --- /dev/null +++ b/wit/deps/spin@2.0.0/rdbms-types.wit @@ -0,0 +1,80 @@ +interface rdbms-types { + /// Errors related to interacting with a database. + variant error { + connection-failed(string), + bad-parameter(string), + query-failed(string), + value-conversion-failed(string), + other(string) + } + + /// Data types for a database column + enum db-data-type { + boolean, + int8, + int16, + int32, + int64, + uint8, + uint16, + uint32, + uint64, + floating32, + floating64, + str, + binary, + other, + } + + /// Database values + variant db-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + unsupported, + } + + /// Values used in parameterized queries + variant parameter-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + } + + /// A database column + record column { + name: string, + data-type: db-data-type, + } + + /// A database row + type row = list; + + /// A set of database rows + record row-set { + columns: list, + rows: list, + } +} diff --git a/wit/deps/spin@2.0.0/redis.wit b/wit/deps/spin@2.0.0/redis.wit new file mode 100644 index 00000000..27446ebd --- /dev/null +++ b/wit/deps/spin@2.0.0/redis.wit @@ -0,0 +1,70 @@ +interface redis { + /// Errors related to interacting with Redis + variant error { + /// An invalid address string + invalid-address, + /// There are too many open connections + too-many-connections, + /// A retrieved value was not of the correct type + type-error, + /// Some other error occurred + other(string), + } + + resource connection { + /// Open a connection to the Redis instance at `address`. + open: static func(address: string) -> result; + + /// Publish a Redis message to the specified channel. + publish: func(channel: string, payload: payload) -> result<_, error>; + + /// Get the value of a key. + get: func(key: string) -> result, error>; + + /// Set key to value. + /// + /// If key already holds a value, it is overwritten. + set: func(key: string, value: payload) -> result<_, error>; + + /// Increments the number stored at key by one. + /// + /// If the key does not exist, it is set to 0 before performing the operation. + /// An `error::type-error` is returned if the key contains a value of the wrong type + /// or contains a string that can not be represented as integer. + incr: func(key: string) -> result; + + /// Removes the specified keys. + /// + /// A key is ignored if it does not exist. Returns the number of keys deleted. + del: func(keys: list) -> result; + + /// Add the specified `values` to the set named `key`, returning the number of newly-added values. + sadd: func(key: string, values: list) -> result; + + /// Retrieve the contents of the set named `key`. + smembers: func(key: string) -> result, error>; + + /// Remove the specified `values` from the set named `key`, returning the number of newly-removed values. + srem: func(key: string, values: list) -> result; + + /// Execute an arbitrary Redis command and receive the result. + execute: func(command: string, arguments: list) -> result, error>; + } + + /// The message payload. + type payload = list; + + /// A parameter type for the general-purpose `execute` function. + variant redis-parameter { + int64(s64), + binary(payload) + } + + /// A return type for the general-purpose `execute` function. + variant redis-result { + nil, + status(string), + int64(s64), + binary(payload) + } +} diff --git a/wit/deps/spin@2.0.0/sqlite.wit b/wit/deps/spin@2.0.0/sqlite.wit new file mode 100644 index 00000000..d82f2d90 --- /dev/null +++ b/wit/deps/spin@2.0.0/sqlite.wit @@ -0,0 +1,50 @@ +interface sqlite { + /// A handle to an open sqlite instance + resource connection { + /// Open a connection to a named database instance. + /// + /// If `database` is "default", the default instance is opened. + /// + /// `error::no-such-database` will be raised if the `name` is not recognized. + open: static func(database: string) -> result; + + /// Execute a statement returning back data if there is any + execute: func(statement: string, parameters: list) -> result; + } + + /// The set of errors which may be raised by functions in this interface + variant error { + /// The host does not recognize the database name requested. + no-such-database, + /// The requesting component does not have access to the specified database (which may or may not exist). + access-denied, + /// The provided connection is not valid + invalid-connection, + /// The database has reached its capacity + database-full, + /// Some implementation-specific error has occurred (e.g. I/O) + io(string) + } + + /// A result of a query + record query-result { + /// The names of the columns retrieved in the query + columns: list, + /// the row results each containing the values for all the columns for a given row + rows: list, + } + + /// A set of values for each of the columns in a query-result + record row-result { + values: list + } + + /// A single column's result from a database query + variant value { + integer(s64), + real(f64), + text(string), + blob(list), + null + } +} diff --git a/wit/deps/spin@2.0.0/variables.wit b/wit/deps/spin@2.0.0/variables.wit new file mode 100644 index 00000000..6c0511a8 --- /dev/null +++ b/wit/deps/spin@2.0.0/variables.wit @@ -0,0 +1,18 @@ +interface variables { + /// Get an application variable value for the current component. + /// + /// The name must match one defined in in the component manifest. + get: func(name: string) -> result; + + /// The set of errors which may be raised by functions in this interface. + variant error { + /// The provided variable name is invalid. + invalid-name(string), + /// The provided variable is undefined. + undefined(string), + /// A variables provider specific error has occurred. + provider(string), + /// Some implementation-specific error has occurred. + other(string), + } +} diff --git a/wit/deps/spin@2.0.0/world.wit b/wit/deps/spin@2.0.0/world.wit new file mode 100644 index 00000000..b16e4290 --- /dev/null +++ b/wit/deps/spin@2.0.0/world.wit @@ -0,0 +1,41 @@ +package fermyon:spin@2.0.0; + +/// The full world of a guest targeting an http-trigger +world http-trigger { + include platform; + export wasi:http/incoming-handler@0.2.0; +} + +/// Like `http-trigger`, but using WASI 0.2.0-rc-2023-10-18 +world http-trigger-rc20231018 { + include platform-rc20231018; + export wasi:http/incoming-handler@0.2.0-rc-2023-10-18; +} + +/// The imports needed for a guest to run on a Spin host +world platform { + include wasi:cli/imports@0.2.0; + import wasi:http/outgoing-handler@0.2.0; + import llm; + import redis; + import mqtt; + import postgres; + import mysql; + import sqlite; + import key-value; + import variables; +} + +/// Like `platform`, but using WASI 0.2.0-rc-2023-10-18 +world platform-rc20231018 { + include wasi:cli/reactor@0.2.0-rc-2023-10-18; + import wasi:http/outgoing-handler@0.2.0-rc-2023-10-18; + import llm; + import redis; + import mqtt; + import postgres; + import mysql; + import sqlite; + import key-value; + import variables; +} diff --git a/wit/deps/spin@unversioned/config.wit b/wit/deps/spin@unversioned/config.wit new file mode 100644 index 00000000..ac465fbe --- /dev/null +++ b/wit/deps/spin@unversioned/config.wit @@ -0,0 +1,12 @@ +interface config { + // Get a configuration value for the current component. + // The config key must match one defined in in the component manifest. + get-config: func(key: string) -> result; + + variant error { + provider(string), + invalid-key(string), + invalid-schema(string), + other(string), + } +} diff --git a/wit/deps/spin@unversioned/http-types.wit b/wit/deps/spin@unversioned/http-types.wit new file mode 100644 index 00000000..c941cc97 --- /dev/null +++ b/wit/deps/spin@unversioned/http-types.wit @@ -0,0 +1,44 @@ +interface http-types { + type http-status = u16; + + type body = list; + + type headers = list>; + + type params = list>; + + type uri = string; + + enum method { + get, + post, + put, + delete, + patch, + head, + options, + } + + record request { + method: method, + uri: uri, + headers: headers, + params: params, + body: option, + } + + record response { + status: http-status, + headers: option, + body: option, + } + + enum http-error { + success, + destination-not-allowed, + invalid-url, + request-error, + runtime-error, + too-many-requests, + } +} diff --git a/wit/deps/spin@unversioned/http.wit b/wit/deps/spin@unversioned/http.wit new file mode 100644 index 00000000..6ca943cf --- /dev/null +++ b/wit/deps/spin@unversioned/http.wit @@ -0,0 +1,5 @@ +interface http { + use http-types.{request, response, http-error}; + + send-request: func(req: request) -> result; +} diff --git a/wit/deps/spin@unversioned/inbound-http.wit b/wit/deps/spin@unversioned/inbound-http.wit new file mode 100644 index 00000000..968c5762 --- /dev/null +++ b/wit/deps/spin@unversioned/inbound-http.wit @@ -0,0 +1,5 @@ +interface inbound-http { + use http-types.{request, response}; + + handle-request: func(req: request) -> response; +} diff --git a/wit/deps/spin@unversioned/inbound-redis.wit b/wit/deps/spin@unversioned/inbound-redis.wit new file mode 100644 index 00000000..a991e5de --- /dev/null +++ b/wit/deps/spin@unversioned/inbound-redis.wit @@ -0,0 +1,6 @@ +interface inbound-redis { + use redis-types.{payload, error}; + + // The entrypoint for a Redis handler. + handle-message: func(message: payload) -> result<_, error>; +} diff --git a/wit/deps/spin@unversioned/key-value.wit b/wit/deps/spin@unversioned/key-value.wit new file mode 100644 index 00000000..314a758c --- /dev/null +++ b/wit/deps/spin@unversioned/key-value.wit @@ -0,0 +1,80 @@ +interface key-value { + // A handle to an open key-value store + type store = u32; + + // The set of errors which may be raised by functions in this interface + variant error { + // Too many stores have been opened simultaneously. Closing one or more + // stores prior to retrying may address this. + store-table-full, + + // The host does not recognize the store name requested. Defining and + // configuring a store with that name in a runtime configuration file + // may address this. + no-such-store, + + // The requesting component does not have access to the specified store + // (which may or may not exist). + access-denied, + + // The store handle provided is not recognized, i.e. it was either never + // opened or has been closed. + invalid-store, + + // No key-value tuple exists for the specified key in the specified + // store. + no-such-key, + + // Some implementation-specific error has occurred (e.g. I/O) + io(string) + } + + // Open the store with the specified name. + // + // If `name` is "default", the default store is opened. Otherwise, + // `name` must refer to a store defined and configured in a runtime + // configuration file supplied with the application. + // + // `error::no-such-store` will be raised if the `name` is not recognized. + open: func(name: string) -> result; + + // Get the value associated with the specified `key` from the specified + // `store`. + // + // `error::invalid-store` will be raised if `store` is not a valid handle + // to an open store, and `error::no-such-key` will be raised if there is no + // tuple for `key` in `store`. + get: func(store: store, key: string) -> result, error>; + + // Set the `value` associated with the specified `key` in the specified + // `store`, overwriting any existing value. + // + // `error::invalid-store` will be raised if `store` is not a valid handle + // to an open store. + set: func(store: store, key: string, value: list) -> result<_, error>; + + // Delete the tuple with the specified `key` from the specified `store`. + // + // `error::invalid-store` will be raised if `store` is not a valid handle + // to an open store. No error is raised if a tuple did not previously + // exist for `key`. + delete: func(store: store, key: string) -> result<_, error>; + + // Return whether a tuple exists for the specified `key` in the specified + // `store`. + // + // `error::invalid-store` will be raised if `store` is not a valid handle + // to an open store. + exists: func(store: store, key: string) -> result; + + // Return a list of all the keys in the specified `store`. + // + // `error::invalid-store` will be raised if `store` is not a valid handle + // to an open store. + get-keys: func(store: store) -> result, error>; + + // Close the specified `store`. + // + // This has no effect if `store` is not a valid handle to an open store. + close: func(store: store); +} diff --git a/wit/deps/spin@unversioned/llm.wit b/wit/deps/spin@unversioned/llm.wit new file mode 100644 index 00000000..bcb59b86 --- /dev/null +++ b/wit/deps/spin@unversioned/llm.wit @@ -0,0 +1,70 @@ +// A WASI interface dedicated to performing inferencing for Large Language Models. +interface llm { + /// A Large Language Model. + type inferencing-model = string; + + /// Inference request parameters + record inferencing-params { + /// The maximum tokens that should be inferred. + /// + /// Note: the backing implementation may return less tokens. + max-tokens: u32, + /// The amount the model should avoid repeating tokens. + repeat-penalty: f32, + /// The number of tokens the model should apply the repeat penalty to. + repeat-penalty-last-n-token-count: u32, + /// The randomness with which the next token is selected. + temperature: f32, + /// The number of possible next tokens the model will choose from. + top-k: u32, + /// The probability total of next tokens the model will choose from. + top-p: f32 + } + + /// The set of errors which may be raised by functions in this interface + variant error { + model-not-supported, + runtime-error(string), + invalid-input(string) + } + + /// An inferencing result + record inferencing-result { + /// The text generated by the model + // TODO: this should be a stream + text: string, + /// Usage information about the inferencing request + usage: inferencing-usage + } + + /// Usage information related to the inferencing result + record inferencing-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + /// Number of tokens generated by the inferencing operation + generated-token-count: u32 + } + + /// Perform inferencing using the provided model and prompt with the given optional params + infer: func(model: inferencing-model, prompt: string, params: option) -> result; + + /// The model used for generating embeddings + type embedding-model = string; + + /// Generate embeddings for the supplied list of text + generate-embeddings: func(model: embedding-model, text: list) -> result; + + /// Result of generating embeddings + record embeddings-result { + /// The embeddings generated by the request + embeddings: list>, + /// Usage related to the embeddings generation request + usage: embeddings-usage + } + + /// Usage related to an embeddings generation request + record embeddings-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + } +} diff --git a/wit/deps/spin@unversioned/mysql.wit b/wit/deps/spin@unversioned/mysql.wit new file mode 100644 index 00000000..dd1b9c3e --- /dev/null +++ b/wit/deps/spin@unversioned/mysql.wit @@ -0,0 +1,19 @@ +interface mysql { + use rdbms-types.{parameter-value, row-set}; + + // General purpose error. + variant mysql-error { + success, + connection-failed(string), + bad-parameter(string), + query-failed(string), + value-conversion-failed(string), + other-error(string) + } + + // query the database: select + query: func(address: string, statement: string, params: list) -> result; + + // execute command to the database: insert, update, delete + execute: func(address: string, statement: string, params: list) -> result<_, mysql-error>; +} diff --git a/wit/deps/spin@unversioned/postgres.wit b/wit/deps/spin@unversioned/postgres.wit new file mode 100644 index 00000000..e82ef42c --- /dev/null +++ b/wit/deps/spin@unversioned/postgres.wit @@ -0,0 +1,19 @@ +interface postgres { + use rdbms-types.{parameter-value, row-set}; + + // General purpose error. + variant pg-error { + success, + connection-failed(string), + bad-parameter(string), + query-failed(string), + value-conversion-failed(string), + other-error(string) + } + + // query the database: select + query: func(address: string, statement: string, params: list) -> result; + + // execute command to the database: insert, update, delete + execute: func(address: string, statement: string, params: list) -> result; +} diff --git a/wit/deps/spin@unversioned/rdbms-types.wit b/wit/deps/spin@unversioned/rdbms-types.wit new file mode 100644 index 00000000..8f9c9c38 --- /dev/null +++ b/wit/deps/spin@unversioned/rdbms-types.wit @@ -0,0 +1,65 @@ +interface rdbms-types { + enum db-data-type { + boolean, + int8, + int16, + int32, + int64, + uint8, + uint16, + uint32, + uint64, + floating32, + floating64, + str, + binary, + other, + } + + variant db-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + unsupported, + } + + variant parameter-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + } + + record column { + name: string, + data-type: db-data-type, + } + + type row = list; + + record row-set { + columns: list, + rows: list, + } +} diff --git a/wit/deps/spin@unversioned/redis-types.wit b/wit/deps/spin@unversioned/redis-types.wit new file mode 100644 index 00000000..6970f63e --- /dev/null +++ b/wit/deps/spin@unversioned/redis-types.wit @@ -0,0 +1,24 @@ +interface redis-types { + // General purpose error. + enum error { + success, + error, + } + + /// The message payload. + type payload = list; + + /// A parameter type for the general-purpose `execute` function. + variant redis-parameter { + int64(s64), + binary(payload) + } + + /// A return type for the general-purpose `execute` function. + variant redis-result { + nil, + status(string), + int64(s64), + binary(payload) + } +} diff --git a/wit/deps/spin@unversioned/redis.wit b/wit/deps/spin@unversioned/redis.wit new file mode 100644 index 00000000..1b64906b --- /dev/null +++ b/wit/deps/spin@unversioned/redis.wit @@ -0,0 +1,31 @@ +interface redis { + use redis-types.{payload, redis-parameter, redis-result, error}; + + // Publish a Redis message to the specificed channel and return an error, if any. + publish: func(address: string, channel: string, payload: payload) -> result<_, error>; + + // Get the value of a key. + get: func(address: string, key: string) -> result; + + // Set key to value. If key alreads holds a value, it is overwritten. + set: func(address: string, key: string, value: payload) -> result<_, error>; + + // Increments the number stored at key by one. If the key does not exist, it is set to 0 before performing the operation. + // An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer. + incr: func(address: string, key: string) -> result; + + // Removes the specified keys. A key is ignored if it does not exist. + del: func(address: string, keys: list) -> result; + + // Add the specified `values` to the set named `key`, returning the number of newly-added values. + sadd: func(address: string, key: string, values: list) -> result; + + // Retrieve the contents of the set named `key`. + smembers: func(address: string, key: string) -> result, error>; + + // Remove the specified `values` from the set named `key`, returning the number of newly-removed values. + srem: func(address: string, key: string, values: list) -> result; + + // Execute an arbitrary Redis command and receive the result. + execute: func(address: string, command: string, arguments: list) -> result, error>; +} diff --git a/wit/deps/spin@unversioned/sqlite.wit b/wit/deps/spin@unversioned/sqlite.wit new file mode 100644 index 00000000..d5abcb2b --- /dev/null +++ b/wit/deps/spin@unversioned/sqlite.wit @@ -0,0 +1,52 @@ +interface sqlite { + // A handle to an open sqlite instance + type connection = u32; + + // The set of errors which may be raised by functions in this interface + variant error { + // The host does not recognize the database name requested. + no-such-database, + // The requesting component does not have access to the specified database (which may or may not exist). + access-denied, + // The provided connection is not valid + invalid-connection, + // The database has reached its capacity + database-full, + // Some implementation-specific error has occurred (e.g. I/O) + io(string) + } + + // Open a connection to a named database instance. + // + // If `database` is "default", the default instance is opened. + // + // `error::no-such-database` will be raised if the `name` is not recognized. + open: func(database: string) -> result; + + // Execute a statement returning back data if there is any + execute: func(conn: connection, statement: string, parameters: list) -> result; + + // Close the specified `connection`. + close: func(conn: connection); + + // A result of a query + record query-result { + // The names of the columns retrieved in the query + columns: list, + // the row results each containing the values for all the columns for a given row + rows: list, + } + + // A set of values for each of the columns in a query-result + record row-result { + values: list + } + + variant value { + integer(s64), + real(f64), + text(string), + blob(list), + null + } +} diff --git a/wit/deps/spin@unversioned/world.wit b/wit/deps/spin@unversioned/world.wit new file mode 100644 index 00000000..603a7602 --- /dev/null +++ b/wit/deps/spin@unversioned/world.wit @@ -0,0 +1,29 @@ +package fermyon:spin; + +world host { + include platform; + + export inbound-http; + export inbound-redis; +} + +world redis-trigger { + include platform; + export inbound-redis; +} + +world http-trigger { + include platform; + export inbound-http; +} + +world platform { + import config; + import http; + import postgres; + import mysql; + import sqlite; + import redis; + import key-value; + import llm; +} diff --git a/wit/deps/wasi-runtime-config-2024-09-27/store.wit b/wit/deps/wasi-runtime-config-2024-09-27/store.wit new file mode 100644 index 00000000..794379a7 --- /dev/null +++ b/wit/deps/wasi-runtime-config-2024-09-27/store.wit @@ -0,0 +1,30 @@ +interface store { + /// An error type that encapsulates the different errors that can occur fetching configuration values. + variant error { + /// This indicates an error from an "upstream" config source. + /// As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue buckets, etc), + /// the error message is a string. + upstream(string), + /// This indicates an error from an I/O operation. + /// As this could be almost _anything_ (such as a file read, network connection, etc), + /// the error message is a string. + /// Depending on how this ends up being consumed, + /// we may consider moving this to use the `wasi:io/error` type instead. + /// For simplicity right now in supporting multiple implementations, it is being left as a string. + io(string), + } + + /// Gets a configuration value of type `string` associated with the `key`. + /// + /// The value is returned as an `option`. If the key is not found, + /// `Ok(none)` is returned. If an error occurs, an `Err(error)` is returned. + get: func( + /// A string key to fetch + key: string + ) -> result, error>; + + /// Gets a list of configuration key-value pairs of type `string`. + /// + /// If an error occurs, an `Err(error)` is returned. + get-all: func() -> result>, error>; +} diff --git a/wit/deps/wasi-runtime-config-2024-09-27/world.wit b/wit/deps/wasi-runtime-config-2024-09-27/world.wit new file mode 100644 index 00000000..e879af51 --- /dev/null +++ b/wit/deps/wasi-runtime-config-2024-09-27/world.wit @@ -0,0 +1,6 @@ +package wasi:config@0.2.0-draft-2024-09-27; + +world imports { + /// The interface for wasi:config/store + import store; +} \ No newline at end of file diff --git a/wit/http-types.wit b/wit/http-types.wit deleted file mode 100644 index e0626954..00000000 --- a/wit/http-types.wit +++ /dev/null @@ -1,59 +0,0 @@ -// This is a temporary workaround very similar to https://github.com/deislabs/wasi-experimental-http. -// Once asynchronous functions, streams, and the upstream HTTP API are available, this should be removed. - -// The HTTP status code. -// This is currently an unsigned 16-bit integer, -// but it could be represented as an enum containing -// all possible HTTP status codes. -type http-status = u16 - -// The HTTP body. -// Currently, this is a synchonous byte array, but it should be -// possible to have a stream for both request and response bodies. -type body = list - -// The HTTP headers represented as a list of (name, value) pairs. -type headers = list> - -// The HTTP parameter queries, represented as a list of (name, value) pairs. -type params = list> - -// The HTTP URI of the current request. -type uri = string - -// The HTTP method. -enum method { - get, - post, - put, - delete, - patch, - head, - options, -} - -// An HTTP request. -record request { - method: method, - uri: uri, - headers: headers, - params: params, - body: option, -} - -// An HTTP response. -record response { - status: http-status, - headers: option, - body: option, -} - -// HTTP errors returned by the runtime. -enum http-error { - success, - destination-not-allowed, - invalid-url, - request-error, - runtime-error, - too-many-requests, -} diff --git a/wit/key-value.wit b/wit/key-value.wit deleted file mode 100644 index a37b1d48..00000000 --- a/wit/key-value.wit +++ /dev/null @@ -1,78 +0,0 @@ -// A handle to an open key-value store -type store = u32 - -// The set of errors which may be raised by functions in this interface -variant error { - // Too many stores have been opened simultaneously. Closing one or more - // stores prior to retrying may address this. - store-table-full, - - // The host does not recognize the store name requested. Defining and - // configuring a store with that name in a runtime configuration file - // may address this. - no-such-store, - - // The requesting component does not have access to the specified store - // (which may or may not exist). - access-denied, - - // The store handle provided is not recognized, i.e. it was either never - // opened or has been closed. - invalid-store, - - // No key-value tuple exists for the specified key in the specified - // store. - no-such-key, - - // Some implementation-specific error has occurred (e.g. I/O) - io(string) -} - -// Open the store with the specified name. -// -// If `name` is "default", the default store is opened. Otherwise, -// `name` must refer to a store defined and configured in a runtime -// configuration file supplied with the application. -// -// `error::no-such-store` will be raised if the `name` is not recognized. -open: func(name: string) -> expected - -// Get the value associated with the specified `key` from the specified -// `store`. -// -// `error::invalid-store` will be raised if `store` is not a valid handle -// to an open store, and `error::no-such-key` will be raised if there is no -// tuple for `key` in `store`. -get: func(store: store, key: string) -> expected, error> - -// Set the `value` associated with the specified `key` in the specified -// `store`, overwriting any existing value. -// -// `error::invalid-store` will be raised if `store` is not a valid handle -// to an open store. -set: func(store: store, key: string, value: list) -> expected - -// Delete the tuple with the specified `key` from the specified `store`. -// -// `error::invalid-store` will be raised if `store` is not a valid handle -// to an open store. No error is raised if a tuple did not previously -// exist for `key`. -delete: func(store: store, key: string) -> expected - -// Return whether a tuple exists for the specified `key` in the specified -// `store`. -// -// `error::invalid-store` will be raised if `store` is not a valid handle -// to an open store. -exists: func(store: store, key: string) -> expected - -// Return a list of all the keys in the specified `store`. -// -// `error::invalid-store` will be raised if `store` is not a valid handle -// to an open store. -get-keys: func(store: store) -> expected, error> - -// Close the specified `store`. -// -// This has no effect if `store` is not a valid handle to an open store. -close: func(store: store) diff --git a/wit/mysql-types.wit b/wit/mysql-types.wit deleted file mode 100644 index a18f5d73..00000000 --- a/wit/mysql-types.wit +++ /dev/null @@ -1,10 +0,0 @@ -// General purpose error. -// TODO: We can provide richer info than this: https://docs.rs/mysql/latest/mysql/error/enum.Error.html -variant mysql-error { - success, - connection-failed(string), - bad-parameter(string), - query-failed(string), - value-conversion-failed(string), - other-error(string) -} diff --git a/wit/outbound-mysql.wit b/wit/outbound-mysql.wit deleted file mode 100644 index 8cd07277..00000000 --- a/wit/outbound-mysql.wit +++ /dev/null @@ -1,8 +0,0 @@ -use * from mysql-types -use * from rdbms-types - -// query the database: select -query: func(address: string, statement: string, params: list) -> expected - -// execute command to the database: insert, update, delete -execute: func(address: string, statement: string, params: list) -> expected diff --git a/wit/outbound-pg.wit b/wit/outbound-pg.wit deleted file mode 100644 index 94a7c799..00000000 --- a/wit/outbound-pg.wit +++ /dev/null @@ -1,8 +0,0 @@ -use * from pg-types -use * from rdbms-types - -// query the database: select -query: func(address: string, statement: string, params: list) -> expected - -// execute command to the database: insert, update, delete -execute: func(address: string, statement: string, params: list) -> expected diff --git a/wit/outbound-redis.wit b/wit/outbound-redis.wit deleted file mode 100644 index 5a7cbd4c..00000000 --- a/wit/outbound-redis.wit +++ /dev/null @@ -1,29 +0,0 @@ -use * from redis-types - -// Publish a Redis message to the specificed channel and return an error, if any. -publish: func(address: string, channel: string, payload: payload) -> expected - -// Get the value of a key. -get: func(address: string, key: string) -> expected - -// Set key to value. If key alreads holds a value, it is overwritten. -set: func(address: string, key: string, value: payload) -> expected - -// Increments the number stored at key by one. If the key does not exist, it is set to 0 before performing the operation. -// An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer. -incr: func(address: string, key: string) -> expected - -// Removes the specified keys. A key is ignored if it does not exist. -del: func(address: string, keys: list) -> expected - -// Add the specified `values` to the set named `key`, returning the number of newly-added values. -sadd: func(address: string, key: string, values: list) -> expected - -// Retrieve the contents of the set named `key`. -smembers: func(address: string, key: string) -> expected, error> - -// Remove the specified `values` from the set named `key`, returning the number of newly-removed values. -srem: func(address: string, key: string, values: list) -> expected - -// Execute an arbitrary Redis command and receive the result. -execute: func(address: string, command: string, arguments: list) -> expected, error> diff --git a/wit/pg-types.wit b/wit/pg-types.wit deleted file mode 100644 index 8e0336b6..00000000 --- a/wit/pg-types.wit +++ /dev/null @@ -1,9 +0,0 @@ -// General purpose error. -variant pg-error { - success, - connection-failed(string), - bad-parameter(string), - query-failed(string), - value-conversion-failed(string), - other-error(string) -} diff --git a/wit/rdbms-types.wit b/wit/rdbms-types.wit deleted file mode 100644 index 393479ae..00000000 --- a/wit/rdbms-types.wit +++ /dev/null @@ -1,63 +0,0 @@ -enum db-data-type { - boolean, - int8, - int16, - int32, - int64, - uint8, - uint16, - uint32, - uint64, - floating32, - floating64, - str, - binary, - other, -} - -variant db-value { - boolean(bool), - int8(s8), - int16(s16), - int32(s32), - int64(s64), - uint8(u8), - uint16(u16), - uint32(u32), - uint64(u64), - floating32(float32), - floating64(float64), - str(string), - binary(list), - db-null, - unsupported, -} - -variant parameter-value { - boolean(bool), - int8(s8), - int16(s16), - int32(s32), - int64(s64), - uint8(u8), - uint16(u16), - uint32(u32), - uint64(u64), - floating32(float32), - floating64(float64), - str(string), - binary(list), - db-null, -} - -record column { - name: string, - data-type: db-data-type, -} - -type row = list - -record row-set { - columns: list, - rows: list, -} diff --git a/wit/redis-types.wit b/wit/redis-types.wit deleted file mode 100644 index 2f45ddff..00000000 --- a/wit/redis-types.wit +++ /dev/null @@ -1,22 +0,0 @@ -// General purpose error. -enum error { - success, - error, -} - -// The message payload. -type payload = list - -// A parameter type for the general-purpose `execute` function. -variant redis-parameter { - int64(s64), - binary(payload) -} - -// A return type for the general-purpose `execute` function. -variant redis-result { - nil, - status(string), - int64(s64), - binary(payload) -} diff --git a/wit/spin-config.wit b/wit/spin-config.wit deleted file mode 100644 index d4788522..00000000 --- a/wit/spin-config.wit +++ /dev/null @@ -1,10 +0,0 @@ -// Get a configuration value for the current component. -// The config key must match one defined in in the component manifest. -get-config: func(key: string) -> expected - -variant error { - provider(string), - invalid-key(string), - invalid-schema(string), - other(string), -} \ No newline at end of file diff --git a/wit/spin-http.wit b/wit/spin-http.wit deleted file mode 100644 index 27da7427..00000000 --- a/wit/spin-http.wit +++ /dev/null @@ -1,4 +0,0 @@ -use * from http-types - -// The entrypoint for an HTTP handler. -handle-http-request: func(req: request) -> response diff --git a/wit/spin-redis.wit b/wit/spin-redis.wit deleted file mode 100644 index c51c3b47..00000000 --- a/wit/spin-redis.wit +++ /dev/null @@ -1,4 +0,0 @@ -use * from redis-types - -// The entrypoint for a Redis handler. -handle-redis-message: func(message: payload) -> expected diff --git a/wit/sqlite.wit b/wit/sqlite.wit deleted file mode 100644 index 8bf9384b..00000000 --- a/wit/sqlite.wit +++ /dev/null @@ -1,50 +0,0 @@ -// A handle to an open sqlite instance -type connection = u32 - -// The set of errors which may be raised by functions in this interface -variant error { - // The host does not recognize the database name requested. - no-such-database, - // The requesting component does not have access to the specified database (which may or may not exist). - access-denied, - // The provided connection is not valid - invalid-connection, - // The database has reached its capacity - database-full, - // Some implementation-specific error has occurred (e.g. I/O) - io(string) -} - -// Open a connection to a named database instance. -// -// If `database` is "default", the default instance is opened. -// -// `error::no-such-database` will be raised if the `name` is not recognized. -open: func(name: string) -> expected - -// Execute a statement -execute: func(conn: connection, statement: string, parameters: list) -> expected - -// Close the specified `connection`. -close: func(conn: connection) - -// A result of a query -record query-result { - // The names of the columns retrieved in the query - columns: list, - // the row results each containing the values for all the columns for a given row - rows: list, -} - -// A set of values for each of the columns in a query-result -record row-result { - values: list -} - -variant value { - integer(s64), - real(float64), - text(string), - blob(list), - null -} diff --git a/wit/wasi-outbound-http.wit b/wit/wasi-outbound-http.wit deleted file mode 100644 index 0502129d..00000000 --- a/wit/wasi-outbound-http.wit +++ /dev/null @@ -1,4 +0,0 @@ -use * from http-types - -// Send an HTTP request and return a response or a potential error. -request: func(req: request) -> expected diff --git a/wit/world.wit b/wit/world.wit new file mode 100644 index 00000000..07da9cd4 --- /dev/null +++ b/wit/world.wit @@ -0,0 +1,15 @@ +package fermyon:spin@3.0.0; + +/// The full world of a guest targeting an http-trigger +world http-trigger { + include platform; + export wasi:http/incoming-handler@0.2.0; +} + +/// The imports needed for a guest to run on a Spin host +world platform { + include fermyon:spin/platform@2.0.0; + include wasi:keyvalue/imports@0.2.0-draft2; + import spin:postgres/postgres@3.0.0; + import wasi:config/store@0.2.0-draft-2024-09-27; +}