diff --git a/.gitignore b/.gitignore index 723a981..841af69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ .spin +*.wasm diff --git a/go/Makefile b/go/Makefile new file mode 100644 index 0000000..de26bce --- /dev/null +++ b/go/Makefile @@ -0,0 +1,3 @@ +.phony: go-bindings +go-bindings: + go run go.bytecodealliance.org/cmd/wit-bindgen-go generate --world imports --out internal ../../wit \ No newline at end of file diff --git a/go/README.md b/go/README.md index e6808f5..c2c1b65 100644 --- a/go/README.md +++ b/go/README.md @@ -1,3 +1,22 @@ # OpenTelemetry WASI for Go -TODO Not implemented yet +## Requirements +- [Go](https://go.dev/dl/) version `1.24` +- [Tinygo](https://github.com/tinygo-org/tinygo/releases/tag/v0.38.0) version `0.38` + +## Usage + +```sh +git clone --depth 1 --branch factor-otel https://github.com/asteurer/otel-spin +cargo install --path otel-spin +spin plugin update +spin plugin install otel +``` + +```sh +cd examples/spin-basic +spin build +spin otel setup +spin otel up +curl localhost:3000 +``` \ No newline at end of file diff --git a/go/conversion.go b/go/conversion.go new file mode 100644 index 0000000..35bedf6 --- /dev/null +++ b/go/conversion.go @@ -0,0 +1,135 @@ +package wasi_otel + +import ( + "time" + + wasiTrace "github.com/calebschoepp/opentelemetry-wasi/internal/wasi/otel/tracing" + "go.bytecodealliance.org/cm" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/sdk/instrumentation" + sdkTrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" +) + +func toWasiTraceState(s trace.TraceState) wasiTrace.TraceState { + // TODO: double check that this actually works + result := make([][2]string, 0) + s.Walk(func(k, v string) bool { + result = append(result, [2]string{k, v}) + return true + }) + + return wasiTrace.TraceState(cm.ToList(result)) +} + +func toWasiDateTime(t time.Time) wasiTrace.DateTime { + // TODO: Make sure this is retrieving the correct time + return wasiTrace.DateTime{ + Seconds: uint64(t.Second()), + Nanoseconds: uint32(t.Nanosecond()), + } +} + +func toWasiAttributes(attributes []attribute.KeyValue) cm.List[wasiTrace.KeyValue] { + result := cm.NewList[wasiTrace.KeyValue](nil, 0) + for _, entry := range attributes { + result = cm.NewList(&wasiTrace.KeyValue{ + Key: wasiTrace.Key(entry.Key), + Value: toWasiValue(entry.Value), + }, len(attributes)) + } + + return result +} + +func toWasiEvents(events []sdkTrace.Event) cm.List[wasiTrace.Event] { + result := cm.NewList[wasiTrace.Event](nil, 0) + for _, event := range events { + result = cm.NewList(&wasiTrace.Event{ + Name: event.Name, + Time: toWasiDateTime(event.Time), + Attributes: toWasiAttributes(event.Attributes), + }, len(events)) + } + + return result +} + +func toWasiSpanContext(s trace.SpanContext) wasiTrace.SpanContext { + return wasiTrace.SpanContext{ + TraceID: wasiTrace.TraceID(s.TraceID().String()), + SpanID: wasiTrace.SpanID(s.SpanID().String()), + TraceFlags: wasiTrace.TraceFlags(s.TraceFlags()), + IsRemote: s.IsRemote(), + TraceState: toWasiTraceState(s.TraceState()), + } +} + +func toWasiLinks(links []sdkTrace.Link) cm.List[wasiTrace.Link] { + result := cm.NewList[wasiTrace.Link](nil, 0) + for _, link := range links { + result = cm.NewList(&wasiTrace.Link{ + SpanContext: toWasiSpanContext(link.SpanContext), + Attributes: toWasiAttributes(link.Attributes), + }, len(links)) + } + + return result +} + +func toWasiInstrumentationScope(s instrumentation.Scope) wasiTrace.InstrumentationScope { + return wasiTrace.InstrumentationScope{ + Name: s.Name, + Version: getOption(s.Version), + SchemaURL: getOption(s.SchemaURL), + Attributes: toWasiAttributes(s.Attributes.ToSlice()), + } +} + +func toWasiStatus(s sdkTrace.Status) wasiTrace.Status { + switch s.Code { + case codes.Error: + return wasiTrace.StatusError(s.Description) + case codes.Ok: + return wasiTrace.StatusOK() + default: + return wasiTrace.StatusUnset() + } +} + +func toWasiValue(v attribute.Value) wasiTrace.Value { + switch v.Type() { + case attribute.STRING: + return wasiTrace.ValueString_(v.AsString()) + case attribute.BOOL: + return wasiTrace.ValueBool(v.AsBool()) + case attribute.FLOAT64: + return wasiTrace.ValueF64(v.AsFloat64()) + case attribute.INT64: + return wasiTrace.ValueS64(v.AsInt64()) + case attribute.STRINGSLICE: + stringSlice := v.AsStringSlice() + return wasiTrace.ValueStringArray(cm.ToList(stringSlice)) + case attribute.BOOLSLICE: + boolSlice := v.AsBoolSlice() + return wasiTrace.ValueBoolArray(cm.ToList(boolSlice)) + case attribute.FLOAT64SLICE: + floatSlice := v.AsFloat64Slice() + return wasiTrace.ValueF64Array(cm.ToList(floatSlice)) + case attribute.INT64SLICE: + intSlice := v.AsInt64Slice() + return wasiTrace.ValueS64Array(cm.ToList(intSlice)) + default: + return wasiTrace.ValueString_(v.AsString()) + } +} + +func getOption[T comparable](v T) cm.Option[T] { + // TODO: Claude claims that this is the best way to do this function. VALIDATE + var empty T + if v == empty { + return cm.None[T]() + } + return cm.Some(v) +} diff --git a/go/examples/bare-bones-wasi/Makefile b/go/examples/bare-bones-wasi/Makefile new file mode 100644 index 0000000..ffd8cb6 --- /dev/null +++ b/go/examples/bare-bones-wasi/Makefile @@ -0,0 +1,10 @@ +# NOTE: the `tinygo build` command also works with `-target=wasip2` +.phony: build +build: + @wkg wit fetch -d pkg/sdk/wit + @wkg wit build -d pkg/sdk/wit + @cd pkg/app && tinygo build -target=wasip1 -o ../../main.wasm main.go + +.phony: run +run: + @wasmtime main.wasm \ No newline at end of file diff --git a/go/examples/bare-bones-wasi/pkg/app/go.mod b/go/examples/bare-bones-wasi/pkg/app/go.mod new file mode 100644 index 0000000..117f7dd --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/app/go.mod @@ -0,0 +1,9 @@ +module asteurer.com + +go 1.24.4 + +require sdk.com v0.0.0 + +require go.bytecodealliance.org/cm v0.3.0 // indirect + +replace sdk.com => ../sdk diff --git a/go/examples/bare-bones-wasi/pkg/app/go.sum b/go/examples/bare-bones-wasi/pkg/app/go.sum new file mode 100644 index 0000000..cf6e1ee --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/app/go.sum @@ -0,0 +1,2 @@ +go.bytecodealliance.org/cm v0.3.0 h1:VhV+4vjZPUGCozCg9+up+FNL3YU6XR+XKghk7kQ0vFc= +go.bytecodealliance.org/cm v0.3.0/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= diff --git a/go/examples/bare-bones-wasi/pkg/app/main.go b/go/examples/bare-bones-wasi/pkg/app/main.go new file mode 100644 index 0000000..6a83569 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/app/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + + "sdk.com" +) + +func init() { + fmt.Println(sdk.AddExternal(123, 456)) +} + +func main() {} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/go.mod b/go/examples/bare-bones-wasi/pkg/sdk/go.mod new file mode 100644 index 0000000..be89b50 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/go.mod @@ -0,0 +1,22 @@ +module sdk.com + +go 1.24.4 + +tool go.bytecodealliance.org/cmd/wit-bindgen-go + +require go.bytecodealliance.org/cm v0.3.0 + +require ( + github.com/coreos/go-semver v0.3.1 // indirect + github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/regclient/regclient v0.8.3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tetratelabs/wazero v1.9.0 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect + github.com/urfave/cli/v3 v3.3.3 // indirect + go.bytecodealliance.org v0.7.0 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/sys v0.33.0 // indirect +) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/go.sum b/go/examples/bare-bones-wasi/pkg/sdk/go.sum new file mode 100644 index 0000000..c07539d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/go.sum @@ -0,0 +1,48 @@ +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/olareg/olareg v0.1.2 h1:75G8X6E9FUlzL/CSjgFcYfMgNzlc7CxULpUUNsZBIvI= +github.com/olareg/olareg v0.1.2/go.mod h1:TWs+N6pO1S4bdB6eerzUm/ITRQ6kw91mVf9ZYeGtw+Y= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/regclient/regclient v0.8.3 h1:AFAPu/vmOYGyY22AIgzdBUKbzH+83lEpRioRYJ/reCs= +github.com/regclient/regclient v0.8.3/go.mod h1:gjQh5uBVZoo/CngchghtQh9Hx81HOMKRRDd5WPcPkbk= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +go.bytecodealliance.org v0.7.0 h1:CTJ1eb5kFhBKHw1/xycxxz4SmVWNKXYHhrA78oLNXhY= +go.bytecodealliance.org v0.7.0/go.mod h1:PCLMft5yTQsHT9oNPWlq0I6Qdmo6THvdky2AZHjNUkA= +go.bytecodealliance.org/cm v0.3.0 h1:VhV+4vjZPUGCozCg9+up+FNL3YU6XR+XKghk7kQ0vFc= +go.bytecodealliance.org/cm v0.3.0/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/abi.go new file mode 100644 index 0000000..3603f49 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/abi.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package add + +func lift_Numbers(f0 uint32, f1 uint32) (v Numbers) { + v.X = (uint32)(f0) + v.Y = (uint32)(f1) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.exports.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.exports.go new file mode 100644 index 0000000..712d36f --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.exports.go @@ -0,0 +1,11 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package add + +// Exports represents the caller-defined exports from "docs:adder/add@0.1.0". +var Exports struct { + // Add represents the caller-defined, exported function "add". + // + // add: func(nums: numbers) -> u32 + Add func(nums Numbers) (result uint32) +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wasm.go new file mode 100644 index 0000000..5d7ad24 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wasm.go @@ -0,0 +1,14 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package add + +// This file contains wasmimport and wasmexport declarations for "docs:adder@0.1.0". + +//go:wasmexport docs:adder/add@0.1.0#add +//export docs:adder/add@0.1.0#add +func wasmexport_Add(nums0 uint32, nums1 uint32) (result0 uint32) { + nums := lift_Numbers((uint32)(nums0), (uint32)(nums1)) + result := Exports.Add(nums) + result0 = (uint32)(result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wit.go new file mode 100644 index 0000000..06e7ba5 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/add.wit.go @@ -0,0 +1,20 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package add represents the exported interface "docs:adder/add@0.1.0". +package add + +import ( + "go.bytecodealliance.org/cm" +) + +// Numbers represents the record "docs:adder/add@0.1.0#numbers". +// +// record numbers { +// x: u32, +// y: u32, +// } +type Numbers struct { + _ cm.HostLayout `json:"-"` + X uint32 `json:"x"` + Y uint32 `json:"y"` +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/add/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/adder/adder.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/adder/adder.wit.go new file mode 100644 index 0000000..7f823c6 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/docs/adder/adder/adder.wit.go @@ -0,0 +1,4 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package adder represents the world "docs:adder/adder@0.1.0". +package adder diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wasm.go new file mode 100644 index 0000000..89bb596 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wasm.go @@ -0,0 +1,21 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package environment + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/environment@0.2.0 get-environment +//go:noescape +func wasmimport_GetEnvironment(result *cm.List[[2]string]) + +//go:wasmimport wasi:cli/environment@0.2.0 get-arguments +//go:noescape +func wasmimport_GetArguments(result *cm.List[string]) + +//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd +//go:noescape +func wasmimport_InitialCWD(result *cm.Option[string]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wit.go new file mode 100644 index 0000000..068bed3 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/environment/environment.wit.go @@ -0,0 +1,38 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package environment represents the imported interface "wasi:cli/environment@0.2.0". +package environment + +import ( + "go.bytecodealliance.org/cm" +) + +// GetEnvironment represents the imported function "get-environment". +// +// get-environment: func() -> list> +// +//go:nosplit +func GetEnvironment() (result cm.List[[2]string]) { + wasmimport_GetEnvironment(&result) + return +} + +// GetArguments represents the imported function "get-arguments". +// +// get-arguments: func() -> list +// +//go:nosplit +func GetArguments() (result cm.List[string]) { + wasmimport_GetArguments(&result) + return +} + +// InitialCWD represents the imported function "initial-cwd". +// +// initial-cwd: func() -> option +// +//go:nosplit +func InitialCWD() (result cm.Option[string]) { + wasmimport_InitialCWD(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wasm.go new file mode 100644 index 0000000..849d5f5 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package exit + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/exit@0.2.0 exit +//go:noescape +func wasmimport_Exit(status0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wit.go new file mode 100644 index 0000000..ba0f0ab --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/exit/exit.wit.go @@ -0,0 +1,19 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package exit represents the imported interface "wasi:cli/exit@0.2.0". +package exit + +import ( + "go.bytecodealliance.org/cm" +) + +// Exit represents the imported function "exit". +// +// exit: func(status: result) +// +//go:nosplit +func Exit(status cm.BoolResult) { + status0 := (uint32)(status) + wasmimport_Exit((uint32)(status0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wasm.go new file mode 100644 index 0000000..462cf17 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package stderr + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr +//go:noescape +func wasmimport_GetStderr() (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wit.go new file mode 100644 index 0000000..9b338dc --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stderr/stderr.wit.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package stderr represents the imported interface "wasi:cli/stderr@0.2.0". +package stderr + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/streams" +) + +// OutputStream represents the imported type alias "wasi:cli/stderr@0.2.0#output-stream". +// +// See [streams.OutputStream] for more information. +type OutputStream = streams.OutputStream + +// GetStderr represents the imported function "get-stderr". +// +// get-stderr: func() -> output-stream +// +//go:nosplit +func GetStderr() (result OutputStream) { + result0 := wasmimport_GetStderr() + result = cm.Reinterpret[OutputStream]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wasm.go new file mode 100644 index 0000000..374eb25 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package stdin + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin +//go:noescape +func wasmimport_GetStdin() (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wit.go new file mode 100644 index 0000000..d16e240 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdin/stdin.wit.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package stdin represents the imported interface "wasi:cli/stdin@0.2.0". +package stdin + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/streams" +) + +// InputStream represents the imported type alias "wasi:cli/stdin@0.2.0#input-stream". +// +// See [streams.InputStream] for more information. +type InputStream = streams.InputStream + +// GetStdin represents the imported function "get-stdin". +// +// get-stdin: func() -> input-stream +// +//go:nosplit +func GetStdin() (result InputStream) { + result0 := wasmimport_GetStdin() + result = cm.Reinterpret[InputStream]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wasm.go new file mode 100644 index 0000000..68e4a3d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package stdout + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout +//go:noescape +func wasmimport_GetStdout() (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wit.go new file mode 100644 index 0000000..6c6ccbe --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/stdout/stdout.wit.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package stdout represents the imported interface "wasi:cli/stdout@0.2.0". +package stdout + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/streams" +) + +// OutputStream represents the imported type alias "wasi:cli/stdout@0.2.0#output-stream". +// +// See [streams.OutputStream] for more information. +type OutputStream = streams.OutputStream + +// GetStdout represents the imported function "get-stdout". +// +// get-stdout: func() -> output-stream +// +//go:nosplit +func GetStdout() (result OutputStream) { + result0 := wasmimport_GetStdout() + result = cm.Reinterpret[OutputStream]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wasm.go new file mode 100644 index 0000000..1df3794 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package terminalinput + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input +//go:noescape +func wasmimport_TerminalInputResourceDrop(self0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wit.go new file mode 100644 index 0000000..18b9a9d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-input/terminal-input.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package terminalinput represents the imported interface "wasi:cli/terminal-input@0.2.0". +package terminalinput + +import ( + "go.bytecodealliance.org/cm" +) + +// TerminalInput represents the imported resource "wasi:cli/terminal-input@0.2.0#terminal-input". +// +// resource terminal-input +type TerminalInput cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "terminal-input". +// +// Drops a resource handle. +// +//go:nosplit +func (self TerminalInput) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TerminalInputResourceDrop((uint32)(self0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wasm.go new file mode 100644 index 0000000..fb35fc4 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package terminaloutput + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output +//go:noescape +func wasmimport_TerminalOutputResourceDrop(self0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wit.go new file mode 100644 index 0000000..823aaf5 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-output/terminal-output.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package terminaloutput represents the imported interface "wasi:cli/terminal-output@0.2.0". +package terminaloutput + +import ( + "go.bytecodealliance.org/cm" +) + +// TerminalOutput represents the imported resource "wasi:cli/terminal-output@0.2.0#terminal-output". +// +// resource terminal-output +type TerminalOutput cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "terminal-output". +// +// Drops a resource handle. +// +//go:nosplit +func (self TerminalOutput) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TerminalOutputResourceDrop((uint32)(self0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wasm.go new file mode 100644 index 0000000..be9af72 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package terminalstderr + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr +//go:noescape +func wasmimport_GetTerminalStderr(result *cm.Option[TerminalOutput]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wit.go new file mode 100644 index 0000000..d2e642a --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stderr/terminal-stderr.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package terminalstderr represents the imported interface "wasi:cli/terminal-stderr@0.2.0". +package terminalstderr + +import ( + "go.bytecodealliance.org/cm" + terminaloutput "sdk.com/internal/wasi/cli/terminal-output" +) + +// TerminalOutput represents the imported type alias "wasi:cli/terminal-stderr@0.2.0#terminal-output". +// +// See [terminaloutput.TerminalOutput] for more information. +type TerminalOutput = terminaloutput.TerminalOutput + +// GetTerminalStderr represents the imported function "get-terminal-stderr". +// +// get-terminal-stderr: func() -> option +// +//go:nosplit +func GetTerminalStderr() (result cm.Option[TerminalOutput]) { + wasmimport_GetTerminalStderr(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wasm.go new file mode 100644 index 0000000..e3b3ac6 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package terminalstdin + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin +//go:noescape +func wasmimport_GetTerminalStdin(result *cm.Option[TerminalInput]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wit.go new file mode 100644 index 0000000..985eeb0 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdin/terminal-stdin.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package terminalstdin represents the imported interface "wasi:cli/terminal-stdin@0.2.0". +package terminalstdin + +import ( + "go.bytecodealliance.org/cm" + terminalinput "sdk.com/internal/wasi/cli/terminal-input" +) + +// TerminalInput represents the imported type alias "wasi:cli/terminal-stdin@0.2.0#terminal-input". +// +// See [terminalinput.TerminalInput] for more information. +type TerminalInput = terminalinput.TerminalInput + +// GetTerminalStdin represents the imported function "get-terminal-stdin". +// +// get-terminal-stdin: func() -> option +// +//go:nosplit +func GetTerminalStdin() (result cm.Option[TerminalInput]) { + wasmimport_GetTerminalStdin(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wasm.go new file mode 100644 index 0000000..fa750ad --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package terminalstdout + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0". + +//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout +//go:noescape +func wasmimport_GetTerminalStdout(result *cm.Option[TerminalOutput]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wit.go new file mode 100644 index 0000000..c636e5b --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/cli/terminal-stdout/terminal-stdout.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package terminalstdout represents the imported interface "wasi:cli/terminal-stdout@0.2.0". +package terminalstdout + +import ( + "go.bytecodealliance.org/cm" + terminaloutput "sdk.com/internal/wasi/cli/terminal-output" +) + +// TerminalOutput represents the imported type alias "wasi:cli/terminal-stdout@0.2.0#terminal-output". +// +// See [terminaloutput.TerminalOutput] for more information. +type TerminalOutput = terminaloutput.TerminalOutput + +// GetTerminalStdout represents the imported function "get-terminal-stdout". +// +// get-terminal-stdout: func() -> option +// +//go:nosplit +func GetTerminalStdout() (result cm.Option[TerminalOutput]) { + wasmimport_GetTerminalStdout(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wasm.go new file mode 100644 index 0000000..36a1720 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wasm.go @@ -0,0 +1,21 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package monotonicclock + +// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0". + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now +//go:noescape +func wasmimport_Now() (result0 uint64) + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution +//go:noescape +func wasmimport_Resolution() (result0 uint64) + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant +//go:noescape +func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32) + +//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration +//go:noescape +func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wit.go new file mode 100644 index 0000000..857e17f --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/monotonic-clock/monotonic-clock.wit.go @@ -0,0 +1,70 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package monotonicclock represents the imported interface "wasi:clocks/monotonic-clock@0.2.0". +package monotonicclock + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/poll" +) + +// Pollable represents the imported type alias "wasi:clocks/monotonic-clock@0.2.0#pollable". +// +// See [poll.Pollable] for more information. +type Pollable = poll.Pollable + +// Instant represents the u64 "wasi:clocks/monotonic-clock@0.2.0#instant". +// +// type instant = u64 +type Instant uint64 + +// Duration represents the u64 "wasi:clocks/monotonic-clock@0.2.0#duration". +// +// type duration = u64 +type Duration uint64 + +// Now represents the imported function "now". +// +// now: func() -> instant +// +//go:nosplit +func Now() (result Instant) { + result0 := wasmimport_Now() + result = (Instant)((uint64)(result0)) + return +} + +// Resolution represents the imported function "resolution". +// +// resolution: func() -> duration +// +//go:nosplit +func Resolution() (result Duration) { + result0 := wasmimport_Resolution() + result = (Duration)((uint64)(result0)) + return +} + +// SubscribeInstant represents the imported function "subscribe-instant". +// +// subscribe-instant: func(when: instant) -> pollable +// +//go:nosplit +func SubscribeInstant(when Instant) (result Pollable) { + when0 := (uint64)(when) + result0 := wasmimport_SubscribeInstant((uint64)(when0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// SubscribeDuration represents the imported function "subscribe-duration". +// +// subscribe-duration: func(when: duration) -> pollable +// +//go:nosplit +func SubscribeDuration(when Duration) (result Pollable) { + when0 := (uint64)(when) + result0 := wasmimport_SubscribeDuration((uint64)(when0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wasm.go new file mode 100644 index 0000000..321ff3f --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package wallclock + +// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0". + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 now +//go:noescape +func wasmimport_Now(result *DateTime) + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution +//go:noescape +func wasmimport_Resolution(result *DateTime) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wit.go new file mode 100644 index 0000000..4cb5e3b --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/clocks/wall-clock/wall-clock.wit.go @@ -0,0 +1,40 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package wallclock represents the imported interface "wasi:clocks/wall-clock@0.2.0". +package wallclock + +import ( + "go.bytecodealliance.org/cm" +) + +// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime". +// +// record datetime { +// seconds: u64, +// nanoseconds: u32, +// } +type DateTime struct { + _ cm.HostLayout `json:"-"` + Seconds uint64 `json:"seconds"` + Nanoseconds uint32 `json:"nanoseconds"` +} + +// Now represents the imported function "now". +// +// now: func() -> datetime +// +//go:nosplit +func Now() (result DateTime) { + wasmimport_Now(&result) + return +} + +// Resolution represents the imported function "resolution". +// +// resolution: func() -> datetime +// +//go:nosplit +func Resolution() (result DateTime) { + wasmimport_Resolution(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wasm.go new file mode 100644 index 0000000..1bcd416 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package preopens + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0". + +//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories +//go:noescape +func wasmimport_GetDirectories(result *cm.List[cm.Tuple[Descriptor, string]]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wit.go new file mode 100644 index 0000000..0c9b6b3 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/preopens/preopens.wit.go @@ -0,0 +1,24 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package preopens represents the imported interface "wasi:filesystem/preopens@0.2.0". +package preopens + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/filesystem/types" +) + +// Descriptor represents the imported type alias "wasi:filesystem/preopens@0.2.0#descriptor". +// +// See [types.Descriptor] for more information. +type Descriptor = types.Descriptor + +// GetDirectories represents the imported function "get-directories". +// +// get-directories: func() -> list> +// +//go:nosplit +func GetDirectories() (result cm.List[cm.Tuple[Descriptor, string]]) { + wasmimport_GetDirectories(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/abi.go new file mode 100644 index 0000000..5bfef42 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/abi.go @@ -0,0 +1,50 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package types + +import ( + "go.bytecodealliance.org/cm" + wallclock "sdk.com/internal/wasi/clocks/wall-clock" + "unsafe" +) + +// MetadataHashValueShape is used for storage in variant or result types. +type MetadataHashValueShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(MetadataHashValue{})]byte +} + +// TupleListU8BoolShape is used for storage in variant or result types. +type TupleListU8BoolShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte +} + +func lower_DateTime(v wallclock.DateTime) (f0 uint64, f1 uint32) { + f0 = (uint64)(v.Seconds) + f1 = (uint32)(v.Nanoseconds) + return +} + +func lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) { + f0 = (uint32)(v.Tag()) + switch f0 { + case 2: // timestamp + v1, v2 := lower_DateTime(*cm.Case[DateTime](&v, 2)) + f1 = (uint64)(v1) + f2 = (uint32)(v2) + } + return +} + +// DescriptorStatShape is used for storage in variant or result types. +type DescriptorStatShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(DescriptorStat{})]byte +} + +// OptionDirectoryEntryShape is used for storage in variant or result types. +type OptionDirectoryEntryShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wasm.go new file mode 100644 index 0000000..b97dad8 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wasm.go @@ -0,0 +1,133 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package types + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0". + +//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor +//go:noescape +func wasmimport_DescriptorResourceDrop(self0 uint32) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise +//go:noescape +func wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, advice0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream +//go:noescape +func wasmimport_DescriptorAppendViaStream(self0 uint32, result *cm.Result[OutputStream, OutputStream, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at +//go:noescape +func wasmimport_DescriptorCreateDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags +//go:noescape +func wasmimport_DescriptorGetFlags(self0 uint32, result *cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type +//go:noescape +func wasmimport_DescriptorGetType(self0 uint32, result *cm.Result[DescriptorType, DescriptorType, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object +//go:noescape +func wasmimport_DescriptorIsSameObject(self0 uint32, other0 uint32) (result0 uint32) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at +//go:noescape +func wasmimport_DescriptorLinkAt(self0 uint32, oldPathFlags0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash +//go:noescape +func wasmimport_DescriptorMetadataHash(self0 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at +//go:noescape +func wasmimport_DescriptorMetadataHashAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at +//go:noescape +func wasmimport_DescriptorOpenAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, openFlags0 uint32, flags0 uint32, result *cm.Result[Descriptor, Descriptor, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read +//go:noescape +func wasmimport_DescriptorRead(self0 uint32, length0 uint64, offset0 uint64, result *cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory +//go:noescape +func wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream +//go:noescape +func wasmimport_DescriptorReadViaStream(self0 uint32, offset0 uint64, result *cm.Result[InputStream, InputStream, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at +//go:noescape +func wasmimport_DescriptorReadLinkAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[string, string, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at +//go:noescape +func wasmimport_DescriptorRemoveDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at +//go:noescape +func wasmimport_DescriptorRenameAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size +//go:noescape +func wasmimport_DescriptorSetSize(self0 uint32, size0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times +//go:noescape +func wasmimport_DescriptorSetTimes(self0 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at +//go:noescape +func wasmimport_DescriptorSetTimesAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat +//go:noescape +func wasmimport_DescriptorStat(self0 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at +//go:noescape +func wasmimport_DescriptorStatAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at +//go:noescape +func wasmimport_DescriptorSymlinkAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync +//go:noescape +func wasmimport_DescriptorSync(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data +//go:noescape +func wasmimport_DescriptorSyncData(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at +//go:noescape +func wasmimport_DescriptorUnlinkFileAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write +//go:noescape +func wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, offset0 uint64, result *cm.Result[uint64, FileSize, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream +//go:noescape +func wasmimport_DescriptorWriteViaStream(self0 uint32, offset0 uint64, result *cm.Result[OutputStream, OutputStream, ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream +//go:noescape +func wasmimport_DirectoryEntryStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry +//go:noescape +func wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode]) + +//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code +//go:noescape +func wasmimport_FilesystemErrorCode(err0 uint32, result *cm.Option[ErrorCode]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wit.go new file mode 100644 index 0000000..c45ac54 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/filesystem/types/types.wit.go @@ -0,0 +1,826 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package types represents the imported interface "wasi:filesystem/types@0.2.0". +package types + +import ( + "go.bytecodealliance.org/cm" + wallclock "sdk.com/internal/wasi/clocks/wall-clock" + "sdk.com/internal/wasi/io/streams" +) + +// InputStream represents the imported type alias "wasi:filesystem/types@0.2.0#input-stream". +// +// See [streams.InputStream] for more information. +type InputStream = streams.InputStream + +// OutputStream represents the imported type alias "wasi:filesystem/types@0.2.0#output-stream". +// +// See [streams.OutputStream] for more information. +type OutputStream = streams.OutputStream + +// Error represents the imported type alias "wasi:filesystem/types@0.2.0#error". +// +// See [streams.Error] for more information. +type Error = streams.Error + +// DateTime represents the type alias "wasi:filesystem/types@0.2.0#datetime". +// +// See [wallclock.DateTime] for more information. +type DateTime = wallclock.DateTime + +// FileSize represents the u64 "wasi:filesystem/types@0.2.0#filesize". +// +// type filesize = u64 +type FileSize uint64 + +// DescriptorType represents the enum "wasi:filesystem/types@0.2.0#descriptor-type". +// +// enum descriptor-type { +// unknown, +// block-device, +// character-device, +// directory, +// fifo, +// symbolic-link, +// regular-file, +// socket +// } +type DescriptorType uint8 + +const ( + DescriptorTypeUnknown DescriptorType = iota + DescriptorTypeBlockDevice + DescriptorTypeCharacterDevice + DescriptorTypeDirectory + DescriptorTypeFIFO + DescriptorTypeSymbolicLink + DescriptorTypeRegularFile + DescriptorTypeSocket +) + +var _DescriptorTypeStrings = [8]string{ + "unknown", + "block-device", + "character-device", + "directory", + "fifo", + "symbolic-link", + "regular-file", + "socket", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e DescriptorType) String() string { + return _DescriptorTypeStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e DescriptorType) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *DescriptorType) UnmarshalText(text []byte) error { + return _DescriptorTypeUnmarshalCase(e, text) +} + +var _DescriptorTypeUnmarshalCase = cm.CaseUnmarshaler[DescriptorType](_DescriptorTypeStrings[:]) + +// DescriptorFlags represents the flags "wasi:filesystem/types@0.2.0#descriptor-flags". +// +// flags descriptor-flags { +// read, +// write, +// file-integrity-sync, +// data-integrity-sync, +// requested-write-sync, +// mutate-directory, +// } +type DescriptorFlags uint8 + +const ( + DescriptorFlagsRead DescriptorFlags = 1 << iota + DescriptorFlagsWrite + DescriptorFlagsFileIntegritySync + DescriptorFlagsDataIntegritySync + DescriptorFlagsRequestedWriteSync + DescriptorFlagsMutateDirectory +) + +// PathFlags represents the flags "wasi:filesystem/types@0.2.0#path-flags". +// +// flags path-flags { +// symlink-follow, +// } +type PathFlags uint8 + +const ( + PathFlagsSymlinkFollow PathFlags = 1 << iota +) + +// OpenFlags represents the flags "wasi:filesystem/types@0.2.0#open-flags". +// +// flags open-flags { +// create, +// directory, +// exclusive, +// truncate, +// } +type OpenFlags uint8 + +const ( + OpenFlagsCreate OpenFlags = 1 << iota + OpenFlagsDirectory + OpenFlagsExclusive + OpenFlagsTruncate +) + +// LinkCount represents the u64 "wasi:filesystem/types@0.2.0#link-count". +// +// type link-count = u64 +type LinkCount uint64 + +// DescriptorStat represents the record "wasi:filesystem/types@0.2.0#descriptor-stat". +// +// record descriptor-stat { +// %type: descriptor-type, +// link-count: link-count, +// size: filesize, +// data-access-timestamp: option, +// data-modification-timestamp: option, +// status-change-timestamp: option, +// } +type DescriptorStat struct { + _ cm.HostLayout `json:"-"` + Type DescriptorType `json:"type"` + LinkCount LinkCount `json:"link-count"` + Size FileSize `json:"size"` + DataAccessTimestamp cm.Option[DateTime] `json:"data-access-timestamp"` + DataModificationTimestamp cm.Option[DateTime] `json:"data-modification-timestamp"` + StatusChangeTimestamp cm.Option[DateTime] `json:"status-change-timestamp"` +} + +// NewTimestamp represents the variant "wasi:filesystem/types@0.2.0#new-timestamp". +// +// variant new-timestamp { +// no-change, +// now, +// timestamp(datetime), +// } +type NewTimestamp cm.Variant[uint8, DateTime, DateTime] + +// NewTimestampNoChange returns a [NewTimestamp] of case "no-change". +func NewTimestampNoChange() NewTimestamp { + var data struct{} + return cm.New[NewTimestamp](0, data) +} + +// NoChange returns true if [NewTimestamp] represents the variant case "no-change". +func (self *NewTimestamp) NoChange() bool { + return self.Tag() == 0 +} + +// NewTimestampNow returns a [NewTimestamp] of case "now". +func NewTimestampNow() NewTimestamp { + var data struct{} + return cm.New[NewTimestamp](1, data) +} + +// Now returns true if [NewTimestamp] represents the variant case "now". +func (self *NewTimestamp) Now() bool { + return self.Tag() == 1 +} + +// NewTimestampTimestamp returns a [NewTimestamp] of case "timestamp". +func NewTimestampTimestamp(data DateTime) NewTimestamp { + return cm.New[NewTimestamp](2, data) +} + +// Timestamp returns a non-nil *[DateTime] if [NewTimestamp] represents the variant case "timestamp". +func (self *NewTimestamp) Timestamp() *DateTime { + return cm.Case[DateTime](self, 2) +} + +var _NewTimestampStrings = [3]string{ + "no-change", + "now", + "timestamp", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v NewTimestamp) String() string { + return _NewTimestampStrings[v.Tag()] +} + +// DirectoryEntry represents the record "wasi:filesystem/types@0.2.0#directory-entry". +// +// record directory-entry { +// %type: descriptor-type, +// name: string, +// } +type DirectoryEntry struct { + _ cm.HostLayout `json:"-"` + Type DescriptorType `json:"type"` + Name string `json:"name"` +} + +// ErrorCode represents the enum "wasi:filesystem/types@0.2.0#error-code". +// +// enum error-code { +// access, +// would-block, +// already, +// bad-descriptor, +// busy, +// deadlock, +// quota, +// exist, +// file-too-large, +// illegal-byte-sequence, +// in-progress, +// interrupted, +// invalid, +// io, +// is-directory, +// loop, +// too-many-links, +// message-size, +// name-too-long, +// no-device, +// no-entry, +// no-lock, +// insufficient-memory, +// insufficient-space, +// not-directory, +// not-empty, +// not-recoverable, +// unsupported, +// no-tty, +// no-such-device, +// overflow, +// not-permitted, +// pipe, +// read-only, +// invalid-seek, +// text-file-busy, +// cross-device +// } +type ErrorCode uint8 + +const ( + ErrorCodeAccess ErrorCode = iota + ErrorCodeWouldBlock + ErrorCodeAlready + ErrorCodeBadDescriptor + ErrorCodeBusy + ErrorCodeDeadlock + ErrorCodeQuota + ErrorCodeExist + ErrorCodeFileTooLarge + ErrorCodeIllegalByteSequence + ErrorCodeInProgress + ErrorCodeInterrupted + ErrorCodeInvalid + ErrorCodeIO + ErrorCodeIsDirectory + ErrorCodeLoop + ErrorCodeTooManyLinks + ErrorCodeMessageSize + ErrorCodeNameTooLong + ErrorCodeNoDevice + ErrorCodeNoEntry + ErrorCodeNoLock + ErrorCodeInsufficientMemory + ErrorCodeInsufficientSpace + ErrorCodeNotDirectory + ErrorCodeNotEmpty + ErrorCodeNotRecoverable + ErrorCodeUnsupported + ErrorCodeNoTTY + ErrorCodeNoSuchDevice + ErrorCodeOverflow + ErrorCodeNotPermitted + ErrorCodePipe + ErrorCodeReadOnly + ErrorCodeInvalidSeek + ErrorCodeTextFileBusy + ErrorCodeCrossDevice +) + +var _ErrorCodeStrings = [37]string{ + "access", + "would-block", + "already", + "bad-descriptor", + "busy", + "deadlock", + "quota", + "exist", + "file-too-large", + "illegal-byte-sequence", + "in-progress", + "interrupted", + "invalid", + "io", + "is-directory", + "loop", + "too-many-links", + "message-size", + "name-too-long", + "no-device", + "no-entry", + "no-lock", + "insufficient-memory", + "insufficient-space", + "not-directory", + "not-empty", + "not-recoverable", + "unsupported", + "no-tty", + "no-such-device", + "overflow", + "not-permitted", + "pipe", + "read-only", + "invalid-seek", + "text-file-busy", + "cross-device", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e ErrorCode) String() string { + return _ErrorCodeStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e ErrorCode) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *ErrorCode) UnmarshalText(text []byte) error { + return _ErrorCodeUnmarshalCase(e, text) +} + +var _ErrorCodeUnmarshalCase = cm.CaseUnmarshaler[ErrorCode](_ErrorCodeStrings[:]) + +// Advice represents the enum "wasi:filesystem/types@0.2.0#advice". +// +// enum advice { +// normal, +// sequential, +// random, +// will-need, +// dont-need, +// no-reuse +// } +type Advice uint8 + +const ( + AdviceNormal Advice = iota + AdviceSequential + AdviceRandom + AdviceWillNeed + AdviceDontNeed + AdviceNoReuse +) + +var _AdviceStrings = [6]string{ + "normal", + "sequential", + "random", + "will-need", + "dont-need", + "no-reuse", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e Advice) String() string { + return _AdviceStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e Advice) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *Advice) UnmarshalText(text []byte) error { + return _AdviceUnmarshalCase(e, text) +} + +var _AdviceUnmarshalCase = cm.CaseUnmarshaler[Advice](_AdviceStrings[:]) + +// MetadataHashValue represents the record "wasi:filesystem/types@0.2.0#metadata-hash-value". +// +// record metadata-hash-value { +// lower: u64, +// upper: u64, +// } +type MetadataHashValue struct { + _ cm.HostLayout `json:"-"` + Lower uint64 `json:"lower"` + Upper uint64 `json:"upper"` +} + +// Descriptor represents the imported resource "wasi:filesystem/types@0.2.0#descriptor". +// +// resource descriptor +type Descriptor cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "descriptor". +// +// Drops a resource handle. +// +//go:nosplit +func (self Descriptor) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorResourceDrop((uint32)(self0)) + return +} + +// Advise represents the imported method "advise". +// +// advise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) Advise(offset FileSize, length FileSize, advice Advice) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + offset0 := (uint64)(offset) + length0 := (uint64)(length) + advice0 := (uint32)(advice) + wasmimport_DescriptorAdvise((uint32)(self0), (uint64)(offset0), (uint64)(length0), (uint32)(advice0), &result) + return +} + +// AppendViaStream represents the imported method "append-via-stream". +// +// append-via-stream: func() -> result +// +//go:nosplit +func (self Descriptor) AppendViaStream() (result cm.Result[OutputStream, OutputStream, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorAppendViaStream((uint32)(self0), &result) + return +} + +// CreateDirectoryAt represents the imported method "create-directory-at". +// +// create-directory-at: func(path: string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) CreateDirectoryAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorCreateDirectoryAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// GetFlags represents the imported method "get-flags". +// +// get-flags: func() -> result +// +//go:nosplit +func (self Descriptor) GetFlags() (result cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorGetFlags((uint32)(self0), &result) + return +} + +// GetType represents the imported method "get-type". +// +// get-type: func() -> result +// +//go:nosplit +func (self Descriptor) GetType() (result cm.Result[DescriptorType, DescriptorType, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorGetType((uint32)(self0), &result) + return +} + +// IsSameObject represents the imported method "is-same-object". +// +// is-same-object: func(other: borrow) -> bool +// +//go:nosplit +func (self Descriptor) IsSameObject(other Descriptor) (result bool) { + self0 := cm.Reinterpret[uint32](self) + other0 := cm.Reinterpret[uint32](other) + result0 := wasmimport_DescriptorIsSameObject((uint32)(self0), (uint32)(other0)) + result = (bool)(cm.U32ToBool((uint32)(result0))) + return +} + +// LinkAt represents the imported method "link-at". +// +// link-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, +// new-path: string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) LinkAt(oldPathFlags PathFlags, oldPath string, newDescriptor Descriptor, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + oldPathFlags0 := (uint32)(oldPathFlags) + oldPath0, oldPath1 := cm.LowerString(oldPath) + newDescriptor0 := cm.Reinterpret[uint32](newDescriptor) + newPath0, newPath1 := cm.LowerString(newPath) + wasmimport_DescriptorLinkAt((uint32)(self0), (uint32)(oldPathFlags0), (*uint8)(oldPath0), (uint32)(oldPath1), (uint32)(newDescriptor0), (*uint8)(newPath0), (uint32)(newPath1), &result) + return +} + +// MetadataHash represents the imported method "metadata-hash". +// +// metadata-hash: func() -> result +// +//go:nosplit +func (self Descriptor) MetadataHash() (result cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorMetadataHash((uint32)(self0), &result) + return +} + +// MetadataHashAt represents the imported method "metadata-hash-at". +// +// metadata-hash-at: func(path-flags: path-flags, path: string) -> result +// +//go:nosplit +func (self Descriptor) MetadataHashAt(pathFlags PathFlags, path string) (result cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + pathFlags0 := (uint32)(pathFlags) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorMetadataHashAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// OpenAt represents the imported method "open-at". +// +// open-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: +// descriptor-flags) -> result +// +//go:nosplit +func (self Descriptor) OpenAt(pathFlags PathFlags, path string, openFlags OpenFlags, flags DescriptorFlags) (result cm.Result[Descriptor, Descriptor, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + pathFlags0 := (uint32)(pathFlags) + path0, path1 := cm.LowerString(path) + openFlags0 := (uint32)(openFlags) + flags0 := (uint32)(flags) + wasmimport_DescriptorOpenAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), (uint32)(openFlags0), (uint32)(flags0), &result) + return +} + +// Read represents the imported method "read". +// +// read: func(length: filesize, offset: filesize) -> result, bool>, +// error-code> +// +//go:nosplit +func (self Descriptor) Read(length FileSize, offset FileSize) (result cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + length0 := (uint64)(length) + offset0 := (uint64)(offset) + wasmimport_DescriptorRead((uint32)(self0), (uint64)(length0), (uint64)(offset0), &result) + return +} + +// ReadDirectory represents the imported method "read-directory". +// +// read-directory: func() -> result +// +//go:nosplit +func (self Descriptor) ReadDirectory() (result cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorReadDirectory((uint32)(self0), &result) + return +} + +// ReadViaStream represents the imported method "read-via-stream". +// +// read-via-stream: func(offset: filesize) -> result +// +//go:nosplit +func (self Descriptor) ReadViaStream(offset FileSize) (result cm.Result[InputStream, InputStream, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + offset0 := (uint64)(offset) + wasmimport_DescriptorReadViaStream((uint32)(self0), (uint64)(offset0), &result) + return +} + +// ReadLinkAt represents the imported method "readlink-at". +// +// readlink-at: func(path: string) -> result +// +//go:nosplit +func (self Descriptor) ReadLinkAt(path string) (result cm.Result[string, string, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorReadLinkAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// RemoveDirectoryAt represents the imported method "remove-directory-at". +// +// remove-directory-at: func(path: string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) RemoveDirectoryAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorRemoveDirectoryAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// RenameAt represents the imported method "rename-at". +// +// rename-at: func(old-path: string, new-descriptor: borrow, new-path: +// string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) RenameAt(oldPath string, newDescriptor Descriptor, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + oldPath0, oldPath1 := cm.LowerString(oldPath) + newDescriptor0 := cm.Reinterpret[uint32](newDescriptor) + newPath0, newPath1 := cm.LowerString(newPath) + wasmimport_DescriptorRenameAt((uint32)(self0), (*uint8)(oldPath0), (uint32)(oldPath1), (uint32)(newDescriptor0), (*uint8)(newPath0), (uint32)(newPath1), &result) + return +} + +// SetSize represents the imported method "set-size". +// +// set-size: func(size: filesize) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) SetSize(size FileSize) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + size0 := (uint64)(size) + wasmimport_DescriptorSetSize((uint32)(self0), (uint64)(size0), &result) + return +} + +// SetTimes represents the imported method "set-times". +// +// set-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp: +// new-timestamp) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) SetTimes(dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + dataAccessTimestamp0, dataAccessTimestamp1, dataAccessTimestamp2 := lower_NewTimestamp(dataAccessTimestamp) + dataModificationTimestamp0, dataModificationTimestamp1, dataModificationTimestamp2 := lower_NewTimestamp(dataModificationTimestamp) + wasmimport_DescriptorSetTimes((uint32)(self0), (uint32)(dataAccessTimestamp0), (uint64)(dataAccessTimestamp1), (uint32)(dataAccessTimestamp2), (uint32)(dataModificationTimestamp0), (uint64)(dataModificationTimestamp1), (uint32)(dataModificationTimestamp2), &result) + return +} + +// SetTimesAt represents the imported method "set-times-at". +// +// set-times-at: func(path-flags: path-flags, path: string, data-access-timestamp: +// new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) SetTimesAt(pathFlags PathFlags, path string, dataAccessTimestamp NewTimestamp, dataModificationTimestamp NewTimestamp) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + pathFlags0 := (uint32)(pathFlags) + path0, path1 := cm.LowerString(path) + dataAccessTimestamp0, dataAccessTimestamp1, dataAccessTimestamp2 := lower_NewTimestamp(dataAccessTimestamp) + dataModificationTimestamp0, dataModificationTimestamp1, dataModificationTimestamp2 := lower_NewTimestamp(dataModificationTimestamp) + wasmimport_DescriptorSetTimesAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), (uint32)(dataAccessTimestamp0), (uint64)(dataAccessTimestamp1), (uint32)(dataAccessTimestamp2), (uint32)(dataModificationTimestamp0), (uint64)(dataModificationTimestamp1), (uint32)(dataModificationTimestamp2), &result) + return +} + +// Stat represents the imported method "stat". +// +// stat: func() -> result +// +//go:nosplit +func (self Descriptor) Stat() (result cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorStat((uint32)(self0), &result) + return +} + +// StatAt represents the imported method "stat-at". +// +// stat-at: func(path-flags: path-flags, path: string) -> result +// +//go:nosplit +func (self Descriptor) StatAt(pathFlags PathFlags, path string) (result cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + pathFlags0 := (uint32)(pathFlags) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorStatAt((uint32)(self0), (uint32)(pathFlags0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// SymlinkAt represents the imported method "symlink-at". +// +// symlink-at: func(old-path: string, new-path: string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) SymlinkAt(oldPath string, newPath string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + oldPath0, oldPath1 := cm.LowerString(oldPath) + newPath0, newPath1 := cm.LowerString(newPath) + wasmimport_DescriptorSymlinkAt((uint32)(self0), (*uint8)(oldPath0), (uint32)(oldPath1), (*uint8)(newPath0), (uint32)(newPath1), &result) + return +} + +// Sync represents the imported method "sync". +// +// sync: func() -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) Sync() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorSync((uint32)(self0), &result) + return +} + +// SyncData represents the imported method "sync-data". +// +// sync-data: func() -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) SyncData() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DescriptorSyncData((uint32)(self0), &result) + return +} + +// UnlinkFileAt represents the imported method "unlink-file-at". +// +// unlink-file-at: func(path: string) -> result<_, error-code> +// +//go:nosplit +func (self Descriptor) UnlinkFileAt(path string) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + path0, path1 := cm.LowerString(path) + wasmimport_DescriptorUnlinkFileAt((uint32)(self0), (*uint8)(path0), (uint32)(path1), &result) + return +} + +// Write represents the imported method "write". +// +// write: func(buffer: list, offset: filesize) -> result +// +//go:nosplit +func (self Descriptor) Write(buffer cm.List[uint8], offset FileSize) (result cm.Result[uint64, FileSize, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + buffer0, buffer1 := cm.LowerList(buffer) + offset0 := (uint64)(offset) + wasmimport_DescriptorWrite((uint32)(self0), (*uint8)(buffer0), (uint32)(buffer1), (uint64)(offset0), &result) + return +} + +// WriteViaStream represents the imported method "write-via-stream". +// +// write-via-stream: func(offset: filesize) -> result +// +//go:nosplit +func (self Descriptor) WriteViaStream(offset FileSize) (result cm.Result[OutputStream, OutputStream, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + offset0 := (uint64)(offset) + wasmimport_DescriptorWriteViaStream((uint32)(self0), (uint64)(offset0), &result) + return +} + +// DirectoryEntryStream represents the imported resource "wasi:filesystem/types@0.2.0#directory-entry-stream". +// +// resource directory-entry-stream +type DirectoryEntryStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "directory-entry-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self DirectoryEntryStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DirectoryEntryStreamResourceDrop((uint32)(self0)) + return +} + +// ReadDirectoryEntry represents the imported method "read-directory-entry". +// +// read-directory-entry: func() -> result, error-code> +// +//go:nosplit +func (self DirectoryEntryStream) ReadDirectoryEntry() (result cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_DirectoryEntryStreamReadDirectoryEntry((uint32)(self0), &result) + return +} + +// FilesystemErrorCode represents the imported function "filesystem-error-code". +// +// filesystem-error-code: func(err: borrow) -> option +// +//go:nosplit +func FilesystemErrorCode(err Error) (result cm.Option[ErrorCode]) { + err0 := cm.Reinterpret[uint32](err) + wasmimport_FilesystemErrorCode((uint32)(err0), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wasm.go new file mode 100644 index 0000000..e254b5d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package ioerror + +// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0". + +//go:wasmimport wasi:io/error@0.2.0 [resource-drop]error +//go:noescape +func wasmimport_ErrorResourceDrop(self0 uint32) + +//go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string +//go:noescape +func wasmimport_ErrorToDebugString(self0 uint32, result *string) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wit.go new file mode 100644 index 0000000..828e977 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/error/error.wit.go @@ -0,0 +1,35 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package ioerror represents the imported interface "wasi:io/error@0.2.0". +package ioerror + +import ( + "go.bytecodealliance.org/cm" +) + +// Error represents the imported resource "wasi:io/error@0.2.0#error". +// +// resource error +type Error cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "error". +// +// Drops a resource handle. +// +//go:nosplit +func (self Error) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_ErrorResourceDrop((uint32)(self0)) + return +} + +// ToDebugString represents the imported method "to-debug-string". +// +// to-debug-string: func() -> string +// +//go:nosplit +func (self Error) ToDebugString() (result string) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_ErrorToDebugString((uint32)(self0), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wasm.go new file mode 100644 index 0000000..f7c55c3 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wasm.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package poll + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0". + +//go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable +//go:noescape +func wasmimport_PollableResourceDrop(self0 uint32) + +//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block +//go:noescape +func wasmimport_PollableBlock(self0 uint32) + +//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready +//go:noescape +func wasmimport_PollableReady(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:io/poll@0.2.0 poll +//go:noescape +func wasmimport_Poll(in0 *Pollable, in1 uint32, result *cm.List[uint32]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wit.go new file mode 100644 index 0000000..ad9e956 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/poll/poll.wit.go @@ -0,0 +1,58 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package poll represents the imported interface "wasi:io/poll@0.2.0". +package poll + +import ( + "go.bytecodealliance.org/cm" +) + +// Pollable represents the imported resource "wasi:io/poll@0.2.0#pollable". +// +// resource pollable +type Pollable cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "pollable". +// +// Drops a resource handle. +// +//go:nosplit +func (self Pollable) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_PollableResourceDrop((uint32)(self0)) + return +} + +// Block represents the imported method "block". +// +// block: func() +// +//go:nosplit +func (self Pollable) Block() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_PollableBlock((uint32)(self0)) + return +} + +// Ready represents the imported method "ready". +// +// ready: func() -> bool +// +//go:nosplit +func (self Pollable) Ready() (result bool) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_PollableReady((uint32)(self0)) + result = (bool)(cm.U32ToBool((uint32)(result0))) + return +} + +// Poll represents the imported function "poll". +// +// poll: func(in: list>) -> list +// +//go:nosplit +func Poll(in cm.List[Pollable]) (result cm.List[uint32]) { + in0, in1 := cm.LowerList(in) + wasmimport_Poll((*Pollable)(in0), (uint32)(in1), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wasm.go new file mode 100644 index 0000000..eec5664 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wasm.go @@ -0,0 +1,77 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package streams + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0". + +//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]input-stream +//go:noescape +func wasmimport_InputStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-read +//go:noescape +func wasmimport_InputStreamBlockingRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-skip +//go:noescape +func wasmimport_InputStreamBlockingSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.read +//go:noescape +func wasmimport_InputStreamRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.skip +//go:noescape +func wasmimport_InputStreamSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.subscribe +//go:noescape +func wasmimport_InputStreamSubscribe(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]output-stream +//go:noescape +func wasmimport_OutputStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-flush +//go:noescape +func wasmimport_OutputStreamBlockingFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-splice +//go:noescape +func wasmimport_OutputStreamBlockingSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-and-flush +//go:noescape +func wasmimport_OutputStreamBlockingWriteAndFlush(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-zeroes-and-flush +//go:noescape +func wasmimport_OutputStreamBlockingWriteZeroesAndFlush(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.check-write +//go:noescape +func wasmimport_OutputStreamCheckWrite(self0 uint32, result *cm.Result[uint64, uint64, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.flush +//go:noescape +func wasmimport_OutputStreamFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.splice +//go:noescape +func wasmimport_OutputStreamSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.subscribe +//go:noescape +func wasmimport_OutputStreamSubscribe(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write +//go:noescape +func wasmimport_OutputStreamWrite(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError]) + +//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write-zeroes +//go:noescape +func wasmimport_OutputStreamWriteZeroes(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wit.go new file mode 100644 index 0000000..d8dbf4e --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/io/streams/streams.wit.go @@ -0,0 +1,270 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package streams represents the imported interface "wasi:io/streams@0.2.0". +package streams + +import ( + "go.bytecodealliance.org/cm" + ioerror "sdk.com/internal/wasi/io/error" + "sdk.com/internal/wasi/io/poll" +) + +// Error represents the imported type alias "wasi:io/streams@0.2.0#error". +// +// See [ioerror.Error] for more information. +type Error = ioerror.Error + +// Pollable represents the imported type alias "wasi:io/streams@0.2.0#pollable". +// +// See [poll.Pollable] for more information. +type Pollable = poll.Pollable + +// StreamError represents the imported variant "wasi:io/streams@0.2.0#stream-error". +// +// variant stream-error { +// last-operation-failed(error), +// closed, +// } +type StreamError cm.Variant[uint8, Error, Error] + +// StreamErrorLastOperationFailed returns a [StreamError] of case "last-operation-failed". +func StreamErrorLastOperationFailed(data Error) StreamError { + return cm.New[StreamError](0, data) +} + +// LastOperationFailed returns a non-nil *[Error] if [StreamError] represents the variant case "last-operation-failed". +func (self *StreamError) LastOperationFailed() *Error { + return cm.Case[Error](self, 0) +} + +// StreamErrorClosed returns a [StreamError] of case "closed". +func StreamErrorClosed() StreamError { + var data struct{} + return cm.New[StreamError](1, data) +} + +// Closed returns true if [StreamError] represents the variant case "closed". +func (self *StreamError) Closed() bool { + return self.Tag() == 1 +} + +var _StreamErrorStrings = [2]string{ + "last-operation-failed", + "closed", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v StreamError) String() string { + return _StreamErrorStrings[v.Tag()] +} + +// InputStream represents the imported resource "wasi:io/streams@0.2.0#input-stream". +// +// resource input-stream +type InputStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "input-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self InputStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_InputStreamResourceDrop((uint32)(self0)) + return +} + +// BlockingRead represents the imported method "blocking-read". +// +// blocking-read: func(len: u64) -> result, stream-error> +// +//go:nosplit +func (self InputStream) BlockingRead(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_InputStreamBlockingRead((uint32)(self0), (uint64)(len0), &result) + return +} + +// BlockingSkip represents the imported method "blocking-skip". +// +// blocking-skip: func(len: u64) -> result +// +//go:nosplit +func (self InputStream) BlockingSkip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_InputStreamBlockingSkip((uint32)(self0), (uint64)(len0), &result) + return +} + +// Read represents the imported method "read". +// +// read: func(len: u64) -> result, stream-error> +// +//go:nosplit +func (self InputStream) Read(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_InputStreamRead((uint32)(self0), (uint64)(len0), &result) + return +} + +// Skip represents the imported method "skip". +// +// skip: func(len: u64) -> result +// +//go:nosplit +func (self InputStream) Skip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_InputStreamSkip((uint32)(self0), (uint64)(len0), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self InputStream) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_InputStreamSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// OutputStream represents the imported resource "wasi:io/streams@0.2.0#output-stream". +// +// resource output-stream +type OutputStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "output-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self OutputStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutputStreamResourceDrop((uint32)(self0)) + return +} + +// BlockingFlush represents the imported method "blocking-flush". +// +// blocking-flush: func() -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) BlockingFlush() (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutputStreamBlockingFlush((uint32)(self0), &result) + return +} + +// BlockingSplice represents the imported method "blocking-splice". +// +// blocking-splice: func(src: borrow, len: u64) -> result +// +//go:nosplit +func (self OutputStream) BlockingSplice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + src0 := cm.Reinterpret[uint32](src) + len0 := (uint64)(len_) + wasmimport_OutputStreamBlockingSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &result) + return +} + +// BlockingWriteAndFlush represents the imported method "blocking-write-and-flush". +// +// blocking-write-and-flush: func(contents: list) -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) BlockingWriteAndFlush(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + contents0, contents1 := cm.LowerList(contents) + wasmimport_OutputStreamBlockingWriteAndFlush((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &result) + return +} + +// BlockingWriteZeroesAndFlush represents the imported method "blocking-write-zeroes-and-flush". +// +// blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) BlockingWriteZeroesAndFlush(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_OutputStreamBlockingWriteZeroesAndFlush((uint32)(self0), (uint64)(len0), &result) + return +} + +// CheckWrite represents the imported method "check-write". +// +// check-write: func() -> result +// +//go:nosplit +func (self OutputStream) CheckWrite() (result cm.Result[uint64, uint64, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutputStreamCheckWrite((uint32)(self0), &result) + return +} + +// Flush represents the imported method "flush". +// +// flush: func() -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) Flush() (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutputStreamFlush((uint32)(self0), &result) + return +} + +// Splice represents the imported method "splice". +// +// splice: func(src: borrow, len: u64) -> result +// +//go:nosplit +func (self OutputStream) Splice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + src0 := cm.Reinterpret[uint32](src) + len0 := (uint64)(len_) + wasmimport_OutputStreamSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self OutputStream) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_OutputStreamSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// Write represents the imported method "write". +// +// write: func(contents: list) -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) Write(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + contents0, contents1 := cm.LowerList(contents) + wasmimport_OutputStreamWrite((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &result) + return +} + +// WriteZeroes represents the imported method "write-zeroes". +// +// write-zeroes: func(len: u64) -> result<_, stream-error> +// +//go:nosplit +func (self OutputStream) WriteZeroes(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) { + self0 := cm.Reinterpret[uint32](self) + len0 := (uint64)(len_) + wasmimport_OutputStreamWriteZeroes((uint32)(self0), (uint64)(len0), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wasm.go new file mode 100644 index 0000000..e94356d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package insecureseed + +// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". + +//go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed +//go:noescape +func wasmimport_InsecureSeed(result *[2]uint64) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wit.go new file mode 100644 index 0000000..e701d1b --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure-seed/insecure-seed.wit.go @@ -0,0 +1,14 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package insecureseed represents the imported interface "wasi:random/insecure-seed@0.2.0". +package insecureseed + +// InsecureSeed represents the imported function "insecure-seed". +// +// insecure-seed: func() -> tuple +// +//go:nosplit +func InsecureSeed() (result [2]uint64) { + wasmimport_InsecureSeed(&result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wasm.go new file mode 100644 index 0000000..498bfe4 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wasm.go @@ -0,0 +1,17 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package insecure + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". + +//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes +//go:noescape +func wasmimport_GetInsecureRandomBytes(len0 uint64, result *cm.List[uint8]) + +//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64 +//go:noescape +func wasmimport_GetInsecureRandomU64() (result0 uint64) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wit.go new file mode 100644 index 0000000..f32282c --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/insecure/insecure.wit.go @@ -0,0 +1,30 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package insecure represents the imported interface "wasi:random/insecure@0.2.0". +package insecure + +import ( + "go.bytecodealliance.org/cm" +) + +// GetInsecureRandomBytes represents the imported function "get-insecure-random-bytes". +// +// get-insecure-random-bytes: func(len: u64) -> list +// +//go:nosplit +func GetInsecureRandomBytes(len_ uint64) (result cm.List[uint8]) { + len0 := (uint64)(len_) + wasmimport_GetInsecureRandomBytes((uint64)(len0), &result) + return +} + +// GetInsecureRandomU64 represents the imported function "get-insecure-random-u64". +// +// get-insecure-random-u64: func() -> u64 +// +//go:nosplit +func GetInsecureRandomU64() (result uint64) { + result0 := wasmimport_GetInsecureRandomU64() + result = (uint64)((uint64)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wasm.go new file mode 100644 index 0000000..9096457 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wasm.go @@ -0,0 +1,17 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package random + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0". + +//go:wasmimport wasi:random/random@0.2.0 get-random-bytes +//go:noescape +func wasmimport_GetRandomBytes(len0 uint64, result *cm.List[uint8]) + +//go:wasmimport wasi:random/random@0.2.0 get-random-u64 +//go:noescape +func wasmimport_GetRandomU64() (result0 uint64) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wit.go new file mode 100644 index 0000000..98bb777 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/random/random/random.wit.go @@ -0,0 +1,30 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package random represents the imported interface "wasi:random/random@0.2.0". +package random + +import ( + "go.bytecodealliance.org/cm" +) + +// GetRandomBytes represents the imported function "get-random-bytes". +// +// get-random-bytes: func(len: u64) -> list +// +//go:nosplit +func GetRandomBytes(len_ uint64) (result cm.List[uint8]) { + len0 := (uint64)(len_) + wasmimport_GetRandomBytes((uint64)(len0), &result) + return +} + +// GetRandomU64 represents the imported function "get-random-u64". +// +// get-random-u64: func() -> u64 +// +//go:nosplit +func GetRandomU64() (result uint64) { + result0 := wasmimport_GetRandomU64() + result = (uint64)((uint64)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wasm.go new file mode 100644 index 0000000..eb113e2 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package instancenetwork + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/instance-network@0.2.0 instance-network +//go:noescape +func wasmimport_InstanceNetwork() (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wit.go new file mode 100644 index 0000000..39068c6 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/instance-network/instance-network.wit.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package instancenetwork represents the imported interface "wasi:sockets/instance-network@0.2.0". +package instancenetwork + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/sockets/network" +) + +// Network represents the imported type alias "wasi:sockets/instance-network@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// InstanceNetwork represents the imported function "instance-network". +// +// instance-network: func() -> network +// +//go:nosplit +func InstanceNetwork() (result Network) { + result0 := wasmimport_InstanceNetwork() + result = cm.Reinterpret[Network]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/abi.go new file mode 100644 index 0000000..a63f0d0 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/abi.go @@ -0,0 +1,14 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package ipnamelookup + +import ( + "go.bytecodealliance.org/cm" + "unsafe" +) + +// OptionIPAddressShape is used for storage in variant or result types. +type OptionIPAddressShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Option[IPAddress]{})]byte +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wasm.go new file mode 100644 index 0000000..da5fb00 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wasm.go @@ -0,0 +1,25 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package ipnamelookup + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [resource-drop]resolve-address-stream +//go:noescape +func wasmimport_ResolveAddressStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.resolve-next-address +//go:noescape +func wasmimport_ResolveAddressStreamResolveNextAddress(self0 uint32, result *cm.Result[OptionIPAddressShape, cm.Option[IPAddress], ErrorCode]) + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.subscribe +//go:noescape +func wasmimport_ResolveAddressStreamSubscribe(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 resolve-addresses +//go:noescape +func wasmimport_ResolveAddresses(network0 uint32, name0 *uint8, name1 uint32, result *cm.Result[ResolveAddressStream, ResolveAddressStream, ErrorCode]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wit.go new file mode 100644 index 0000000..bd49a6a --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/ip-name-lookup/ip-name-lookup.wit.go @@ -0,0 +1,82 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package ipnamelookup represents the imported interface "wasi:sockets/ip-name-lookup@0.2.0". +package ipnamelookup + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/poll" + "sdk.com/internal/wasi/sockets/network" +) + +// Pollable represents the imported type alias "wasi:sockets/ip-name-lookup@0.2.0#pollable". +// +// See [poll.Pollable] for more information. +type Pollable = poll.Pollable + +// Network represents the imported type alias "wasi:sockets/ip-name-lookup@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// ErrorCode represents the type alias "wasi:sockets/ip-name-lookup@0.2.0#error-code". +// +// See [network.ErrorCode] for more information. +type ErrorCode = network.ErrorCode + +// IPAddress represents the type alias "wasi:sockets/ip-name-lookup@0.2.0#ip-address". +// +// See [network.IPAddress] for more information. +type IPAddress = network.IPAddress + +// ResolveAddressStream represents the imported resource "wasi:sockets/ip-name-lookup@0.2.0#resolve-address-stream". +// +// resource resolve-address-stream +type ResolveAddressStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "resolve-address-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self ResolveAddressStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_ResolveAddressStreamResourceDrop((uint32)(self0)) + return +} + +// ResolveNextAddress represents the imported method "resolve-next-address". +// +// resolve-next-address: func() -> result, error-code> +// +//go:nosplit +func (self ResolveAddressStream) ResolveNextAddress() (result cm.Result[OptionIPAddressShape, cm.Option[IPAddress], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_ResolveAddressStreamResolveNextAddress((uint32)(self0), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self ResolveAddressStream) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_ResolveAddressStreamSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// ResolveAddresses represents the imported function "resolve-addresses". +// +// resolve-addresses: func(network: borrow, name: string) -> result +// +//go:nosplit +func ResolveAddresses(network_ Network, name string) (result cm.Result[ResolveAddressStream, ResolveAddressStream, ErrorCode]) { + network0 := cm.Reinterpret[uint32](network_) + name0, name1 := cm.LowerString(name) + wasmimport_ResolveAddresses((uint32)(network0), (*uint8)(name0), (uint32)(name1), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/abi.go new file mode 100644 index 0000000..248787a --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/abi.go @@ -0,0 +1,20 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package network + +import ( + "go.bytecodealliance.org/cm" + "unsafe" +) + +// IPv6AddressShape is used for storage in variant or result types. +type IPv6AddressShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(IPv6Address{})]byte +} + +// IPv6SocketAddressShape is used for storage in variant or result types. +type IPv6SocketAddressShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(IPv6SocketAddress{})]byte +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wasm.go new file mode 100644 index 0000000..012a79f --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wasm.go @@ -0,0 +1,9 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package network + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/network@0.2.0 [resource-drop]network +//go:noescape +func wasmimport_NetworkResourceDrop(self0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wit.go new file mode 100644 index 0000000..8d61db8 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/network/network.wit.go @@ -0,0 +1,267 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package network represents the imported interface "wasi:sockets/network@0.2.0". +package network + +import ( + "go.bytecodealliance.org/cm" +) + +// Network represents the imported resource "wasi:sockets/network@0.2.0#network". +// +// resource network +type Network cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "network". +// +// Drops a resource handle. +// +//go:nosplit +func (self Network) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_NetworkResourceDrop((uint32)(self0)) + return +} + +// ErrorCode represents the enum "wasi:sockets/network@0.2.0#error-code". +// +// enum error-code { +// unknown, +// access-denied, +// not-supported, +// invalid-argument, +// out-of-memory, +// timeout, +// concurrency-conflict, +// not-in-progress, +// would-block, +// invalid-state, +// new-socket-limit, +// address-not-bindable, +// address-in-use, +// remote-unreachable, +// connection-refused, +// connection-reset, +// connection-aborted, +// datagram-too-large, +// name-unresolvable, +// temporary-resolver-failure, +// permanent-resolver-failure +// } +type ErrorCode uint8 + +const ( + ErrorCodeUnknown ErrorCode = iota + ErrorCodeAccessDenied + ErrorCodeNotSupported + ErrorCodeInvalidArgument + ErrorCodeOutOfMemory + ErrorCodeTimeout + ErrorCodeConcurrencyConflict + ErrorCodeNotInProgress + ErrorCodeWouldBlock + ErrorCodeInvalidState + ErrorCodeNewSocketLimit + ErrorCodeAddressNotBindable + ErrorCodeAddressInUse + ErrorCodeRemoteUnreachable + ErrorCodeConnectionRefused + ErrorCodeConnectionReset + ErrorCodeConnectionAborted + ErrorCodeDatagramTooLarge + ErrorCodeNameUnresolvable + ErrorCodeTemporaryResolverFailure + ErrorCodePermanentResolverFailure +) + +var _ErrorCodeStrings = [21]string{ + "unknown", + "access-denied", + "not-supported", + "invalid-argument", + "out-of-memory", + "timeout", + "concurrency-conflict", + "not-in-progress", + "would-block", + "invalid-state", + "new-socket-limit", + "address-not-bindable", + "address-in-use", + "remote-unreachable", + "connection-refused", + "connection-reset", + "connection-aborted", + "datagram-too-large", + "name-unresolvable", + "temporary-resolver-failure", + "permanent-resolver-failure", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e ErrorCode) String() string { + return _ErrorCodeStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e ErrorCode) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *ErrorCode) UnmarshalText(text []byte) error { + return _ErrorCodeUnmarshalCase(e, text) +} + +var _ErrorCodeUnmarshalCase = cm.CaseUnmarshaler[ErrorCode](_ErrorCodeStrings[:]) + +// IPAddressFamily represents the enum "wasi:sockets/network@0.2.0#ip-address-family". +// +// enum ip-address-family { +// ipv4, +// ipv6 +// } +type IPAddressFamily uint8 + +const ( + IPAddressFamilyIPv4 IPAddressFamily = iota + IPAddressFamilyIPv6 +) + +var _IPAddressFamilyStrings = [2]string{ + "ipv4", + "ipv6", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e IPAddressFamily) String() string { + return _IPAddressFamilyStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e IPAddressFamily) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *IPAddressFamily) UnmarshalText(text []byte) error { + return _IPAddressFamilyUnmarshalCase(e, text) +} + +var _IPAddressFamilyUnmarshalCase = cm.CaseUnmarshaler[IPAddressFamily](_IPAddressFamilyStrings[:]) + +// IPv4Address represents the tuple "wasi:sockets/network@0.2.0#ipv4-address". +// +// type ipv4-address = tuple +type IPv4Address [4]uint8 + +// IPv6Address represents the tuple "wasi:sockets/network@0.2.0#ipv6-address". +// +// type ipv6-address = tuple +type IPv6Address [8]uint16 + +// IPAddress represents the variant "wasi:sockets/network@0.2.0#ip-address". +// +// variant ip-address { +// ipv4(ipv4-address), +// ipv6(ipv6-address), +// } +type IPAddress cm.Variant[uint8, IPv6AddressShape, IPv6Address] + +// IPAddressIPv4 returns a [IPAddress] of case "ipv4". +func IPAddressIPv4(data IPv4Address) IPAddress { + return cm.New[IPAddress](0, data) +} + +// IPv4 returns a non-nil *[IPv4Address] if [IPAddress] represents the variant case "ipv4". +func (self *IPAddress) IPv4() *IPv4Address { + return cm.Case[IPv4Address](self, 0) +} + +// IPAddressIPv6 returns a [IPAddress] of case "ipv6". +func IPAddressIPv6(data IPv6Address) IPAddress { + return cm.New[IPAddress](1, data) +} + +// IPv6 returns a non-nil *[IPv6Address] if [IPAddress] represents the variant case "ipv6". +func (self *IPAddress) IPv6() *IPv6Address { + return cm.Case[IPv6Address](self, 1) +} + +var _IPAddressStrings = [2]string{ + "ipv4", + "ipv6", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v IPAddress) String() string { + return _IPAddressStrings[v.Tag()] +} + +// IPv4SocketAddress represents the record "wasi:sockets/network@0.2.0#ipv4-socket-address". +// +// record ipv4-socket-address { +// port: u16, +// address: ipv4-address, +// } +type IPv4SocketAddress struct { + _ cm.HostLayout `json:"-"` + Port uint16 `json:"port"` + Address IPv4Address `json:"address"` +} + +// IPv6SocketAddress represents the record "wasi:sockets/network@0.2.0#ipv6-socket-address". +// +// record ipv6-socket-address { +// port: u16, +// flow-info: u32, +// address: ipv6-address, +// scope-id: u32, +// } +type IPv6SocketAddress struct { + _ cm.HostLayout `json:"-"` + Port uint16 `json:"port"` + FlowInfo uint32 `json:"flow-info"` + Address IPv6Address `json:"address"` + ScopeID uint32 `json:"scope-id"` +} + +// IPSocketAddress represents the variant "wasi:sockets/network@0.2.0#ip-socket-address". +// +// variant ip-socket-address { +// ipv4(ipv4-socket-address), +// ipv6(ipv6-socket-address), +// } +type IPSocketAddress cm.Variant[uint8, IPv6SocketAddressShape, IPv6SocketAddress] + +// IPSocketAddressIPv4 returns a [IPSocketAddress] of case "ipv4". +func IPSocketAddressIPv4(data IPv4SocketAddress) IPSocketAddress { + return cm.New[IPSocketAddress](0, data) +} + +// IPv4 returns a non-nil *[IPv4SocketAddress] if [IPSocketAddress] represents the variant case "ipv4". +func (self *IPSocketAddress) IPv4() *IPv4SocketAddress { + return cm.Case[IPv4SocketAddress](self, 0) +} + +// IPSocketAddressIPv6 returns a [IPSocketAddress] of case "ipv6". +func IPSocketAddressIPv6(data IPv6SocketAddress) IPSocketAddress { + return cm.New[IPSocketAddress](1, data) +} + +// IPv6 returns a non-nil *[IPv6SocketAddress] if [IPSocketAddress] represents the variant case "ipv6". +func (self *IPSocketAddress) IPv6() *IPv6SocketAddress { + return cm.Case[IPv6SocketAddress](self, 1) +} + +var _IPSocketAddressStrings = [2]string{ + "ipv4", + "ipv6", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v IPSocketAddress) String() string { + return _IPSocketAddressStrings[v.Tag()] +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wasm.go new file mode 100644 index 0000000..b7b4315 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package tcpcreatesocket + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/tcp-create-socket@0.2.0 create-tcp-socket +//go:noescape +func wasmimport_CreateTCPSocket(addressFamily0 uint32, result *cm.Result[TCPSocket, TCPSocket, ErrorCode]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wit.go new file mode 100644 index 0000000..987f2a0 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp-create-socket/tcp-create-socket.wit.go @@ -0,0 +1,42 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package tcpcreatesocket represents the imported interface "wasi:sockets/tcp-create-socket@0.2.0". +package tcpcreatesocket + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/sockets/network" + "sdk.com/internal/wasi/sockets/tcp" +) + +// Network represents the imported type alias "wasi:sockets/tcp-create-socket@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// ErrorCode represents the type alias "wasi:sockets/tcp-create-socket@0.2.0#error-code". +// +// See [network.ErrorCode] for more information. +type ErrorCode = network.ErrorCode + +// IPAddressFamily represents the type alias "wasi:sockets/tcp-create-socket@0.2.0#ip-address-family". +// +// See [network.IPAddressFamily] for more information. +type IPAddressFamily = network.IPAddressFamily + +// TCPSocket represents the imported type alias "wasi:sockets/tcp-create-socket@0.2.0#tcp-socket". +// +// See [tcp.TCPSocket] for more information. +type TCPSocket = tcp.TCPSocket + +// CreateTCPSocket represents the imported function "create-tcp-socket". +// +// create-tcp-socket: func(address-family: ip-address-family) -> result +// +//go:nosplit +func CreateTCPSocket(addressFamily IPAddressFamily) (result cm.Result[TCPSocket, TCPSocket, ErrorCode]) { + addressFamily0 := (uint32)(addressFamily) + wasmimport_CreateTCPSocket((uint32)(addressFamily0), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/abi.go new file mode 100644 index 0000000..8996a53 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/abi.go @@ -0,0 +1,88 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package tcp + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/sockets/network" + "unsafe" +) + +// TupleTCPSocketInputStreamOutputStreamShape is used for storage in variant or result types. +type TupleTCPSocketInputStreamOutputStreamShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Tuple3[TCPSocket, InputStream, OutputStream]{})]byte +} + +// TupleInputStreamOutputStreamShape is used for storage in variant or result types. +type TupleInputStreamOutputStreamShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Tuple[InputStream, OutputStream]{})]byte +} + +// IPSocketAddressShape is used for storage in variant or result types. +type IPSocketAddressShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(IPSocketAddress{})]byte +} + +func lower_IPv4Address(v network.IPv4Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32) { + f0 = (uint32)(v[0]) + f1 = (uint32)(v[1]) + f2 = (uint32)(v[2]) + f3 = (uint32)(v[3]) + return +} + +func lower_IPv4SocketAddress(v network.IPv4SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32) { + f0 = (uint32)(v.Port) + f1, f2, f3, f4 = lower_IPv4Address(v.Address) + return +} + +func lower_IPv6Address(v network.IPv6Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32) { + f0 = (uint32)(v[0]) + f1 = (uint32)(v[1]) + f2 = (uint32)(v[2]) + f3 = (uint32)(v[3]) + f4 = (uint32)(v[4]) + f5 = (uint32)(v[5]) + f6 = (uint32)(v[6]) + f7 = (uint32)(v[7]) + return +} + +func lower_IPv6SocketAddress(v network.IPv6SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32) { + f0 = (uint32)(v.Port) + f1 = (uint32)(v.FlowInfo) + f2, f3, f4, f5, f6, f7, f8, f9 = lower_IPv6Address(v.Address) + f10 = (uint32)(v.ScopeID) + return +} + +func lower_IPSocketAddress(v network.IPSocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32) { + f0 = (uint32)(v.Tag()) + switch f0 { + case 0: // ipv4 + v1, v2, v3, v4, v5 := lower_IPv4SocketAddress(*cm.Case[network.IPv4SocketAddress](&v, 0)) + f1 = (uint32)(v1) + f2 = (uint32)(v2) + f3 = (uint32)(v3) + f4 = (uint32)(v4) + f5 = (uint32)(v5) + case 1: // ipv6 + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 := lower_IPv6SocketAddress(*cm.Case[network.IPv6SocketAddress](&v, 1)) + f1 = (uint32)(v1) + f2 = (uint32)(v2) + f3 = (uint32)(v3) + f4 = (uint32)(v4) + f5 = (uint32)(v5) + f6 = (uint32)(v6) + f7 = (uint32)(v7) + f8 = (uint32)(v8) + f9 = (uint32)(v9) + f10 = (uint32)(v10) + f11 = (uint32)(v11) + } + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wasm.go new file mode 100644 index 0000000..d6e56c2 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wasm.go @@ -0,0 +1,125 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package tcp + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/tcp@0.2.0 [resource-drop]tcp-socket +//go:noescape +func wasmimport_TCPSocketResourceDrop(self0 uint32) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.accept +//go:noescape +func wasmimport_TCPSocketAccept(self0 uint32, result *cm.Result[TupleTCPSocketInputStreamOutputStreamShape, cm.Tuple3[TCPSocket, InputStream, OutputStream], ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.address-family +//go:noescape +func wasmimport_TCPSocketAddressFamily(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-bind +//go:noescape +func wasmimport_TCPSocketFinishBind(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-connect +//go:noescape +func wasmimport_TCPSocketFinishConnect(self0 uint32, result *cm.Result[TupleInputStreamOutputStreamShape, cm.Tuple[InputStream, OutputStream], ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.finish-listen +//go:noescape +func wasmimport_TCPSocketFinishListen(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.hop-limit +//go:noescape +func wasmimport_TCPSocketHopLimit(self0 uint32, result *cm.Result[uint8, uint8, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.is-listening +//go:noescape +func wasmimport_TCPSocketIsListening(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-count +//go:noescape +func wasmimport_TCPSocketKeepAliveCount(self0 uint32, result *cm.Result[uint32, uint32, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-enabled +//go:noescape +func wasmimport_TCPSocketKeepAliveEnabled(self0 uint32, result *cm.Result[ErrorCode, bool, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-idle-time +//go:noescape +func wasmimport_TCPSocketKeepAliveIdleTime(self0 uint32, result *cm.Result[uint64, Duration, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.keep-alive-interval +//go:noescape +func wasmimport_TCPSocketKeepAliveInterval(self0 uint32, result *cm.Result[uint64, Duration, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.local-address +//go:noescape +func wasmimport_TCPSocketLocalAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.receive-buffer-size +//go:noescape +func wasmimport_TCPSocketReceiveBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.remote-address +//go:noescape +func wasmimport_TCPSocketRemoteAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.send-buffer-size +//go:noescape +func wasmimport_TCPSocketSendBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-hop-limit +//go:noescape +func wasmimport_TCPSocketSetHopLimit(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-count +//go:noescape +func wasmimport_TCPSocketSetKeepAliveCount(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-enabled +//go:noescape +func wasmimport_TCPSocketSetKeepAliveEnabled(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-idle-time +//go:noescape +func wasmimport_TCPSocketSetKeepAliveIdleTime(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-keep-alive-interval +//go:noescape +func wasmimport_TCPSocketSetKeepAliveInterval(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-listen-backlog-size +//go:noescape +func wasmimport_TCPSocketSetListenBacklogSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-receive-buffer-size +//go:noescape +func wasmimport_TCPSocketSetReceiveBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.set-send-buffer-size +//go:noescape +func wasmimport_TCPSocketSetSendBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.shutdown +//go:noescape +func wasmimport_TCPSocketShutdown(self0 uint32, shutdownType0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-bind +//go:noescape +func wasmimport_TCPSocketStartBind(self0 uint32, network0 uint32, localAddress0 uint32, localAddress1 uint32, localAddress2 uint32, localAddress3 uint32, localAddress4 uint32, localAddress5 uint32, localAddress6 uint32, localAddress7 uint32, localAddress8 uint32, localAddress9 uint32, localAddress10 uint32, localAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-connect +//go:noescape +func wasmimport_TCPSocketStartConnect(self0 uint32, network0 uint32, remoteAddress0 uint32, remoteAddress1 uint32, remoteAddress2 uint32, remoteAddress3 uint32, remoteAddress4 uint32, remoteAddress5 uint32, remoteAddress6 uint32, remoteAddress7 uint32, remoteAddress8 uint32, remoteAddress9 uint32, remoteAddress10 uint32, remoteAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.start-listen +//go:noescape +func wasmimport_TCPSocketStartListen(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/tcp@0.2.0 [method]tcp-socket.subscribe +//go:noescape +func wasmimport_TCPSocketSubscribe(self0 uint32) (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wit.go new file mode 100644 index 0000000..eb70b48 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/tcp/tcp.wit.go @@ -0,0 +1,433 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package tcp represents the imported interface "wasi:sockets/tcp@0.2.0". +package tcp + +import ( + "go.bytecodealliance.org/cm" + monotonicclock "sdk.com/internal/wasi/clocks/monotonic-clock" + "sdk.com/internal/wasi/io/poll" + "sdk.com/internal/wasi/io/streams" + "sdk.com/internal/wasi/sockets/network" +) + +// InputStream represents the imported type alias "wasi:sockets/tcp@0.2.0#input-stream". +// +// See [streams.InputStream] for more information. +type InputStream = streams.InputStream + +// OutputStream represents the imported type alias "wasi:sockets/tcp@0.2.0#output-stream". +// +// See [streams.OutputStream] for more information. +type OutputStream = streams.OutputStream + +// Pollable represents the imported type alias "wasi:sockets/tcp@0.2.0#pollable". +// +// See [poll.Pollable] for more information. +type Pollable = poll.Pollable + +// Duration represents the type alias "wasi:sockets/tcp@0.2.0#duration". +// +// See [monotonicclock.Duration] for more information. +type Duration = monotonicclock.Duration + +// Network represents the imported type alias "wasi:sockets/tcp@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// ErrorCode represents the type alias "wasi:sockets/tcp@0.2.0#error-code". +// +// See [network.ErrorCode] for more information. +type ErrorCode = network.ErrorCode + +// IPSocketAddress represents the type alias "wasi:sockets/tcp@0.2.0#ip-socket-address". +// +// See [network.IPSocketAddress] for more information. +type IPSocketAddress = network.IPSocketAddress + +// IPAddressFamily represents the type alias "wasi:sockets/tcp@0.2.0#ip-address-family". +// +// See [network.IPAddressFamily] for more information. +type IPAddressFamily = network.IPAddressFamily + +// ShutdownType represents the enum "wasi:sockets/tcp@0.2.0#shutdown-type". +// +// enum shutdown-type { +// receive, +// send, +// both +// } +type ShutdownType uint8 + +const ( + ShutdownTypeReceive ShutdownType = iota + ShutdownTypeSend + ShutdownTypeBoth +) + +var _ShutdownTypeStrings = [3]string{ + "receive", + "send", + "both", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e ShutdownType) String() string { + return _ShutdownTypeStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e ShutdownType) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *ShutdownType) UnmarshalText(text []byte) error { + return _ShutdownTypeUnmarshalCase(e, text) +} + +var _ShutdownTypeUnmarshalCase = cm.CaseUnmarshaler[ShutdownType](_ShutdownTypeStrings[:]) + +// TCPSocket represents the imported resource "wasi:sockets/tcp@0.2.0#tcp-socket". +// +// resource tcp-socket +type TCPSocket cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "tcp-socket". +// +// Drops a resource handle. +// +//go:nosplit +func (self TCPSocket) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketResourceDrop((uint32)(self0)) + return +} + +// Accept represents the imported method "accept". +// +// accept: func() -> result, error-code> +// +//go:nosplit +func (self TCPSocket) Accept() (result cm.Result[TupleTCPSocketInputStreamOutputStreamShape, cm.Tuple3[TCPSocket, InputStream, OutputStream], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketAccept((uint32)(self0), &result) + return +} + +// AddressFamily represents the imported method "address-family". +// +// address-family: func() -> ip-address-family +// +//go:nosplit +func (self TCPSocket) AddressFamily() (result IPAddressFamily) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_TCPSocketAddressFamily((uint32)(self0)) + result = (network.IPAddressFamily)((uint32)(result0)) + return +} + +// FinishBind represents the imported method "finish-bind". +// +// finish-bind: func() -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) FinishBind() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketFinishBind((uint32)(self0), &result) + return +} + +// FinishConnect represents the imported method "finish-connect". +// +// finish-connect: func() -> result, error-code> +// +//go:nosplit +func (self TCPSocket) FinishConnect() (result cm.Result[TupleInputStreamOutputStreamShape, cm.Tuple[InputStream, OutputStream], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketFinishConnect((uint32)(self0), &result) + return +} + +// FinishListen represents the imported method "finish-listen". +// +// finish-listen: func() -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) FinishListen() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketFinishListen((uint32)(self0), &result) + return +} + +// HopLimit represents the imported method "hop-limit". +// +// hop-limit: func() -> result +// +//go:nosplit +func (self TCPSocket) HopLimit() (result cm.Result[uint8, uint8, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketHopLimit((uint32)(self0), &result) + return +} + +// IsListening represents the imported method "is-listening". +// +// is-listening: func() -> bool +// +//go:nosplit +func (self TCPSocket) IsListening() (result bool) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_TCPSocketIsListening((uint32)(self0)) + result = (bool)(cm.U32ToBool((uint32)(result0))) + return +} + +// KeepAliveCount represents the imported method "keep-alive-count". +// +// keep-alive-count: func() -> result +// +//go:nosplit +func (self TCPSocket) KeepAliveCount() (result cm.Result[uint32, uint32, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketKeepAliveCount((uint32)(self0), &result) + return +} + +// KeepAliveEnabled represents the imported method "keep-alive-enabled". +// +// keep-alive-enabled: func() -> result +// +//go:nosplit +func (self TCPSocket) KeepAliveEnabled() (result cm.Result[ErrorCode, bool, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketKeepAliveEnabled((uint32)(self0), &result) + return +} + +// KeepAliveIdleTime represents the imported method "keep-alive-idle-time". +// +// keep-alive-idle-time: func() -> result +// +//go:nosplit +func (self TCPSocket) KeepAliveIdleTime() (result cm.Result[uint64, Duration, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketKeepAliveIdleTime((uint32)(self0), &result) + return +} + +// KeepAliveInterval represents the imported method "keep-alive-interval". +// +// keep-alive-interval: func() -> result +// +//go:nosplit +func (self TCPSocket) KeepAliveInterval() (result cm.Result[uint64, Duration, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketKeepAliveInterval((uint32)(self0), &result) + return +} + +// LocalAddress represents the imported method "local-address". +// +// local-address: func() -> result +// +//go:nosplit +func (self TCPSocket) LocalAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketLocalAddress((uint32)(self0), &result) + return +} + +// ReceiveBufferSize represents the imported method "receive-buffer-size". +// +// receive-buffer-size: func() -> result +// +//go:nosplit +func (self TCPSocket) ReceiveBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketReceiveBufferSize((uint32)(self0), &result) + return +} + +// RemoteAddress represents the imported method "remote-address". +// +// remote-address: func() -> result +// +//go:nosplit +func (self TCPSocket) RemoteAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketRemoteAddress((uint32)(self0), &result) + return +} + +// SendBufferSize represents the imported method "send-buffer-size". +// +// send-buffer-size: func() -> result +// +//go:nosplit +func (self TCPSocket) SendBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketSendBufferSize((uint32)(self0), &result) + return +} + +// SetHopLimit represents the imported method "set-hop-limit". +// +// set-hop-limit: func(value: u8) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetHopLimit(value uint8) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint32)(value) + wasmimport_TCPSocketSetHopLimit((uint32)(self0), (uint32)(value0), &result) + return +} + +// SetKeepAliveCount represents the imported method "set-keep-alive-count". +// +// set-keep-alive-count: func(value: u32) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetKeepAliveCount(value uint32) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint32)(value) + wasmimport_TCPSocketSetKeepAliveCount((uint32)(self0), (uint32)(value0), &result) + return +} + +// SetKeepAliveEnabled represents the imported method "set-keep-alive-enabled". +// +// set-keep-alive-enabled: func(value: bool) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetKeepAliveEnabled(value bool) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint32)(cm.BoolToU32(value)) + wasmimport_TCPSocketSetKeepAliveEnabled((uint32)(self0), (uint32)(value0), &result) + return +} + +// SetKeepAliveIdleTime represents the imported method "set-keep-alive-idle-time". +// +// set-keep-alive-idle-time: func(value: duration) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetKeepAliveIdleTime(value Duration) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_TCPSocketSetKeepAliveIdleTime((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetKeepAliveInterval represents the imported method "set-keep-alive-interval". +// +// set-keep-alive-interval: func(value: duration) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetKeepAliveInterval(value Duration) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_TCPSocketSetKeepAliveInterval((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetListenBacklogSize represents the imported method "set-listen-backlog-size". +// +// set-listen-backlog-size: func(value: u64) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetListenBacklogSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_TCPSocketSetListenBacklogSize((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetReceiveBufferSize represents the imported method "set-receive-buffer-size". +// +// set-receive-buffer-size: func(value: u64) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetReceiveBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_TCPSocketSetReceiveBufferSize((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetSendBufferSize represents the imported method "set-send-buffer-size". +// +// set-send-buffer-size: func(value: u64) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) SetSendBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_TCPSocketSetSendBufferSize((uint32)(self0), (uint64)(value0), &result) + return +} + +// Shutdown represents the imported method "shutdown". +// +// shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) Shutdown(shutdownType ShutdownType) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + shutdownType0 := (uint32)(shutdownType) + wasmimport_TCPSocketShutdown((uint32)(self0), (uint32)(shutdownType0), &result) + return +} + +// StartBind represents the imported method "start-bind". +// +// start-bind: func(network: borrow, local-address: ip-socket-address) -> +// result<_, error-code> +// +//go:nosplit +func (self TCPSocket) StartBind(network_ Network, localAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + network0 := cm.Reinterpret[uint32](network_) + localAddress0, localAddress1, localAddress2, localAddress3, localAddress4, localAddress5, localAddress6, localAddress7, localAddress8, localAddress9, localAddress10, localAddress11 := lower_IPSocketAddress(localAddress) + wasmimport_TCPSocketStartBind((uint32)(self0), (uint32)(network0), (uint32)(localAddress0), (uint32)(localAddress1), (uint32)(localAddress2), (uint32)(localAddress3), (uint32)(localAddress4), (uint32)(localAddress5), (uint32)(localAddress6), (uint32)(localAddress7), (uint32)(localAddress8), (uint32)(localAddress9), (uint32)(localAddress10), (uint32)(localAddress11), &result) + return +} + +// StartConnect represents the imported method "start-connect". +// +// start-connect: func(network: borrow, remote-address: ip-socket-address) +// -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) StartConnect(network_ Network, remoteAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + network0 := cm.Reinterpret[uint32](network_) + remoteAddress0, remoteAddress1, remoteAddress2, remoteAddress3, remoteAddress4, remoteAddress5, remoteAddress6, remoteAddress7, remoteAddress8, remoteAddress9, remoteAddress10, remoteAddress11 := lower_IPSocketAddress(remoteAddress) + wasmimport_TCPSocketStartConnect((uint32)(self0), (uint32)(network0), (uint32)(remoteAddress0), (uint32)(remoteAddress1), (uint32)(remoteAddress2), (uint32)(remoteAddress3), (uint32)(remoteAddress4), (uint32)(remoteAddress5), (uint32)(remoteAddress6), (uint32)(remoteAddress7), (uint32)(remoteAddress8), (uint32)(remoteAddress9), (uint32)(remoteAddress10), (uint32)(remoteAddress11), &result) + return +} + +// StartListen represents the imported method "start-listen". +// +// start-listen: func() -> result<_, error-code> +// +//go:nosplit +func (self TCPSocket) StartListen() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_TCPSocketStartListen((uint32)(self0), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self TCPSocket) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_TCPSocketSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wasm.go new file mode 100644 index 0000000..94b1ab6 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package udpcreatesocket + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/udp-create-socket@0.2.0 create-udp-socket +//go:noescape +func wasmimport_CreateUDPSocket(addressFamily0 uint32, result *cm.Result[UDPSocket, UDPSocket, ErrorCode]) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wit.go new file mode 100644 index 0000000..59746b0 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp-create-socket/udp-create-socket.wit.go @@ -0,0 +1,42 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package udpcreatesocket represents the imported interface "wasi:sockets/udp-create-socket@0.2.0". +package udpcreatesocket + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/sockets/network" + "sdk.com/internal/wasi/sockets/udp" +) + +// Network represents the imported type alias "wasi:sockets/udp-create-socket@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// ErrorCode represents the type alias "wasi:sockets/udp-create-socket@0.2.0#error-code". +// +// See [network.ErrorCode] for more information. +type ErrorCode = network.ErrorCode + +// IPAddressFamily represents the type alias "wasi:sockets/udp-create-socket@0.2.0#ip-address-family". +// +// See [network.IPAddressFamily] for more information. +type IPAddressFamily = network.IPAddressFamily + +// UDPSocket represents the imported type alias "wasi:sockets/udp-create-socket@0.2.0#udp-socket". +// +// See [udp.UDPSocket] for more information. +type UDPSocket = udp.UDPSocket + +// CreateUDPSocket represents the imported function "create-udp-socket". +// +// create-udp-socket: func(address-family: ip-address-family) -> result +// +//go:nosplit +func CreateUDPSocket(addressFamily IPAddressFamily) (result cm.Result[UDPSocket, UDPSocket, ErrorCode]) { + addressFamily0 := (uint32)(addressFamily) + wasmimport_CreateUDPSocket((uint32)(addressFamily0), &result) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/abi.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/abi.go new file mode 100644 index 0000000..bc43585 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/abi.go @@ -0,0 +1,103 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package udp + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/sockets/network" + "unsafe" +) + +// IPSocketAddressShape is used for storage in variant or result types. +type IPSocketAddressShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(IPSocketAddress{})]byte +} + +func lower_IPv4Address(v network.IPv4Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32) { + f0 = (uint32)(v[0]) + f1 = (uint32)(v[1]) + f2 = (uint32)(v[2]) + f3 = (uint32)(v[3]) + return +} + +func lower_IPv4SocketAddress(v network.IPv4SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32) { + f0 = (uint32)(v.Port) + f1, f2, f3, f4 = lower_IPv4Address(v.Address) + return +} + +func lower_IPv6Address(v network.IPv6Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32) { + f0 = (uint32)(v[0]) + f1 = (uint32)(v[1]) + f2 = (uint32)(v[2]) + f3 = (uint32)(v[3]) + f4 = (uint32)(v[4]) + f5 = (uint32)(v[5]) + f6 = (uint32)(v[6]) + f7 = (uint32)(v[7]) + return +} + +func lower_IPv6SocketAddress(v network.IPv6SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32) { + f0 = (uint32)(v.Port) + f1 = (uint32)(v.FlowInfo) + f2, f3, f4, f5, f6, f7, f8, f9 = lower_IPv6Address(v.Address) + f10 = (uint32)(v.ScopeID) + return +} + +func lower_IPSocketAddress(v network.IPSocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32) { + f0 = (uint32)(v.Tag()) + switch f0 { + case 0: // ipv4 + v1, v2, v3, v4, v5 := lower_IPv4SocketAddress(*cm.Case[network.IPv4SocketAddress](&v, 0)) + f1 = (uint32)(v1) + f2 = (uint32)(v2) + f3 = (uint32)(v3) + f4 = (uint32)(v4) + f5 = (uint32)(v5) + case 1: // ipv6 + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 := lower_IPv6SocketAddress(*cm.Case[network.IPv6SocketAddress](&v, 1)) + f1 = (uint32)(v1) + f2 = (uint32)(v2) + f3 = (uint32)(v3) + f4 = (uint32)(v4) + f5 = (uint32)(v5) + f6 = (uint32)(v6) + f7 = (uint32)(v7) + f8 = (uint32)(v8) + f9 = (uint32)(v9) + f10 = (uint32)(v10) + f11 = (uint32)(v11) + } + return +} + +// TupleIncomingDatagramStreamOutgoingDatagramStreamShape is used for storage in variant or result types. +type TupleIncomingDatagramStreamOutgoingDatagramStreamShape struct { + _ cm.HostLayout + shape [unsafe.Sizeof(cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream]{})]byte +} + +func lower_OptionIPSocketAddress(v cm.Option[IPSocketAddress]) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32, f12 uint32) { + some := v.Some() + if some != nil { + f0 = 1 + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 := lower_IPSocketAddress(*some) + f1 = (uint32)(v1) + f2 = (uint32)(v2) + f3 = (uint32)(v3) + f4 = (uint32)(v4) + f5 = (uint32)(v5) + f6 = (uint32)(v6) + f7 = (uint32)(v7) + f8 = (uint32)(v8) + f9 = (uint32)(v9) + f10 = (uint32)(v10) + f11 = (uint32)(v11) + f12 = (uint32)(v12) + } + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/empty.s b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wasm.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wasm.go new file mode 100644 index 0000000..83ce8ca --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wasm.go @@ -0,0 +1,93 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package udp + +import ( + "go.bytecodealliance.org/cm" +) + +// This file contains wasmimport and wasmexport declarations for "wasi:sockets@0.2.0". + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]udp-socket +//go:noescape +func wasmimport_UDPSocketResourceDrop(self0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.address-family +//go:noescape +func wasmimport_UDPSocketAddressFamily(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.finish-bind +//go:noescape +func wasmimport_UDPSocketFinishBind(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.local-address +//go:noescape +func wasmimport_UDPSocketLocalAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.receive-buffer-size +//go:noescape +func wasmimport_UDPSocketReceiveBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.remote-address +//go:noescape +func wasmimport_UDPSocketRemoteAddress(self0 uint32, result *cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.send-buffer-size +//go:noescape +func wasmimport_UDPSocketSendBufferSize(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-receive-buffer-size +//go:noescape +func wasmimport_UDPSocketSetReceiveBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-send-buffer-size +//go:noescape +func wasmimport_UDPSocketSetSendBufferSize(self0 uint32, value0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.set-unicast-hop-limit +//go:noescape +func wasmimport_UDPSocketSetUnicastHopLimit(self0 uint32, value0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.start-bind +//go:noescape +func wasmimport_UDPSocketStartBind(self0 uint32, network0 uint32, localAddress0 uint32, localAddress1 uint32, localAddress2 uint32, localAddress3 uint32, localAddress4 uint32, localAddress5 uint32, localAddress6 uint32, localAddress7 uint32, localAddress8 uint32, localAddress9 uint32, localAddress10 uint32, localAddress11 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.stream +//go:noescape +func wasmimport_UDPSocketStream(self0 uint32, remoteAddress0 uint32, remoteAddress1 uint32, remoteAddress2 uint32, remoteAddress3 uint32, remoteAddress4 uint32, remoteAddress5 uint32, remoteAddress6 uint32, remoteAddress7 uint32, remoteAddress8 uint32, remoteAddress9 uint32, remoteAddress10 uint32, remoteAddress11 uint32, remoteAddress12 uint32, result *cm.Result[TupleIncomingDatagramStreamOutgoingDatagramStreamShape, cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream], ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.subscribe +//go:noescape +func wasmimport_UDPSocketSubscribe(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]udp-socket.unicast-hop-limit +//go:noescape +func wasmimport_UDPSocketUnicastHopLimit(self0 uint32, result *cm.Result[uint8, uint8, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]incoming-datagram-stream +//go:noescape +func wasmimport_IncomingDatagramStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.receive +//go:noescape +func wasmimport_IncomingDatagramStreamReceive(self0 uint32, maxResults0 uint64, result *cm.Result[cm.List[IncomingDatagram], cm.List[IncomingDatagram], ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]incoming-datagram-stream.subscribe +//go:noescape +func wasmimport_IncomingDatagramStreamSubscribe(self0 uint32) (result0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [resource-drop]outgoing-datagram-stream +//go:noescape +func wasmimport_OutgoingDatagramStreamResourceDrop(self0 uint32) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.check-send +//go:noescape +func wasmimport_OutgoingDatagramStreamCheckSend(self0 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.send +//go:noescape +func wasmimport_OutgoingDatagramStreamSend(self0 uint32, datagrams0 *OutgoingDatagram, datagrams1 uint32, result *cm.Result[uint64, uint64, ErrorCode]) + +//go:wasmimport wasi:sockets/udp@0.2.0 [method]outgoing-datagram-stream.subscribe +//go:noescape +func wasmimport_OutgoingDatagramStreamSubscribe(self0 uint32) (result0 uint32) diff --git a/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wit.go b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wit.go new file mode 100644 index 0000000..3bda4e6 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/internal/wasi/sockets/udp/udp.wit.go @@ -0,0 +1,319 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package udp represents the imported interface "wasi:sockets/udp@0.2.0". +package udp + +import ( + "go.bytecodealliance.org/cm" + "sdk.com/internal/wasi/io/poll" + "sdk.com/internal/wasi/sockets/network" +) + +// Pollable represents the imported type alias "wasi:sockets/udp@0.2.0#pollable". +// +// See [poll.Pollable] for more information. +type Pollable = poll.Pollable + +// Network represents the imported type alias "wasi:sockets/udp@0.2.0#network". +// +// See [network.Network] for more information. +type Network = network.Network + +// ErrorCode represents the type alias "wasi:sockets/udp@0.2.0#error-code". +// +// See [network.ErrorCode] for more information. +type ErrorCode = network.ErrorCode + +// IPSocketAddress represents the type alias "wasi:sockets/udp@0.2.0#ip-socket-address". +// +// See [network.IPSocketAddress] for more information. +type IPSocketAddress = network.IPSocketAddress + +// IPAddressFamily represents the type alias "wasi:sockets/udp@0.2.0#ip-address-family". +// +// See [network.IPAddressFamily] for more information. +type IPAddressFamily = network.IPAddressFamily + +// IncomingDatagram represents the record "wasi:sockets/udp@0.2.0#incoming-datagram". +// +// record incoming-datagram { +// data: list, +// remote-address: ip-socket-address, +// } +type IncomingDatagram struct { + _ cm.HostLayout `json:"-"` + Data cm.List[uint8] `json:"data"` + RemoteAddress IPSocketAddress `json:"remote-address"` +} + +// OutgoingDatagram represents the record "wasi:sockets/udp@0.2.0#outgoing-datagram". +// +// record outgoing-datagram { +// data: list, +// remote-address: option, +// } +type OutgoingDatagram struct { + _ cm.HostLayout `json:"-"` + Data cm.List[uint8] `json:"data"` + RemoteAddress cm.Option[IPSocketAddress] `json:"remote-address"` +} + +// UDPSocket represents the imported resource "wasi:sockets/udp@0.2.0#udp-socket". +// +// resource udp-socket +type UDPSocket cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "udp-socket". +// +// Drops a resource handle. +// +//go:nosplit +func (self UDPSocket) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketResourceDrop((uint32)(self0)) + return +} + +// AddressFamily represents the imported method "address-family". +// +// address-family: func() -> ip-address-family +// +//go:nosplit +func (self UDPSocket) AddressFamily() (result IPAddressFamily) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_UDPSocketAddressFamily((uint32)(self0)) + result = (network.IPAddressFamily)((uint32)(result0)) + return +} + +// FinishBind represents the imported method "finish-bind". +// +// finish-bind: func() -> result<_, error-code> +// +//go:nosplit +func (self UDPSocket) FinishBind() (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketFinishBind((uint32)(self0), &result) + return +} + +// LocalAddress represents the imported method "local-address". +// +// local-address: func() -> result +// +//go:nosplit +func (self UDPSocket) LocalAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketLocalAddress((uint32)(self0), &result) + return +} + +// ReceiveBufferSize represents the imported method "receive-buffer-size". +// +// receive-buffer-size: func() -> result +// +//go:nosplit +func (self UDPSocket) ReceiveBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketReceiveBufferSize((uint32)(self0), &result) + return +} + +// RemoteAddress represents the imported method "remote-address". +// +// remote-address: func() -> result +// +//go:nosplit +func (self UDPSocket) RemoteAddress() (result cm.Result[IPSocketAddressShape, IPSocketAddress, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketRemoteAddress((uint32)(self0), &result) + return +} + +// SendBufferSize represents the imported method "send-buffer-size". +// +// send-buffer-size: func() -> result +// +//go:nosplit +func (self UDPSocket) SendBufferSize() (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketSendBufferSize((uint32)(self0), &result) + return +} + +// SetReceiveBufferSize represents the imported method "set-receive-buffer-size". +// +// set-receive-buffer-size: func(value: u64) -> result<_, error-code> +// +//go:nosplit +func (self UDPSocket) SetReceiveBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_UDPSocketSetReceiveBufferSize((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetSendBufferSize represents the imported method "set-send-buffer-size". +// +// set-send-buffer-size: func(value: u64) -> result<_, error-code> +// +//go:nosplit +func (self UDPSocket) SetSendBufferSize(value uint64) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint64)(value) + wasmimport_UDPSocketSetSendBufferSize((uint32)(self0), (uint64)(value0), &result) + return +} + +// SetUnicastHopLimit represents the imported method "set-unicast-hop-limit". +// +// set-unicast-hop-limit: func(value: u8) -> result<_, error-code> +// +//go:nosplit +func (self UDPSocket) SetUnicastHopLimit(value uint8) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + value0 := (uint32)(value) + wasmimport_UDPSocketSetUnicastHopLimit((uint32)(self0), (uint32)(value0), &result) + return +} + +// StartBind represents the imported method "start-bind". +// +// start-bind: func(network: borrow, local-address: ip-socket-address) -> +// result<_, error-code> +// +//go:nosplit +func (self UDPSocket) StartBind(network_ Network, localAddress IPSocketAddress) (result cm.Result[ErrorCode, struct{}, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + network0 := cm.Reinterpret[uint32](network_) + localAddress0, localAddress1, localAddress2, localAddress3, localAddress4, localAddress5, localAddress6, localAddress7, localAddress8, localAddress9, localAddress10, localAddress11 := lower_IPSocketAddress(localAddress) + wasmimport_UDPSocketStartBind((uint32)(self0), (uint32)(network0), (uint32)(localAddress0), (uint32)(localAddress1), (uint32)(localAddress2), (uint32)(localAddress3), (uint32)(localAddress4), (uint32)(localAddress5), (uint32)(localAddress6), (uint32)(localAddress7), (uint32)(localAddress8), (uint32)(localAddress9), (uint32)(localAddress10), (uint32)(localAddress11), &result) + return +} + +// Stream represents the imported method "stream". +// +// %stream: func(remote-address: option) -> result, error-code> +// +//go:nosplit +func (self UDPSocket) Stream(remoteAddress cm.Option[IPSocketAddress]) (result cm.Result[TupleIncomingDatagramStreamOutgoingDatagramStreamShape, cm.Tuple[IncomingDatagramStream, OutgoingDatagramStream], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + remoteAddress0, remoteAddress1, remoteAddress2, remoteAddress3, remoteAddress4, remoteAddress5, remoteAddress6, remoteAddress7, remoteAddress8, remoteAddress9, remoteAddress10, remoteAddress11, remoteAddress12 := lower_OptionIPSocketAddress(remoteAddress) + wasmimport_UDPSocketStream((uint32)(self0), (uint32)(remoteAddress0), (uint32)(remoteAddress1), (uint32)(remoteAddress2), (uint32)(remoteAddress3), (uint32)(remoteAddress4), (uint32)(remoteAddress5), (uint32)(remoteAddress6), (uint32)(remoteAddress7), (uint32)(remoteAddress8), (uint32)(remoteAddress9), (uint32)(remoteAddress10), (uint32)(remoteAddress11), (uint32)(remoteAddress12), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self UDPSocket) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_UDPSocketSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// UnicastHopLimit represents the imported method "unicast-hop-limit". +// +// unicast-hop-limit: func() -> result +// +//go:nosplit +func (self UDPSocket) UnicastHopLimit() (result cm.Result[uint8, uint8, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_UDPSocketUnicastHopLimit((uint32)(self0), &result) + return +} + +// IncomingDatagramStream represents the imported resource "wasi:sockets/udp@0.2.0#incoming-datagram-stream". +// +// resource incoming-datagram-stream +type IncomingDatagramStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "incoming-datagram-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self IncomingDatagramStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_IncomingDatagramStreamResourceDrop((uint32)(self0)) + return +} + +// Receive represents the imported method "receive". +// +// receive: func(max-results: u64) -> result, error-code> +// +//go:nosplit +func (self IncomingDatagramStream) Receive(maxResults uint64) (result cm.Result[cm.List[IncomingDatagram], cm.List[IncomingDatagram], ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + maxResults0 := (uint64)(maxResults) + wasmimport_IncomingDatagramStreamReceive((uint32)(self0), (uint64)(maxResults0), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self IncomingDatagramStream) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_IncomingDatagramStreamSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} + +// OutgoingDatagramStream represents the imported resource "wasi:sockets/udp@0.2.0#outgoing-datagram-stream". +// +// resource outgoing-datagram-stream +type OutgoingDatagramStream cm.Resource + +// ResourceDrop represents the imported resource-drop for resource "outgoing-datagram-stream". +// +// Drops a resource handle. +// +//go:nosplit +func (self OutgoingDatagramStream) ResourceDrop() { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutgoingDatagramStreamResourceDrop((uint32)(self0)) + return +} + +// CheckSend represents the imported method "check-send". +// +// check-send: func() -> result +// +//go:nosplit +func (self OutgoingDatagramStream) CheckSend() (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + wasmimport_OutgoingDatagramStreamCheckSend((uint32)(self0), &result) + return +} + +// Send represents the imported method "send". +// +// send: func(datagrams: list) -> result +// +//go:nosplit +func (self OutgoingDatagramStream) Send(datagrams cm.List[OutgoingDatagram]) (result cm.Result[uint64, uint64, ErrorCode]) { + self0 := cm.Reinterpret[uint32](self) + datagrams0, datagrams1 := cm.LowerList(datagrams) + wasmimport_OutgoingDatagramStreamSend((uint32)(self0), (*OutgoingDatagram)(datagrams0), (uint32)(datagrams1), &result) + return +} + +// Subscribe represents the imported method "subscribe". +// +// subscribe: func() -> pollable +// +//go:nosplit +func (self OutgoingDatagramStream) Subscribe() (result Pollable) { + self0 := cm.Reinterpret[uint32](self) + result0 := wasmimport_OutgoingDatagramStreamSubscribe((uint32)(self0)) + result = cm.Reinterpret[Pollable]((uint32)(result0)) + return +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/sdk.go b/go/examples/bare-bones-wasi/pkg/sdk/sdk.go new file mode 100644 index 0000000..696cd89 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/sdk.go @@ -0,0 +1,18 @@ +package sdk + +import ( + "sdk.com/internal/docs/adder/add" +) + +func addInternal(s add.Numbers) uint32 { + return s.X + s.Y +} + +func AddExternal(x, y uint32) uint32 { + s := add.Numbers{ + X: x, + Y: y, + } + + return addInternal(s) +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/add.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/add.wit new file mode 100644 index 0000000..bd8bad5 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/add.wit @@ -0,0 +1,16 @@ +package docs:adder@0.1.0; + +interface add { + record numbers { + x: u32, + y: u32, + } + + add: func(nums: numbers) -> u32; +} + + +world adder { + include wasi:cli/imports@0.2.0; + export add; +} \ No newline at end of file diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-cli-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-cli-0.2.0/package.wit new file mode 100644 index 0000000..0a2737b --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-cli-0.2.0/package.wit @@ -0,0 +1,159 @@ +package wasi:cli@0.2.0; + +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} + +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} + +interface run { + /// Run the program. + run: func() -> result; +} + +interface stdin { + use wasi:io/streams@0.2.0.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stderr: func() -> output-stream; +} + +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +interface terminal-output { + /// The output side of a terminal. + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} + +world imports { + import environment; + import exit; + import wasi:io/error@0.2.0; + import wasi:io/poll@0.2.0; + import wasi:io/streams@0.2.0; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.0; + import wasi:clocks/wall-clock@0.2.0; + import wasi:filesystem/types@0.2.0; + import wasi:filesystem/preopens@0.2.0; + import wasi:sockets/network@0.2.0; + import wasi:sockets/instance-network@0.2.0; + import wasi:sockets/udp@0.2.0; + import wasi:sockets/udp-create-socket@0.2.0; + import wasi:sockets/tcp@0.2.0; + import wasi:sockets/tcp-create-socket@0.2.0; + import wasi:sockets/ip-name-lookup@0.2.0; + import wasi:random/random@0.2.0; + import wasi:random/insecure@0.2.0; + import wasi:random/insecure-seed@0.2.0; +} +world command { + import environment; + import exit; + import wasi:io/error@0.2.0; + import wasi:io/poll@0.2.0; + import wasi:io/streams@0.2.0; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.0; + import wasi:clocks/wall-clock@0.2.0; + import wasi:filesystem/types@0.2.0; + import wasi:filesystem/preopens@0.2.0; + import wasi:sockets/network@0.2.0; + import wasi:sockets/instance-network@0.2.0; + import wasi:sockets/udp@0.2.0; + import wasi:sockets/udp-create-socket@0.2.0; + import wasi:sockets/tcp@0.2.0; + import wasi:sockets/tcp-create-socket@0.2.0; + import wasi:sockets/ip-name-lookup@0.2.0; + import wasi:random/random@0.2.0; + import wasi:random/insecure@0.2.0; + import wasi:random/insecure-seed@0.2.0; + + export run; +} diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-clocks-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-clocks-0.2.0/package.wit new file mode 100644 index 0000000..9e0ba3d --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-clocks-0.2.0/package.wit @@ -0,0 +1,29 @@ +package wasi:clocks@0.2.0; + +interface monotonic-clock { + use wasi:io/poll@0.2.0.{pollable}; + + type instant = u64; + + type duration = u64; + + now: func() -> instant; + + resolution: func() -> duration; + + subscribe-instant: func(when: instant) -> pollable; + + subscribe-duration: func(when: duration) -> pollable; +} + +interface wall-clock { + record datetime { + seconds: u64, + nanoseconds: u32, + } + + now: func() -> datetime; + + resolution: func() -> datetime; +} + diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-filesystem-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-filesystem-0.2.0/package.wit new file mode 100644 index 0000000..cb6a2be --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-filesystem-0.2.0/package.wit @@ -0,0 +1,158 @@ +package wasi:filesystem@0.2.0; + +interface types { + use wasi:io/streams@0.2.0.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0.{datetime}; + + type filesize = u64; + + enum descriptor-type { + unknown, + block-device, + character-device, + directory, + fifo, + symbolic-link, + regular-file, + socket, + } + + flags descriptor-flags { + read, + write, + file-integrity-sync, + data-integrity-sync, + requested-write-sync, + mutate-directory, + } + + flags path-flags { + symlink-follow, + } + + flags open-flags { + create, + directory, + exclusive, + truncate, + } + + type link-count = u64; + + record descriptor-stat { + %type: descriptor-type, + link-count: link-count, + size: filesize, + data-access-timestamp: option, + data-modification-timestamp: option, + status-change-timestamp: option, + } + + variant new-timestamp { + no-change, + now, + timestamp(datetime), + } + + record directory-entry { + %type: descriptor-type, + name: string, + } + + enum error-code { + access, + would-block, + already, + bad-descriptor, + busy, + deadlock, + quota, + exist, + file-too-large, + illegal-byte-sequence, + in-progress, + interrupted, + invalid, + io, + is-directory, + loop, + too-many-links, + message-size, + name-too-long, + no-device, + no-entry, + no-lock, + insufficient-memory, + insufficient-space, + not-directory, + not-empty, + not-recoverable, + unsupported, + no-tty, + no-such-device, + overflow, + not-permitted, + pipe, + read-only, + invalid-seek, + text-file-busy, + cross-device, + } + + enum advice { + normal, + sequential, + random, + will-need, + dont-need, + no-reuse, + } + + record metadata-hash-value { + lower: u64, + upper: u64, + } + + resource descriptor { + read-via-stream: func(offset: filesize) -> result; + write-via-stream: func(offset: filesize) -> result; + append-via-stream: func() -> result; + advise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>; + sync-data: func() -> result<_, error-code>; + get-flags: func() -> result; + get-type: func() -> result; + set-size: func(size: filesize) -> result<_, error-code>; + set-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + read: func(length: filesize, offset: filesize) -> result, bool>, error-code>; + write: func(buffer: list, offset: filesize) -> result; + read-directory: func() -> result; + sync: func() -> result<_, error-code>; + create-directory-at: func(path: string) -> result<_, error-code>; + stat: func() -> result; + stat-at: func(path-flags: path-flags, path: string) -> result; + set-times-at: func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + link-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + open-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result; + readlink-at: func(path: string) -> result; + remove-directory-at: func(path: string) -> result<_, error-code>; + rename-at: func(old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + symlink-at: func(old-path: string, new-path: string) -> result<_, error-code>; + unlink-file-at: func(path: string) -> result<_, error-code>; + is-same-object: func(other: borrow) -> bool; + metadata-hash: func() -> result; + metadata-hash-at: func(path-flags: path-flags, path: string) -> result; + } + + resource directory-entry-stream { + read-directory-entry: func() -> result, error-code>; + } + + filesystem-error-code: func(err: borrow) -> option; +} + +interface preopens { + use types.{descriptor}; + + get-directories: func() -> list>; +} + diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-io-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-io-0.2.0/package.wit new file mode 100644 index 0000000..1840029 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-io-0.2.0/package.wit @@ -0,0 +1,48 @@ +package wasi:io@0.2.0; + +interface error { + resource error { + to-debug-string: func() -> string; + } +} + +interface poll { + resource pollable { + ready: func() -> bool; + block: func(); + } + + poll: func(in: list>) -> list; +} + +interface streams { + use error.{error}; + use poll.{pollable}; + + variant stream-error { + last-operation-failed(error), + closed, + } + + resource input-stream { + read: func(len: u64) -> result, stream-error>; + blocking-read: func(len: u64) -> result, stream-error>; + skip: func(len: u64) -> result; + blocking-skip: func(len: u64) -> result; + subscribe: func() -> pollable; + } + + resource output-stream { + check-write: func() -> result; + write: func(contents: list) -> result<_, stream-error>; + blocking-write-and-flush: func(contents: list) -> result<_, stream-error>; + flush: func() -> result<_, stream-error>; + blocking-flush: func() -> result<_, stream-error>; + subscribe: func() -> pollable; + write-zeroes: func(len: u64) -> result<_, stream-error>; + blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>; + splice: func(src: borrow, len: u64) -> result; + blocking-splice: func(src: borrow, len: u64) -> result; + } +} + diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-random-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-random-0.2.0/package.wit new file mode 100644 index 0000000..58c179e --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-random-0.2.0/package.wit @@ -0,0 +1,18 @@ +package wasi:random@0.2.0; + +interface random { + get-random-bytes: func(len: u64) -> list; + + get-random-u64: func() -> u64; +} + +interface insecure { + get-insecure-random-bytes: func(len: u64) -> list; + + get-insecure-random-u64: func() -> u64; +} + +interface insecure-seed { + insecure-seed: func() -> tuple; +} + diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-sockets-0.2.0/package.wit b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-sockets-0.2.0/package.wit new file mode 100644 index 0000000..0602b85 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wit/deps/wasi-sockets-0.2.0/package.wit @@ -0,0 +1,179 @@ +package wasi:sockets@0.2.0; + +interface network { + resource network; + + enum error-code { + unknown, + access-denied, + not-supported, + invalid-argument, + out-of-memory, + timeout, + concurrency-conflict, + not-in-progress, + would-block, + invalid-state, + new-socket-limit, + address-not-bindable, + address-in-use, + remote-unreachable, + connection-refused, + connection-reset, + connection-aborted, + datagram-too-large, + name-unresolvable, + temporary-resolver-failure, + permanent-resolver-failure, + } + + enum ip-address-family { + ipv4, + ipv6, + } + + type ipv4-address = tuple; + + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, + address: ipv4-address, + } + + record ipv6-socket-address { + port: u16, + flow-info: u32, + address: ipv6-address, + scope-id: u32, + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } +} + +interface instance-network { + use network.{network}; + + instance-network: func() -> network; +} + +interface udp { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + record incoming-datagram { + data: list, + remote-address: ip-socket-address, + } + + record outgoing-datagram { + data: list, + remote-address: option, + } + + resource udp-socket { + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + %stream: func(remote-address: option) -> result, error-code>; + local-address: func() -> result; + remote-address: func() -> result; + address-family: func() -> ip-address-family; + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + subscribe: func() -> pollable; + } + + resource incoming-datagram-stream { + receive: func(max-results: u64) -> result, error-code>; + subscribe: func() -> pollable; + } + + resource outgoing-datagram-stream { + check-send: func() -> result; + send: func(datagrams: list) -> result; + subscribe: func() -> pollable; + } +} + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + use udp.{udp-socket}; + + create-udp-socket: func(address-family: ip-address-family) -> result; +} + +interface tcp { + use wasi:io/streams@0.2.0.{input-stream, output-stream}; + use wasi:io/poll@0.2.0.{pollable}; + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + enum shutdown-type { + receive, + send, + both, + } + + resource tcp-socket { + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result, error-code>; + start-listen: func() -> result<_, error-code>; + finish-listen: func() -> result<_, error-code>; + accept: func() -> result, error-code>; + local-address: func() -> result; + remote-address: func() -> result; + is-listening: func() -> bool; + address-family: func() -> ip-address-family; + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + keep-alive-enabled: func() -> result; + set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; + keep-alive-idle-time: func() -> result; + set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; + keep-alive-interval: func() -> result; + set-keep-alive-interval: func(value: duration) -> result<_, error-code>; + keep-alive-count: func() -> result; + set-keep-alive-count: func(value: u32) -> result<_, error-code>; + hop-limit: func() -> result; + set-hop-limit: func(value: u8) -> result<_, error-code>; + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + subscribe: func() -> pollable; + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + use tcp.{tcp-socket}; + + create-tcp-socket: func(address-family: ip-address-family) -> result; +} + +interface ip-name-lookup { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-address}; + + resource resolve-address-stream { + resolve-next-address: func() -> result, error-code>; + subscribe: func() -> pollable; + } + + resolve-addresses: func(network: borrow, name: string) -> result; +} + diff --git a/go/examples/bare-bones-wasi/pkg/sdk/wkg.lock b/go/examples/bare-bones-wasi/pkg/sdk/wkg.lock new file mode 100644 index 0000000..1604270 --- /dev/null +++ b/go/examples/bare-bones-wasi/pkg/sdk/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:cli" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:e7e85458e11caf76554b724ebf4f113259decf0f3b1ee2e2930de096f72114a7" diff --git a/go/examples/bare-bones-wasi/wkg.lock b/go/examples/bare-bones-wasi/wkg.lock new file mode 100644 index 0000000..1604270 --- /dev/null +++ b/go/examples/bare-bones-wasi/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:cli" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:e7e85458e11caf76554b724ebf4f113259decf0f3b1ee2e2930de096f72114a7" diff --git a/go/examples/spin-basic/.gitignore b/go/examples/spin-basic/.gitignore new file mode 100644 index 0000000..b565010 --- /dev/null +++ b/go/examples/spin-basic/.gitignore @@ -0,0 +1,2 @@ +main.wasm +.spin/ diff --git a/go/examples/spin-basic/go.mod b/go/examples/spin-basic/go.mod new file mode 100644 index 0000000..57db4ac --- /dev/null +++ b/go/examples/spin-basic/go.mod @@ -0,0 +1,26 @@ +module spin-basic + +go 1.24.4 + +require ( + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/julienschmidt/httprouter v1.3.0 // indirect + go.bytecodealliance.org/cm v0.3.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + golang.org/x/sys v0.33.0 // indirect +) + +require ( + github.com/calebschoepp/opentelemetry-wasi v0.0.0 + github.com/spinframework/spin-go-sdk/v3 v3.0.0 + go.opentelemetry.io/otel v1.37.0 + go.opentelemetry.io/otel/sdk v1.37.0 + go.opentelemetry.io/otel/trace v1.37.0 +) + +replace github.com/calebschoepp/opentelemetry-wasi => ../.. + +replace github.com/spinframework/spin-go-sdk/v3 => ../../../../../spin-go-sdk/v3 diff --git a/go/examples/spin-basic/go.sum b/go/examples/spin-basic/go.sum new file mode 100644 index 0000000..a65c939 --- /dev/null +++ b/go/examples/spin-basic/go.sum @@ -0,0 +1,35 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.bytecodealliance.org/cm v0.3.0 h1:VhV+4vjZPUGCozCg9+up+FNL3YU6XR+XKghk7kQ0vFc= +go.bytecodealliance.org/cm v0.3.0/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/examples/spin-basic/main.go b/go/examples/spin-basic/main.go new file mode 100644 index 0000000..f73802b --- /dev/null +++ b/go/examples/spin-basic/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "net/http" + + spinhttp "github.com/spinframework/spin-go-sdk/v3/http" + + otelWasi "github.com/calebschoepp/opentelemetry-wasi" + spinkv "github.com/spinframework/spin-go-sdk/v3/kv" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + sdkTrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + wasiProcessor := otelWasi.NewWasiProcessor() + tracerProvider := sdkTrace.NewTracerProvider( + sdkTrace.WithSpanProcessor(wasiProcessor), + ) + + otel.SetTracerProvider(tracerProvider) + tracer := otel.Tracer("basic-spin") + + wasiPropagator := otelWasi.NewTraceContextPropagator() + wasiPropagator.Extract(r.Context()) + + ctx, span := tracer.Start(r.Context(), "main-operation") + defer span.End() + + span.SetAttributes(attribute.String("my-attribute", "my-value")) + span.AddEvent( + "Main span event", + trace.WithAttributes(attribute.String("foo", "1")), + ) + + _, childSpan := tracer.Start(ctx, "child-operation") + childSpan.AddEvent( + "Sub span event", + trace.WithAttributes(attribute.String("bar", "1")), + ) + defer childSpan.End() + + store, err := spinkv.OpenDefault() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Failed to open kv store")) + } + + if err := store.Set("foo", []byte("bar")); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Failed to write to kv store")) + } + + w.Header().Set("content-type", "text/plain") + fmt.Fprintln(w, "Hello, world!") + }) +} + +func main() {} diff --git a/go/examples/spin-basic/spin.toml b/go/examples/spin-basic/spin.toml new file mode 100644 index 0000000..4ddd60d --- /dev/null +++ b/go/examples/spin-basic/spin.toml @@ -0,0 +1,19 @@ +spin_manifest_version = 2 + +[application] +name = "spin-basic" +version = "0.1.0" +authors = ["Andrew Steurer <94206073+asteurer@users.noreply.github.com>"] +description = "" + +[[trigger.http]] +route = "/..." +component = "spin-basic" + +[component.spin-basic] +source = "main.wasm" +allowed_outbound_hosts = [] +key_value_stores = ["default"] +[component.spin-basic.build] +command = "tinygo build --wit-package $(go list -mod=readonly -m -f '{{.Dir}}' github.com/calebschoepp/opentelemetry-wasi)/go/wasip2/examples/spin-basic/wit --wit-world imports -target=wasip2 -gc=leaking -buildmode=c-shared -no-debug -o main.wasm ." +watch = ["**/*.go", "go.mod"] diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/command.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/command.wit new file mode 100644 index 0000000..d7ea2d9 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/command.wit @@ -0,0 +1,7 @@ +package wasi:cli@0.2.0-rc-2023-10-18; + +world command { + include reactor; + + export run; +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/environment.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/environment.wit new file mode 100644 index 0000000..7006523 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/environment.wit @@ -0,0 +1,18 @@ +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/exit.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/exit.wit new file mode 100644 index 0000000..d0c2b82 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/exit.wit @@ -0,0 +1,4 @@ +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/reactor.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/reactor.wit new file mode 100644 index 0000000..904b994 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/reactor.wit @@ -0,0 +1,32 @@ +package wasi:cli@0.2.0-rc-2023-10-18; + +world reactor { + import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/timezone@0.2.0-rc-2023-10-18; + import wasi:filesystem/types@0.2.0-rc-2023-10-18; + import wasi:filesystem/preopens@0.2.0-rc-2023-10-18; + import wasi:sockets/instance-network@0.2.0-rc-2023-10-18; + import wasi:sockets/ip-name-lookup@0.2.0-rc-2023-10-18; + import wasi:sockets/network@0.2.0-rc-2023-10-18; + import wasi:sockets/tcp-create-socket@0.2.0-rc-2023-10-18; + import wasi:sockets/tcp@0.2.0-rc-2023-10-18; + import wasi:sockets/udp-create-socket@0.2.0-rc-2023-10-18; + import wasi:sockets/udp@0.2.0-rc-2023-10-18; + import wasi:random/random@0.2.0-rc-2023-10-18; + import wasi:random/insecure@0.2.0-rc-2023-10-18; + import wasi:random/insecure-seed@0.2.0-rc-2023-10-18; + import wasi:io/poll@0.2.0-rc-2023-10-18; + import wasi:io/streams@0.2.0-rc-2023-10-18; + + import environment; + import exit; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/run.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/run.wit new file mode 100644 index 0000000..a70ee8c --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/run.wit @@ -0,0 +1,4 @@ +interface run { + /// Run the program. + run: func() -> result; +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/stdio.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/stdio.wit new file mode 100644 index 0000000..513ca92 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/stdio.wit @@ -0,0 +1,17 @@ +interface stdin { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; + + get-stderr: func() -> output-stream; +} diff --git a/go/examples/spin-basic/wit/deps/cli-2023-10-18/terminal.wit b/go/examples/spin-basic/wit/deps/cli-2023-10-18/terminal.wit new file mode 100644 index 0000000..4749576 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/cli-2023-10-18/terminal.wit @@ -0,0 +1,47 @@ +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; + + // In the future, this may include functions for disabling echoing, + // disabling input buffering so that keyboard events are sent through + // immediately, querying supported features, and so on. +} + +interface terminal-output { + /// The output side of a terminal. + resource terminal-output; + + // In the future, this may include functions for querying the terminal + // size, being notified of terminal size changes, querying supported + // features, and so on. +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} diff --git a/go/examples/spin-basic/wit/deps/clocks-2023-10-18/monotonic-clock.wit b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/monotonic-clock.wit new file mode 100644 index 0000000..c0ecb52 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/monotonic-clock.wit @@ -0,0 +1,32 @@ +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +/// +/// It is intended for measuring elapsed time. +interface monotonic-clock { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + + /// A timestamp in nanoseconds. + type instant = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; + + /// Query the resolution of the clock. + resolution: func() -> instant; + + /// Create a `pollable` which will resolve once the specified time has been + /// reached. + subscribe: func( + when: instant, + absolute: bool + ) -> pollable; +} diff --git a/go/examples/spin-basic/wit/deps/clocks-2023-10-18/timezone.wit b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/timezone.wit new file mode 100644 index 0000000..e717e7b --- /dev/null +++ b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/timezone.wit @@ -0,0 +1,48 @@ +interface timezone { + use wall-clock.{datetime}; + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + utc-offset: func(when: datetime) -> s32; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } +} diff --git a/go/examples/spin-basic/wit/deps/clocks-2023-10-18/wall-clock.wit b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/wall-clock.wit new file mode 100644 index 0000000..c395649 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/wall-clock.wit @@ -0,0 +1,41 @@ +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; +} diff --git a/go/examples/spin-basic/wit/deps/clocks-2023-10-18/world.wit b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/world.wit new file mode 100644 index 0000000..cdfb51d --- /dev/null +++ b/go/examples/spin-basic/wit/deps/clocks-2023-10-18/world.wit @@ -0,0 +1,7 @@ +package wasi:clocks@0.2.0-rc-2023-10-18; + +world imports { + import monotonic-clock; + import wall-clock; + import timezone; +} diff --git a/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/preopens.wit b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/preopens.wit new file mode 100644 index 0000000..3f787ac --- /dev/null +++ b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/preopens.wit @@ -0,0 +1,6 @@ +interface preopens { + use types.{descriptor}; + + /// Return the set of preopened directories, and their path. + get-directories: func() -> list>; +} diff --git a/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/types.wit b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/types.wit new file mode 100644 index 0000000..af36135 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/types.wit @@ -0,0 +1,810 @@ +/// WASI filesystem is a filesystem API primarily intended to let users run WASI +/// programs that access their files on their existing filesystems, without +/// significant overhead. +/// +/// It is intended to be roughly portable between Unix-family platforms and +/// Windows, though it does not hide many of the major differences. +/// +/// Paths are passed as interface-type `string`s, meaning they must consist of +/// a sequence of Unicode Scalar Values (USVs). Some filesystems may contain +/// paths which are not accessible by this API. +/// +/// The directory separator in WASI is always the forward-slash (`/`). +/// +/// All paths in WASI are relative paths, and are interpreted relative to a +/// `descriptor` referring to a base directory. If a `path` argument to any WASI +/// function starts with `/`, or if any step of resolving a `path`, including +/// `..` and symbolic link steps, reaches a directory outside of the base +/// directory, or reaches a symlink to an absolute or rooted path in the +/// underlying filesystem, the function fails with `error-code::not-permitted`. +/// +/// For more information about WASI path resolution and sandboxing, see +/// [WASI filesystem path resolution]. +/// +/// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md +interface types { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0-rc-2023-10-18.{datetime}; + + /// File size or length of a region within a file. + type filesize = u64; + + /// The type of a filesystem object referenced by a descriptor. + /// + /// Note: This was called `filetype` in earlier versions of WASI. + enum descriptor-type { + /// The type of the descriptor or file is unknown or is different from + /// any of the other types specified. + unknown, + /// The descriptor refers to a block device inode. + block-device, + /// The descriptor refers to a character device inode. + character-device, + /// The descriptor refers to a directory inode. + directory, + /// The descriptor refers to a named pipe. + fifo, + /// The file refers to a symbolic link inode. + symbolic-link, + /// The descriptor refers to a regular file inode. + regular-file, + /// The descriptor refers to a socket. + socket, + } + + /// Descriptor flags. + /// + /// Note: This was called `fdflags` in earlier versions of WASI. + flags descriptor-flags { + /// Read mode: Data can be read. + read, + /// Write mode: Data can be written to. + write, + /// Request that writes be performed according to synchronized I/O file + /// integrity completion. The data stored in the file and the file's + /// metadata are synchronized. This is similar to `O_SYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + file-integrity-sync, + /// Request that writes be performed according to synchronized I/O data + /// integrity completion. Only the data stored in the file is + /// synchronized. This is similar to `O_DSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + data-integrity-sync, + /// Requests that reads be performed at the same level of integrety + /// requested for writes. This is similar to `O_RSYNC` in POSIX. + /// + /// The precise semantics of this operation have not yet been defined for + /// WASI. At this time, it should be interpreted as a request, and not a + /// requirement. + requested-write-sync, + /// Mutating directories mode: Directory contents may be mutated. + /// + /// When this flag is unset on a descriptor, operations using the + /// descriptor which would create, rename, delete, modify the data or + /// metadata of filesystem objects, or obtain another handle which + /// would permit any of those, shall fail with `error-code::read-only` if + /// they would otherwise succeed. + /// + /// This may only be set on directories. + mutate-directory, + } + + /// File attributes. + /// + /// Note: This was called `filestat` in earlier versions of WASI. + record descriptor-stat { + /// File type. + %type: descriptor-type, + /// Number of hard links to the file. + link-count: link-count, + /// For regular files, the file size in bytes. For symbolic links, the + /// length in bytes of the pathname contained in the symbolic link. + size: filesize, + /// Last data access timestamp. + /// + /// If the `option` is none, the platform doesn't maintain an access + /// timestamp for this file. + data-access-timestamp: option, + /// Last data modification timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// modification timestamp for this file. + data-modification-timestamp: option, + /// Last file status-change timestamp. + /// + /// If the `option` is none, the platform doesn't maintain a + /// status-change timestamp for this file. + status-change-timestamp: option, + } + + /// Flags determining the method of how paths are resolved. + flags path-flags { + /// As long as the resolved path corresponds to a symbolic link, it is + /// expanded. + symlink-follow, + } + + /// Open flags used by `open-at`. + flags open-flags { + /// Create file if it does not exist, similar to `O_CREAT` in POSIX. + create, + /// Fail if not a directory, similar to `O_DIRECTORY` in POSIX. + directory, + /// Fail if file already exists, similar to `O_EXCL` in POSIX. + exclusive, + /// Truncate file to size 0, similar to `O_TRUNC` in POSIX. + truncate, + } + + /// Permissions mode used by `open-at`, `change-file-permissions-at`, and + /// similar. + flags modes { + /// True if the resource is considered readable by the containing + /// filesystem. + readable, + /// True if the resource is considered writable by the containing + /// filesystem. + writable, + /// True if the resource is considered executable by the containing + /// filesystem. This does not apply to directories. + executable, + } + + /// Access type used by `access-at`. + variant access-type { + /// Test for readability, writeability, or executability. + access(modes), + + /// Test whether the path exists. + exists, + } + + /// Number of hard links to an inode. + type link-count = u64; + + /// When setting a timestamp, this gives the value to set it to. + variant new-timestamp { + /// Leave the timestamp set to its previous value. + no-change, + /// Set the timestamp to the current time of the system clock associated + /// with the filesystem. + now, + /// Set the timestamp to the given value. + timestamp(datetime), + } + + /// A directory entry. + record directory-entry { + /// The type of the file referred to by this directory entry. + %type: descriptor-type, + + /// The name of the object. + name: string, + } + + /// Error codes returned by functions, similar to `errno` in POSIX. + /// Not all of these error codes are returned by the functions provided by this + /// API; some are used in higher-level library layers, and others are provided + /// merely for alignment with POSIX. + enum error-code { + /// Permission denied, similar to `EACCES` in POSIX. + access, + /// Resource unavailable, or operation would block, similar to `EAGAIN` and `EWOULDBLOCK` in POSIX. + would-block, + /// Connection already in progress, similar to `EALREADY` in POSIX. + already, + /// Bad descriptor, similar to `EBADF` in POSIX. + bad-descriptor, + /// Device or resource busy, similar to `EBUSY` in POSIX. + busy, + /// Resource deadlock would occur, similar to `EDEADLK` in POSIX. + deadlock, + /// Storage quota exceeded, similar to `EDQUOT` in POSIX. + quota, + /// File exists, similar to `EEXIST` in POSIX. + exist, + /// File too large, similar to `EFBIG` in POSIX. + file-too-large, + /// Illegal byte sequence, similar to `EILSEQ` in POSIX. + illegal-byte-sequence, + /// Operation in progress, similar to `EINPROGRESS` in POSIX. + in-progress, + /// Interrupted function, similar to `EINTR` in POSIX. + interrupted, + /// Invalid argument, similar to `EINVAL` in POSIX. + invalid, + /// I/O error, similar to `EIO` in POSIX. + io, + /// Is a directory, similar to `EISDIR` in POSIX. + is-directory, + /// Too many levels of symbolic links, similar to `ELOOP` in POSIX. + loop, + /// Too many links, similar to `EMLINK` in POSIX. + too-many-links, + /// Message too large, similar to `EMSGSIZE` in POSIX. + message-size, + /// Filename too long, similar to `ENAMETOOLONG` in POSIX. + name-too-long, + /// No such device, similar to `ENODEV` in POSIX. + no-device, + /// No such file or directory, similar to `ENOENT` in POSIX. + no-entry, + /// No locks available, similar to `ENOLCK` in POSIX. + no-lock, + /// Not enough space, similar to `ENOMEM` in POSIX. + insufficient-memory, + /// No space left on device, similar to `ENOSPC` in POSIX. + insufficient-space, + /// Not a directory or a symbolic link to a directory, similar to `ENOTDIR` in POSIX. + not-directory, + /// Directory not empty, similar to `ENOTEMPTY` in POSIX. + not-empty, + /// State not recoverable, similar to `ENOTRECOVERABLE` in POSIX. + not-recoverable, + /// Not supported, similar to `ENOTSUP` and `ENOSYS` in POSIX. + unsupported, + /// Inappropriate I/O control operation, similar to `ENOTTY` in POSIX. + no-tty, + /// No such device or address, similar to `ENXIO` in POSIX. + no-such-device, + /// Value too large to be stored in data type, similar to `EOVERFLOW` in POSIX. + overflow, + /// Operation not permitted, similar to `EPERM` in POSIX. + not-permitted, + /// Broken pipe, similar to `EPIPE` in POSIX. + pipe, + /// Read-only file system, similar to `EROFS` in POSIX. + read-only, + /// Invalid seek, similar to `ESPIPE` in POSIX. + invalid-seek, + /// Text file busy, similar to `ETXTBSY` in POSIX. + text-file-busy, + /// Cross-device link, similar to `EXDEV` in POSIX. + cross-device, + } + + /// File or memory access pattern advisory information. + enum advice { + /// The application has no advice to give on its behavior with respect + /// to the specified data. + normal, + /// The application expects to access the specified data sequentially + /// from lower offsets to higher offsets. + sequential, + /// The application expects to access the specified data in a random + /// order. + random, + /// The application expects to access the specified data in the near + /// future. + will-need, + /// The application expects that it will not access the specified data + /// in the near future. + dont-need, + /// The application expects to access the specified data once and then + /// not reuse it thereafter. + no-reuse, + } + + /// A 128-bit hash value, split into parts because wasm doesn't have a + /// 128-bit integer type. + record metadata-hash-value { + /// 64 bits of a 128-bit hash value. + lower: u64, + /// Another 64 bits of a 128-bit hash value. + upper: u64, + } + + /// A descriptor is a reference to a filesystem object, which may be a file, + /// directory, named pipe, special file, or other object on which filesystem + /// calls may be made. + resource descriptor { + /// Return a stream for reading from a file, if available. + /// + /// May fail with an error-code describing why the file cannot be read. + /// + /// Multiple read, write, and append streams may be active on the same open + /// file and they do not interfere with each other. + /// + /// Note: This allows using `read-stream`, which is similar to `read` in POSIX. + read-via-stream: func( + /// The offset within the file at which to start reading. + offset: filesize, + ) -> result; + + /// Return a stream for writing to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be written. + /// + /// Note: This allows using `write-stream`, which is similar to `write` in + /// POSIX. + write-via-stream: func( + /// The offset within the file at which to start writing. + offset: filesize, + ) -> result; + + /// Return a stream for appending to a file, if available. + /// + /// May fail with an error-code describing why the file cannot be appended. + /// + /// Note: This allows using `write-stream`, which is similar to `write` with + /// `O_APPEND` in in POSIX. + append-via-stream: func() -> result; + + /// Provide file advisory information on a descriptor. + /// + /// This is similar to `posix_fadvise` in POSIX. + advise: func( + /// The offset within the file to which the advisory applies. + offset: filesize, + /// The length of the region to which the advisory applies. + length: filesize, + /// The advice. + advice: advice + ) -> result<_, error-code>; + + /// Synchronize the data of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fdatasync` in POSIX. + sync-data: func() -> result<_, error-code>; + + /// Get flags associated with a descriptor. + /// + /// Note: This returns similar flags to `fcntl(fd, F_GETFL)` in POSIX. + /// + /// Note: This returns the value that was the `fs_flags` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-flags: func() -> result; + + /// Get the dynamic type of a descriptor. + /// + /// Note: This returns the same value as the `type` field of the `fd-stat` + /// returned by `stat`, `stat-at` and similar. + /// + /// Note: This returns similar flags to the `st_mode & S_IFMT` value provided + /// by `fstat` in POSIX. + /// + /// Note: This returns the value that was the `fs_filetype` value returned + /// from `fdstat_get` in earlier versions of WASI. + get-type: func() -> result; + + /// Adjust the size of an open file. If this increases the file's size, the + /// extra bytes are filled with zeros. + /// + /// Note: This was called `fd_filestat_set_size` in earlier versions of WASI. + set-size: func(size: filesize) -> result<_, error-code>; + + /// Adjust the timestamps of an open file or directory. + /// + /// Note: This is similar to `futimens` in POSIX. + /// + /// Note: This was called `fd_filestat_set_times` in earlier versions of WASI. + set-times: func( + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Read from a descriptor, without using and updating the descriptor's offset. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a bool which, when true, indicates that the end of the + /// file was reached. The returned list will contain up to `length` bytes; it + /// may return fewer than requested, if the end of the file is reached or + /// if the I/O operation is interrupted. + /// + /// In the future, this may change to return a `stream`. + /// + /// Note: This is similar to `pread` in POSIX. + read: func( + /// The maximum number of bytes to read. + length: filesize, + /// The offset within the file at which to read. + offset: filesize, + ) -> result, bool>, error-code>; + + /// Write to a descriptor, without using and updating the descriptor's offset. + /// + /// It is valid to write past the end of a file; the file is extended to the + /// extent of the write, with bytes between the previous end and the start of + /// the write set to zero. + /// + /// In the future, this may change to take a `stream`. + /// + /// Note: This is similar to `pwrite` in POSIX. + write: func( + /// Data to write + buffer: list, + /// The offset within the file at which to write. + offset: filesize, + ) -> result; + + /// Read directory entries from a directory. + /// + /// On filesystems where directories contain entries referring to themselves + /// and their parents, often named `.` and `..` respectively, these entries + /// are omitted. + /// + /// This always returns a new stream which starts at the beginning of the + /// directory. Multiple streams may be active on the same directory, and they + /// do not interfere with each other. + read-directory: func() -> result; + + /// Synchronize the data and metadata of a file to disk. + /// + /// This function succeeds with no effect if the file descriptor is not + /// opened for writing. + /// + /// Note: This is similar to `fsync` in POSIX. + sync: func() -> result<_, error-code>; + + /// Create a directory. + /// + /// Note: This is similar to `mkdirat` in POSIX. + create-directory-at: func( + /// The relative path at which to create the directory. + path: string, + ) -> result<_, error-code>; + + /// Return the attributes of an open file or directory. + /// + /// Note: This is similar to `fstat` in POSIX, except that it does not return + /// device and inode information. For testing whether two descriptors refer to + /// the same underlying filesystem object, use `is-same-object`. To obtain + /// additional data that can be used do determine whether a file has been + /// modified, use `metadata-hash`. + /// + /// Note: This was called `fd_filestat_get` in earlier versions of WASI. + stat: func() -> result; + + /// Return the attributes of a file or directory. + /// + /// Note: This is similar to `fstatat` in POSIX, except that it does not + /// return device and inode information. See the `stat` description for a + /// discussion of alternatives. + /// + /// Note: This was called `path_filestat_get` in earlier versions of WASI. + stat-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + + /// Adjust the timestamps of a file or directory. + /// + /// Note: This is similar to `utimensat` in POSIX. + /// + /// Note: This was called `path_filestat_set_times` in earlier versions of + /// WASI. + set-times-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to operate on. + path: string, + /// The desired values of the data access timestamp. + data-access-timestamp: new-timestamp, + /// The desired values of the data modification timestamp. + data-modification-timestamp: new-timestamp, + ) -> result<_, error-code>; + + /// Create a hard link. + /// + /// Note: This is similar to `linkat` in POSIX. + link-at: func( + /// Flags determining the method of how the path is resolved. + old-path-flags: path-flags, + /// The relative source path from which to link. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path at which to create the hard link. + new-path: string, + ) -> result<_, error-code>; + + /// Open a file or directory. + /// + /// The returned descriptor is not guaranteed to be the lowest-numbered + /// descriptor not currently open/ it is randomized to prevent applications + /// from depending on making assumptions about indexes, since this is + /// error-prone in multi-threaded contexts. The returned descriptor is + /// guaranteed to be less than 2**31. + /// + /// If `flags` contains `descriptor-flags::mutate-directory`, and the base + /// descriptor doesn't have `descriptor-flags::mutate-directory` set, + /// `open-at` fails with `error-code::read-only`. + /// + /// If `flags` contains `write` or `mutate-directory`, or `open-flags` + /// contains `truncate` or `create`, and the base descriptor doesn't have + /// `descriptor-flags::mutate-directory` set, `open-at` fails with + /// `error-code::read-only`. + /// + /// Note: This is similar to `openat` in POSIX. + open-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the object to open. + path: string, + /// The method by which to open the file. + open-flags: open-flags, + /// Flags to use for the resulting descriptor. + %flags: descriptor-flags, + /// Permissions to use when creating a new file. + modes: modes + ) -> result; + + /// Read the contents of a symbolic link. + /// + /// If the contents contain an absolute or rooted path in the underlying + /// filesystem, this function fails with `error-code::not-permitted`. + /// + /// Note: This is similar to `readlinkat` in POSIX. + readlink-at: func( + /// The relative path of the symbolic link from which to read. + path: string, + ) -> result; + + /// Remove a directory. + /// + /// Return `error-code::not-empty` if the directory is not empty. + /// + /// Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + remove-directory-at: func( + /// The relative path to a directory to remove. + path: string, + ) -> result<_, error-code>; + + /// Rename a filesystem object. + /// + /// Note: This is similar to `renameat` in POSIX. + rename-at: func( + /// The relative source path of the file or directory to rename. + old-path: string, + /// The base directory for `new-path`. + new-descriptor: borrow, + /// The relative destination path to which to rename the file or directory. + new-path: string, + ) -> result<_, error-code>; + + /// Create a symbolic link (also known as a "symlink"). + /// + /// If `old-path` starts with `/`, the function fails with + /// `error-code::not-permitted`. + /// + /// Note: This is similar to `symlinkat` in POSIX. + symlink-at: func( + /// The contents of the symbolic link. + old-path: string, + /// The relative destination path at which to create the symbolic link. + new-path: string, + ) -> result<_, error-code>; + + /// Check accessibility of a filesystem path. + /// + /// Check whether the given filesystem path names an object which is + /// readable, writable, or executable, or whether it exists. + /// + /// This does not a guarantee that subsequent accesses will succeed, as + /// filesystem permissions may be modified asynchronously by external + /// entities. + /// + /// Note: This is similar to `faccessat` with the `AT_EACCESS` flag in POSIX. + access-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to check. + path: string, + /// The type of check to perform. + %type: access-type + ) -> result<_, error-code>; + + /// Unlink a filesystem object that is not a directory. + /// + /// Return `error-code::is-directory` if the path refers to a directory. + /// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + unlink-file-at: func( + /// The relative path to a file to unlink. + path: string, + ) -> result<_, error-code>; + + /// Change the permissions of a filesystem object that is not a directory. + /// + /// Note that the ultimate meanings of these permissions is + /// filesystem-specific. + /// + /// Note: This is similar to `fchmodat` in POSIX. + change-file-permissions-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to operate on. + path: string, + /// The new permissions for the filesystem object. + modes: modes, + ) -> result<_, error-code>; + + /// Change the permissions of a directory. + /// + /// Note that the ultimate meanings of these permissions is + /// filesystem-specific. + /// + /// Unlike in POSIX, the `executable` flag is not reinterpreted as a "search" + /// flag. `read` on a directory implies readability and searchability, and + /// `execute` is not valid for directories. + /// + /// Note: This is similar to `fchmodat` in POSIX. + change-directory-permissions-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path to operate on. + path: string, + /// The new permissions for the directory. + modes: modes, + ) -> result<_, error-code>; + + /// Request a shared advisory lock for an open file. + /// + /// This requests a *shared* lock; more than one shared lock can be held for + /// a file at the same time. + /// + /// If the open file has an exclusive lock, this function downgrades the lock + /// to a shared lock. If it has a shared lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified how shared locks interact with locks acquired by + /// non-WASI programs. + /// + /// This function blocks until the lock can be acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_SH)` in Unix. + lock-shared: func() -> result<_, error-code>; + + /// Request an exclusive advisory lock for an open file. + /// + /// This requests an *exclusive* lock; no other locks may be held for the + /// file while an exclusive lock is held. + /// + /// If the open file has a shared lock and there are no exclusive locks held + /// for the file, this function upgrades the lock to an exclusive lock. If the + /// open file already has an exclusive lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified whether this function succeeds if the file descriptor + /// is not opened for writing. It is unspecified how exclusive locks interact + /// with locks acquired by non-WASI programs. + /// + /// This function blocks until the lock can be acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_EX)` in Unix. + lock-exclusive: func() -> result<_, error-code>; + + /// Request a shared advisory lock for an open file. + /// + /// This requests a *shared* lock; more than one shared lock can be held for + /// a file at the same time. + /// + /// If the open file has an exclusive lock, this function downgrades the lock + /// to a shared lock. If it has a shared lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified how shared locks interact with locks acquired by + /// non-WASI programs. + /// + /// This function returns `error-code::would-block` if the lock cannot be + /// acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_SH | LOCK_NB)` in Unix. + try-lock-shared: func() -> result<_, error-code>; + + /// Request an exclusive advisory lock for an open file. + /// + /// This requests an *exclusive* lock; no other locks may be held for the + /// file while an exclusive lock is held. + /// + /// If the open file has a shared lock and there are no exclusive locks held + /// for the file, this function upgrades the lock to an exclusive lock. If the + /// open file already has an exclusive lock, this function has no effect. + /// + /// This requests an *advisory* lock, meaning that the file could be accessed + /// by other programs that don't hold the lock. + /// + /// It is unspecified whether this function succeeds if the file descriptor + /// is not opened for writing. It is unspecified how exclusive locks interact + /// with locks acquired by non-WASI programs. + /// + /// This function returns `error-code::would-block` if the lock cannot be + /// acquired. + /// + /// Not all filesystems support locking; on filesystems which don't support + /// locking, this function returns `error-code::unsupported`. + /// + /// Note: This is similar to `flock(fd, LOCK_EX | LOCK_NB)` in Unix. + try-lock-exclusive: func() -> result<_, error-code>; + + /// Release a shared or exclusive lock on an open file. + /// + /// Note: This is similar to `flock(fd, LOCK_UN)` in Unix. + unlock: func() -> result<_, error-code>; + + /// Test whether two descriptors refer to the same filesystem object. + /// + /// In POSIX, this corresponds to testing whether the two descriptors have the + /// same device (`st_dev`) and inode (`st_ino` or `d_ino`) numbers. + /// wasi-filesystem does not expose device and inode numbers, so this function + /// may be used instead. + is-same-object: func(other: borrow) -> bool; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a descriptor. + /// + /// This returns a hash of the last-modification timestamp and file size, and + /// may also include the inode number, device number, birth timestamp, and + /// other metadata fields that may change when the file is modified or + /// replaced. It may also include a secret value chosen by the + /// implementation and not otherwise exposed. + /// + /// Implementations are encourated to provide the following properties: + /// + /// - If the file is not modified or replaced, the computed hash value should + /// usually not change. + /// - If the object is modified or replaced, the computed hash value should + /// usually change. + /// - The inputs to the hash should not be easily computable from the + /// computed hash. + /// + /// However, none of these is required. + metadata-hash: func() -> result; + + /// Return a hash of the metadata associated with a filesystem object referred + /// to by a directory descriptor and a relative path. + /// + /// This performs the same hash computation as `metadata-hash`. + metadata-hash-at: func( + /// Flags determining the method of how the path is resolved. + path-flags: path-flags, + /// The relative path of the file or directory to inspect. + path: string, + ) -> result; + } + + /// A stream of directory entries. + resource directory-entry-stream { + /// Read a single directory entry from a `directory-entry-stream`. + read-directory-entry: func() -> result, error-code>; + } + + /// Attempts to extract a filesystem-related `error-code` from the stream + /// `error` provided. + /// + /// Stream operations which return `stream-error::last-operation-failed` + /// have a payload with more information about the operation that failed. + /// This payload can be passed through to this function to see if there's + /// filesystem-related information about the error to return. + /// + /// Note that this function is fallible because not all stream-related + /// errors are filesystem-related errors. + filesystem-error-code: func(err: borrow) -> option; +} diff --git a/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/world.wit b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/world.wit new file mode 100644 index 0000000..3f953f8 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/filesystem-2023-10-18/world.wit @@ -0,0 +1,6 @@ +package wasi:filesystem@0.2.0-rc-2023-10-18; + +world imports { + import types; + import preopens; +} diff --git a/go/examples/spin-basic/wit/deps/http-2023-10-18/incoming-handler.wit b/go/examples/spin-basic/wit/deps/http-2023-10-18/incoming-handler.wit new file mode 100644 index 0000000..6968d63 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/http-2023-10-18/incoming-handler.wit @@ -0,0 +1,24 @@ +// The `wasi:http/incoming-handler` interface is meant to be exported by +// components and called by the host in response to a new incoming HTTP +// response. +// +// NOTE: in Preview3, this interface will be merged with +// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface +// that takes a `request` parameter and returns a `response` result. +// +interface incoming-handler { + use types.{incoming-request, response-outparam}; + + // The `handle` function takes an outparam instead of returning its response + // so that the component may stream its response while streaming any other + // request or response bodies. The callee MUST write a response to the + // `response-outparam` and then finish the response before returning. The `handle` + // function is allowed to continue execution after finishing the response's + // output stream. While this post-response execution is taken off the + // critical path, since there is no return value, there is no way to report + // its success or failure. + handle: func( + request: incoming-request, + response-out: response-outparam + ); +} diff --git a/go/examples/spin-basic/wit/deps/http-2023-10-18/outgoing-handler.wit b/go/examples/spin-basic/wit/deps/http-2023-10-18/outgoing-handler.wit new file mode 100644 index 0000000..286e283 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/http-2023-10-18/outgoing-handler.wit @@ -0,0 +1,20 @@ +// The `wasi:http/outgoing-handler` interface is meant to be imported by +// components and implemented by the host. +// +// NOTE: in Preview3, this interface will be merged with +// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface +// that takes a `request` parameter and returns a `response` result. +// +interface outgoing-handler { + use types.{outgoing-request, request-options, future-incoming-response, error}; + + // The parameter and result types of the `handle` function allow the caller + // to concurrently stream the bodies of the outgoing request and the incoming + // response. + // Consumes the outgoing-request. Gives an error if the outgoing-request + // is invalid or cannot be satisfied by this handler. + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff --git a/go/examples/spin-basic/wit/deps/http-2023-10-18/proxy.wit b/go/examples/spin-basic/wit/deps/http-2023-10-18/proxy.wit new file mode 100644 index 0000000..dde0659 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/http-2023-10-18/proxy.wit @@ -0,0 +1,34 @@ +package wasi:http@0.2.0-rc-2023-10-18; + +// The `wasi:http/proxy` world captures a widely-implementable intersection of +// hosts that includes HTTP forward and reverse proxies. Components targeting +// this world may concurrently stream in and out any number of incoming and +// outgoing HTTP requests. +world proxy { + // HTTP proxies have access to time and randomness. + import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; + import wasi:clocks/timezone@0.2.0-rc-2023-10-18; + import wasi:random/random@0.2.0-rc-2023-10-18; + + // Proxies have standard output and error streams which are expected to + // terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.2.0-rc-2023-10-18; + import wasi:cli/stderr@0.2.0-rc-2023-10-18; + + // TODO: this is a temporary workaround until component tooling is able to + // gracefully handle the absence of stdin. Hosts must return an eof stream + // for this import, which is what wasi-libc + tooling will do automatically + // when this import is properly removed. + import wasi:cli/stdin@0.2.0-rc-2023-10-18; + + // This is the default handler to use when user code simply wants to make an + // HTTP request (e.g., via `fetch()`). + import outgoing-handler; + + // The host delivers incoming HTTP requests to a component by calling the + // `handle` function of this exported interface. A host may arbitrarily reuse + // or not reuse component instance when delivering incoming HTTP requests and + // thus a component must be able to handle 0..N calls to `handle`. + export incoming-handler; +} diff --git a/go/examples/spin-basic/wit/deps/http-2023-10-18/types.wit b/go/examples/spin-basic/wit/deps/http-2023-10-18/types.wit new file mode 100644 index 0000000..2471f04 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/http-2023-10-18/types.wit @@ -0,0 +1,208 @@ +/// The `wasi:http/types` interface is meant to be imported by components to +/// define the HTTP resource types and operations used by the component's +/// imported and exported interfaces. +interface types { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream}; + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + + // This type corresponds to HTTP standard Methods. + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + variant scheme { + HTTP, + HTTPS, + other(string) + } + + // TODO: perhaps better align with HTTP semantics? + /// This type enumerates the different kinds of errors that may occur when + /// initially returning a response. + variant error { + invalid-url(string), + timeout-error(string), + protocol-error(string), + unexpected-error(string) + } + + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. + resource fields { + // Multiple values for a header are multiple entries in the list with the + // same key. + constructor(entries: list>>); + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + get: func(name: string) -> list>; + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + set: func(name: string, value: list>); + delete: func(name: string); + append: func(name: string, value: list); + + // Values off wire are not necessarily well formed, so they are given by + // list instead of string. + entries: func() -> list>>; + + // Deep copy of all contents in a fields. + clone: func() -> fields; + } + + type headers = fields; + type trailers = fields; + + /// The following block defines the `incoming-request` and `outgoing-request` + /// resource types that correspond to HTTP standard Requests. + /// + /// The `consume` and `write` methods may only be called once (and + /// return failure thereafter). + resource incoming-request { + method: func() -> method; + + path-with-query: func() -> option; + + scheme: func() -> option; + + authority: func() -> option; + + headers: func() -> /* child */ headers; + + /// Returns the input-stream child at most once. + /// + /// If called more than once, subsequent calls return an error. + consume: func() -> result; + } + + resource outgoing-request { + constructor( + method: method, + path-with-query: option, + scheme: option, + authority: option, + headers: borrow + ); + + /// Will return the outgoing-body child at most once. + /// + /// If called more than once, subsequent calls return an error. + write: func() -> result< /* child */ outgoing-body>; + } + + /// Additional optional parameters that can be set when making a request. + record request-options { + // The following timeouts are specific to the HTTP protocol and work + // independently of the overall timeouts passed to `io.poll.poll-list`. + + /// The timeout for the initial connect. + connect-timeout-ms: option, + + /// The timeout for receiving the first byte of the response body. + first-byte-timeout-ms: option, + + /// The timeout for receiving the next chunk of bytes in the response body + /// stream. + between-bytes-timeout-ms: option + } + + /// The following block defines a special resource type used by the + /// `wasi:http/incoming-handler` interface. When resource types are added, this + /// block can be replaced by a proper `resource response-outparam { ... }` + /// definition. Later, with Preview3, the need for an outparam goes away entirely + /// (the `wasi:http/handler` interface used for both incoming and outgoing can + /// simply return a `stream`). + resource response-outparam { + set: static func(param: response-outparam, response: result); + } + + // This type corresponds to the HTTP standard Status Code. + type status-code = u16; + + /// The following block defines the `incoming-response` and `outgoing-response` + /// resource types that correspond to HTTP standard Responses. + /// + /// The `consume` and `write` methods may only be called once (and return failure thereafter). + resource incoming-response { + status: func() -> status-code; + + headers: func() -> /* child */ headers; + + // May be called at most once. returns error if called additional times. + // TODO: make incoming-request-consume work the same way, giving a child + // incoming-body. + consume: func() -> result; + } + + resource incoming-body { + // returned input-stream is a child - the implementation may trap if + // incoming-body is dropped (or consumed by call to + // incoming-body-finish) before the input-stream is dropped. + // May be called at most once. returns error if called additional times. + %stream: func() -> result; + + // takes ownership of incoming-body. this will trap if the + // incoming-body-stream child is still alive! + finish: static func(this: incoming-body) -> + /* transitive child of the incoming-response of incoming-body */ future-trailers; + } + + resource future-trailers { + /// Pollable that resolves when the body has been fully read, and the trailers + /// are ready to be consumed. + subscribe: func() -> /* child */ pollable; + + /// Retrieve reference to trailers, if they are ready. + get: func() -> option>; + } + + resource outgoing-response { + constructor(status-code: status-code, headers: borrow); + + /// Will give the child outgoing-response at most once. subsequent calls will + /// return an error. + write: func() -> result; + } + + resource outgoing-body { + /// Will give the child output-stream at most once. subsequent calls will + /// return an error. + write: func() -> result; + + /// Finalize an outgoing body, optionally providing trailers. This must be + /// called to signal that the response is complete. If the `outgoing-body` is + /// dropped without calling `outgoing-body-finalize`, the implementation + /// should treat the body as corrupted. + finish: static func(this: outgoing-body, trailers: option); + } + + /// The following block defines a special resource type used by the + /// `wasi:http/outgoing-handler` interface to emulate + /// `future>` in advance of Preview3. Given a + /// `future-incoming-response`, the client can call the non-blocking `get` + /// method to get the result if it is available. If the result is not available, + /// the client can call `listen` to get a `pollable` that can be passed to + /// `wasi:io/poll.poll-list`. + resource future-incoming-response { + /// option indicates readiness. + /// outer result indicates you are allowed to get the + /// incoming-response-or-error at most once. subsequent calls after ready + /// will return an error here. + /// inner result indicates whether the incoming-response was available, or an + /// error occured. + get: func() -> option>>; + + subscribe: func() -> /* child */ pollable; + } +} diff --git a/go/examples/spin-basic/wit/deps/io-2023-10-18/poll.wit b/go/examples/spin-basic/wit/deps/io-2023-10-18/poll.wit new file mode 100644 index 0000000..74835e6 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/io-2023-10-18/poll.wit @@ -0,0 +1,32 @@ +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +interface poll { + /// A "pollable" handle. + resource pollable; + + /// Poll for completion on a set of pollables. + /// + /// This function takes a list of pollables, which identify I/O sources of + /// interest, and waits until one or more of the events is ready for I/O. + /// + /// The result `list` contains one or more indices of handles in the + /// argument list that is ready for I/O. + /// + /// If the list contains more elements than can be indexed with a `u32` + /// value, this function traps. + /// + /// A timeout can be implemented by adding a pollable from the + /// wasi-clocks API to the list. + /// + /// This function does not return a `result`; polling in itself does not + /// do any I/O so it doesn't fail. If any of the I/O sources identified by + /// the pollables has an error, it is indicated by marking the source as + /// being reaedy for I/O. + poll-list: func(in: list>) -> list; + + /// Poll for completion on a single pollable. + /// + /// This function is similar to `poll-list`, but operates on only a single + /// pollable. When it returns, the handle is ready for I/O. + poll-one: func(in: borrow); +} diff --git a/go/examples/spin-basic/wit/deps/io-2023-10-18/streams.wit b/go/examples/spin-basic/wit/deps/io-2023-10-18/streams.wit new file mode 100644 index 0000000..c9600b7 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/io-2023-10-18/streams.wit @@ -0,0 +1,287 @@ +/// WASI I/O is an I/O abstraction API which is currently focused on providing +/// stream types. +/// +/// In the future, the component model is expected to add built-in stream types; +/// when it does, they are expected to subsume this API. +interface streams { + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + last-operation-failed(error), + /// The stream is closed: no more input will be accepted by the + /// stream. A closed output-stream will return this error on all + /// future operations. + closed + } + + /// Contextual error information about the last failure that happened on + /// a read, write, or flush from an `input-stream` or `output-stream`. + /// + /// This type is returned through the `stream-error` type whenever an + /// operation on a stream directly fails or an error is discovered + /// after-the-fact, for example when a write's failure shows up through a + /// later `flush` or `check-write`. + /// + /// Interfaces such as `wasi:filesystem/types` provide functionality to + /// further "downcast" this error into interface-specific error information. + resource error { + /// Returns a string that's suitable to assist humans in debugging this + /// error. + /// + /// The returned string will change across platforms and hosts which + /// means that parsing it, for example, would be a + /// platform-compatibility hazard. + to-debug-string: func() -> string; + } + + /// An input bytestream. + /// + /// `input-stream`s are *non-blocking* to the extent practical on underlying + /// platforms. I/O operations always return promptly; if fewer bytes are + /// promptly available than requested, they return the number of bytes promptly + /// available, which could even be zero. To wait for data to be available, + /// use the `subscribe` function to obtain a `pollable` which can be polled + /// for using `wasi:io/poll`. + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// This function returns a list of bytes containing the data that was + /// read, along with a `stream-status` which, indicates whether further + /// reads are expected to produce data. The returned list will contain up to + /// `len` bytes; it may return fewer than requested, but not more. An + /// empty list and `stream-status:open` indicates no more data is + /// available at this time, and that the pollable given by `subscribe` + /// will be ready when more data is available. + /// + /// Once a stream has reached the end, subsequent calls to `read` or + /// `skip` will always report `stream-status:ended` rather than producing more + /// data. + /// + /// When the caller gives a `len` of 0, it represents a request to read 0 + /// bytes. This read should always succeed and return an empty list and + /// the current `stream-status`. + /// + /// The `len` parameter is a `u64`, which could represent a list of u8 which + /// is not possible to allocate in wasm32, or not desirable to allocate as + /// as a return value by the callee. The callee may return a list of bytes + /// less than `len` in size while more bytes are available for reading. + read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, identical to `read`. + blocking-read: func( + /// The maximum number of bytes to read + len: u64 + ) -> result, stream-error>; + + /// Skip bytes from a stream. + /// + /// This is similar to the `read` function, but avoids copying the + /// bytes into the instance. + /// + /// Once a stream has reached the end, subsequent calls to read or + /// `skip` will always report end-of-stream rather than producing more + /// data. + /// + /// This function returns the number of bytes skipped, along with a + /// `stream-status` indicating whether the end of the stream was + /// reached. The returned value will be at most `len`; it may be less. + skip: func( + /// The maximum number of bytes to skip. + len: u64, + ) -> result; + + /// Skip bytes from a stream, after blocking until at least one byte + /// can be skipped. Except for blocking behavior, identical to `skip`. + blocking-skip: func( + /// The maximum number of bytes to skip. + len: u64, + ) -> result; + + /// Create a `pollable` which will resolve once either the specified stream + /// has bytes available to read or the other end of the stream has been + /// closed. + /// The created `pollable` is a child resource of the `input-stream`. + /// Implementations may trap if the `input-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + subscribe: func() -> pollable; + } + + + /// An output bytestream. + /// + /// `output-stream`s are *non-blocking* to the extent practical on + /// underlying platforms. Except where specified otherwise, I/O operations also + /// always return promptly, after the number of bytes that can be written + /// promptly, which could even be zero. To wait for the stream to be ready to + /// accept data, the `subscribe` function to obtain a `pollable` which can be + /// polled for using `wasi:io/poll`. + resource output-stream { + /// Check readiness for writing. This function never blocks. + /// + /// Returns the number of bytes permitted for the next call to `write`, + /// or an error. Calling `write` with more bytes than this function has + /// permitted will trap. + /// + /// When this function returns 0 bytes, the `subscribe` pollable will + /// become ready when this function will report at least 1 byte, or an + /// error. + check-write: func() -> result; + + /// Perform a write. This function never blocks. + /// + /// Precondition: check-write gave permit of Ok(n) and contents has a + /// length of less than or equal to n. Otherwise, this function will trap. + /// + /// returns Err(closed) without writing if the stream has closed since + /// the last call to check-write provided a permit. + write: func( + contents: list + ) -> result<_, stream-error>; + + /// Perform a write of up to 4096 bytes, and then flush the stream. Block + /// until all of these operations are complete, or an error occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-and-flush: func( + contents: list + ) -> result<_, stream-error>; + + /// Request to flush buffered output. This function never blocks. + /// + /// This tells the output-stream that the caller intends any buffered + /// output to be flushed. the output which is expected to be flushed + /// is all that has been passed to `write` prior to this call. + /// + /// Upon calling this function, the `output-stream` will not accept any + /// writes (`check-write` will return `ok(0)`) until the flush has + /// completed. The `subscribe` pollable will become ready when the + /// flush has completed and the stream can accept more writes. + flush: func() -> result<_, stream-error>; + + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + blocking-flush: func() -> result<_, stream-error>; + + /// Create a `pollable` which will resolve once the output-stream + /// is ready for more writing, or an error has occured. When this + /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an + /// error. + /// + /// If the stream is closed, this pollable is always ready immediately. + /// + /// The created `pollable` is a child resource of the `output-stream`. + /// Implementations may trap if the `output-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + subscribe: func() -> pollable; + + /// Write zeroes to a stream. + /// + /// this should be used precisely like `write` with the exact same + /// preconditions (must use check-write first), but instead of + /// passing a list of bytes, you simply pass the number of zero-bytes + /// that should be written. + write-zeroes: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Perform a write of up to 4096 zeroes, and then flush the stream. + /// Block until all of these operations are complete, or an error + /// occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// poll-one(pollable); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// poll-one(pollable); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-zeroes-and-flush: func( + /// The number of zero-bytes to write + len: u64 + ) -> result<_, stream-error>; + + /// Read from one stream and write to another. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + /// + /// Unlike other I/O functions, this function blocks until all the data + /// read from the input stream has been written to the output stream. + splice: func( + /// The stream to read from + src: input-stream, + /// The number of bytes to splice + len: u64, + ) -> result; + + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until at least + /// one byte can be read. + blocking-splice: func( + /// The stream to read from + src: input-stream, + /// The number of bytes to splice + len: u64, + ) -> result; + + /// Forward the entire contents of an input stream to an output stream. + /// + /// This function repeatedly reads from the input stream and writes + /// the data to the output stream, until the end of the input stream + /// is reached, or an error is encountered. + /// + /// Unlike other I/O functions, this function blocks until the end + /// of the input stream is seen and all the data has been written to + /// the output stream. + /// + /// This function returns the number of bytes transferred, and the status of + /// the output stream. + forward: func( + /// The stream to read from + src: input-stream + ) -> result; + } +} diff --git a/go/examples/spin-basic/wit/deps/io-2023-10-18/world.wit b/go/examples/spin-basic/wit/deps/io-2023-10-18/world.wit new file mode 100644 index 0000000..a0bcd31 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/io-2023-10-18/world.wit @@ -0,0 +1 @@ +package wasi:io@0.2.0-rc-2023-10-18; diff --git a/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure-seed.wit b/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure-seed.wit new file mode 100644 index 0000000..139aed1 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure-seed.wit @@ -0,0 +1,24 @@ +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +interface insecure-seed { + /// Return a 128-bit value that may contain a pseudo-random value. + /// + /// The returned value is not required to be computed from a CSPRNG, and may + /// even be entirely deterministic. Host implementations are encouraged to + /// provide pseudo-random values to any program exposed to + /// attacker-controlled content, to enable DoS protection built into many + /// languages' hash-map implementations. + /// + /// This function is intended to only be called once, by a source language + /// to initialize Denial Of Service (DoS) protection in its hash-map + /// implementation. + /// + /// # Expected future evolution + /// + /// This will likely be changed to a value import, to prevent it from being + /// called multiple times and potentially used for purposes other than DoS + /// protection. + insecure-seed: func() -> tuple; +} diff --git a/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure.wit b/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure.wit new file mode 100644 index 0000000..2ffd223 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/random-2023-10-18/insecure.wit @@ -0,0 +1,21 @@ +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +interface insecure { + /// Return `len` insecure pseudo-random bytes. + /// + /// This function is not cryptographically secure. Do not use it for + /// anything related to security. + /// + /// There are no requirements on the values of the returned bytes, however + /// implementations are encouraged to return evenly distributed values with + /// a long period. + get-insecure-random-bytes: func(len: u64) -> list; + + /// Return an insecure pseudo-random `u64` value. + /// + /// This function returns the same type of pseudo-random data as + /// `get-insecure-random-bytes`, represented as a `u64`. + get-insecure-random-u64: func() -> u64; +} diff --git a/go/examples/spin-basic/wit/deps/random-2023-10-18/random.wit b/go/examples/spin-basic/wit/deps/random-2023-10-18/random.wit new file mode 100644 index 0000000..2c3c6a8 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/random-2023-10-18/random.wit @@ -0,0 +1,25 @@ +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +interface random { + /// Return `len` cryptographically-secure random or pseudo-random bytes. + /// + /// This function must produce data at least as cryptographically secure and + /// fast as an adequately seeded cryptographically-secure pseudo-random + /// number generator (CSPRNG). It must not block, from the perspective of + /// the calling program, under any circumstances, including on the first + /// request and on requests for numbers of bytes. The returned data must + /// always be unpredictable. + /// + /// This function must always return fresh data. Deterministic environments + /// must omit this function, rather than implementing it with deterministic + /// data. + get-random-bytes: func(len: u64) -> list; + + /// Return a cryptographically-secure random or pseudo-random `u64` value. + /// + /// This function returns the same type of data as `get-random-bytes`, + /// represented as a `u64`. + get-random-u64: func() -> u64; +} diff --git a/go/examples/spin-basic/wit/deps/random-2023-10-18/world.wit b/go/examples/spin-basic/wit/deps/random-2023-10-18/world.wit new file mode 100644 index 0000000..dcbff93 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/random-2023-10-18/world.wit @@ -0,0 +1,7 @@ +package wasi:random@0.2.0-rc-2023-10-18; + +world imports { + import random; + import insecure; + import insecure-seed; +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/instance-network.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/instance-network.wit new file mode 100644 index 0000000..14e4479 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/instance-network.wit @@ -0,0 +1,9 @@ + +/// This interface provides a value-export of the default network handle.. +interface instance-network { + use network.{network}; + + /// Get a handle to the default network. + instance-network: func() -> network; + +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/ip-name-lookup.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/ip-name-lookup.wit new file mode 100644 index 0000000..f2dab32 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/ip-name-lookup.wit @@ -0,0 +1,61 @@ + +interface ip-name-lookup { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-address, ip-address-family}; + + + /// Resolve an internet host name to a list of IP addresses. + /// + /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. + /// + /// # Parameters + /// - `name`: The name to look up. IP addresses are not allowed. Unicode domain names are automatically converted + /// to ASCII using IDNA encoding. + /// - `address-family`: If provided, limit the results to addresses of this specific address family. + /// - `include-unavailable`: When set to true, this function will also return addresses of which the runtime + /// thinks (or knows) can't be connected to at the moment. For example, this will return IPv6 addresses on + /// systems without an active IPv6 interface. Notes: + /// - Even when no public IPv6 interfaces are present or active, names like "localhost" can still resolve to an IPv6 address. + /// - Whatever is "available" or "unavailable" is volatile and can change everytime a network cable is unplugged. + /// + /// This function never blocks. It either immediately fails or immediately returns successfully with a `resolve-address-stream` + /// that can be used to (asynchronously) fetch the results. + /// + /// At the moment, the stream never completes successfully with 0 items. Ie. the first call + /// to `resolve-next-address` never returns `ok(none)`. This may change in the future. + /// + /// # Typical errors + /// - `invalid-argument`: `name` is a syntactically invalid domain name. + /// - `invalid-argument`: `name` is an IP address. + /// - `not-supported`: The specified `address-family` is not supported. (EAI_FAMILY) + /// + /// # References: + /// - + /// - + /// - + /// - + resolve-addresses: func(network: borrow, name: string, address-family: option, include-unavailable: bool) -> result; + + resource resolve-address-stream { + /// Returns the next address from the resolver. + /// + /// This function should be called multiple times. On each call, it will + /// return the next address in connection order preference. If all + /// addresses have been exhausted, this function returns `none`. + /// + /// This function never returns IPv4-mapped IPv6 addresses. + /// + /// # Typical errors + /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) + /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) + /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) + /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) + resolve-next-address: func() -> result, error-code>; + + /// Create a `pollable` which will resolve once the stream is ready for I/O. + /// + /// Note: this function is here for WASI Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/network.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/network.wit new file mode 100644 index 0000000..fc51604 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/network.wit @@ -0,0 +1,146 @@ + +interface network { + /// An opaque resource that represents access to (a subset of) the network. + /// This enables context-based security for networking. + /// There is no need for this to map 1:1 to a physical network interface. + resource network; + + /// Error codes. + /// + /// In theory, every API can return any error code. + /// In practice, API's typically only return the errors documented per API + /// combined with a couple of errors that are always possible: + /// - `unknown` + /// - `access-denied` + /// - `not-supported` + /// - `out-of-memory` + /// - `concurrency-conflict` + /// + /// See each individual API for what the POSIX equivalents are. They sometimes differ per API. + enum error-code { + // ### GENERAL ERRORS ### + + /// Unknown error + unknown, + + /// Access denied. + /// + /// POSIX equivalent: EACCES, EPERM + access-denied, + + /// The operation is not supported. + /// + /// POSIX equivalent: EOPNOTSUPP + not-supported, + + /// One of the arguments is invalid. + /// + /// POSIX equivalent: EINVAL + invalid-argument, + + /// Not enough memory to complete the operation. + /// + /// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY + out-of-memory, + + /// The operation timed out before it could finish completely. + timeout, + + /// This operation is incompatible with another asynchronous operation that is already in progress. + /// + /// POSIX equivalent: EALREADY + concurrency-conflict, + + /// Trying to finish an asynchronous operation that: + /// - has not been started yet, or: + /// - was already finished by a previous `finish-*` call. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + not-in-progress, + + /// The operation has been aborted because it could not be completed immediately. + /// + /// Note: this is scheduled to be removed when `future`s are natively supported. + would-block, + + + + // ### TCP & UDP SOCKET ERRORS ### + + /// The operation is not valid in the socket's current state. + invalid-state, + + /// A new socket resource could not be created because of a system limit. + new-socket-limit, + + /// A bind operation failed because the provided address is not an address that the `network` can bind to. + address-not-bindable, + + /// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. + address-in-use, + + /// The remote address is not reachable + remote-unreachable, + + + // ### TCP SOCKET ERRORS ### + + /// The connection was forcefully rejected + connection-refused, + + /// The connection was reset. + connection-reset, + + /// A connection was aborted. + connection-aborted, + + // ### UDP SOCKET ERRORS ### + datagram-too-large, + + + // ### NAME LOOKUP ERRORS ### + + /// Name does not exist or has no suitable associated IP addresses. + name-unresolvable, + + /// A temporary failure in name resolution occurred. + temporary-resolver-failure, + + /// A permanent failure in name resolution occurred. + permanent-resolver-failure, + } + + enum ip-address-family { + /// Similar to `AF_INET` in POSIX. + ipv4, + + /// Similar to `AF_INET6` in POSIX. + ipv6, + } + + type ipv4-address = tuple; + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, // sin_port + address: ipv4-address, // sin_addr + } + + record ipv6-socket-address { + port: u16, // sin6_port + flow-info: u32, // sin6_flowinfo + address: ipv6-address, // sin6_addr + scope-id: u32, // sin6_scope_id + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } + +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp-create-socket.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp-create-socket.wit new file mode 100644 index 0000000..a9a3373 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp-create-socket.wit @@ -0,0 +1,26 @@ + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + use tcp.{tcp-socket}; + + /// Create a new TCP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect` + /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + create-tcp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp.wit new file mode 100644 index 0000000..448f629 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/tcp.wit @@ -0,0 +1,268 @@ + +interface tcp { + use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream, output-stream}; + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + enum shutdown-type { + /// Similar to `SHUT_RD` in POSIX. + receive, + + /// Similar to `SHUT_WR` in POSIX. + send, + + /// Similar to `SHUT_RDWR` in POSIX. + both, + } + + + /// A TCP socket handle. + resource tcp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// When a socket is not explicitly bound, the first invocation to a listen or connect operation will + /// implicitly bind the socket. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) + /// - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Connect to a remote endpoint. + /// + /// On success: + /// - the socket is transitioned into the Connection state + /// - a pair of streams is returned that can be used to read & write to the connection + /// + /// POSIX mentions: + /// > If connect() fails, the state of the socket is unspecified. Conforming applications should + /// > close the file descriptor and create a new socket before attempting to reconnect. + /// + /// WASI prescribes the following behavior: + /// - If `connect` fails because an input/state validation error, the socket should remain usable. + /// - If a connection was actually attempted but failed, the socket should become unusable for further network communication. + /// Besides `drop`, any method after such a failure may return an error. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) + /// - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address, but the socket has `ipv6-only` enabled. (EINVAL, EADDRNOTAVAIL on Illumos) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) + /// - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// - `invalid-state`: The socket is already in the Connection state. (EISCONN) + /// - `invalid-state`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows) + /// + /// # Typical `finish` errors + /// - `timeout`: Connection timed out. (ETIMEDOUT) + /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) + /// - `connection-reset`: The connection was reset. (ECONNRESET) + /// - `connection-aborted`: The connection was aborted. (ECONNABORTED) + /// - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `not-in-progress`: A `connect` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result, error-code>; + + /// Start listening for new connections. + /// + /// Transitions the socket into the Listener state. + /// + /// Unlike POSIX: + /// - this function is async. This enables interactive WASI hosts to inject permission prompts. + /// - the socket must already be explicitly bound. + /// + /// # Typical `start` errors + /// - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) + /// - `invalid-state`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD) + /// - `invalid-state`: The socket is already in the Listener state. + /// + /// # Typical `finish` errors + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) + /// - `not-in-progress`: A `listen` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + start-listen: func() -> result<_, error-code>; + finish-listen: func() -> result<_, error-code>; + + /// Accept a new client socket. + /// + /// The returned socket is bound and in the Connection state. The following properties are inherited from the listener socket: + /// - `address-family` + /// - `ipv6-only` + /// - `keep-alive` + /// - `no-delay` + /// - `unicast-hop-limit` + /// - `receive-buffer-size` + /// - `send-buffer-size` + /// + /// On success, this function returns the newly accepted client socket along with + /// a pair of streams that can be used to read & write to the connection. + /// + /// # Typical errors + /// - `invalid-state`: Socket is not in the Listener state. (EINVAL) + /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) + /// - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References + /// - + /// - + /// - + /// - + accept: func() -> result, error-code>; + + /// Get the bound local address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the remote address. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> result<_, error-code>; + + /// Hints the desired listen queue size. Implementations are free to ignore this. + /// + /// # Typical errors + /// - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. + /// - `invalid-state`: (set) The socket is already in the Connection state. + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + + /// Equivalent to the SO_KEEPALIVE socket option. + keep-alive: func() -> result; + set-keep-alive: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the TCP_NODELAY socket option. + /// + /// The default value is `false`. + no-delay: func() -> result; + set-no-delay: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + /// + /// # Typical errors + /// - `invalid-argument`: (set) The TTL value must be 1 or higher. + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. + /// In other words, after setting a value, reading the same setting back may return a different value. + /// + /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of + /// actual data to be sent/received by the application, because the kernel might also use the buffer space + /// for internal metadata structures. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + /// + /// # Typical errors + /// - `invalid-state`: (set) The socket is already in the Connection state. + /// - `invalid-state`: (set) The socket is already in the Listener state. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + + /// Create a `pollable` which will resolve once the socket is ready for I/O. + /// + /// Note: this function is here for WASI Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + + /// Initiate a graceful shutdown. + /// + /// - receive: the socket is not expecting to receive any more data from the peer. All subsequent read + /// operations on the `input-stream` associated with this socket will return an End Of Stream indication. + /// Any data still in the receive queue at time of calling `shutdown` will be discarded. + /// - send: the socket is not expecting to send any more data to the peer. All subsequent write + /// operations on the `output-stream` associated with this socket will return an error. + /// - both: same effect as receive & send combined. + /// + /// The shutdown function does not close (drop) the socket. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not in the Connection state. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp-create-socket.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp-create-socket.wit new file mode 100644 index 0000000..e026359 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp-create-socket.wit @@ -0,0 +1,26 @@ + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + use udp.{udp-socket}; + + /// Create a new UDP socket. + /// + /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. + /// + /// This function does not require a network capability handle. This is considered to be safe because + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` is called, + /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. + /// + /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. + /// + /// # Typical errors + /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) + /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) + /// + /// # References: + /// - + /// - + /// - + /// - + create-udp-socket: func(address-family: ip-address-family) -> result; +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp.wit new file mode 100644 index 0000000..91a8c6c --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/udp.wit @@ -0,0 +1,213 @@ + +interface udp { + use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + + record datagram { + data: list, // Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes. + remote-address: ip-socket-address, + + /// Possible future additions: + /// local-address: ip-socket-address, // IP_PKTINFO / IP_RECVDSTADDR / IPV6_PKTINFO + /// local-interface: u32, // IP_PKTINFO / IP_RECVIF + /// ttl: u8, // IP_RECVTTL + /// dscp: u6, // IP_RECVTOS + /// ecn: u2, // IP_RECVTOS + } + + + + /// A UDP socket handle. + resource udp-socket { + /// Bind the socket to a specific network on the provided IP address and port. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. + /// + /// When a socket is not explicitly bound, the first invocation to connect will implicitly bind the socket. + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) + /// - `invalid-state`: The socket is already bound. (EINVAL) + /// + /// # Typical `finish` errors + /// - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `not-in-progress`: A `bind` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + + /// Set the destination address. + /// + /// The local-address is updated based on the best network path to `remote-address`. + /// + /// When a destination address is set: + /// - all receive operations will only return datagrams sent from the provided `remote-address`. + /// - the `send` function can only be used to send to this destination. + /// + /// Note that this function does not generate any network traffic and the peer is not aware of this "connection". + /// + /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. + /// + /// # Typical `start` errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The socket is already bound to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. + /// + /// # Typical `finish` errors + /// - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) + /// - `not-in-progress`: A `connect` operation is not in progress. + /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result<_, error-code>; + + /// Receive messages on the socket. + /// + /// This function attempts to receive up to `max-results` datagrams on the socket without blocking. + /// The returned list may contain fewer elements than requested, but never more. + /// If `max-results` is 0, this function returns successfully with an empty list. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. (EINVAL) + /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) + /// - `would-block`: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + receive: func(max-results: u64) -> result, error-code>; + + /// Send messages on the socket. + /// + /// This function attempts to send all provided `datagrams` on the socket without blocking and + /// returns how many messages were actually sent (or queued for sending). + /// + /// This function semantically behaves the same as iterating the `datagrams` list and sequentially + /// sending each individual datagram until either the end of the list has been reached or the first error occurred. + /// If at least one datagram has been sent successfully, this function never returns an error. + /// + /// If the input list is empty, the function returns `ok(0)`. + /// + /// The remote address option is required. To send a message to the "connected" peer, + /// call `remote-address` to get their address. + /// + /// # Typical errors + /// - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) + /// - `invalid-argument`: `remote-address` is a non-IPv4-mapped IPv6 address, but the socket was bound to a specific IPv4-mapped IPv6 address. (or vice versa) + /// - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) + /// - `invalid-argument`: The socket is in "connected" mode and the `datagram.remote-address` does not match the address passed to `connect`. (EISCONN) + /// - `invalid-state`: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind. + /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) + /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) + /// - `would-block`: The send buffer is currently full. (EWOULDBLOCK, EAGAIN) + /// + /// # References + /// - + /// - + /// - + /// - + /// - + /// - + /// - + /// - + send: func(datagrams: list) -> result; + + /// Get the current bound address. + /// + /// POSIX mentions: + /// > If the socket has not been bound to a local name, the value + /// > stored in the object pointed to by `address` is unspecified. + /// + /// WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not bound to any local address. + /// + /// # References + /// - + /// - + /// - + /// - + local-address: func() -> result; + + /// Get the address set with `connect`. + /// + /// # Typical errors + /// - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) + /// + /// # References + /// - + /// - + /// - + /// - + remote-address: func() -> result; + + /// Whether this is a IPv4 or IPv6 socket. + /// + /// Equivalent to the SO_DOMAIN socket option. + address-family: func() -> ip-address-family; + + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. + /// + /// Equivalent to the IPV6_V6ONLY socket option. + /// + /// # Typical errors + /// - `not-supported`: (get/set) `this` socket is an IPv4 socket. + /// - `invalid-state`: (set) The socket is already bound. + /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) + ipv6-only: func() -> result; + set-ipv6-only: func(value: bool) -> result<_, error-code>; + + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + + /// The kernel buffer space reserved for sends/receives on this socket. + /// + /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. + /// In other words, after setting a value, reading the same setting back may return a different value. + /// + /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of + /// actual data to be sent/received by the application, because the kernel might also use the buffer space + /// for internal metadata structures. + /// + /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + + /// Create a `pollable` which will resolve once the socket is ready for I/O. + /// + /// Note: this function is here for WASI Preview2 only. + /// It's planned to be removed when `future` is natively supported in Preview3. + subscribe: func() -> pollable; + } +} diff --git a/go/examples/spin-basic/wit/deps/sockets-2023-10-18/world.wit b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/world.wit new file mode 100644 index 0000000..d16530c --- /dev/null +++ b/go/examples/spin-basic/wit/deps/sockets-2023-10-18/world.wit @@ -0,0 +1,11 @@ +package wasi:sockets@0.2.0-rc-2023-10-18; + +world imports { + import instance-network; + import network; + import udp; + import udp-create-socket; + import tcp; + import tcp-create-socket; + import ip-name-lookup; +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/key-value.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/key-value.wit new file mode 100644 index 0000000..7ba4ed9 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/key-value.wit @@ -0,0 +1,47 @@ +interface key-value { + /// An open key-value store + resource store { + /// Open the store with the specified label. + /// + /// `label` must refer to a store allowed in the spin.toml manifest. + /// + /// `error::no-such-store` will be raised if the `label` is not recognized. + open: static func(label: string) -> result; + + /// Get the value associated with the specified `key` + /// + /// Returns `ok(none)` if the key does not exist. + get: func(key: string) -> result>, error>; + + /// Set the `value` associated with the specified `key` overwriting any existing value. + set: func(key: string, value: list) -> result<_, error>; + + /// Delete the tuple with the specified `key` + /// + /// No error is raised if a tuple did not previously exist for `key`. + delete: func(key: string) -> result<_, error>; + + /// Return whether a tuple exists for the specified `key` + exists: func(key: string) -> result; + + /// Return a list of all the keys + get-keys: func() -> result, error>; + } + + /// The set of errors which may be raised by functions in this interface + variant error { + /// Too many stores have been opened simultaneously. Closing one or more + /// stores prior to retrying may address this. + store-table-full, + + /// The host does not recognize the store label requested. + no-such-store, + + /// The requesting component does not have access to the specified store + /// (which may or may not exist). + access-denied, + + /// Some implementation-specific error has occurred (e.g. I/O) + other(string) + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/llm.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/llm.wit new file mode 100644 index 0000000..bcb59b8 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/llm.wit @@ -0,0 +1,70 @@ +// A WASI interface dedicated to performing inferencing for Large Language Models. +interface llm { + /// A Large Language Model. + type inferencing-model = string; + + /// Inference request parameters + record inferencing-params { + /// The maximum tokens that should be inferred. + /// + /// Note: the backing implementation may return less tokens. + max-tokens: u32, + /// The amount the model should avoid repeating tokens. + repeat-penalty: f32, + /// The number of tokens the model should apply the repeat penalty to. + repeat-penalty-last-n-token-count: u32, + /// The randomness with which the next token is selected. + temperature: f32, + /// The number of possible next tokens the model will choose from. + top-k: u32, + /// The probability total of next tokens the model will choose from. + top-p: f32 + } + + /// The set of errors which may be raised by functions in this interface + variant error { + model-not-supported, + runtime-error(string), + invalid-input(string) + } + + /// An inferencing result + record inferencing-result { + /// The text generated by the model + // TODO: this should be a stream + text: string, + /// Usage information about the inferencing request + usage: inferencing-usage + } + + /// Usage information related to the inferencing result + record inferencing-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + /// Number of tokens generated by the inferencing operation + generated-token-count: u32 + } + + /// Perform inferencing using the provided model and prompt with the given optional params + infer: func(model: inferencing-model, prompt: string, params: option) -> result; + + /// The model used for generating embeddings + type embedding-model = string; + + /// Generate embeddings for the supplied list of text + generate-embeddings: func(model: embedding-model, text: list) -> result; + + /// Result of generating embeddings + record embeddings-result { + /// The embeddings generated by the request + embeddings: list>, + /// Usage related to the embeddings generation request + usage: embeddings-usage + } + + /// Usage related to an embeddings generation request + record embeddings-usage { + /// Number of tokens in the prompt + prompt-token-count: u32, + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/mqtt.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/mqtt.wit new file mode 100644 index 0000000..32f04fb --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/mqtt.wit @@ -0,0 +1,31 @@ +interface mqtt { + /// Errors related to interacting with Mqtt + variant error { + /// An invalid address string + invalid-address, + /// There are too many open connections + too-many-connections, + /// Connection failure e.g. address not allowed. + connection-failed(string), + /// Some other error occurred + other(string), + } + + /// QoS for publishing Mqtt messages + enum qos { + at-most-once, + at-least-once, + exactly-once, + } + + resource connection { + /// Open a connection to the Mqtt instance at `address`. + open: static func(address: string, username: string, password: string, keep-alive-interval-in-secs: u64) -> result; + + /// Publish an Mqtt message to the specified `topic`. + publish: func(topic: string, payload: payload, qos: qos) -> result<_, error>; + } + + /// The message payload. + type payload = list; +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/mysql.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/mysql.wit new file mode 100644 index 0000000..446cf89 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/mysql.wit @@ -0,0 +1,15 @@ +interface mysql { + use rdbms-types.{parameter-value, row-set, error}; + + /// A connection to a MySQL database. + resource connection { + /// Open a connection to the MySQL instance at `address`. + open: static func(address: string) -> result; + + /// query the database: select + query: func(statement: string, params: list) -> result; + + /// execute command to the database: insert, update, delete + execute: func(statement: string, params: list) -> result<_, error>; + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/postgres.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/postgres.wit new file mode 100644 index 0000000..ebe1ec6 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/postgres.wit @@ -0,0 +1,15 @@ +interface postgres { + use rdbms-types.{parameter-value, row-set, error}; + + /// A connection to a postgres database. + resource connection { + /// Open a connection to the Postgres instance at `address`. + open: static func(address: string) -> result; + + /// Query the database. + query: func(statement: string, params: list) -> result; + + /// Execute command to the database. + execute: func(statement: string, params: list) -> result; + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/rdbms-types.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/rdbms-types.wit new file mode 100644 index 0000000..aff2e96 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/rdbms-types.wit @@ -0,0 +1,80 @@ +interface rdbms-types { + /// Errors related to interacting with a database. + variant error { + connection-failed(string), + bad-parameter(string), + query-failed(string), + value-conversion-failed(string), + other(string) + } + + /// Data types for a database column + enum db-data-type { + boolean, + int8, + int16, + int32, + int64, + uint8, + uint16, + uint32, + uint64, + floating32, + floating64, + str, + binary, + other, + } + + /// Database values + variant db-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + unsupported, + } + + /// Values used in parameterized queries + variant parameter-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + uint8(u8), + uint16(u16), + uint32(u32), + uint64(u64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + db-null, + } + + /// A database column + record column { + name: string, + data-type: db-data-type, + } + + /// A database row + type row = list; + + /// A set of database rows + record row-set { + columns: list, + rows: list, + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/redis.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/redis.wit new file mode 100644 index 0000000..27446eb --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/redis.wit @@ -0,0 +1,70 @@ +interface redis { + /// Errors related to interacting with Redis + variant error { + /// An invalid address string + invalid-address, + /// There are too many open connections + too-many-connections, + /// A retrieved value was not of the correct type + type-error, + /// Some other error occurred + other(string), + } + + resource connection { + /// Open a connection to the Redis instance at `address`. + open: static func(address: string) -> result; + + /// Publish a Redis message to the specified channel. + publish: func(channel: string, payload: payload) -> result<_, error>; + + /// Get the value of a key. + get: func(key: string) -> result, error>; + + /// Set key to value. + /// + /// If key already holds a value, it is overwritten. + set: func(key: string, value: payload) -> result<_, error>; + + /// Increments the number stored at key by one. + /// + /// If the key does not exist, it is set to 0 before performing the operation. + /// An `error::type-error` is returned if the key contains a value of the wrong type + /// or contains a string that can not be represented as integer. + incr: func(key: string) -> result; + + /// Removes the specified keys. + /// + /// A key is ignored if it does not exist. Returns the number of keys deleted. + del: func(keys: list) -> result; + + /// Add the specified `values` to the set named `key`, returning the number of newly-added values. + sadd: func(key: string, values: list) -> result; + + /// Retrieve the contents of the set named `key`. + smembers: func(key: string) -> result, error>; + + /// Remove the specified `values` from the set named `key`, returning the number of newly-removed values. + srem: func(key: string, values: list) -> result; + + /// Execute an arbitrary Redis command and receive the result. + execute: func(command: string, arguments: list) -> result, error>; + } + + /// The message payload. + type payload = list; + + /// A parameter type for the general-purpose `execute` function. + variant redis-parameter { + int64(s64), + binary(payload) + } + + /// A return type for the general-purpose `execute` function. + variant redis-result { + nil, + status(string), + int64(s64), + binary(payload) + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/sqlite.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/sqlite.wit new file mode 100644 index 0000000..d82f2d9 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/sqlite.wit @@ -0,0 +1,50 @@ +interface sqlite { + /// A handle to an open sqlite instance + resource connection { + /// Open a connection to a named database instance. + /// + /// If `database` is "default", the default instance is opened. + /// + /// `error::no-such-database` will be raised if the `name` is not recognized. + open: static func(database: string) -> result; + + /// Execute a statement returning back data if there is any + execute: func(statement: string, parameters: list) -> result; + } + + /// The set of errors which may be raised by functions in this interface + variant error { + /// The host does not recognize the database name requested. + no-such-database, + /// The requesting component does not have access to the specified database (which may or may not exist). + access-denied, + /// The provided connection is not valid + invalid-connection, + /// The database has reached its capacity + database-full, + /// Some implementation-specific error has occurred (e.g. I/O) + io(string) + } + + /// A result of a query + record query-result { + /// The names of the columns retrieved in the query + columns: list, + /// the row results each containing the values for all the columns for a given row + rows: list, + } + + /// A set of values for each of the columns in a query-result + record row-result { + values: list + } + + /// A single column's result from a database query + variant value { + integer(s64), + real(f64), + text(string), + blob(list), + null + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/variables.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/variables.wit new file mode 100644 index 0000000..6c0511a --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/variables.wit @@ -0,0 +1,18 @@ +interface variables { + /// Get an application variable value for the current component. + /// + /// The name must match one defined in in the component manifest. + get: func(name: string) -> result; + + /// The set of errors which may be raised by functions in this interface. + variant error { + /// The provided variable name is invalid. + invalid-name(string), + /// The provided variable is undefined. + undefined(string), + /// A variables provider specific error has occurred. + provider(string), + /// Some implementation-specific error has occurred. + other(string), + } +} diff --git a/go/examples/spin-basic/wit/deps/spin@2.0.0/world.wit b/go/examples/spin-basic/wit/deps/spin@2.0.0/world.wit new file mode 100644 index 0000000..b16e429 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/spin@2.0.0/world.wit @@ -0,0 +1,41 @@ +package fermyon:spin@2.0.0; + +/// The full world of a guest targeting an http-trigger +world http-trigger { + include platform; + export wasi:http/incoming-handler@0.2.0; +} + +/// Like `http-trigger`, but using WASI 0.2.0-rc-2023-10-18 +world http-trigger-rc20231018 { + include platform-rc20231018; + export wasi:http/incoming-handler@0.2.0-rc-2023-10-18; +} + +/// The imports needed for a guest to run on a Spin host +world platform { + include wasi:cli/imports@0.2.0; + import wasi:http/outgoing-handler@0.2.0; + import llm; + import redis; + import mqtt; + import postgres; + import mysql; + import sqlite; + import key-value; + import variables; +} + +/// Like `platform`, but using WASI 0.2.0-rc-2023-10-18 +world platform-rc20231018 { + include wasi:cli/reactor@0.2.0-rc-2023-10-18; + import wasi:http/outgoing-handler@0.2.0-rc-2023-10-18; + import llm; + import redis; + import mqtt; + import postgres; + import mysql; + import sqlite; + import key-value; + import variables; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-cli-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-cli-0.2.0/package.wit new file mode 100644 index 0000000..0a2737b --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-cli-0.2.0/package.wit @@ -0,0 +1,159 @@ +package wasi:cli@0.2.0; + +interface environment { + /// Get the POSIX-style environment variables. + /// + /// Each environment variable is provided as a pair of string variable names + /// and string value. + /// + /// Morally, these are a value import, but until value imports are available + /// in the component model, this import function should return the same + /// values each time it is called. + get-environment: func() -> list>; + + /// Get the POSIX-style arguments to the program. + get-arguments: func() -> list; + + /// Return a path that programs should use as their initial current working + /// directory, interpreting `.` as shorthand for this. + initial-cwd: func() -> option; +} + +interface exit { + /// Exit the current instance and any linked instances. + exit: func(status: result); +} + +interface run { + /// Run the program. + run: func() -> result; +} + +interface stdin { + use wasi:io/streams@0.2.0.{input-stream}; + + get-stdin: func() -> input-stream; +} + +interface stdout { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stdout: func() -> output-stream; +} + +interface stderr { + use wasi:io/streams@0.2.0.{output-stream}; + + get-stderr: func() -> output-stream; +} + +/// Terminal input. +/// +/// In the future, this may include functions for disabling echoing, +/// disabling input buffering so that keyboard events are sent through +/// immediately, querying supported features, and so on. +interface terminal-input { + /// The input side of a terminal. + resource terminal-input; +} + +/// Terminal output. +/// +/// In the future, this may include functions for querying the terminal +/// size, being notified of terminal size changes, querying supported +/// features, and so on. +interface terminal-output { + /// The output side of a terminal. + resource terminal-output; +} + +/// An interface providing an optional `terminal-input` for stdin as a +/// link-time authority. +interface terminal-stdin { + use terminal-input.{terminal-input}; + + /// If stdin is connected to a terminal, return a `terminal-input` handle + /// allowing further interaction with it. + get-terminal-stdin: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stdout as a +/// link-time authority. +interface terminal-stdout { + use terminal-output.{terminal-output}; + + /// If stdout is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stdout: func() -> option; +} + +/// An interface providing an optional `terminal-output` for stderr as a +/// link-time authority. +interface terminal-stderr { + use terminal-output.{terminal-output}; + + /// If stderr is connected to a terminal, return a `terminal-output` handle + /// allowing further interaction with it. + get-terminal-stderr: func() -> option; +} + +world imports { + import environment; + import exit; + import wasi:io/error@0.2.0; + import wasi:io/poll@0.2.0; + import wasi:io/streams@0.2.0; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.0; + import wasi:clocks/wall-clock@0.2.0; + import wasi:filesystem/types@0.2.0; + import wasi:filesystem/preopens@0.2.0; + import wasi:sockets/network@0.2.0; + import wasi:sockets/instance-network@0.2.0; + import wasi:sockets/udp@0.2.0; + import wasi:sockets/udp-create-socket@0.2.0; + import wasi:sockets/tcp@0.2.0; + import wasi:sockets/tcp-create-socket@0.2.0; + import wasi:sockets/ip-name-lookup@0.2.0; + import wasi:random/random@0.2.0; + import wasi:random/insecure@0.2.0; + import wasi:random/insecure-seed@0.2.0; +} +world command { + import environment; + import exit; + import wasi:io/error@0.2.0; + import wasi:io/poll@0.2.0; + import wasi:io/streams@0.2.0; + import stdin; + import stdout; + import stderr; + import terminal-input; + import terminal-output; + import terminal-stdin; + import terminal-stdout; + import terminal-stderr; + import wasi:clocks/monotonic-clock@0.2.0; + import wasi:clocks/wall-clock@0.2.0; + import wasi:filesystem/types@0.2.0; + import wasi:filesystem/preopens@0.2.0; + import wasi:sockets/network@0.2.0; + import wasi:sockets/instance-network@0.2.0; + import wasi:sockets/udp@0.2.0; + import wasi:sockets/udp-create-socket@0.2.0; + import wasi:sockets/tcp@0.2.0; + import wasi:sockets/tcp-create-socket@0.2.0; + import wasi:sockets/ip-name-lookup@0.2.0; + import wasi:random/random@0.2.0; + import wasi:random/insecure@0.2.0; + import wasi:random/insecure-seed@0.2.0; + + export run; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-clocks-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-clocks-0.2.0/package.wit new file mode 100644 index 0000000..9acd578 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-clocks-0.2.0/package.wit @@ -0,0 +1,90 @@ +package wasi:clocks@0.2.0; + +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +/// +/// It is intended for measuring elapsed time. +interface monotonic-clock { + use wasi:io/poll@0.2.0.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + type instant = u64; + + /// A duration of time, in nanoseconds. + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// occured. + subscribe-instant: func(when: instant) -> pollable; + + /// Create a `pollable` which will resolve once the given duration has + /// elapsed, starting at the time at which this function was called. + /// occured. + subscribe-duration: func(when: duration) -> pollable; +} + +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + resolution: func() -> datetime; +} + +world imports { + import wasi:io/poll@0.2.0; + import monotonic-clock; + import wall-clock; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-filesystem-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-filesystem-0.2.0/package.wit new file mode 100644 index 0000000..cb6a2be --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-filesystem-0.2.0/package.wit @@ -0,0 +1,158 @@ +package wasi:filesystem@0.2.0; + +interface types { + use wasi:io/streams@0.2.0.{input-stream, output-stream, error}; + use wasi:clocks/wall-clock@0.2.0.{datetime}; + + type filesize = u64; + + enum descriptor-type { + unknown, + block-device, + character-device, + directory, + fifo, + symbolic-link, + regular-file, + socket, + } + + flags descriptor-flags { + read, + write, + file-integrity-sync, + data-integrity-sync, + requested-write-sync, + mutate-directory, + } + + flags path-flags { + symlink-follow, + } + + flags open-flags { + create, + directory, + exclusive, + truncate, + } + + type link-count = u64; + + record descriptor-stat { + %type: descriptor-type, + link-count: link-count, + size: filesize, + data-access-timestamp: option, + data-modification-timestamp: option, + status-change-timestamp: option, + } + + variant new-timestamp { + no-change, + now, + timestamp(datetime), + } + + record directory-entry { + %type: descriptor-type, + name: string, + } + + enum error-code { + access, + would-block, + already, + bad-descriptor, + busy, + deadlock, + quota, + exist, + file-too-large, + illegal-byte-sequence, + in-progress, + interrupted, + invalid, + io, + is-directory, + loop, + too-many-links, + message-size, + name-too-long, + no-device, + no-entry, + no-lock, + insufficient-memory, + insufficient-space, + not-directory, + not-empty, + not-recoverable, + unsupported, + no-tty, + no-such-device, + overflow, + not-permitted, + pipe, + read-only, + invalid-seek, + text-file-busy, + cross-device, + } + + enum advice { + normal, + sequential, + random, + will-need, + dont-need, + no-reuse, + } + + record metadata-hash-value { + lower: u64, + upper: u64, + } + + resource descriptor { + read-via-stream: func(offset: filesize) -> result; + write-via-stream: func(offset: filesize) -> result; + append-via-stream: func() -> result; + advise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>; + sync-data: func() -> result<_, error-code>; + get-flags: func() -> result; + get-type: func() -> result; + set-size: func(size: filesize) -> result<_, error-code>; + set-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + read: func(length: filesize, offset: filesize) -> result, bool>, error-code>; + write: func(buffer: list, offset: filesize) -> result; + read-directory: func() -> result; + sync: func() -> result<_, error-code>; + create-directory-at: func(path: string) -> result<_, error-code>; + stat: func() -> result; + stat-at: func(path-flags: path-flags, path: string) -> result; + set-times-at: func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>; + link-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + open-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result; + readlink-at: func(path: string) -> result; + remove-directory-at: func(path: string) -> result<_, error-code>; + rename-at: func(old-path: string, new-descriptor: borrow, new-path: string) -> result<_, error-code>; + symlink-at: func(old-path: string, new-path: string) -> result<_, error-code>; + unlink-file-at: func(path: string) -> result<_, error-code>; + is-same-object: func(other: borrow) -> bool; + metadata-hash: func() -> result; + metadata-hash-at: func(path-flags: path-flags, path: string) -> result; + } + + resource directory-entry-stream { + read-directory-entry: func() -> result, error-code>; + } + + filesystem-error-code: func(err: borrow) -> option; +} + +interface preopens { + use types.{descriptor}; + + get-directories: func() -> list>; +} + diff --git a/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/handler.wit b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/handler.wit new file mode 100644 index 0000000..a34a064 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/handler.wit @@ -0,0 +1,43 @@ +/// This interface defines a handler of incoming HTTP Requests. It should +/// be exported by components which can respond to HTTP Requests. +interface incoming-handler { + use types.{incoming-request, response-outparam}; + + /// This function is invoked with an incoming HTTP Request, and a resource + /// `response-outparam` which provides the capability to reply with an HTTP + /// Response. The response is sent by calling the `response-outparam.set` + /// method, which allows execution to continue after the response has been + /// sent. This enables both streaming to the response body, and performing other + /// work. + /// + /// The implementor of this function must write a response to the + /// `response-outparam` before returning, or else the caller will respond + /// with an error on its behalf. + handle: func( + request: incoming-request, + response-out: response-outparam + ); +} + +/// This interface defines a handler of outgoing HTTP Requests. It should be +/// imported by components which wish to make HTTP Requests. +interface outgoing-handler { + use types.{ + outgoing-request, request-options, future-incoming-response, error-code + }; + + /// This function is invoked with an outgoing HTTP Request, and it returns + /// a resource `future-incoming-response` which represents an HTTP Response + /// which may arrive in the future. + /// + /// The `options` argument accepts optional parameters for the HTTP + /// protocol's transport layer. + /// + /// This function may return an error if the `outgoing-request` is invalid + /// or not allowed to be made. Otherwise, protocol errors are reported + /// through the `future-incoming-response`. + handle: func( + request: outgoing-request, + options: option + ) -> result; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/proxy.wit b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/proxy.wit new file mode 100644 index 0000000..687c24d --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/proxy.wit @@ -0,0 +1,32 @@ +package wasi:http@0.2.0; + +/// The `wasi:http/proxy` world captures a widely-implementable intersection of +/// hosts that includes HTTP forward and reverse proxies. Components targeting +/// this world may concurrently stream in and out any number of incoming and +/// outgoing HTTP requests. +world proxy { + /// HTTP proxies have access to time and randomness. + include wasi:clocks/imports@0.2.0; + import wasi:random/random@0.2.0; + + /// Proxies have standard output and error streams which are expected to + /// terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.2.0; + import wasi:cli/stderr@0.2.0; + + /// TODO: this is a temporary workaround until component tooling is able to + /// gracefully handle the absence of stdin. Hosts must return an eof stream + /// for this import, which is what wasi-libc + tooling will do automatically + /// when this import is properly removed. + import wasi:cli/stdin@0.2.0; + + /// This is the default handler to use when user code simply wants to make an + /// HTTP request (e.g., via `fetch()`). + import outgoing-handler; + + /// The host delivers incoming HTTP requests to a component by calling the + /// `handle` function of this exported interface. A host may arbitrarily reuse + /// or not reuse component instance when delivering incoming HTTP requests and + /// thus a component must be able to handle 0..N calls to `handle`. + export incoming-handler; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/types.wit b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/types.wit new file mode 100644 index 0000000..755ac6a --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-http-0.2.0/types.wit @@ -0,0 +1,570 @@ +/// This interface defines all of the types and methods for implementing +/// HTTP Requests and Responses, both incoming and outgoing, as well as +/// their headers, trailers, and bodies. +interface types { + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use wasi:io/streams@0.2.0.{input-stream, output-stream}; + use wasi:io/error@0.2.0.{error as io-error}; + use wasi:io/poll@0.2.0.{pollable}; + + /// This type corresponds to HTTP standard Methods. + variant method { + get, + head, + post, + put, + delete, + connect, + options, + trace, + patch, + other(string) + } + + /// This type corresponds to HTTP standard Related Schemes. + variant scheme { + HTTP, + HTTPS, + other(string) + } + + /// These cases are inspired by the IANA HTTP Proxy Error Types: + /// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types + variant error-code { + DNS-timeout, + DNS-error(DNS-error-payload), + destination-not-found, + destination-unavailable, + destination-IP-prohibited, + destination-IP-unroutable, + connection-refused, + connection-terminated, + connection-timeout, + connection-read-timeout, + connection-write-timeout, + connection-limit-reached, + TLS-protocol-error, + TLS-certificate-error, + TLS-alert-received(TLS-alert-received-payload), + HTTP-request-denied, + HTTP-request-length-required, + HTTP-request-body-size(option), + HTTP-request-method-invalid, + HTTP-request-URI-invalid, + HTTP-request-URI-too-long, + HTTP-request-header-section-size(option), + HTTP-request-header-size(option), + HTTP-request-trailer-section-size(option), + HTTP-request-trailer-size(field-size-payload), + HTTP-response-incomplete, + HTTP-response-header-section-size(option), + HTTP-response-header-size(field-size-payload), + HTTP-response-body-size(option), + HTTP-response-trailer-section-size(option), + HTTP-response-trailer-size(field-size-payload), + HTTP-response-transfer-coding(option), + HTTP-response-content-coding(option), + HTTP-response-timeout, + HTTP-upgrade-failed, + HTTP-protocol-error, + loop-detected, + configuration-error, + /// This is a catch-all error for anything that doesn't fit cleanly into a + /// more specific case. It also includes an optional string for an + /// unstructured description of the error. Users should not depend on the + /// string for diagnosing errors, as it's not required to be consistent + /// between implementations. + internal-error(option) + } + + /// Defines the case payload type for `DNS-error` above: + record DNS-error-payload { + rcode: option, + info-code: option + } + + /// Defines the case payload type for `TLS-alert-received` above: + record TLS-alert-received-payload { + alert-id: option, + alert-message: option + } + + /// Defines the case payload type for `HTTP-response-{header,trailer}-size` above: + record field-size-payload { + field-name: option, + field-size: option + } + + /// Attempts to extract a http-related `error` from the wasi:io `error` + /// provided. + /// + /// Stream operations which return + /// `wasi:io/stream/stream-error::last-operation-failed` have a payload of + /// type `wasi:io/error/error` with more information about the operation + /// that failed. This payload can be passed through to this function to see + /// if there's http-related information about the error to return. + /// + /// Note that this function is fallible because not all io-errors are + /// http-related errors. + http-error-code: func(err: borrow) -> option; + + /// This type enumerates the different kinds of errors that may occur when + /// setting or appending to a `fields` resource. + variant header-error { + /// This error indicates that a `field-key` or `field-value` was + /// syntactically invalid when used with an operation that sets headers in a + /// `fields`. + invalid-syntax, + + /// This error indicates that a forbidden `field-key` was used when trying + /// to set a header in a `fields`. + forbidden, + + /// This error indicates that the operation on the `fields` was not + /// permitted because the fields are immutable. + immutable, + } + + /// Field keys are always strings. + type field-key = string; + + /// Field values should always be ASCII strings. However, in + /// reality, HTTP implementations often have to interpret malformed values, + /// so they are provided as a list of bytes. + type field-value = list; + + /// This following block defines the `fields` resource which corresponds to + /// HTTP standard Fields. Fields are a common representation used for both + /// Headers and Trailers. + /// + /// A `fields` may be mutable or immutable. A `fields` created using the + /// constructor, `from-list`, or `clone` will be mutable, but a `fields` + /// resource given by other means (including, but not limited to, + /// `incoming-request.headers`, `outgoing-request.headers`) might be be + /// immutable. In an immutable fields, the `set`, `append`, and `delete` + /// operations will fail with `header-error.immutable`. + resource fields { + + /// Construct an empty HTTP Fields. + /// + /// The resulting `fields` is mutable. + constructor(); + + /// Construct an HTTP Fields. + /// + /// The resulting `fields` is mutable. + /// + /// The list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + /// + /// The tuple is a pair of the field key, represented as a string, and + /// Value, represented as a list of bytes. In a valid Fields, all keys + /// and values are valid UTF-8 strings. However, values are not always + /// well-formed, so they are represented as a raw list of bytes. + /// + /// An error result will be returned if any header or value was + /// syntactically invalid, or if a header was forbidden. + from-list: static func( + entries: list> + ) -> result; + + /// Get all of the values corresponding to a key. If the key is not present + /// in this `fields`, an empty list is returned. However, if the key is + /// present but empty, this is represented by a list with one or more + /// empty field-values present. + get: func(name: field-key) -> list; + + /// Returns `true` when the key is present in this `fields`. If the key is + /// syntactically invalid, `false` is returned. + has: func(name: field-key) -> bool; + + /// Set all of the values for a key. Clears any existing values for that + /// key, if they have been set. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + set: func(name: field-key, value: list) -> result<_, header-error>; + + /// Delete all values for a key. Does nothing if no values for the key + /// exist. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + delete: func(name: field-key) -> result<_, header-error>; + + /// Append a value for a key. Does not change or delete any existing + /// values for that key. + /// + /// Fails with `header-error.immutable` if the `fields` are immutable. + append: func(name: field-key, value: field-value) -> result<_, header-error>; + + /// Retrieve the full set of keys and values in the Fields. Like the + /// constructor, the list represents each key-value pair. + /// + /// The outer list represents each key-value pair in the Fields. Keys + /// which have multiple values are represented by multiple entries in this + /// list with the same key. + entries: func() -> list>; + + /// Make a deep copy of the Fields. Equivelant in behavior to calling the + /// `fields` constructor on the return value of `entries`. The resulting + /// `fields` is mutable. + clone: func() -> fields; + } + + /// Headers is an alias for Fields. + type headers = fields; + + /// Trailers is an alias for Fields. + type trailers = fields; + + /// Represents an incoming HTTP Request. + resource incoming-request { + + /// Returns the method of the incoming request. + method: func() -> method; + + /// Returns the path with query parameters from the request, as a string. + path-with-query: func() -> option; + + /// Returns the protocol scheme from the request. + scheme: func() -> option; + + /// Returns the authority from the request, if it was present. + authority: func() -> option; + + /// Get the `headers` associated with the request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// The `headers` returned are a child resource: it must be dropped before + /// the parent `incoming-request` is dropped. Dropping this + /// `incoming-request` before all children are dropped will trap. + headers: func() -> headers; + + /// Gives the `incoming-body` associated with this request. Will only + /// return success at most once, and subsequent calls will return error. + consume: func() -> result; + } + + /// Represents an outgoing HTTP Request. + resource outgoing-request { + + /// Construct a new `outgoing-request` with a default `method` of `GET`, and + /// `none` values for `path-with-query`, `scheme`, and `authority`. + /// + /// * `headers` is the HTTP Headers for the Request. + /// + /// It is possible to construct, or manipulate with the accessor functions + /// below, an `outgoing-request` with an invalid combination of `scheme` + /// and `authority`, or `headers` which are not permitted to be sent. + /// It is the obligation of the `outgoing-handler.handle` implementation + /// to reject invalid constructions of `outgoing-request`. + constructor( + headers: headers + ); + + /// Returns the resource corresponding to the outgoing Body for this + /// Request. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-request` can be retrieved at most once. Subsequent + /// calls will return error. + body: func() -> result; + + /// Get the Method for the Request. + method: func() -> method; + /// Set the Method for the Request. Fails if the string present in a + /// `method.other` argument is not a syntactically valid method. + set-method: func(method: method) -> result; + + /// Get the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. + path-with-query: func() -> option; + /// Set the combination of the HTTP Path and Query for the Request. + /// When `none`, this represents an empty Path and empty Query. Fails is the + /// string given is not a syntactically valid path and query uri component. + set-path-with-query: func(path-with-query: option) -> result; + + /// Get the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. + scheme: func() -> option; + /// Set the HTTP Related Scheme for the Request. When `none`, the + /// implementation may choose an appropriate default scheme. Fails if the + /// string given is not a syntactically valid uri scheme. + set-scheme: func(scheme: option) -> result; + + /// Get the HTTP Authority for the Request. A value of `none` may be used + /// with Related Schemes which do not require an Authority. The HTTP and + /// HTTPS schemes always require an authority. + authority: func() -> option; + /// Set the HTTP Authority for the Request. A value of `none` may be used + /// with Related Schemes which do not require an Authority. The HTTP and + /// HTTPS schemes always require an authority. Fails if the string given is + /// not a syntactically valid uri authority. + set-authority: func(authority: option) -> result; + + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transfered to + /// another component by e.g. `outgoing-handler.handle`. + headers: func() -> headers; + } + + /// Parameters for making an HTTP Request. Each of these parameters is + /// currently an optional timeout applicable to the transport layer of the + /// HTTP protocol. + /// + /// These timeouts are separate from any the user may use to bound a + /// blocking call to `wasi:io/poll.poll`. + resource request-options { + /// Construct a default `request-options` value. + constructor(); + + /// The timeout for the initial connect to the HTTP Server. + connect-timeout: func() -> option; + + /// Set the timeout for the initial connect to the HTTP Server. An error + /// return value indicates that this timeout is not supported. + set-connect-timeout: func(duration: option) -> result; + + /// The timeout for receiving the first byte of the Response body. + first-byte-timeout: func() -> option; + + /// Set the timeout for receiving the first byte of the Response body. An + /// error return value indicates that this timeout is not supported. + set-first-byte-timeout: func(duration: option) -> result; + + /// The timeout for receiving subsequent chunks of bytes in the Response + /// body stream. + between-bytes-timeout: func() -> option; + + /// Set the timeout for receiving subsequent chunks of bytes in the Response + /// body stream. An error return value indicates that this timeout is not + /// supported. + set-between-bytes-timeout: func(duration: option) -> result; + } + + /// Represents the ability to send an HTTP Response. + /// + /// This resource is used by the `wasi:http/incoming-handler` interface to + /// allow a Response to be sent corresponding to the Request provided as the + /// other argument to `incoming-handler.handle`. + resource response-outparam { + + /// Set the value of the `response-outparam` to either send a response, + /// or indicate an error. + /// + /// This method consumes the `response-outparam` to ensure that it is + /// called at most once. If it is never called, the implementation + /// will respond with an error. + /// + /// The user may provide an `error` to `response` to allow the + /// implementation determine how to respond with an HTTP error response. + set: static func( + param: response-outparam, + response: result, + ); + } + + /// This type corresponds to the HTTP standard Status Code. + type status-code = u16; + + /// Represents an incoming HTTP Response. + resource incoming-response { + + /// Returns the status code from the incoming response. + status: func() -> status-code; + + /// Returns the headers from the incoming response. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `incoming-response` is dropped. + headers: func() -> headers; + + /// Returns the incoming body. May be called at most once. Returns error + /// if called additional times. + consume: func() -> result; + } + + /// Represents an incoming HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, indicating that the full contents of the + /// body have been received. This resource represents the contents as + /// an `input-stream` and the delivery of trailers as a `future-trailers`, + /// and ensures that the user of this interface may only be consuming either + /// the body contents or waiting on trailers at any given time. + resource incoming-body { + + /// Returns the contents of the body, as a stream of bytes. + /// + /// Returns success on first call: the stream representing the contents + /// can be retrieved at most once. Subsequent calls will return error. + /// + /// The returned `input-stream` resource is a child: it must be dropped + /// before the parent `incoming-body` is dropped, or consumed by + /// `incoming-body.finish`. + /// + /// This invariant ensures that the implementation can determine whether + /// the user is consuming the contents of the body, waiting on the + /// `future-trailers` to be ready, or neither. This allows for network + /// backpressure is to be applied when the user is consuming the body, + /// and for that backpressure to not inhibit delivery of the trailers if + /// the user does not read the entire body. + %stream: func() -> result; + + /// Takes ownership of `incoming-body`, and returns a `future-trailers`. + /// This function will trap if the `input-stream` child is still alive. + finish: static func(this: incoming-body) -> future-trailers; + } + + /// Represents a future which may eventaully return trailers, or an error. + /// + /// In the case that the incoming HTTP Request or Response did not have any + /// trailers, this future will resolve to the empty set of trailers once the + /// complete Request or Response body has been received. + resource future-trailers { + + /// Returns a pollable which becomes ready when either the trailers have + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + subscribe: func() -> pollable; + + /// Returns the contents of the trailers, or an error which occured, + /// once the future is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the trailers or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the HTTP Request or Response + /// body, as well as any trailers, were received successfully, or that an + /// error occured receiving them. The optional `trailers` indicates whether + /// or not trailers were present in the body. + /// + /// When some `trailers` are returned by this method, the `trailers` + /// resource is immutable, and a child. Use of the `set`, `append`, or + /// `delete` methods will return an error, and the resource must be + /// dropped before the parent `future-trailers` is dropped. + get: func() -> option, error-code>>>; + } + + /// Represents an outgoing HTTP Response. + resource outgoing-response { + + /// Construct an `outgoing-response`, with a default `status-code` of `200`. + /// If a different `status-code` is needed, it must be set via the + /// `set-status-code` method. + /// + /// * `headers` is the HTTP Headers for the Response. + constructor(headers: headers); + + /// Get the HTTP Status Code for the Response. + status-code: func() -> status-code; + + /// Set the HTTP Status Code for the Response. Fails if the status-code + /// given is not a valid http status code. + set-status-code: func(status-code: status-code) -> result; + + /// Get the headers associated with the Request. + /// + /// The returned `headers` resource is immutable: `set`, `append`, and + /// `delete` operations will fail with `header-error.immutable`. + /// + /// This headers resource is a child: it must be dropped before the parent + /// `outgoing-request` is dropped, or its ownership is transfered to + /// another component by e.g. `outgoing-handler.handle`. + headers: func() -> headers; + + /// Returns the resource corresponding to the outgoing Body for this Response. + /// + /// Returns success on the first call: the `outgoing-body` resource for + /// this `outgoing-response` can be retrieved at most once. Subsequent + /// calls will return error. + body: func() -> result; + } + + /// Represents an outgoing HTTP Request or Response's Body. + /// + /// A body has both its contents - a stream of bytes - and a (possibly + /// empty) set of trailers, inducating the full contents of the body + /// have been sent. This resource represents the contents as an + /// `output-stream` child resource, and the completion of the body (with + /// optional trailers) with a static function that consumes the + /// `outgoing-body` resource, and ensures that the user of this interface + /// may not write to the body contents after the body has been finished. + /// + /// If the user code drops this resource, as opposed to calling the static + /// method `finish`, the implementation should treat the body as incomplete, + /// and that an error has occured. The implementation should propogate this + /// error to the HTTP protocol by whatever means it has available, + /// including: corrupting the body on the wire, aborting the associated + /// Request, or sending a late status code for the Response. + resource outgoing-body { + + /// Returns a stream for writing the body contents. + /// + /// The returned `output-stream` is a child resource: it must be dropped + /// before the parent `outgoing-body` resource is dropped (or finished), + /// otherwise the `outgoing-body` drop or `finish` will trap. + /// + /// Returns success on the first call: the `output-stream` resource for + /// this `outgoing-body` may be retrieved at most once. Subsequent calls + /// will return error. + write: func() -> result; + + /// Finalize an outgoing body, optionally providing trailers. This must be + /// called to signal that the response is complete. If the `outgoing-body` + /// is dropped without calling `outgoing-body.finalize`, the implementation + /// should treat the body as corrupted. + /// + /// Fails if the body's `outgoing-request` or `outgoing-response` was + /// constructed with a Content-Length header, and the contents written + /// to the body (via `write`) does not match the value given in the + /// Content-Length. + finish: static func( + this: outgoing-body, + trailers: option + ) -> result<_, error-code>; + } + + /// Represents a future which may eventaully return an incoming HTTP + /// Response, or an error. + /// + /// This resource is returned by the `wasi:http/outgoing-handler` interface to + /// provide the HTTP Response corresponding to the sent Request. + resource future-incoming-response { + /// Returns a pollable which becomes ready when either the Response has + /// been received, or an error has occured. When this pollable is ready, + /// the `get` method will return `some`. + subscribe: func() -> pollable; + + /// Returns the incoming HTTP Response, or an error, once one is ready. + /// + /// The outer `option` represents future readiness. Users can wait on this + /// `option` to become `some` using the `subscribe` method. + /// + /// The outer `result` is used to retrieve the response or error at most + /// once. It will be success on the first call in which the outer option + /// is `some`, and error on subsequent calls. + /// + /// The inner `result` represents that either the incoming HTTP Response + /// status and headers have recieved successfully, or that an error + /// occured. Errors may also occur while consuming the response body, + /// but those will be reported by the `incoming-body` and its + /// `output-stream` child. + get: func() -> option>>; + + } +} diff --git a/go/examples/spin-basic/wit/deps/wasi-io-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-io-0.2.0/package.wit new file mode 100644 index 0000000..192e1cd --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-io-0.2.0/package.wit @@ -0,0 +1,292 @@ +package wasi:io@0.2.0; + +interface error { + /// A resource which represents some error information. + /// + /// The only method provided by this resource is `to-debug-string`, + /// which provides some human-readable information about the error. + /// + /// In the `wasi:io` package, this resource is returned through the + /// `wasi:io/streams/stream-error` type. + /// + /// To provide more specific error information, other interfaces may + /// provide functions to further "downcast" this error into more specific + /// error information. For example, `error`s returned in streams derived + /// from filesystem types to be described using the filesystem's own + /// error-code type, using the function + /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter + /// `borrow` and returns + /// `option`. + /// + /// The set of functions which can "downcast" an `error` into a more + /// concrete type is open. + resource error { + /// Returns a string that is suitable to assist humans in debugging + /// this error. + /// + /// WARNING: The returned string should not be consumed mechanically! + /// It may change across platforms, hosts, or other implementation + /// details. Parsing this string is a major platform-compatibility + /// hazard. + to-debug-string: func() -> string; + } +} + +/// A poll API intended to let users wait for I/O events on multiple handles +/// at once. +interface poll { + /// `pollable` represents a single I/O event which may be ready, or not. + resource pollable { + /// Return the readiness of a pollable. This function never blocks. + /// + /// Returns `true` when the pollable is ready, and `false` otherwise. + ready: func() -> bool; + /// `block` returns immediately if the pollable is ready, and otherwise + /// blocks until ready. + /// + /// This function is equivalent to calling `poll.poll` on a list + /// containing only this pollable. + block: func(); + } + + /// Poll for completion on a set of pollables. + /// + /// This function takes a list of pollables, which identify I/O sources of + /// interest, and waits until one or more of the events is ready for I/O. + /// + /// The result `list` contains one or more indices of handles in the + /// argument list that is ready for I/O. + /// + /// If the list contains more elements than can be indexed with a `u32` + /// value, this function traps. + /// + /// A timeout can be implemented by adding a pollable from the + /// wasi-clocks API to the list. + /// + /// This function does not return a `result`; polling in itself does not + /// do any I/O so it doesn't fail. If any of the I/O sources identified by + /// the pollables has an error, it is indicated by marking the source as + /// being reaedy for I/O. + poll: func(in: list>) -> list; +} + +/// WASI I/O is an I/O abstraction API which is currently focused on providing +/// stream types. +/// +/// In the future, the component model is expected to add built-in stream types; +/// when it does, they are expected to subsume this API. +interface streams { + use error.{error}; + use poll.{pollable}; + + /// An error for input-stream and output-stream operations. + variant stream-error { + /// The last operation (a write or flush) failed before completion. + /// + /// More information is available in the `error` payload. + last-operation-failed(error), + /// The stream is closed: no more input will be accepted by the + /// stream. A closed output-stream will return this error on all + /// future operations. + closed, + } + + /// An input bytestream. + /// + /// `input-stream`s are *non-blocking* to the extent practical on underlying + /// platforms. I/O operations always return promptly; if fewer bytes are + /// promptly available than requested, they return the number of bytes promptly + /// available, which could even be zero. To wait for data to be available, + /// use the `subscribe` function to obtain a `pollable` which can be polled + /// for using `wasi:io/poll`. + resource input-stream { + /// Perform a non-blocking read from the stream. + /// + /// When the source of a `read` is binary data, the bytes from the source + /// are returned verbatim. When the source of a `read` is known to the + /// implementation to be text, bytes containing the UTF-8 encoding of the + /// text are returned. + /// + /// This function returns a list of bytes containing the read data, + /// when successful. The returned list will contain up to `len` bytes; + /// it may return fewer than requested, but not more. The list is + /// empty when no bytes are available for reading at this time. The + /// pollable given by `subscribe` will be ready when more bytes are + /// available. + /// + /// This function fails with a `stream-error` when the operation + /// encounters an error, giving `last-operation-failed`, or when the + /// stream is closed, giving `closed`. + /// + /// When the caller gives a `len` of 0, it represents a request to + /// read 0 bytes. If the stream is still open, this call should + /// succeed and return an empty list, or otherwise fail with `closed`. + /// + /// The `len` parameter is a `u64`, which could represent a list of u8 which + /// is not possible to allocate in wasm32, or not desirable to allocate as + /// as a return value by the callee. The callee may return a list of bytes + /// less than `len` in size while more bytes are available for reading. + read: func(len: u64) -> result, stream-error>; + /// Read bytes from a stream, after blocking until at least one byte can + /// be read. Except for blocking, behavior is identical to `read`. + blocking-read: func(len: u64) -> result, stream-error>; + /// Skip bytes from a stream. Returns number of bytes skipped. + /// + /// Behaves identical to `read`, except instead of returning a list + /// of bytes, returns the number of bytes consumed from the stream. + skip: func(len: u64) -> result; + /// Skip bytes from a stream, after blocking until at least one byte + /// can be skipped. Except for blocking behavior, identical to `skip`. + blocking-skip: func(len: u64) -> result; + /// Create a `pollable` which will resolve once either the specified stream + /// has bytes available to read or the other end of the stream has been + /// closed. + /// The created `pollable` is a child resource of the `input-stream`. + /// Implementations may trap if the `input-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + subscribe: func() -> pollable; + } + + /// An output bytestream. + /// + /// `output-stream`s are *non-blocking* to the extent practical on + /// underlying platforms. Except where specified otherwise, I/O operations also + /// always return promptly, after the number of bytes that can be written + /// promptly, which could even be zero. To wait for the stream to be ready to + /// accept data, the `subscribe` function to obtain a `pollable` which can be + /// polled for using `wasi:io/poll`. + resource output-stream { + /// Check readiness for writing. This function never blocks. + /// + /// Returns the number of bytes permitted for the next call to `write`, + /// or an error. Calling `write` with more bytes than this function has + /// permitted will trap. + /// + /// When this function returns 0 bytes, the `subscribe` pollable will + /// become ready when this function will report at least 1 byte, or an + /// error. + check-write: func() -> result; + /// Perform a write. This function never blocks. + /// + /// When the destination of a `write` is binary data, the bytes from + /// `contents` are written verbatim. When the destination of a `write` is + /// known to the implementation to be text, the bytes of `contents` are + /// transcoded from UTF-8 into the encoding of the destination and then + /// written. + /// + /// Precondition: check-write gave permit of Ok(n) and contents has a + /// length of less than or equal to n. Otherwise, this function will trap. + /// + /// returns Err(closed) without writing if the stream has closed since + /// the last call to check-write provided a permit. + write: func(contents: list) -> result<_, stream-error>; + /// Perform a write of up to 4096 bytes, and then flush the stream. Block + /// until all of these operations are complete, or an error occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write`, and `flush`, and is implemented with the + /// following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while !contents.is_empty() { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, contents.len()); + /// let (chunk, rest) = contents.split_at(len); + /// this.write(chunk ); // eliding error handling + /// contents = rest; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-and-flush: func(contents: list) -> result<_, stream-error>; + /// Request to flush buffered output. This function never blocks. + /// + /// This tells the output-stream that the caller intends any buffered + /// output to be flushed. the output which is expected to be flushed + /// is all that has been passed to `write` prior to this call. + /// + /// Upon calling this function, the `output-stream` will not accept any + /// writes (`check-write` will return `ok(0)`) until the flush has + /// completed. The `subscribe` pollable will become ready when the + /// flush has completed and the stream can accept more writes. + flush: func() -> result<_, stream-error>; + /// Request to flush buffered output, and block until flush completes + /// and stream is ready for writing again. + blocking-flush: func() -> result<_, stream-error>; + /// Create a `pollable` which will resolve once the output-stream + /// is ready for more writing, or an error has occured. When this + /// pollable is ready, `check-write` will return `ok(n)` with n>0, or an + /// error. + /// + /// If the stream is closed, this pollable is always ready immediately. + /// + /// The created `pollable` is a child resource of the `output-stream`. + /// Implementations may trap if the `output-stream` is dropped before + /// all derived `pollable`s created with this function are dropped. + subscribe: func() -> pollable; + /// Write zeroes to a stream. + /// + /// This should be used precisely like `write` with the exact same + /// preconditions (must use check-write first), but instead of + /// passing a list of bytes, you simply pass the number of zero-bytes + /// that should be written. + write-zeroes: func(len: u64) -> result<_, stream-error>; + /// Perform a write of up to 4096 zeroes, and then flush the stream. + /// Block until all of these operations are complete, or an error + /// occurs. + /// + /// This is a convenience wrapper around the use of `check-write`, + /// `subscribe`, `write-zeroes`, and `flush`, and is implemented with + /// the following pseudo-code: + /// + /// ```text + /// let pollable = this.subscribe(); + /// while num_zeroes != 0 { + /// // Wait for the stream to become writable + /// pollable.block(); + /// let Ok(n) = this.check-write(); // eliding error handling + /// let len = min(n, num_zeroes); + /// this.write-zeroes(len); // eliding error handling + /// num_zeroes -= len; + /// } + /// this.flush(); + /// // Wait for completion of `flush` + /// pollable.block(); + /// // Check for any errors that arose during `flush` + /// let _ = this.check-write(); // eliding error handling + /// ``` + blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>; + /// Read from one stream and write to another. + /// + /// The behavior of splice is equivelant to: + /// 1. calling `check-write` on the `output-stream` + /// 2. calling `read` on the `input-stream` with the smaller of the + /// `check-write` permitted length and the `len` provided to `splice` + /// 3. calling `write` on the `output-stream` with that read data. + /// + /// Any error reported by the call to `check-write`, `read`, or + /// `write` ends the splice and reports that error. + /// + /// This function returns the number of bytes transferred; it may be less + /// than `len`. + splice: func(src: borrow, len: u64) -> result; + /// Read from one stream and write to another, with blocking. + /// + /// This is similar to `splice`, except that it blocks until the + /// `output-stream` is ready for writing, and the `input-stream` + /// is ready for reading, before performing the `splice`. + blocking-splice: func(src: borrow, len: u64) -> result; + } +} + +world imports { + import error; + import poll; + import streams; +} diff --git a/go/examples/spin-basic/wit/deps/wasi-random-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-random-0.2.0/package.wit new file mode 100644 index 0000000..58c179e --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-random-0.2.0/package.wit @@ -0,0 +1,18 @@ +package wasi:random@0.2.0; + +interface random { + get-random-bytes: func(len: u64) -> list; + + get-random-u64: func() -> u64; +} + +interface insecure { + get-insecure-random-bytes: func(len: u64) -> list; + + get-insecure-random-u64: func() -> u64; +} + +interface insecure-seed { + insecure-seed: func() -> tuple; +} + diff --git a/go/examples/spin-basic/wit/deps/wasi-sockets-0.2.0/package.wit b/go/examples/spin-basic/wit/deps/wasi-sockets-0.2.0/package.wit new file mode 100644 index 0000000..0602b85 --- /dev/null +++ b/go/examples/spin-basic/wit/deps/wasi-sockets-0.2.0/package.wit @@ -0,0 +1,179 @@ +package wasi:sockets@0.2.0; + +interface network { + resource network; + + enum error-code { + unknown, + access-denied, + not-supported, + invalid-argument, + out-of-memory, + timeout, + concurrency-conflict, + not-in-progress, + would-block, + invalid-state, + new-socket-limit, + address-not-bindable, + address-in-use, + remote-unreachable, + connection-refused, + connection-reset, + connection-aborted, + datagram-too-large, + name-unresolvable, + temporary-resolver-failure, + permanent-resolver-failure, + } + + enum ip-address-family { + ipv4, + ipv6, + } + + type ipv4-address = tuple; + + type ipv6-address = tuple; + + variant ip-address { + ipv4(ipv4-address), + ipv6(ipv6-address), + } + + record ipv4-socket-address { + port: u16, + address: ipv4-address, + } + + record ipv6-socket-address { + port: u16, + flow-info: u32, + address: ipv6-address, + scope-id: u32, + } + + variant ip-socket-address { + ipv4(ipv4-socket-address), + ipv6(ipv6-socket-address), + } +} + +interface instance-network { + use network.{network}; + + instance-network: func() -> network; +} + +interface udp { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + record incoming-datagram { + data: list, + remote-address: ip-socket-address, + } + + record outgoing-datagram { + data: list, + remote-address: option, + } + + resource udp-socket { + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + %stream: func(remote-address: option) -> result, error-code>; + local-address: func() -> result; + remote-address: func() -> result; + address-family: func() -> ip-address-family; + unicast-hop-limit: func() -> result; + set-unicast-hop-limit: func(value: u8) -> result<_, error-code>; + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + subscribe: func() -> pollable; + } + + resource incoming-datagram-stream { + receive: func(max-results: u64) -> result, error-code>; + subscribe: func() -> pollable; + } + + resource outgoing-datagram-stream { + check-send: func() -> result; + send: func(datagrams: list) -> result; + subscribe: func() -> pollable; + } +} + +interface udp-create-socket { + use network.{network, error-code, ip-address-family}; + use udp.{udp-socket}; + + create-udp-socket: func(address-family: ip-address-family) -> result; +} + +interface tcp { + use wasi:io/streams@0.2.0.{input-stream, output-stream}; + use wasi:io/poll@0.2.0.{pollable}; + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use network.{network, error-code, ip-socket-address, ip-address-family}; + + enum shutdown-type { + receive, + send, + both, + } + + resource tcp-socket { + start-bind: func(network: borrow, local-address: ip-socket-address) -> result<_, error-code>; + finish-bind: func() -> result<_, error-code>; + start-connect: func(network: borrow, remote-address: ip-socket-address) -> result<_, error-code>; + finish-connect: func() -> result, error-code>; + start-listen: func() -> result<_, error-code>; + finish-listen: func() -> result<_, error-code>; + accept: func() -> result, error-code>; + local-address: func() -> result; + remote-address: func() -> result; + is-listening: func() -> bool; + address-family: func() -> ip-address-family; + set-listen-backlog-size: func(value: u64) -> result<_, error-code>; + keep-alive-enabled: func() -> result; + set-keep-alive-enabled: func(value: bool) -> result<_, error-code>; + keep-alive-idle-time: func() -> result; + set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>; + keep-alive-interval: func() -> result; + set-keep-alive-interval: func(value: duration) -> result<_, error-code>; + keep-alive-count: func() -> result; + set-keep-alive-count: func(value: u32) -> result<_, error-code>; + hop-limit: func() -> result; + set-hop-limit: func(value: u8) -> result<_, error-code>; + receive-buffer-size: func() -> result; + set-receive-buffer-size: func(value: u64) -> result<_, error-code>; + send-buffer-size: func() -> result; + set-send-buffer-size: func(value: u64) -> result<_, error-code>; + subscribe: func() -> pollable; + shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>; + } +} + +interface tcp-create-socket { + use network.{network, error-code, ip-address-family}; + use tcp.{tcp-socket}; + + create-tcp-socket: func(address-family: ip-address-family) -> result; +} + +interface ip-name-lookup { + use wasi:io/poll@0.2.0.{pollable}; + use network.{network, error-code, ip-address}; + + resource resolve-address-stream { + resolve-next-address: func() -> result, error-code>; + subscribe: func() -> pollable; + } + + resolve-addresses: func(network: borrow, name: string) -> result; +} + diff --git a/go/examples/spin-basic/wit/tracing.wit b/go/examples/spin-basic/wit/tracing.wit new file mode 100644 index 0000000..8ac7385 --- /dev/null +++ b/go/examples/spin-basic/wit/tracing.wit @@ -0,0 +1,168 @@ +interface tracing { + use wasi:clocks/wall-clock@0.2.0.{datetime}; + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + // Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal + } + + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + variant value { + /// A string value. + %string(string), + /// A boolean value. + %bool(bool), + /// A double precision floating point value. + %f64(f64), + /// A signed 64 bit integer value. + %s64(s64), + /// A homogeneous array of string values. + string-array(list), + /// A homogeneous array of boolean values. + bool-array(list), + /// A homogeneous array of double precision floating point values. + f64-array(list), + /// A homogeneous array of 64 bit integer values. + s64-array(list), + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } + + /// Describes the instrumentation scope that produced a span. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + + /// The library version. + version: option, + + /// Schema URL used by this library. + /// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/schemas/overview.md#schema-url + schema-url: option, + + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} diff --git a/go/examples/spin-basic/wit/world.wit b/go/examples/spin-basic/wit/world.wit new file mode 100644 index 0000000..7f5462c --- /dev/null +++ b/go/examples/spin-basic/wit/world.wit @@ -0,0 +1,18 @@ +package wasi:otel@0.2.0-draft; + +world imports { + import wasi:cli/environment@0.2.0; + import wasi:io/streams@0.2.0; + import wasi:cli/stdout@0.2.0; + import wasi:clocks/monotonic-clock@0.2.0; + import wasi:random/random@0.2.0; + import wasi:cli/stderr@0.2.0; + import wasi:cli/stdin@0.2.0; + import wasi:filesystem/types@0.2.0; + import wasi:filesystem/preopens@0.2.0; + import fermyon:spin/key-value@2.0.0; + import wasi:http/types@0.2.0; + import tracing; + + export wasi:http/incoming-handler@0.2.0; +} \ No newline at end of file diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..9429632 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,32 @@ +module github.com/calebschoepp/opentelemetry-wasi + +go 1.24.4 + +tool go.bytecodealliance.org/cmd/wit-bindgen-go + +require ( + go.bytecodealliance.org/cm v0.3.0 + go.opentelemetry.io/otel v1.37.0 + go.opentelemetry.io/otel/sdk v1.37.0 + go.opentelemetry.io/otel/trace v1.37.0 +) + +require ( + github.com/coreos/go-semver v0.3.1 // indirect + github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/regclient/regclient v0.8.3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tetratelabs/wazero v1.9.0 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect + github.com/urfave/cli/v3 v3.3.3 // indirect + go.bytecodealliance.org v0.7.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/sys v0.33.0 // indirect +) diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..c3f376a --- /dev/null +++ b/go/go.sum @@ -0,0 +1,69 @@ +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/olareg/olareg v0.1.2 h1:75G8X6E9FUlzL/CSjgFcYfMgNzlc7CxULpUUNsZBIvI= +github.com/olareg/olareg v0.1.2/go.mod h1:TWs+N6pO1S4bdB6eerzUm/ITRQ6kw91mVf9ZYeGtw+Y= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/regclient/regclient v0.8.3 h1:AFAPu/vmOYGyY22AIgzdBUKbzH+83lEpRioRYJ/reCs= +github.com/regclient/regclient v0.8.3/go.mod h1:gjQh5uBVZoo/CngchghtQh9Hx81HOMKRRDd5WPcPkbk= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +go.bytecodealliance.org v0.7.0 h1:CTJ1eb5kFhBKHw1/xycxxz4SmVWNKXYHhrA78oLNXhY= +go.bytecodealliance.org v0.7.0/go.mod h1:PCLMft5yTQsHT9oNPWlq0I6Qdmo6THvdky2AZHjNUkA= +go.bytecodealliance.org/cm v0.3.0 h1:VhV+4vjZPUGCozCg9+up+FNL3YU6XR+XKghk7kQ0vFc= +go.bytecodealliance.org/cm v0.3.0/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/internal/wasi/clocks/wall-clock/empty.s b/go/internal/wasi/clocks/wall-clock/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/internal/wasi/clocks/wall-clock/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/internal/wasi/clocks/wall-clock/wall-clock.wasm.go b/go/internal/wasi/clocks/wall-clock/wall-clock.wasm.go new file mode 100644 index 0000000..321ff3f --- /dev/null +++ b/go/internal/wasi/clocks/wall-clock/wall-clock.wasm.go @@ -0,0 +1,13 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package wallclock + +// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0". + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 now +//go:noescape +func wasmimport_Now(result *DateTime) + +//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution +//go:noescape +func wasmimport_Resolution(result *DateTime) diff --git a/go/internal/wasi/clocks/wall-clock/wall-clock.wit.go b/go/internal/wasi/clocks/wall-clock/wall-clock.wit.go new file mode 100644 index 0000000..9c0a968 --- /dev/null +++ b/go/internal/wasi/clocks/wall-clock/wall-clock.wit.go @@ -0,0 +1,75 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package wallclock represents the imported interface "wasi:clocks/wall-clock@0.2.0". +// +// WASI Wall Clock is a clock API intended to let users query the current +// time. The name "wall" makes an analogy to a "clock on the wall", which +// is not necessarily monotonic as it may be reset. +// +// It is intended to be portable at least between Unix-family platforms and +// Windows. +// +// A wall clock is a clock which measures the date and time according to +// some external reference. +// +// External references may be reset, so this clock is not necessarily +// monotonic, making it unsuitable for measuring elapsed time. +// +// It is intended for reporting the current date and time for humans. +package wallclock + +import ( + "go.bytecodealliance.org/cm" +) + +// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime". +// +// A time and date in seconds plus nanoseconds. +// +// record datetime { +// seconds: u64, +// nanoseconds: u32, +// } +type DateTime struct { + _ cm.HostLayout `json:"-"` + Seconds uint64 `json:"seconds"` + Nanoseconds uint32 `json:"nanoseconds"` +} + +// Now represents the imported function "now". +// +// Read the current value of the clock. +// +// This clock is not monotonic, therefore calling this function repeatedly +// will not necessarily produce a sequence of non-decreasing values. +// +// The returned timestamps represent the number of seconds since +// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], +// also known as [Unix Time]. +// +// The nanoseconds field of the output is always less than 1000000000. +// +// now: func() -> datetime +// +// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 +// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time +// +//go:nosplit +func Now() (result DateTime) { + wasmimport_Now(&result) + return +} + +// Resolution represents the imported function "resolution". +// +// Query the resolution of the clock. +// +// The nanoseconds field of the output is always less than 1000000000. +// +// resolution: func() -> datetime +// +//go:nosplit +func Resolution() (result DateTime) { + wasmimport_Resolution(&result) + return +} diff --git a/go/internal/wasi/otel/imports/imports.wit.go b/go/internal/wasi/otel/imports/imports.wit.go new file mode 100644 index 0000000..8a137c4 --- /dev/null +++ b/go/internal/wasi/otel/imports/imports.wit.go @@ -0,0 +1,4 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package imports represents the world "wasi:otel/imports@0.2.0-draft". +package imports diff --git a/go/internal/wasi/otel/tracing/abi.go b/go/internal/wasi/otel/tracing/abi.go new file mode 100644 index 0000000..4200a48 --- /dev/null +++ b/go/internal/wasi/otel/tracing/abi.go @@ -0,0 +1,16 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package tracing + +import ( + "go.bytecodealliance.org/cm" +) + +func lower_SpanContext(v SpanContext) (f0 *uint8, f1 uint32, f2 *uint8, f3 uint32, f4 uint32, f5 uint32, f6 *[2]string, f7 uint32) { + f0, f1 = cm.LowerString(v.TraceID) + f2, f3 = cm.LowerString(v.SpanID) + f4 = (uint32)(v.TraceFlags) + f5 = (uint32)(cm.BoolToU32(v.IsRemote)) + f6, f7 = cm.LowerList(v.TraceState) + return +} diff --git a/go/internal/wasi/otel/tracing/empty.s b/go/internal/wasi/otel/tracing/empty.s new file mode 100644 index 0000000..5444f20 --- /dev/null +++ b/go/internal/wasi/otel/tracing/empty.s @@ -0,0 +1,3 @@ +// This file exists for testing this package without WebAssembly, +// allowing empty function bodies with a //go:wasmimport directive. +// See https://pkg.go.dev/cmd/compile for more information. diff --git a/go/internal/wasi/otel/tracing/tracing.wasm.go b/go/internal/wasi/otel/tracing/tracing.wasm.go new file mode 100644 index 0000000..ca7fcc5 --- /dev/null +++ b/go/internal/wasi/otel/tracing/tracing.wasm.go @@ -0,0 +1,17 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +package tracing + +// This file contains wasmimport and wasmexport declarations for "wasi:otel@0.2.0-draft". + +//go:wasmimport wasi:otel/tracing@0.2.0-draft on-start +//go:noescape +func wasmimport_OnStart(context0 *uint8, context1 uint32, context2 *uint8, context3 uint32, context4 uint32, context5 uint32, context6 *[2]string, context7 uint32) + +//go:wasmimport wasi:otel/tracing@0.2.0-draft on-end +//go:noescape +func wasmimport_OnEnd(span *SpanData) + +//go:wasmimport wasi:otel/tracing@0.2.0-draft outer-span-context +//go:noescape +func wasmimport_OuterSpanContext(result *SpanContext) diff --git a/go/internal/wasi/otel/tracing/tracing.wit.go b/go/internal/wasi/otel/tracing/tracing.wit.go new file mode 100644 index 0000000..f67234e --- /dev/null +++ b/go/internal/wasi/otel/tracing/tracing.wit.go @@ -0,0 +1,532 @@ +// Code generated by wit-bindgen-go. DO NOT EDIT. + +// Package tracing represents the imported interface "wasi:otel/tracing@0.2.0-draft". +package tracing + +import ( + wallclock "github.com/calebschoepp/opentelemetry-wasi/internal/wasi/clocks/wall-clock" + "go.bytecodealliance.org/cm" +) + +// DateTime represents the type alias "wasi:otel/tracing@0.2.0-draft#datetime". +// +// See [wallclock.DateTime] for more information. +type DateTime = wallclock.DateTime + +// TraceID represents the string "wasi:otel/tracing@0.2.0-draft#trace-id". +// +// The trace that this `span-context` belongs to. +// +// 16 bytes encoded as a hexadecimal string. +// +// type trace-id = string +type TraceID string + +// SpanID represents the string "wasi:otel/tracing@0.2.0-draft#span-id". +// +// The id of this `span-context`. +// +// 8 bytes encoded as a hexadecimal string. +// +// type span-id = string +type SpanID string + +// TraceFlags represents the flags "wasi:otel/tracing@0.2.0-draft#trace-flags". +// +// Flags that can be set on a `span-context`. +// +// flags trace-flags { +// sampled, +// } +type TraceFlags uint8 + +const ( + // Whether the `span` should be sampled or not. + TraceFlagsSampled TraceFlags = 1 << iota +) + +// TraceState represents the list "wasi:otel/tracing@0.2.0-draft#trace-state". +// +// Carries system-specific configuration data, represented as a list of key-value +// pairs. `trace-state` allows multiple tracing systems to participate in the same +// trace. +// +// If any invalid keys or values are provided then the `trace-state` will be treated +// as an empty list. +// +// type trace-state = list> +type TraceState cm.List[[2]string] + +// SpanContext represents the record "wasi:otel/tracing@0.2.0-draft#span-context". +// +// Identifying trace information about a span that can be serialized and propagated. +// +// record span-context { +// trace-id: trace-id, +// span-id: span-id, +// trace-flags: trace-flags, +// is-remote: bool, +// trace-state: trace-state, +// } +type SpanContext struct { + _ cm.HostLayout `json:"-"` + // The `trace-id` for this `span-context`. + TraceID TraceID `json:"trace-id"` + + // The `span-id` for this `span-context`. + SpanID SpanID `json:"span-id"` + + // The `trace-flags` for this `span-context`. + TraceFlags TraceFlags `json:"trace-flags"` + + // Whether this `span-context` was propagated from a remote parent. + IsRemote bool `json:"is-remote"` + + // The `trace-state` for this `span-context`. + TraceState TraceState `json:"trace-state"` +} + +// SpanKind represents the enum "wasi:otel/tracing@0.2.0-draft#span-kind". +// +// Describes the relationship between the Span, its parents, and its children in a +// trace. +// +// enum span-kind { +// client, +// server, +// producer, +// consumer, +// internal +// } +type SpanKind uint8 + +const ( + // Indicates that the span describes a request to some remote service. This span is + // usually the parent of a remote server span and does not end until the response + // is received. + SpanKindClient SpanKind = iota + + // Indicates that the span covers server-side handling of a synchronous RPC or other + // remote request. This span is often the child of a remote client span that was expected + // to wait for a response. + SpanKindServer + + // Indicates that the span describes the initiators of an asynchronous request. This + // parent span will often end before the corresponding child consumer span, possibly + // even before the child span starts. In messaging scenarios with batching, tracing + // individual messages requires a new producer span per message to be created. + SpanKindProducer + + // Indicates that the span describes a child of an asynchronous consumer request. + SpanKindConsumer + + // Default value. Indicates that the span represents an internal operation within + // an application, as opposed to an operations with remote parents or children. + SpanKindInternal +) + +var _SpanKindStrings = [5]string{ + "client", + "server", + "producer", + "consumer", + "internal", +} + +// String implements [fmt.Stringer], returning the enum case name of e. +func (e SpanKind) String() string { + return _SpanKindStrings[e] +} + +// MarshalText implements [encoding.TextMarshaler]. +func (e SpanKind) MarshalText() ([]byte, error) { + return []byte(e.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler], unmarshaling into an enum +// case. Returns an error if the supplied text is not one of the enum cases. +func (e *SpanKind) UnmarshalText(text []byte) error { + return _SpanKindUnmarshalCase(e, text) +} + +var _SpanKindUnmarshalCase = cm.CaseUnmarshaler[SpanKind](_SpanKindStrings[:]) + +// Key represents the string "wasi:otel/tracing@0.2.0-draft#key". +// +// The key part of attribute `key-value` pairs. +// +// type key = string +type Key string + +// Value represents the variant "wasi:otel/tracing@0.2.0-draft#value". +// +// The value part of attribute `key-value` pairs. +// +// variant value { +// %string(string), +// %bool(bool), +// %f64(f64), +// %s64(s64), +// string-array(list), +// bool-array(list), +// f64-array(list), +// s64-array(list), +// } +type Value cm.Variant[uint8, string, float64] + +// ValueString_ returns a [Value] of case "string". +// +// A string value. +func ValueString_(data string) Value { + return cm.New[Value](0, data) +} + +// String_ returns a non-nil *[string] if [Value] represents the variant case "string". +func (self *Value) String_() *string { + return cm.Case[string](self, 0) +} + +// ValueBool returns a [Value] of case "bool". +// +// A boolean value. +func ValueBool(data bool) Value { + return cm.New[Value](1, data) +} + +// Bool returns a non-nil *[bool] if [Value] represents the variant case "bool". +func (self *Value) Bool() *bool { + return cm.Case[bool](self, 1) +} + +// ValueF64 returns a [Value] of case "f64". +// +// A double precision floating point value. +func ValueF64(data float64) Value { + return cm.New[Value](2, data) +} + +// F64 returns a non-nil *[float64] if [Value] represents the variant case "f64". +func (self *Value) F64() *float64 { + return cm.Case[float64](self, 2) +} + +// ValueS64 returns a [Value] of case "s64". +// +// A signed 64 bit integer value. +func ValueS64(data int64) Value { + return cm.New[Value](3, data) +} + +// S64 returns a non-nil *[int64] if [Value] represents the variant case "s64". +func (self *Value) S64() *int64 { + return cm.Case[int64](self, 3) +} + +// ValueStringArray returns a [Value] of case "string-array". +// +// A homogeneous array of string values. +func ValueStringArray(data cm.List[string]) Value { + return cm.New[Value](4, data) +} + +// StringArray returns a non-nil *[cm.List[string]] if [Value] represents the variant case "string-array". +func (self *Value) StringArray() *cm.List[string] { + return cm.Case[cm.List[string]](self, 4) +} + +// ValueBoolArray returns a [Value] of case "bool-array". +// +// A homogeneous array of boolean values. +func ValueBoolArray(data cm.List[bool]) Value { + return cm.New[Value](5, data) +} + +// BoolArray returns a non-nil *[cm.List[bool]] if [Value] represents the variant case "bool-array". +func (self *Value) BoolArray() *cm.List[bool] { + return cm.Case[cm.List[bool]](self, 5) +} + +// ValueF64Array returns a [Value] of case "f64-array". +// +// A homogeneous array of double precision floating point values. +func ValueF64Array(data cm.List[float64]) Value { + return cm.New[Value](6, data) +} + +// F64Array returns a non-nil *[cm.List[float64]] if [Value] represents the variant case "f64-array". +func (self *Value) F64Array() *cm.List[float64] { + return cm.Case[cm.List[float64]](self, 6) +} + +// ValueS64Array returns a [Value] of case "s64-array". +// +// A homogeneous array of 64 bit integer values. +func ValueS64Array(data cm.List[int64]) Value { + return cm.New[Value](7, data) +} + +// S64Array returns a non-nil *[cm.List[int64]] if [Value] represents the variant case "s64-array". +func (self *Value) S64Array() *cm.List[int64] { + return cm.Case[cm.List[int64]](self, 7) +} + +var _ValueStrings = [8]string{ + "string", + "bool", + "f64", + "s64", + "string-array", + "bool-array", + "f64-array", + "s64-array", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v Value) String() string { + return _ValueStrings[v.Tag()] +} + +// KeyValue represents the record "wasi:otel/tracing@0.2.0-draft#key-value". +// +// A key-value pair describing an attribute. +// +// record key-value { +// key: key, +// value: value, +// } +type KeyValue struct { + _ cm.HostLayout `json:"-"` + // The attribute name. + Key Key `json:"key"` + + // The attribute value. + Value Value `json:"value"` +} + +// Event represents the record "wasi:otel/tracing@0.2.0-draft#event". +// +// An event describing a specific moment in time on a span and associated attributes. +// +// record event { +// name: string, +// time: datetime, +// attributes: list, +// } +type Event struct { + _ cm.HostLayout `json:"-"` + // Event name. + Name string `json:"name"` + + // Event time. + Time DateTime `json:"time"` + + // Event attributes. + Attributes cm.List[KeyValue] `json:"attributes"` +} + +// Link represents the record "wasi:otel/tracing@0.2.0-draft#link". +// +// Describes a relationship to another `span`. +// +// record link { +// span-context: span-context, +// attributes: list, +// } +type Link struct { + _ cm.HostLayout `json:"-"` + // Denotes which `span` to link to. + SpanContext SpanContext `json:"span-context"` + + // Attributes describing the link. + Attributes cm.List[KeyValue] `json:"attributes"` +} + +// Status represents the variant "wasi:otel/tracing@0.2.0-draft#status". +// +// The `status` of a `span`. +// +// variant status { +// unset, +// ok, +// error(string), +// } +type Status cm.Variant[uint8, string, string] + +// StatusUnset returns a [Status] of case "unset". +// +// The default status. +func StatusUnset() Status { + var data struct{} + return cm.New[Status](0, data) +} + +// Unset returns true if [Status] represents the variant case "unset". +func (self *Status) Unset() bool { + return self.Tag() == 0 +} + +// StatusOK returns a [Status] of case "ok". +// +// The operation has been validated by an Application developer or Operator to have +// completed successfully. +func StatusOK() Status { + var data struct{} + return cm.New[Status](1, data) +} + +// OK returns true if [Status] represents the variant case "ok". +func (self *Status) OK() bool { + return self.Tag() == 1 +} + +// StatusError returns a [Status] of case "error". +// +// The operation contains an error with a description. +func StatusError(data string) Status { + return cm.New[Status](2, data) +} + +// Error returns a non-nil *[string] if [Status] represents the variant case "error". +func (self *Status) Error() *string { + return cm.Case[string](self, 2) +} + +var _StatusStrings = [3]string{ + "unset", + "ok", + "error", +} + +// String implements [fmt.Stringer], returning the variant case name of v. +func (v Status) String() string { + return _StatusStrings[v.Tag()] +} + +// InstrumentationScope represents the record "wasi:otel/tracing@0.2.0-draft#instrumentation-scope". +// +// Describes the instrumentation scope that produced a span. +// +// record instrumentation-scope { +// name: string, +// version: option, +// schema-url: option, +// attributes: list, +// } +type InstrumentationScope struct { + _ cm.HostLayout `json:"-"` + // Name of the instrumentation scope. + Name string `json:"name"` + + // The library version. + Version cm.Option[string] `json:"version"` + + // Schema URL used by this library. + // https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/schemas/overview.md#schema-url + SchemaURL cm.Option[string] `json:"schema-url"` + + // Specifies the instrumentation scope attributes to associate with emitted telemetry. + Attributes cm.List[KeyValue] `json:"attributes"` +} + +// SpanData represents the record "wasi:otel/tracing@0.2.0-draft#span-data". +// +// The data associated with a span. +// +// record span-data { +// span-context: span-context, +// parent-span-id: string, +// span-kind: span-kind, +// name: string, +// start-time: datetime, +// end-time: datetime, +// attributes: list, +// events: list, +// links: list, +// status: status, +// instrumentation-scope: instrumentation-scope, +// dropped-attributes: u32, +// dropped-events: u32, +// dropped-links: u32, +// } +type SpanData struct { + _ cm.HostLayout `json:"-"` + // Span context. + SpanContext SpanContext `json:"span-context"` + + // Span parent id. + ParentSpanID string `json:"parent-span-id"` + + // Span kind. + SpanKind SpanKind `json:"span-kind"` + + // Span name. + Name string `json:"name"` + + // Span start time. + StartTime DateTime `json:"start-time"` + + // Span end time. + EndTime DateTime `json:"end-time"` + + // Span attributes. + Attributes cm.List[KeyValue] `json:"attributes"` + + // Span events. + Events cm.List[Event] `json:"events"` + + // Span Links. + Links cm.List[Link] `json:"links"` + + // Span status. + Status Status `json:"status"` + + // Instrumentation scope that produced this span. + InstrumentationScope InstrumentationScope `json:"instrumentation-scope"` + + // Number of attributes dropped by the span due to limits being reached. + DroppedAttributes uint32 `json:"dropped-attributes"` + + // Number of events dropped by the span due to limits being reached. + DroppedEvents uint32 `json:"dropped-events"` + + // Number of links dropped by the span due to limits being reached. + DroppedLinks uint32 `json:"dropped-links"` +} + +// OnStart represents the imported function "on-start". +// +// Called when a span is started. +// +// on-start: func(context: span-context) +// +//go:nosplit +func OnStart(context SpanContext) { + context0, context1, context2, context3, context4, context5, context6, context7 := lower_SpanContext(context) + wasmimport_OnStart((*uint8)(context0), (uint32)(context1), (*uint8)(context2), (uint32)(context3), (uint32)(context4), (uint32)(context5), (*[2]string)(context6), (uint32)(context7)) + return +} + +// OnEnd represents the imported function "on-end". +// +// Called when a span is ended. +// +// on-end: func(span: span-data) +// +//go:nosplit +func OnEnd(span SpanData) { + span_ := &span + wasmimport_OnEnd((*SpanData)(span_)) + return +} + +// OuterSpanContext represents the imported function "outer-span-context". +// +// Returns the span context of the host. +// +// outer-span-context: func() -> span-context +// +//go:nosplit +func OuterSpanContext() (result SpanContext) { + wasmimport_OuterSpanContext(&result) + return +} diff --git a/go/processor.go b/go/processor.go new file mode 100644 index 0000000..b2fc0a2 --- /dev/null +++ b/go/processor.go @@ -0,0 +1,73 @@ +package wasi_otel + +import ( + "context" + "fmt" + "sync/atomic" + + wasiTrace "github.com/calebschoepp/opentelemetry-wasi/internal/wasi/otel/tracing" + sdkTrace "go.opentelemetry.io/otel/sdk/trace" +) + +// Source: https://github.com/open-telemetry/opentelemetry-go/blob/20cd7f871fce8fae83ea35958775043d6e94b925/sdk/trace/span_processor.go#L15 + +type WasiProcessor struct { + IsShutdown atomic.Bool +} + +func NewWasiProcessor() *WasiProcessor { + return &WasiProcessor{} +} + +func DefaultWasiProcessor() *WasiProcessor { + return NewWasiProcessor() +} + +func (p *WasiProcessor) OnStart(parent context.Context, s sdkTrace.ReadWriteSpan) { + // TODO: `parent` seems never to be used... + if p.IsShutdown.Load() { + return + } + + wasiTrace.OnStart(toWasiSpanContext(s.SpanContext())) +} + +func (p *WasiProcessor) OnEnd(s sdkTrace.ReadOnlySpan) { + if p.IsShutdown.Load() { + return + } + + wasiTrace.OnEnd(wasiTrace.SpanData{ + SpanContext: toWasiSpanContext(s.SpanContext()), + ParentSpanID: s.Parent().SpanID().String(), + SpanKind: wasiTrace.SpanKind(s.SpanKind()), + Name: s.Name(), + StartTime: toWasiDateTime(s.StartTime()), + EndTime: toWasiDateTime(s.EndTime()), + Attributes: toWasiAttributes(s.Attributes()), + Events: toWasiEvents(s.Events()), + Links: toWasiLinks(s.Links()), + Status: toWasiStatus(s.Status()), + InstrumentationScope: toWasiInstrumentationScope(s.InstrumentationScope()), + DroppedAttributes: uint32(s.DroppedAttributes()), + DroppedEvents: uint32(s.DroppedEvents()), + DroppedLinks: uint32(s.DroppedLinks()), + }) +} + +func (p *WasiProcessor) ForceFlush(ctx context.Context) error { + if p.IsShutdown.Load() { + return fmt.Errorf("processor already shutdown") + } + + return nil +} + +func (p *WasiProcessor) Shutdown(ctx context.Context) error { + err := p.ForceFlush(ctx) + if p.IsShutdown.Swap(true) { + return err + } + + return nil +} diff --git a/go/propagation.go b/go/propagation.go new file mode 100644 index 0000000..8d0609c --- /dev/null +++ b/go/propagation.go @@ -0,0 +1,49 @@ +package wasi_otel + +import ( + "context" + + wasiTrace "github.com/calebschoepp/opentelemetry-wasi/internal/wasi/otel/tracing" + "go.opentelemetry.io/otel/trace" +) + +type WasiPropagator interface { + Extract(cx context.Context) context.Context +} + +type TraceContextPropagator struct{} + +func NewTraceContextPropagator() *TraceContextPropagator { + return &TraceContextPropagator{} +} + +func DefaultTraceContextPropagator() *TraceContextPropagator { + return NewTraceContextPropagator() +} + +func (t TraceContextPropagator) Extract(cx context.Context) context.Context { + // Retrieving span context from the wasm host + hostCx := wasiTrace.OuterSpanContext() + + // Converting wasm host TraceState type to otel TraceState type + var traceState trace.TraceState + for _, entry := range hostCx.TraceState.Slice() { + ts, err := traceState.Insert(entry[0], entry[1]) + if err != nil { + // TODO: not sure how to handle this error + } + traceState = ts + } + + cfg := trace.SpanContextConfig{ + TraceID: trace.TraceID([]byte(hostCx.TraceID)), + SpanID: trace.SpanID([]byte(hostCx.SpanID)), + TraceFlags: trace.TraceFlags(hostCx.TraceFlags), + TraceState: traceState, + Remote: hostCx.IsRemote, + } + + convertedCx := trace.NewSpanContext(cfg) + + return trace.ContextWithRemoteSpanContext(cx, convertedCx) +} diff --git a/go/wkg.lock b/go/wkg.lock new file mode 100644 index 0000000..8b580f4 --- /dev/null +++ b/go/wkg.lock @@ -0,0 +1,30 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:cli" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:e7e85458e11caf76554b724ebf4f113259decf0f3b1ee2e2930de096f72114a7" + +[[packages]] +name = "wasi:clocks" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:51911098e929732f65d1d84f8dc393299f18a9e8de632d854714f37142efe97b" + +[[packages]] +name = "wasi:io" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.0" +version = "0.2.0" +digest = "sha256:c33b1dbf050f64229ff4decbf9a3d3420e0643a86f5f0cea29f81054820020a6" diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 9b87bfc..dc2ad9f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,4 +1,5 @@ mod tracing; +mod types; pub use tracing::*; diff --git a/rust/src/tracing/conversion.rs b/rust/src/tracing/conversion.rs index bed6439..07d64c5 100644 --- a/rust/src/tracing/conversion.rs +++ b/rust/src/tracing/conversion.rs @@ -1,5 +1,4 @@ use crate::wit::wasi::otel::tracing::*; -use std::time::UNIX_EPOCH; impl From for SpanData { fn from(value: opentelemetry_sdk::trace::SpanData) -> Self { @@ -91,57 +90,6 @@ impl From for SpanKind { } } -impl From for Datetime { - fn from(value: std::time::SystemTime) -> Self { - let duration_since_epoch = value - .duration_since(UNIX_EPOCH) - .expect("SystemTime should be after UNIX EPOCH"); - Self { - seconds: duration_since_epoch.as_secs(), - nanoseconds: duration_since_epoch.subsec_nanos(), - } - } -} - -impl From for KeyValue { - fn from(value: opentelemetry::KeyValue) -> Self { - Self { - key: value.key.to_string(), - value: value.value.into(), - } - } -} - -impl From<&opentelemetry::KeyValue> for KeyValue { - fn from(value: &opentelemetry::KeyValue) -> Self { - Self { - key: value.key.to_string(), - value: value.value.clone().into(), - } - } -} - -impl From for Value { - fn from(value: opentelemetry::Value) -> Self { - match value { - opentelemetry::Value::Bool(v) => Self::Bool(v), - opentelemetry::Value::I64(v) => Self::S64(v), - opentelemetry::Value::F64(v) => Self::F64(v), - opentelemetry::Value::String(v) => Self::String(v.to_string()), - opentelemetry::Value::Array(v) => match v { - opentelemetry::Array::Bool(items) => Self::BoolArray(items), - opentelemetry::Array::I64(items) => Self::S64Array(items), - opentelemetry::Array::F64(items) => Self::F64Array(items), - opentelemetry::Array::String(items) => { - Self::StringArray(items.into_iter().map(Into::into).collect()) - } - _ => unimplemented!(), - }, - _ => unimplemented!(), - } - } -} - impl From for Event { fn from(value: opentelemetry::trace::Event) -> Self { Self { diff --git a/rust/src/types.rs b/rust/src/types.rs new file mode 100644 index 0000000..f237773 --- /dev/null +++ b/rust/src/types.rs @@ -0,0 +1 @@ +mod conversion; diff --git a/rust/src/types/conversion.rs b/rust/src/types/conversion.rs new file mode 100644 index 0000000..37fd301 --- /dev/null +++ b/rust/src/types/conversion.rs @@ -0,0 +1,56 @@ +use crate::wit::wasi::{ + clocks0_2_0::wall_clock::Datetime, + otel::types::{KeyValue, Value}, +}; +use std::time::UNIX_EPOCH; + +impl From for KeyValue { + fn from(value: opentelemetry::KeyValue) -> Self { + Self { + key: value.key.to_string(), + value: value.value.into(), + } + } +} + +impl From<&opentelemetry::KeyValue> for KeyValue { + fn from(value: &opentelemetry::KeyValue) -> Self { + Self { + key: value.key.to_string(), + value: value.value.clone().into(), + } + } +} + +impl From for Value { + fn from(value: opentelemetry::Value) -> Self { + match value { + opentelemetry::Value::Bool(v) => Self::Bool(v), + opentelemetry::Value::I64(v) => Self::S64(v), + opentelemetry::Value::F64(v) => Self::F64(v), + opentelemetry::Value::String(v) => Self::String(v.to_string()), + opentelemetry::Value::Array(v) => match v { + opentelemetry::Array::Bool(items) => Self::BoolArray(items), + opentelemetry::Array::I64(items) => Self::S64Array(items), + opentelemetry::Array::F64(items) => Self::F64Array(items), + opentelemetry::Array::String(items) => { + Self::StringArray(items.into_iter().map(Into::into).collect()) + } + _ => unimplemented!(), + }, + _ => unimplemented!(), + } + } +} + +impl From for Datetime { + fn from(value: std::time::SystemTime) -> Self { + let duration_since_epoch = value + .duration_since(UNIX_EPOCH) + .expect("SystemTime should be after UNIX EPOCH"); + Self { + seconds: duration_since_epoch.as_secs(), + nanoseconds: duration_since_epoch.subsec_nanos(), + } + } +} diff --git a/wit/tracing.wit b/wit/tracing.wit index 8ac7385..b45c3fc 100644 --- a/wit/tracing.wit +++ b/wit/tracing.wit @@ -1,6 +1,8 @@ interface tracing { use wasi:clocks/wall-clock@0.2.0.{datetime}; + use types.{key-value}; + /// Called when a span is started. on-start: func(context: span-context); @@ -91,37 +93,6 @@ interface tracing { internal } - /// A key-value pair describing an attribute. - record key-value { - /// The attribute name. - key: key, - /// The attribute value. - value: value, - } - - /// The key part of attribute `key-value` pairs. - type key = string; - - /// The value part of attribute `key-value` pairs. - variant value { - /// A string value. - %string(string), - /// A boolean value. - %bool(bool), - /// A double precision floating point value. - %f64(f64), - /// A signed 64 bit integer value. - %s64(s64), - /// A homogeneous array of string values. - string-array(list), - /// A homogeneous array of boolean values. - bool-array(list), - /// A homogeneous array of double precision floating point values. - f64-array(list), - /// A homogeneous array of 64 bit integer values. - s64-array(list), - } - /// An event describing a specific moment in time on a span and associated attributes. record event { /// Event name. diff --git a/wit/types.wit b/wit/types.wit new file mode 100644 index 0000000..7e42479 --- /dev/null +++ b/wit/types.wit @@ -0,0 +1,32 @@ +interface types { + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + variant value { + /// A string value. + %string(string), + /// A boolean value. + %bool(bool), + /// A double precision floating point value. + %f64(f64), + /// A signed 64 bit integer value. + %s64(s64), + /// A homogeneous array of string values. + string-array(list), + /// A homogeneous array of boolean values. + bool-array(list), + /// A homogeneous array of double precision floating point values. + f64-array(list), + /// A homogeneous array of 64 bit integer values. + s64-array(list), + } +} \ No newline at end of file diff --git a/wit/world.wit b/wit/world.wit index fbd5198..241333b 100644 --- a/wit/world.wit +++ b/wit/world.wit @@ -1,6 +1,7 @@ package wasi:otel@0.2.0-draft; world imports { + import types; import tracing; }