diff --git a/sdk/go/.gitignore b/sdk/go/.gitignore deleted file mode 100644 index a9477a218f..0000000000 --- a/sdk/go/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*/sdk-version-go.c diff --git a/sdk/go/Makefile b/sdk/go/Makefile deleted file mode 100644 index b53fa469c5..0000000000 --- a/sdk/go/Makefile +++ /dev/null @@ -1,129 +0,0 @@ -# ---------------------------------------------------------------------- -# Test -# ---------------------------------------------------------------------- -.PHONY: test -test: test-integration - tinygo test -target=wasi -gc=leaking -v ./http - tinygo test -target=wasi -gc=leaking -v ./redis - -.PHONY: test-integration -test-integration: http/testdata/http-tinygo/main.wasm - go test -v -count=1 . - -http/testdata/http-tinygo/main.wasm: generate -http/testdata/http-tinygo/main.wasm: http/testdata/http-tinygo/main.go - tinygo build -target=wasi -gc=leaking -no-debug -o http/testdata/http-tinygo/main.wasm http/testdata/http-tinygo/main.go - -# ---------------------------------------------------------------------- -# Build examples -# ---------------------------------------------------------------------- -EXAMPLES_DIR = examples - -.PHONY: build-examples -build-examples: generate -build-examples: $(EXAMPLES_DIR)/http-tinygo-outbound-http/outbound-http-to-same-app/main.wasm -build-examples: $(EXAMPLES_DIR)/http-tinygo-outbound-http/tinygo-hello/main.wasm -build-examples: $(EXAMPLES_DIR)/http-tinygo/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-outbound-redis/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-redis/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-key-value/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-sqlite/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-llm/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-outbound-mysql/main.wasm -build-examples: $(EXAMPLES_DIR)/tinygo-outbound-pg/main.wasm -build-examples: $(EXAMPLES_DIR)/variables-tinygo/main.wasm - -$(EXAMPLES_DIR)/%/main.wasm: $(EXAMPLES_DIR)/%/main.go - tinygo build -target=wasi -gc=leaking -no-debug -o $@ $< - -# ---------------------------------------------------------------------- -# 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 version="$$(cd ../rust && cargo run)"; \ - 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 http/testdata/http-tinygo/main.wasm - rm -f $(EXAMPLES_DIR)/http-tinygo/main.wasm - rm -f $(EXAMPLES_DIR)/http-tinygo-outbound-http/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-outbound-redis/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-redis/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-key-value/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-sqlite/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-llm/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-outbound-mysql/main.wasm - rm -f $(EXAMPLES_DIR)/tinygo-outbound-pg/main.wasm - rm -f $(SDK_VERSION_DEST_FILES) diff --git a/sdk/go/examples/http-tinygo-outbound-http/README.md b/sdk/go/examples/http-tinygo-outbound-http/README.md deleted file mode 100644 index 14880b3d83..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# Making outbound HTTP requests from TinyGo 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). - -Creating and sending HTTP requests from Spin components closely follows the Go -`net/http` API. See [tinygo-hello/main.go](./tinygo-hello/main.go). - -Building this as a WebAssembly module can be done using the `tinygo` compiler: - -```shell -$ spin build -Building component outbound-http-to-same-app with `tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go` -Working directory: "./outbound-http-to-same-app" -Building component tinygo-hello with `tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go` -Working directory: "./tinygo-hello" -Finished building all Spin components -``` - -The component configuration must contain a list of all hosts allowed to send -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: - -```toml -[component.tinygo-hello] -source = "tinygo-hello/main.wasm" -allowed_outbound_hosts = [ - "https://random-data-api.fermyon.app", - "https://postman-echo.com", -] -``` - -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`): - -```toml -[component.outbound-http-to-same-app] -source = "outbound-http-to-same-app/main.wasm" -# Use self to make outbound requests to components in the same Spin application. -allowed_outbound_hosts = ["http://self"] -``` - -At this point, we can execute the application with the `spin` CLI: - -```shell -$ RUST_LOG=spin=trace,wasi_outbound_http=trace spin up -``` - -The application can now receive requests on `http://localhost:3000/hello`: - -```shell -$ curl -i localhost:3000/hello -X POST -d "hello there" -HTTP/1.1 200 OK -content-length: 976 -date: Thu, 26 Oct 2023 18:26:17 GMT - -{{"timestamp":1698344776965,"fact":"Reindeer grow new antlers every year"}} -... -``` - -As well as via the `/outbound-http-to-same-app` path to verify outbound http to the `tinygo-hello` component: - -```shell -$ curl -i localhost:3000/outbound-http-to-same-app -HTTP/1.1 200 OK -content-length: 946 -date: Thu, 26 Oct 2023 18:26:53 GMT - -{{{"timestamp":1698344813408,"fact":"Some hummingbirds weigh less than a penny"}} -... -``` - -## Notes - -- this only implements sending HTTP/1.1 requests -- requests are currently blocking and synchronous diff --git a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.mod b/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.mod deleted file mode 100644 index 11caff87f3..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module outbound-http-to-same-app - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../../ diff --git a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.sum b/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/main.go b/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/main.go deleted file mode 100644 index daf21d3620..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/outbound-http-to-same-app/main.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - // Because we included self in `allowed_http_hosts`, we can make outbound - // HTTP requests to our own app using a relative path. - resp, err := spinhttp.Get("/hello") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - fmt.Fprintln(w, resp.Body) - fmt.Fprintln(w, resp.Header.Get("content-type")) - }) -} - -func main() {} diff --git a/sdk/go/examples/http-tinygo-outbound-http/spin.toml b/sdk/go/examples/http-tinygo-outbound-http/spin.toml deleted file mode 100644 index 0210640eed..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/spin.toml +++ /dev/null @@ -1,33 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go that performs outbound HTTP requests." -name = "spin-tinygo-outbound-http" -version = "1.0.0" - -[[trigger.http]] -route = "/hello" -component = "tinygo-hello" - -[[trigger.http]] -route = "/outbound-http-to-same-app" -component = "outbound-http-to-same-app" - -[component.tinygo-hello] -source = "tinygo-hello/main.wasm" -allowed_outbound_hosts = [ - "https://random-data-api.fermyon.app:443", - "https://postman-echo.com:443", -] -[component.tinygo-hello.build] -workdir = "tinygo-hello" -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" - -[component.outbound-http-to-same-app] -source = "outbound-http-to-same-app/main.wasm" -# Use self to make outbound requests to components in the same Spin application. -allowed_outbound_hosts = ["http://self"] -[component.outbound-http-to-same-app.build] -workdir = "outbound-http-to-same-app" -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.mod b/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.mod deleted file mode 100644 index a298543b82..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo-outbound-http - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../../ diff --git a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.sum b/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/main.go b/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/main.go deleted file mode 100644 index 7cf8726c27..0000000000 --- a/sdk/go/examples/http-tinygo-outbound-http/tinygo-hello/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - "net/http" - "os" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - r1, err := spinhttp.Get("https://random-data-api.fermyon.app/animals/json") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - fmt.Fprintln(w, r1.Body) - fmt.Fprintln(w, r1.Header.Get("content-type")) - - r2, err := spinhttp.Post("https://postman-echo.com/post", "text/plain", r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - fmt.Fprintln(w, r2.Body) - - req, err := http.NewRequest("PUT", "https://postman-echo.com/put", bytes.NewBufferString("General Kenobi!")) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - req.Header.Add("foo", "bar") - r3, err := spinhttp.Send(req) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - fmt.Fprintln(w, r3.Body) - - // `spin.toml` is not configured to allow outbound HTTP requests to this host, - // so this request will fail. - if _, err := spinhttp.Get("https://fermyon.com"); err != nil { - fmt.Fprintf(os.Stderr, "Cannot send HTTP request: %v", err) - } - }) -} - -func main() {} diff --git a/sdk/go/examples/http-tinygo-router/README.md b/sdk/go/examples/http-tinygo-router/README.md deleted file mode 100644 index 1a138fe902..0000000000 --- a/sdk/go/examples/http-tinygo-router/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Spin component in TinyGo using the Spin router - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up -``` - -The application can now receive requests on `http://localhost:3000`: - -```shell -$ curl -i localhost:3000/hello/Fermyon -HTTP/1.1 200 OK -content-length: 16 -date: Thu, 26 Oct 2023 18:30:05 GMT - -hello, Fermyon! - -$ curl -i localhost:3000/this/will/be-special -HTTP/1.1 200 OK -content-length: 24 -date: Thu, 26 Oct 2023 18:30:21 GMT - -catch all: /be-special! -``` diff --git a/sdk/go/examples/http-tinygo-router/go.mod b/sdk/go/examples/http-tinygo-router/go.mod deleted file mode 100644 index 522a347082..0000000000 --- a/sdk/go/examples/http-tinygo-router/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/http-tinygo-router/go.sum b/sdk/go/examples/http-tinygo-router/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/http-tinygo-router/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/http-tinygo-router/main.go b/sdk/go/examples/http-tinygo-router/main.go deleted file mode 100644 index 140cf5aec5..0000000000 --- a/sdk/go/examples/http-tinygo-router/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - router := spinhttp.NewRouter() - router.GET("/hello/:name", Hello) - router.GET("/this/will/*catchAll", CatchAll) - - router.ServeHTTP(w, r) - }) -} - -func Hello(w http.ResponseWriter, _ *http.Request, ps spinhttp.Params) { - fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) -} - -func CatchAll(w http.ResponseWriter, _ *http.Request, ps spinhttp.Params) { - fmt.Fprintf(w, "catch all: %s!\n", ps.ByName("catchAll")) -} - -func main() {} diff --git a/sdk/go/examples/http-tinygo-router/spin.toml b/sdk/go/examples/http-tinygo-router/spin.toml deleted file mode 100644 index 8e63f8c864..0000000000 --- a/sdk/go/examples/http-tinygo-router/spin.toml +++ /dev/null @@ -1,16 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." -name = "spin-hello-tinygo" -version = "1.0.0" - -[[trigger.http]] -route = "/..." -component = "tinygo-hello" - -[component.tinygo-hello] -source = "main.wasm" -[component.tinygo-hello.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/http-tinygo/README.md b/sdk/go/examples/http-tinygo/README.md deleted file mode 100644 index 741cddc6f7..0000000000 --- a/sdk/go/examples/http-tinygo/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Spin component in TinyGo - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up -``` - -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! -``` diff --git a/sdk/go/examples/http-tinygo/go.mod b/sdk/go/examples/http-tinygo/go.mod deleted file mode 100644 index 522a347082..0000000000 --- a/sdk/go/examples/http-tinygo/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/http-tinygo/go.sum b/sdk/go/examples/http-tinygo/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/http-tinygo/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/http-tinygo/main.go b/sdk/go/examples/http-tinygo/main.go deleted file mode 100644 index 128d63493f..0000000000 --- a/sdk/go/examples/http-tinygo/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" - "io" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/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, "== 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!") - }) -} - -func main() {} diff --git a/sdk/go/examples/http-tinygo/spin.toml b/sdk/go/examples/http-tinygo/spin.toml deleted file mode 100644 index e7442ba3bf..0000000000 --- a/sdk/go/examples/http-tinygo/spin.toml +++ /dev/null @@ -1,16 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." -name = "spin-hello-tinygo" -version = "1.0.0" - -[[trigger.http]] -route = "/hello" -component = "tinygo-hello" - -[component.tinygo-hello] -source = "main.wasm" -[component.tinygo-hello.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/tinygo-key-value/README.md b/sdk/go/examples/tinygo-key-value/README.md deleted file mode 100644 index 1148760299..0000000000 --- a/sdk/go/examples/tinygo-key-value/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Spin Key Value component in TinyGo - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up -``` - -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 - -no such key -``` diff --git a/sdk/go/examples/tinygo-key-value/go.mod b/sdk/go/examples/tinygo-key-value/go.mod deleted file mode 100644 index 757a43ebd0..0000000000 --- a/sdk/go/examples/tinygo-key-value/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo-key-value - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-key-value/go.sum b/sdk/go/examples/tinygo-key-value/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/tinygo-key-value/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-key-value/main.go b/sdk/go/examples/tinygo-key-value/main.go deleted file mode 100644 index 1826d4b559..0000000000 --- a/sdk/go/examples/tinygo-key-value/main.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "io" - "net/http" - - spin_http "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/kv" -) - -func init() { - // handler for the http trigger - spin_http.Handle(func(w http.ResponseWriter, r *http.Request) { - store, err := kv.OpenStore("default") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - defer store.Close() - - body, err := io.ReadAll(r.Body) - 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 - } - - 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 - } - - 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 - } - - if exists { - w.WriteHeader(http.StatusOK) - return - } - - w.WriteHeader(http.StatusNotFound) - default: - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - } - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-key-value/spin.toml b/sdk/go/examples/tinygo-key-value/spin.toml deleted file mode 100644 index 2df57f8871..0000000000 --- a/sdk/go/examples/tinygo-key-value/spin.toml +++ /dev/null @@ -1,16 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -name = "tinygo-key-value-example" -version = "0.1.0" - -[[trigger.http]] -route = "/..." -component = "key-value" - -[component.key-value] -source = "main.wasm" -key_value_stores = ["default"] -[component.key-value.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/tinygo-llm/.gitignore b/sdk/go/examples/tinygo-llm/.gitignore deleted file mode 100644 index b565010470..0000000000 --- a/sdk/go/examples/tinygo-llm/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -main.wasm -.spin/ diff --git a/sdk/go/examples/tinygo-llm/go.mod b/sdk/go/examples/tinygo-llm/go.mod deleted file mode 100644 index 77edbb649f..0000000000 --- a/sdk/go/examples/tinygo-llm/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/tinygo_llm - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-llm/go.sum b/sdk/go/examples/tinygo-llm/go.sum deleted file mode 100644 index fcb43438db..0000000000 --- a/sdk/go/examples/tinygo-llm/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/fermyon/spin/sdk/go v1.4.1 h1:n8KTYTnkErTJdyMBBEtPmJe8dXrvMT6R7iVWbLRjq5E= -github.com/fermyon/spin/sdk/go v1.4.1/go.mod h1:yb8lGesopgj/GwPzLPATxcOeqWZT/HjrzEFfwbztAXE= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-llm/main.go b/sdk/go/examples/tinygo-llm/main.go deleted file mode 100644 index f0014619f8..0000000000 --- a/sdk/go/examples/tinygo-llm/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/llm" -) - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - result, err := llm.Infer("llama2-chat", "Tell me a joke", nil) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - fmt.Printf("Prompt tokens: %d\n", result.Usage.PromptTokenCount) - fmt.Printf("Generated tokens: %d\n", result.Usage.GeneratedTokenCount) - fmt.Fprint(w, result.Text) - fmt.Fprintf(w, "\n\n") - - embeddings, err := llm.GenerateEmbeddings("all-minilm-l6-v2", []string{"Hello world"}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - fmt.Printf("%d\n", len(embeddings.Embeddings[0])) - fmt.Printf("Prompt Tokens: %d\n", embeddings.Usage.PromptTokenCount) - - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-llm/spin.toml b/sdk/go/examples/tinygo-llm/spin.toml deleted file mode 100644 index 73f5104fb7..0000000000 --- a/sdk/go/examples/tinygo-llm/spin.toml +++ /dev/null @@ -1,19 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -description = "Simple example using the llm sdk." -name = "tinygo-llm" -version = "0.1.0" - -[[trigger.http]] -route = "/..." -component = "tinygo-llm" - -[component.tinygo-llm] -source = "main.wasm" -allowed_outbound_hosts = [] -ai_models = ["llama2-chat", "all-minilm-l6-v2"] -[component.tinygo-llm.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" -watch = ["**/*.go", "go.mod"] diff --git a/sdk/go/examples/tinygo-outbound-mysql/.gitignore b/sdk/go/examples/tinygo-outbound-mysql/.gitignore deleted file mode 100644 index b565010470..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -main.wasm -.spin/ diff --git a/sdk/go/examples/tinygo-outbound-mysql/db/pets.sql b/sdk/go/examples/tinygo-outbound-mysql/db/pets.sql deleted file mode 100644 index bbf91d68ad..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/db/pets.sql +++ /dev/null @@ -1,4 +0,0 @@ -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); -INSERT INTO pets VALUES (3, 'Slats', 'Temptations', true); diff --git a/sdk/go/examples/tinygo-outbound-mysql/go.mod b/sdk/go/examples/tinygo-outbound-mysql/go.mod deleted file mode 100644 index 058d57cf72..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/tinygo_mysql - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-outbound-mysql/go.sum b/sdk/go/examples/tinygo-outbound-mysql/go.sum deleted file mode 100644 index fcb43438db..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/fermyon/spin/sdk/go v1.4.1 h1:n8KTYTnkErTJdyMBBEtPmJe8dXrvMT6R7iVWbLRjq5E= -github.com/fermyon/spin/sdk/go v1.4.1/go.mod h1:yb8lGesopgj/GwPzLPATxcOeqWZT/HjrzEFfwbztAXE= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-outbound-mysql/main.go b/sdk/go/examples/tinygo-outbound-mysql/main.go deleted file mode 100644 index 88937c0269..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "net/http" - "os" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/mysql" -) - -type Pet struct { - ID int64 - Name string - Prey *string // nullable field must be a pointer - IsFinicky bool -} - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - - // addr is the environment variable set in `spin.toml` that points to the - // address of the Mysql server. - addr := os.Getenv("DB_URL") - - db := mysql.Open(addr) - defer db.Close() - - _, err := db.Query("REPLACE INTO pets VALUES (?, 'Maya', ?, ?);", 4, "bananas", true) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - rows, err := db.Query("SELECT * FROM pets") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - var pets []*Pet - for rows.Next() { - var pet Pet - if err := rows.Scan(&pet.ID, &pet.Name, &pet.Prey, &pet.IsFinicky); err != nil { - fmt.Println(err) - } - pets = append(pets, &pet) - } - json.NewEncoder(w).Encode(pets) - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-outbound-mysql/spin.toml b/sdk/go/examples/tinygo-outbound-mysql/spin.toml deleted file mode 100644 index af450e75e5..0000000000 --- a/sdk/go/examples/tinygo-outbound-mysql/spin.toml +++ /dev/null @@ -1,19 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Patrick Jiang "] -description = "" -name = "tinygo-mysql" -version = "0.1.0" - -[[trigger.http]] -route = "/..." -component = "tinygo-mysql" - -[component.tinygo-mysql] -environment = { DB_URL = "mysql://spin:spin@127.0.0.1/spin_dev" } -source = "main.wasm" -allowed_outbound_hosts = ["mysql://127.0.0.1"] -[component.tinygo-mysql.build] -command = "tinygo build -target=wasi -gc=leaking -o main.wasm main.go" -watch = ["**/*.go", "go.mod"] diff --git a/sdk/go/examples/tinygo-outbound-pg/db/pets.sql b/sdk/go/examples/tinygo-outbound-pg/db/pets.sql deleted file mode 100644 index bbf91d68ad..0000000000 --- a/sdk/go/examples/tinygo-outbound-pg/db/pets.sql +++ /dev/null @@ -1,4 +0,0 @@ -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); -INSERT INTO pets VALUES (3, 'Slats', 'Temptations', true); diff --git a/sdk/go/examples/tinygo-outbound-pg/go.mod b/sdk/go/examples/tinygo-outbound-pg/go.mod deleted file mode 100644 index 58dd540dea..0000000000 --- a/sdk/go/examples/tinygo-outbound-pg/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/tinygo_outbound_pg - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-outbound-pg/go.sum b/sdk/go/examples/tinygo-outbound-pg/go.sum deleted file mode 100644 index fcb43438db..0000000000 --- a/sdk/go/examples/tinygo-outbound-pg/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/fermyon/spin/sdk/go v1.4.1 h1:n8KTYTnkErTJdyMBBEtPmJe8dXrvMT6R7iVWbLRjq5E= -github.com/fermyon/spin/sdk/go v1.4.1/go.mod h1:yb8lGesopgj/GwPzLPATxcOeqWZT/HjrzEFfwbztAXE= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-outbound-pg/main.go b/sdk/go/examples/tinygo-outbound-pg/main.go deleted file mode 100644 index ee5a1f5122..0000000000 --- a/sdk/go/examples/tinygo-outbound-pg/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "net/http" - "os" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/pg" -) - -type Pet struct { - ID int64 - Name string - Prey *string // nullable field must be a pointer - IsFinicky bool -} - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - - // addr is the environment variable set in `spin.toml` that points to the - // address of the Mysql server. - addr := os.Getenv("DB_URL") - - db := pg.Open(addr) - defer db.Close() - - _, err := db.Query("INSERT INTO pets VALUES ($1, 'Maya', $2, $3);", int32(4), "bananas", true) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - rows, err := db.Query("SELECT * FROM pets") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - var pets []*Pet - for rows.Next() { - var pet Pet - if err := rows.Scan(&pet.ID, &pet.Name, &pet.Prey, &pet.IsFinicky); err != nil { - fmt.Println(err) - } - pets = append(pets, &pet) - } - json.NewEncoder(w).Encode(pets) - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-outbound-pg/spin.toml b/sdk/go/examples/tinygo-outbound-pg/spin.toml deleted file mode 100644 index 1ccebc3be4..0000000000 --- a/sdk/go/examples/tinygo-outbound-pg/spin.toml +++ /dev/null @@ -1,19 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Patrick Jiang "] -description = "" -name = "tinygo-outbound-pg-example" -version = "0.1.0" - -[[trigger.http]] -route = "/..." -component = "tinygo-outbound-pg-example" - -[component.tinygo-outbound-pg-example] -environment = { DB_URL = "host=localhost user=postgres dbname=spin_dev" } -source = "main.wasm" -allowed_outbound_hosts = ["postgres://localhost"] -[component.tinygo-outbound-pg-example.build] -command = "tinygo build -target=wasi -gc=leaking -o main.wasm main.go" -watch = ["**/*.go", "go.mod"] diff --git a/sdk/go/examples/tinygo-outbound-redis/README.md b/sdk/go/examples/tinygo-outbound-redis/README.md deleted file mode 100644 index fdcb43cfcd..0000000000 --- a/sdk/go/examples/tinygo-outbound-redis/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Spin component in TinyGo making an outbound http call to Redis - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up -``` - -The application can now receive requests on `http://localhost:3000/publish`: - -```shell -$ curl -i localhost:3000/publish -HTTP/1.1 200 OK -content-length: 67 -date: Tue, 29 Nov 2022 07:03:52 GMT - -mykey value was: myvalue -spin-go-incr value: 1 -deleted keys num: 2 -``` diff --git a/sdk/go/examples/tinygo-outbound-redis/go.mod b/sdk/go/examples/tinygo-outbound-redis/go.mod deleted file mode 100644 index a2e966c059..0000000000 --- a/sdk/go/examples/tinygo-outbound-redis/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo-outbound-http - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-outbound-redis/go.sum b/sdk/go/examples/tinygo-outbound-redis/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/tinygo-outbound-redis/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-outbound-redis/main.go b/sdk/go/examples/tinygo-outbound-redis/main.go deleted file mode 100644 index df1bf006d9..0000000000 --- a/sdk/go/examples/tinygo-outbound-redis/main.go +++ /dev/null @@ -1,149 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "os" - "reflect" - "sort" - "strconv" - - spin_http "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/redis" -) - -func init() { - - // handler for the http trigger - spin_http.Handle(func(w http.ResponseWriter, _ *http.Request) { - - // addr is the environment variable set in `spin.toml` that points to the - // address of the Redis server. - addr := os.Getenv("REDIS_ADDRESS") - - // channel is the environment variable set in `spin.toml` that specifies - // the Redis channel that the component will publish to. - channel := os.Getenv("REDIS_CHANNEL") - - // payload is the data publish to the redis channel. - payload := []byte(`Hello redis from tinygo!`) - - rdb := redis.NewClient(addr) - - if err := rdb.Publish(channel, payload); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // set redis `mykey` = `myvalue` - if err := rdb.Set("mykey", []byte("myvalue")); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // get redis payload for `mykey` - if payload, err := rdb.Get("mykey"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } else { - w.Write([]byte("mykey value was: ")) - w.Write(payload) - w.Write([]byte("\n")) - } - - // incr `spin-go-incr` by 1 - if payload, err := rdb.Incr("spin-go-incr"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } else { - w.Write([]byte("spin-go-incr value: ")) - w.Write([]byte(strconv.FormatInt(payload, 10))) - w.Write([]byte("\n")) - } - - // delete `spin-go-incr` and `mykey` - if payload, err := rdb.Del("spin-go-incr", "mykey", "non-existing-key"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } else { - w.Write([]byte("deleted keys num: ")) - w.Write([]byte(strconv.FormatInt(payload, 10))) - w.Write([]byte("\n")) - } - - if _, err := rdb.Sadd("myset", "foo", "bar"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - { - expected := []string{"bar", "foo"} - payload, err := rdb.Smembers("myset") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - sort.Strings(payload) - if !reflect.DeepEqual(payload, expected) { - http.Error( - w, - fmt.Sprintf( - "unexpected SMEMBERS result: expected %v, got %v", - expected, - payload, - ), - http.StatusInternalServerError, - ) - return - } - } - - if _, err := rdb.Srem("myset", "bar"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - { - expected := []string{"foo"} - if payload, err := rdb.Smembers("myset"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } else if !reflect.DeepEqual(payload, expected) { - http.Error( - w, - fmt.Sprintf( - "unexpected SMEMBERS result: expected %v, got %v", - expected, - payload, - ), - http.StatusInternalServerError, - ) - return - } - } - - if _, err := rdb.Execute("set", "message", "hello"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if _, err := rdb.Execute("append", "message", " world"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if payload, err := rdb.Execute("get", "message"); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } else if !reflect.DeepEqual( - payload, - []*redis.Result{{ - Kind: redis.ResultKindBinary, - Val: []byte("hello world"), - }}) { - http.Error(w, "unexpected GET result", http.StatusInternalServerError) - return - } - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-outbound-redis/spin.toml b/sdk/go/examples/tinygo-outbound-redis/spin.toml deleted file mode 100644 index e7703935b6..0000000000 --- a/sdk/go/examples/tinygo-outbound-redis/spin.toml +++ /dev/null @@ -1,17 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -name = "tinygo-outbound-redis-example" -version = "0.1.0" - -[[trigger.http]] -route = "/publish" -component = "outbound-redis" - -[component.outbound-redis] -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=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/tinygo-redis/README.md b/sdk/go/examples/tinygo-redis/README.md deleted file mode 100644 index 67a7174cf5..0000000000 --- a/sdk/go/examples/tinygo-redis/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Spin component in TinyGo using the Redis trigger - -```shell -$ RUST_LOG=spin=trace spin build --up -``` - -```shell -$ redis-cli -127.0.0.1:6379> PUBLISH messages test-message -(integer) 1 -``` diff --git a/sdk/go/examples/tinygo-redis/go.mod b/sdk/go/examples/tinygo-redis/go.mod deleted file mode 100644 index 6520090d9e..0000000000 --- a/sdk/go/examples/tinygo-redis/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/examples/tinygo-redis - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-redis/go.sum b/sdk/go/examples/tinygo-redis/go.sum deleted file mode 100644 index 05ac2a3da6..0000000000 --- a/sdk/go/examples/tinygo-redis/go.sum +++ /dev/null @@ -1 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-redis/main.go b/sdk/go/examples/tinygo-redis/main.go deleted file mode 100644 index 96f897a54d..0000000000 --- a/sdk/go/examples/tinygo-redis/main.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/fermyon/spin/sdk/go/v2/redis" -) - -func init() { - // redis.Handle() must be called in the init() function. - redis.Handle(func(payload []byte) error { - fmt.Println("Payload::::") - fmt.Println(string(payload)) - return nil - }) -} - -// main function must be included for the compiler but is not executed. -func main() {} diff --git a/sdk/go/examples/tinygo-redis/spin.toml b/sdk/go/examples/tinygo-redis/spin.toml deleted file mode 100644 index 52cd365572..0000000000 --- a/sdk/go/examples/tinygo-redis/spin.toml +++ /dev/null @@ -1,19 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Fermyon Engineering "] -description = "A redis application." -name = "spin-redis" -version = "0.1.0" - -[application.trigger.redis] -address = "redis://localhost:6379" - -[[trigger.redis]] -channel = "messages" -component = "echo-message" - -[component.echo-message] -source = "main.wasm" -[component.echo-message.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/examples/tinygo-sqlite/.gitignore b/sdk/go/examples/tinygo-sqlite/.gitignore deleted file mode 100644 index b565010470..0000000000 --- a/sdk/go/examples/tinygo-sqlite/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -main.wasm -.spin/ diff --git a/sdk/go/examples/tinygo-sqlite/db/pets.sql b/sdk/go/examples/tinygo-sqlite/db/pets.sql deleted file mode 100644 index bbf91d68ad..0000000000 --- a/sdk/go/examples/tinygo-sqlite/db/pets.sql +++ /dev/null @@ -1,4 +0,0 @@ -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); -INSERT INTO pets VALUES (3, 'Slats', 'Temptations', true); diff --git a/sdk/go/examples/tinygo-sqlite/go.mod b/sdk/go/examples/tinygo-sqlite/go.mod deleted file mode 100644 index a39bdc92bd..0000000000 --- a/sdk/go/examples/tinygo-sqlite/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/tinygo_sqlite - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/tinygo-sqlite/go.sum b/sdk/go/examples/tinygo-sqlite/go.sum deleted file mode 100644 index fcb43438db..0000000000 --- a/sdk/go/examples/tinygo-sqlite/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/fermyon/spin/sdk/go v1.4.1 h1:n8KTYTnkErTJdyMBBEtPmJe8dXrvMT6R7iVWbLRjq5E= -github.com/fermyon/spin/sdk/go v1.4.1/go.mod h1:yb8lGesopgj/GwPzLPATxcOeqWZT/HjrzEFfwbztAXE= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/tinygo-sqlite/main.go b/sdk/go/examples/tinygo-sqlite/main.go deleted file mode 100644 index 043f492a8c..0000000000 --- a/sdk/go/examples/tinygo-sqlite/main.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/sqlite" -) - -type Pet struct { - ID int64 - Name string - Prey *string // nullable field must be a pointer - IsFinicky bool -} - -func init() { - spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { - db := sqlite.Open("default") - defer db.Close() - - _, err := db.Query("REPLACE INTO pets VALUES (4, 'Maya', ?, false);", "bananas") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - rows, err := db.Query("SELECT * FROM pets") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - var pets []*Pet - for rows.Next() { - var pet Pet - if err := rows.Scan(&pet.ID, &pet.Name, &pet.Prey, &pet.IsFinicky); err != nil { - fmt.Println(err) - } - pets = append(pets, &pet) - } - json.NewEncoder(w).Encode(pets) - }) -} - -func main() {} diff --git a/sdk/go/examples/tinygo-sqlite/spin.toml b/sdk/go/examples/tinygo-sqlite/spin.toml deleted file mode 100644 index c366f4c8c5..0000000000 --- a/sdk/go/examples/tinygo-sqlite/spin.toml +++ /dev/null @@ -1,19 +0,0 @@ -spin_manifest_version = 2 - -[application] -authors = ["Adam Reese "] -description = "" -name = "tinygo-sqlite" -version = "0.1.0" - -[[trigger.http]] -route = "/..." -component = "tinygo-sqlite" - -[component.tinygo-sqlite] -source = "main.wasm" -allowed_outbound_hosts = [] -sqlite_databases = ["default"] -[component.tinygo-sqlite.build] -command = "tinygo build -target=wasi -gc=leaking -o main.wasm main.go" -watch = ["**/*.go", "go.mod"] diff --git a/sdk/go/examples/variables-tinygo/README.md b/sdk/go/examples/variables-tinygo/README.md deleted file mode 100644 index e56da555fa..0000000000 --- a/sdk/go/examples/variables-tinygo/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Spin component in TinyGo using variables - -```shell -$ go mod tidy -$ RUST_LOG=spin=trace spin build --up -``` - -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 - -message: I'm a teapot -``` diff --git a/sdk/go/examples/variables-tinygo/go.mod b/sdk/go/examples/variables-tinygo/go.mod deleted file mode 100644 index 522a347082..0000000000 --- a/sdk/go/examples/variables-tinygo/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/fermyon/spin/templates/spin-http-tinygo - -go 1.20 - -require github.com/fermyon/spin/v2 v2.0.0 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect - -replace github.com/fermyon/spin/v2 v2.0.0 => ../../ diff --git a/sdk/go/examples/variables-tinygo/go.sum b/sdk/go/examples/variables-tinygo/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/examples/variables-tinygo/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/examples/variables-tinygo/main.go b/sdk/go/examples/variables-tinygo/main.go deleted file mode 100644 index d3ab6b5102..0000000000 --- a/sdk/go/examples/variables-tinygo/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/v2/http" - "github.com/fermyon/spin/sdk/go/v2/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/sdk/go/examples/variables-tinygo/spin.toml b/sdk/go/examples/variables-tinygo/spin.toml deleted file mode 100644 index c3f2ef4520..0000000000 --- a/sdk/go/examples/variables-tinygo/spin.toml +++ /dev/null @@ -1,21 +0,0 @@ -spin_manifest_version = 2 - -[application] -name = "spin-variables-tinygo" -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." -version = "1.0.0" - -[variables] -object = { default = "teapot" } - -[[trigger.http]] -route = "/..." -component = "spin-variables-tinygo" - -[component.spin-variables-tinygo] -source = "main.wasm" -[component.spin-variables-tinygo.variables] -message = "I'm a {{object}}" -[component.spin-variables-tinygo.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/go.mod b/sdk/go/go.mod deleted file mode 100644 index 3cbbf1432f..0000000000 --- a/sdk/go/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/fermyon/spin/sdk/go/v2 - -go 1.20 - -require github.com/julienschmidt/httprouter v1.3.0 diff --git a/sdk/go/go.sum b/sdk/go/go.sum deleted file mode 100644 index 096c54e630..0000000000 --- a/sdk/go/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/sdk/go/http/http.go b/sdk/go/http/http.go deleted file mode 100644 index ba4a22c2b1..0000000000 --- a/sdk/go/http/http.go +++ /dev/null @@ -1,116 +0,0 @@ -// Package http contains the helper functions for writing Spin HTTP components -// in TinyGo, as well as for sending outbound HTTP requests. -package http - -import ( - "fmt" - "io" - "net/http" - "os" - - "github.com/julienschmidt/httprouter" -) - -const ( - // The application base path. - HeaderBasePath = "spin-base-path" - // The component route pattern matched, _excluding_ any wildcard indicator. - HeaderComponentRoot = "spin-component-route" - // The full URL of the request. This includes full host and scheme information. - HeaderFullUrl = "spin-full-url" - // The part of the request path that was matched by the route (including - // the base and wildcard indicator if present). - HeaderMatchedRoute = "spin-matched-route" - // The request path relative to the component route (including any base). - HeaderPathInfo = "spin-path-info" - // The component route pattern matched, as written in the component - // manifest (that is, _excluding_ the base, but including the wildcard - // indicator if present). - HeaderRawComponentRoot = "spin-raw-component-route" - // The client address for the request. - 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 - -// Params is a Param-slice, as returned by the router. -// The slice is ordered, the first URL parameter is also the first slice value. -// It is therefore safe to read values by the index. -type Params = httprouter.Params - -// Param is a single URL parameter, consisting of a key and a value. -type Param = httprouter.Param - -// RouterHandle is a function that can be registered to a route to handle HTTP -// requests. Like http.HandlerFunc, but has a third parameter for the values of -// wildcards (variables). -type RouterHandle = httprouter.Handle - -// New returns a new initialized Router. -// Path auto-correction, including trailing slashes, is enabled by default. -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 - -// defaultHandler is a placeholder for returning a useful error to stderr when -// the handler is not set. -var defaultHandler = func(http.ResponseWriter, *http.Request) { - fmt.Fprintln(os.Stderr, "http handler undefined") -} - -// Handle sets the handler function for the http trigger. -// It must be set in an init() function. -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) -} - -// 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) -} - -// 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) -} diff --git a/sdk/go/http/internals.go b/sdk/go/http/internals.go deleted file mode 100644 index 8256a2a48e..0000000000 --- a/sdk/go/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/sdk/go/http/outbound_internals.go b/sdk/go/http/outbound_internals.go deleted file mode 100644 index c371f673ee..0000000000 --- a/sdk/go/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/sdk/go/http/response.go b/sdk/go/http/response.go deleted file mode 100644 index a1b2559c9b..0000000000 --- a/sdk/go/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/sdk/go/http/spin-http.c b/sdk/go/http/spin-http.c deleted file mode 100644 index 780a4adf36..0000000000 --- a/sdk/go/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/sdk/go/http/spin-http.h b/sdk/go/http/spin-http.h deleted file mode 100644 index cd47c95c5e..0000000000 --- a/sdk/go/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/sdk/go/http/testdata/http-tinygo/Makefile b/sdk/go/http/testdata/http-tinygo/Makefile deleted file mode 100644 index 3e71525144..0000000000 --- a/sdk/go/http/testdata/http-tinygo/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -.PHONY: build -build: - tinygo build -target=wasi -gc=leaking -o main.wasm main.go diff --git a/sdk/go/http/testdata/http-tinygo/main.go b/sdk/go/http/testdata/http-tinygo/main.go deleted file mode 100644 index 33777209c6..0000000000 --- a/sdk/go/http/testdata/http-tinygo/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/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/sdk/go/http/testdata/http-tinygo/spin.toml b/sdk/go/http/testdata/http-tinygo/spin.toml deleted file mode 100644 index 10f42ca6e5..0000000000 --- a/sdk/go/http/testdata/http-tinygo/spin.toml +++ /dev/null @@ -1,14 +0,0 @@ -spin_version = "1" -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." -name = "spin-http-tinygo-test" -trigger = { type = "http" } -version = "1.0.0" - -[[component]] -id = "http-tinygo-test" -source = "main.wasm" -[component.trigger] -route = "/hello/..." -[component.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/http/testdata/spin-roundtrip/Makefile b/sdk/go/http/testdata/spin-roundtrip/Makefile deleted file mode 100644 index 3e71525144..0000000000 --- a/sdk/go/http/testdata/spin-roundtrip/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -.PHONY: build -build: - tinygo build -target=wasi -gc=leaking -o main.wasm main.go diff --git a/sdk/go/http/testdata/spin-roundtrip/main.go b/sdk/go/http/testdata/spin-roundtrip/main.go deleted file mode 100644 index f8ee4e8500..0000000000 --- a/sdk/go/http/testdata/spin-roundtrip/main.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - spinhttp "github.com/fermyon/spin/sdk/go/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/sdk/go/http/testdata/spin-roundtrip/spin.toml b/sdk/go/http/testdata/spin-roundtrip/spin.toml deleted file mode 100644 index 4613d21ace..0000000000 --- a/sdk/go/http/testdata/spin-roundtrip/spin.toml +++ /dev/null @@ -1,15 +0,0 @@ -spin_version = "1" -authors = ["Fermyon Engineering "] -description = "A simple Spin application written in (Tiny)Go." -name = "spin-roundtrip-test" -trigger = { type = "http" } -version = "1.0.0" - -[[component]] -id = "http-roundtrip-test" -source = "main.wasm" -allowed_outbound_hosts = ["https://example.com"] -[component.trigger] -route = "/hello/..." -[component.build] -command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go" diff --git a/sdk/go/http/wasi-outbound-http.c b/sdk/go/http/wasi-outbound-http.c deleted file mode 100644 index f767585047..0000000000 --- a/sdk/go/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/sdk/go/http/wasi-outbound-http.h b/sdk/go/http/wasi-outbound-http.h deleted file mode 100644 index ccaac543da..0000000000 --- a/sdk/go/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/sdk/go/integration_test.go b/sdk/go/integration_test.go deleted file mode 100644 index ce17864f46..0000000000 --- a/sdk/go/integration_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package http - -import ( - "bytes" - "context" - "fmt" - "io" - "net" - "net/http" - "os/exec" - "testing" - "time" -) - -const spinBinary = "../../target/debug/spin" - -func retryGet(t *testing.T, url string) *http.Response { - t.Helper() - - const maxTries = 600 // (10min) - for i := 1; i < maxTries; i++ { - // Catch call to `Fail` in other goroutine - if t.Failed() { - t.FailNow() - } - if res, err := http.Get(url); err != nil { - t.Log(err) - } else { - return res - } - time.Sleep(1 * time.Second) - } - t.Fatal("Get request timeout: ", url) - return nil -} - -type testSpin struct { - cancel func() - url string - cmd *exec.Cmd -} - -func startSpin(t *testing.T, spinfile string) *testSpin { - // long timeout because... ci - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - - url := getFreePort(t) - - cmd := exec.CommandContext(ctx, spinBinary, "up", "--build", "--file", spinfile, "--listen", url) - stderr := new(bytes.Buffer) - cmd.Stderr = stderr - if err := cmd.Start(); err != nil { - t.Log(stderr.String()) - t.Fatal(err) - } - - go func() { - cmd.Wait() - if ctx.Err() == nil { - t.Log("spin exited before the test finished:", cmd.ProcessState) - t.Log("stderr:\n", stderr.String()) - t.Fail() - } - }() - - return &testSpin{ - cancel: cancel, - url: fmt.Sprintf("http://%s", url), - cmd: cmd, - } -} - -func build(t *testing.T, dir string) { - t.Helper() - - t.Log("building example: ", dir) - - cmd := exec.Command(spinBinary, "build") - cmd.Dir = dir - - stderr := new(bytes.Buffer) - cmd.Stderr = stderr - if err := cmd.Run(); err != nil { - t.Log(stderr.String()) - t.Errorf("Failed to build %q, %v", dir, err) - } -} - -func TestSpinRoundTrip(t *testing.T) { - spin := startSpin(t, "http/testdata/spin-roundtrip/spin.toml") - defer spin.cancel() - - resp := retryGet(t, spin.url+"/hello") - 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 := "Hello world!\n" - got := string(b) - if want != got { - t.Fatalf("body is not equal: want = %q got = %q", want, got) - } -} - -func TestHTTPTriger(t *testing.T) { - spin := startSpin(t, "http/testdata/http-tinygo/spin.toml") - defer spin.cancel() - - resp := retryGet(t, spin.url+"/hello") - 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 := "Hello world!\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") - } -} - -// TestBuildExamples ensures that the tinygo examples will build successfully. -func TestBuildExamples(t *testing.T) { - for _, example := range []string{ - "examples/http-tinygo", - "examples/http-tinygo-outbound-http", - "examples/tinygo-outbound-redis", - "examples/tinygo-redis", - "examples/tinygo-key-value", - "examples/variables-tinygo", - } { - build(t, example) - } -} - -func getFreePort(t *testing.T) string { - t.Helper() - - a, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal("failed to get free port: ", err) - } - - l, err := net.ListenTCP("tcp", a) - if err != nil { - t.Fatal("failed to get free port: ", err) - } - l.Close() - return l.Addr().String() -} diff --git a/sdk/go/internal/db/driver.go b/sdk/go/internal/db/driver.go deleted file mode 100644 index 2b3ab75719..0000000000 --- a/sdk/go/internal/db/driver.go +++ /dev/null @@ -1,17 +0,0 @@ -package db - -import ( - "database/sql/driver" -) - -// GlobalParameterConverter is a global valueConverter instance to convert parameters. -var GlobalParameterConverter = &valueConverter{} - -var _ driver.ValueConverter = (*valueConverter)(nil) - -// valueConverter is a no-op value converter. -type valueConverter struct{} - -func (c *valueConverter) ConvertValue(v any) (driver.Value, error) { - return driver.Value(v), nil -} diff --git a/sdk/go/kv/key-value.c b/sdk/go/kv/key-value.c deleted file mode 100644 index bcb03cc88e..0000000000 --- a/sdk/go/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/sdk/go/kv/key-value.h b/sdk/go/kv/key-value.h deleted file mode 100644 index 7b78b032c6..0000000000 --- a/sdk/go/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/sdk/go/kv/kv.go b/sdk/go/kv/kv.go deleted file mode 100644 index c521660031..0000000000 --- a/sdk/go/kv/kv.go +++ /dev/null @@ -1,148 +0,0 @@ -// Package kv provides access to key value stores within Spin -// components. -package kv - -// #include "key-value.h" -import "C" -import ( - "errors" - "fmt" - "unsafe" -) - -// 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 -} - -// Close terminates the connection to Store. -func (s *Store) Close() { - if s.active { - C.key_value_close(C.uint32_t(s.ptr)) - } - 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 -} - -// 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 -} - -// Set creates a new key/value 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))) - } - 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))) - } - 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))) - } - list := (*C.key_value_list_string_t)(unsafe.Pointer(&ret.val)) - return fromCStrList(list), 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))) - } - 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))} -} - -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))} -} - -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))) - } - - return result -} - -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))) - default: - return fmt.Errorf("unrecognized error: %v", err.tag) - } -} diff --git a/sdk/go/llm/internals.go b/sdk/go/llm/internals.go deleted file mode 100644 index 4c64427348..0000000000 --- a/sdk/go/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/sdk/go/llm/llm.c b/sdk/go/llm/llm.c deleted file mode 100644 index 474202980a..0000000000 --- a/sdk/go/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/sdk/go/llm/llm.go b/sdk/go/llm/llm.go deleted file mode 100644 index 292c906892..0000000000 --- a/sdk/go/llm/llm.go +++ /dev/null @@ -1,70 +0,0 @@ -// Package llm provides the interface to use Large Language Models in Spin. -package llm - -// InferenceParams is the optional request parameters. -type InferencingParams struct { - // MaxTokens is the maximum tokens that should be inferred. - // Default: 100 - // - // 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 -} - -// 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 -} - -// InferencingUsage represents 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 -} - -// 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) -} - -// EmbeddingsResult of generating embeddings. -type EmbeddingsResult struct { - // Embeddings are the embeddings generated by the request. - Embeddings [][]float32 - // Usage is usage related to an embeddings generation request. - Usage *EmbeddingsUsage -} - -// Embeddings is usage related to an embeddings generation request. -type EmbeddingsUsage struct { - // PromptTokenCount is number of tokens in the prompt. - PromptTokenCount int -} - -// GenerateEmbeddings generates the embeddings for the supplied list of text. -func GenerateEmbeddings(model string, text []string) (*EmbeddingsResult, error) { - return generateEmbeddings(model, text) -} diff --git a/sdk/go/llm/llm.h b/sdk/go/llm/llm.h deleted file mode 100644 index 57c5a49f7b..0000000000 --- a/sdk/go/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/sdk/go/mysql/internals.go b/sdk/go/mysql/internals.go deleted file mode 100644 index 9b03331079..0000000000 --- a/sdk/go/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/sdk/go/mysql/mysql.go b/sdk/go/mysql/mysql.go deleted file mode 100644 index 33a2c60e7b..0000000000 --- a/sdk/go/mysql/mysql.go +++ /dev/null @@ -1,173 +0,0 @@ -package mysql - -import ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "io" - "reflect" - - spindb "github.com/fermyon/spin/sdk/go/v2/internal/db" -) - -// Open returns a new connection to the database. -func Open(address string) *sql.DB { - return sql.OpenDB(&connector{address}) -} - -// 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 -} - -func (c *conn) Close() error { - return 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 -} - -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 -} - -// 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] - } - return query(s.c.address, s.query, params) -} - -// 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] - } - 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") -} - -type rows struct { - columns []string - columnType []uint8 - pos int - len int - rows [][]any - closed bool -} - -var _ driver.Rows = (*rows)(nil) -var _ driver.RowsColumnTypeScanType = (*rows)(nil) -var _ driver.RowsNextResultSet = (*rows)(nil) - -// Columns return column names. -func (r *rows) Columns() []string { - return r.columns -} - -// Close closes the rows iterator. -func (r *rows) Close() error { - r.rows = nil - r.pos = 0 - r.len = 0 - r.closed = true - return nil -} - -// Next moves the cursor to the next row. -func (r *rows) Next(dest []driver.Value) error { - if !r.HasNextResultSet() { - return io.EOF - } - for i := 0; i != len(r.columns); i++ { - dest[i] = driver.Value(r.rows[r.pos][i]) - } - r.pos++ - return nil -} - -// HasNextResultSet is called at the end of the current result set and -// reports whether there is another result set after the current one. -func (r *rows) HasNextResultSet() bool { - return r.pos < r.len -} - -// NextResultSet advances the driver to the next result set even -// if there are remaining rows in the current result set. -// -// NextResultSet should return io.EOF when there are no more result sets. -func (r *rows) NextResultSet() error { - if r.HasNextResultSet() { - r.pos++ - return nil - } - return io.EOF // Per interface spec. -} - -// ColumnTypeScanType return the value type that can be used to scan types into. -func (r *rows) ColumnTypeScanType(index int) reflect.Type { - return colTypeToReflectType(r.columnType[index]) -} diff --git a/sdk/go/mysql/outbound-mysql.c b/sdk/go/mysql/outbound-mysql.c deleted file mode 100644 index f83753f20f..0000000000 --- a/sdk/go/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/sdk/go/mysql/outbound-mysql.h b/sdk/go/mysql/outbound-mysql.h deleted file mode 100644 index 2615ff7131..0000000000 --- a/sdk/go/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/sdk/go/pg/internals.go b/sdk/go/pg/internals.go deleted file mode 100644 index 959626ea56..0000000000 --- a/sdk/go/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/sdk/go/pg/outbound-pg.c b/sdk/go/pg/outbound-pg.c deleted file mode 100644 index 151867af49..0000000000 --- a/sdk/go/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/sdk/go/pg/outbound-pg.h b/sdk/go/pg/outbound-pg.h deleted file mode 100644 index 4284e161e5..0000000000 --- a/sdk/go/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/sdk/go/pg/pg.go b/sdk/go/pg/pg.go deleted file mode 100644 index db7c859e5e..0000000000 --- a/sdk/go/pg/pg.go +++ /dev/null @@ -1,175 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "io" - "reflect" - - spindb "github.com/fermyon/spin/sdk/go/v2/internal/db" -) - -// Open returns a new connection to the database. -func Open(address string) *sql.DB { - return sql.OpenDB(&connector{address}) -} - -// 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 -} - -func (c *conn) Close() error { - return 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 -} - -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 -} - -// 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] - } - return query(s.c.address, s.query, params) -} - -// 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] - } - n, err := execute(s.c.address, s.query, params) - return &result{rowsAffected: int64(n)}, err -} - -// ColumnConverter returns GlobalParameterConverter to prevent using driver.DefaultParameterConverter. -func (s *stmt) ColumnConverter(_ int) driver.ValueConverter { - return spindb.GlobalParameterConverter -} - -type result struct { - rowsAffected int64 -} - -func (r result) LastInsertId() (int64, error) { - return -1, errors.New("LastInsertId is unsupported by this driver") -} - -func (r result) RowsAffected() (int64, error) { - return r.rowsAffected, nil -} - -type rows struct { - columns []string - columnType []uint8 - pos int - len int - rows [][]any - closed bool -} - -var _ driver.Rows = (*rows)(nil) -var _ driver.RowsColumnTypeScanType = (*rows)(nil) -var _ driver.RowsNextResultSet = (*rows)(nil) - -// Columns return column names. -func (r *rows) Columns() []string { - return r.columns -} - -// Close closes the rows iterator. -func (r *rows) Close() error { - r.rows = nil - r.pos = 0 - r.len = 0 - r.closed = true - return nil -} - -// Next moves the cursor to the next row. -func (r *rows) Next(dest []driver.Value) error { - if !r.HasNextResultSet() { - return io.EOF - } - for i := 0; i != len(r.columns); i++ { - dest[i] = driver.Value(r.rows[r.pos][i]) - } - r.pos++ - return nil -} - -// HasNextResultSet is called at the end of the current result set and -// reports whether there is another result set after the current one. -func (r *rows) HasNextResultSet() bool { - return r.pos < r.len -} - -// NextResultSet advances the driver to the next result set even -// if there are remaining rows in the current result set. -// -// NextResultSet should return io.EOF when there are no more result sets. -func (r *rows) NextResultSet() error { - if r.HasNextResultSet() { - r.pos++ - return nil - } - return io.EOF // Per interface spec. -} - -// ColumnTypeScanType return the value type that can be used to scan types into. -func (r *rows) ColumnTypeScanType(index int) reflect.Type { - return colTypeToReflectType(r.columnType[index]) -} diff --git a/sdk/go/readme.md b/sdk/go/readme.md deleted file mode 100644 index 908af0c506..0000000000 --- a/sdk/go/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/fermyon/spin/sdk/go/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/sdk/go/redis/internals.go b/sdk/go/redis/internals.go deleted file mode 100644 index 4b71ab6308..0000000000 --- a/sdk/go/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/sdk/go/redis/internals_test.go b/sdk/go/redis/internals_test.go deleted file mode 100644 index 191fa6eedb..0000000000 --- a/sdk/go/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/sdk/go/redis/outbound-redis.c b/sdk/go/redis/outbound-redis.c deleted file mode 100644 index 40feb7263e..0000000000 --- a/sdk/go/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/sdk/go/redis/outbound-redis.h b/sdk/go/redis/outbound-redis.h deleted file mode 100644 index 4281bd97ed..0000000000 --- a/sdk/go/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/sdk/go/redis/redis.go b/sdk/go/redis/redis.go deleted file mode 100644 index a5b03736eb..0000000000 --- a/sdk/go/redis/redis.go +++ /dev/null @@ -1,139 +0,0 @@ -// Package redis provides the handler function for the Redis trigger, as well -// as access to Redis within Spin components. -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 -} - -// Handle sets the handler function for redis. -// It must be set in an init() function. -func Handle(fn func(payload []byte) error) { - handler = fn -} - -// Client is a Redis client. -type Client struct { - addr string -} - -// NewClient returns a Redis client. -func NewClient(address string) *Client { - return &Client{addr: address} -} - -// 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") - } - return publish(c.addr, channel, payload) -} - -// Get the value of a key. An error is returned if the value stored at key is -// not a string. -func (c *Client) Get(key string) ([]byte, error) { - return get(c.addr, key) -} - -// Set key to value. If key alreads 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") - } - return set(c.addr, key, payload) -} - -// 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. -func (c *Client) Incr(key string) (int64, error) { - return incr(c.addr, key) -} - -// 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) -} - -// 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) -} - -// Smembers gets the elements of the set for the specified key. -func (c *Client) Smembers(key string) ([]string, error) { - return smembers(c.addr, key) -} - -// 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) -} - -// ResultKind represents a result type returned from executing a Redis command. -type ResultKind uint8 - -const ( - ResultKindNil ResultKind = iota - ResultKindStatus - ResultKindInt64 - ResultKindBinary -) - -// String implements fmt.Stringer. -func (r ResultKind) String() string { - switch r { - case ResultKindNil: - return "nil" - case ResultKindStatus: - return "status" - case ResultKindInt64: - return "int64" - case ResultKindBinary: - return "binary" - default: - return "unknown" - } -} - -// GoString implements fmt.GoStringer. -func (r ResultKind) GoString() string { return r.String() } - -// Result represents a value returned from a Redis command. -type Result struct { - Kind ResultKind - Val any -} - -// Execute runs the specified Redis command with the specified arguments, -// returning zero or more results. This is a general-purpose function which -// should work with any Redis command. -// -// Arguments must be string, []byte, int, int64, or int32. -func (c *Client) Execute(command string, arguments ...any) ([]*Result, error) { - var params []*argument - for _, a := range arguments { - p, err := createParameter(a) - if err != nil { - return nil, err - } - params = append(params, p) - } - return execute(c.addr, command, params) -} diff --git a/sdk/go/redis/spin-redis.c b/sdk/go/redis/spin-redis.c deleted file mode 100644 index 665d4ebdbf..0000000000 --- a/sdk/go/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/sdk/go/redis/spin-redis.h b/sdk/go/redis/spin-redis.h deleted file mode 100644 index 9f73ba4061..0000000000 --- a/sdk/go/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/go/sdk_version/sdk-version-go-template.c b/sdk/go/sdk_version/sdk-version-go-template.c deleted file mode 100644 index ebddb4b125..0000000000 --- a/sdk/go/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/sdk/go/sqlite/doc.go b/sdk/go/sqlite/doc.go deleted file mode 100644 index 739f29c7a0..0000000000 --- a/sdk/go/sqlite/doc.go +++ /dev/null @@ -1,27 +0,0 @@ -// Package sqlite provides an interface to sqlite database stores within Spin -// components. -// -// This package is implemented as a driver that conforms to the built-in -// database/sql interface. -// -// db := sqlite.Open("default") -// defer db.Close() -// -// s, err := db.Prepare("REPLACE INTO pets VALUES (4, 'Maya', ?, false);") -// // if err != nil { ... } -// -// _, err = s.Query("bananas") -// // if err != nil { ... } -// -// rows, err := db.Query("SELECT * FROM pets") -// // if err != nil { ... } -// -// var pets []*Pet -// for rows.Next() { -// var pet Pet -// if err := rows.Scan(&pet.ID, &pet.Name, &pet.Prey, &pet.IsFinicky); err != nil { -// ... -// } -// pets = append(pets, &pet) -// } -package sqlite diff --git a/sdk/go/sqlite/internals.go b/sdk/go/sqlite/internals.go deleted file mode 100644 index 441710f37b..0000000000 --- a/sdk/go/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/sdk/go/sqlite/internals_test.go b/sdk/go/sqlite/internals_test.go deleted file mode 100644 index 7e85bb0546..0000000000 --- a/sdk/go/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/sdk/go/sqlite/sqlite.c b/sdk/go/sqlite/sqlite.c deleted file mode 100644 index 62e08af8f6..0000000000 --- a/sdk/go/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/sdk/go/sqlite/sqlite.go b/sdk/go/sqlite/sqlite.go deleted file mode 100644 index b4778e53e9..0000000000 --- a/sdk/go/sqlite/sqlite.go +++ /dev/null @@ -1,186 +0,0 @@ -package sqlite - -import ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "io" - - spindb "github.com/fermyon/spin/sdk/go/v2/internal/db" -) - -// Open returns a new connection to the database. -func Open(name string) *sql.DB { - return sql.OpenDB(&connector{name: name}) -} - -// conn represents a database connection. -type conn struct { - _ptr uint32 -} - -// 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 -} - -// Begin isn't supported. -func (c *conn) Begin() (driver.Tx, error) { - return nil, errors.New("transactions are unsupported by this driver") -} - -// connector implements driver.Connector. -type connector struct { - conn *conn - name string -} - -// Connect returns a connection to the database. -func (d *connector) Connect(_ context.Context) (driver.Conn, error) { - if d.conn != nil { - return d.conn, nil - } - - return d.Open(d.name) -} - -// 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(name string) (driver.Conn, error) { - conn, err := open(name) - if err != nil { - return nil, err - } - - d.conn = conn - - return conn, err -} - -// Close closes the connection to the database. -func (d *connector) Close() error { - if d.conn != nil { - d.conn.Close() - } - - return nil -} - -type rows struct { - columns []string - pos int - len int - rows [][]any - closed bool -} - -var _ driver.Rows = (*rows)(nil) - -// Columns return column names. -func (r *rows) Columns() []string { - return r.columns -} - -// Close closes the rows iterator. -func (r *rows) Close() error { - r.rows = nil - r.pos = 0 - r.len = 0 - r.closed = true - return nil -} - -// Next moves the cursor to the next row. -func (r *rows) Next(dest []driver.Value) error { - if !r.HasNextResultSet() { - return io.EOF - } - for i := 0; i != len(r.columns); i++ { - dest[i] = driver.Value(r.rows[r.pos][i]) - } - r.pos++ - return nil -} - -// HasNextResultSet is called at the end of the current result set and -// reports whether there is another result set after the current one. -func (r *rows) HasNextResultSet() bool { - return r.pos < r.len -} - -// NextResultSet advances the driver to the next result set even -// if there are remaining rows in the current result set. -// -// NextResultSet should return io.EOF when there are no more result sets. -func (r *rows) NextResultSet() error { - if r.HasNextResultSet() { - r.pos++ - return nil - } - return io.EOF // Per interface spec. -} - -type stmt struct { - c *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 -} - -// 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] - } - return s.c.execute(s.query, params) -} - -// 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] - } - _, err := s.c.execute(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") -} diff --git a/sdk/go/sqlite/sqlite.h b/sdk/go/sqlite/sqlite.h deleted file mode 100644 index 7d2e0cd29e..0000000000 --- a/sdk/go/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/sdk/go/variables/internals.go b/sdk/go/variables/internals.go deleted file mode 100644 index 97ab580b81..0000000000 --- a/sdk/go/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/sdk/go/variables/spin-config.c b/sdk/go/variables/spin-config.c deleted file mode 100644 index b2d1ab02e3..0000000000 --- a/sdk/go/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/sdk/go/variables/spin-config.h b/sdk/go/variables/spin-config.h deleted file mode 100644 index 46be58d4d4..0000000000 --- a/sdk/go/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/sdk/go/variables/variables.go b/sdk/go/variables/variables.go deleted file mode 100644 index 5a669a14b4..0000000000 --- a/sdk/go/variables/variables.go +++ /dev/null @@ -1,8 +0,0 @@ -package 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) -} diff --git a/sdk/go/wit/http-types.wit b/sdk/go/wit/http-types.wit deleted file mode 100644 index e062695429..0000000000 --- a/sdk/go/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/sdk/go/wit/key-value.wit b/sdk/go/wit/key-value.wit deleted file mode 100644 index a37b1d4825..0000000000 --- a/sdk/go/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/sdk/go/wit/mysql-types.wit b/sdk/go/wit/mysql-types.wit deleted file mode 100644 index a18f5d7375..0000000000 --- a/sdk/go/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/sdk/go/wit/outbound-mysql.wit b/sdk/go/wit/outbound-mysql.wit deleted file mode 100644 index 8cd0727754..0000000000 --- a/sdk/go/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/sdk/go/wit/outbound-pg.wit b/sdk/go/wit/outbound-pg.wit deleted file mode 100644 index 94a7c7994b..0000000000 --- a/sdk/go/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/sdk/go/wit/outbound-redis.wit b/sdk/go/wit/outbound-redis.wit deleted file mode 100644 index 5a7cbd4c26..0000000000 --- a/sdk/go/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/sdk/go/wit/pg-types.wit b/sdk/go/wit/pg-types.wit deleted file mode 100644 index 8e0336b6b5..0000000000 --- a/sdk/go/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/sdk/go/wit/rdbms-types.wit b/sdk/go/wit/rdbms-types.wit deleted file mode 100644 index 393479ae2c..0000000000 --- a/sdk/go/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/sdk/go/wit/redis-types.wit b/sdk/go/wit/redis-types.wit deleted file mode 100644 index 2f45ddfff7..0000000000 --- a/sdk/go/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/sdk/go/wit/spin-config.wit b/sdk/go/wit/spin-config.wit deleted file mode 100644 index d4788522c2..0000000000 --- a/sdk/go/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/sdk/go/wit/spin-http.wit b/sdk/go/wit/spin-http.wit deleted file mode 100644 index 27da74272b..0000000000 --- a/sdk/go/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/sdk/go/wit/spin-redis.wit b/sdk/go/wit/spin-redis.wit deleted file mode 100644 index c51c3b47e6..0000000000 --- a/sdk/go/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/sdk/go/wit/sqlite.wit b/sdk/go/wit/sqlite.wit deleted file mode 100644 index 8bf9384b55..0000000000 --- a/sdk/go/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/sdk/go/wit/wasi-outbound-http.wit b/sdk/go/wit/wasi-outbound-http.wit deleted file mode 100644 index 0502129d63..0000000000 --- a/sdk/go/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