From 51ee738f1f24723a1896644c3b236821f7ed4575 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Thu, 26 Oct 2023 16:35:02 -0700 Subject: [PATCH] wit/gen: scaffolding for generating a series of Go packages and files wit: ID type This will be removed in a future commit. wit/gen: add Package.Decls internal/go/gen, bindgen, wit: refactor bindgen: Option types bindgen: initial commit of func Go() cmd/wit-bindgen-go: syntax -> wit cmd/wit-bindgen-go: add basic generate command internal/go/gen: Ident type bindgen, internal/go, wit: WIP Generating valid Go names from WIT names: 1. Scan for an explicit mapping, e.g. wasi:clocks/wall-clock -> wasi/clocks/wallclock 2. Perform string conversion, e.g. : -> /, strip - 3. (optional) validate short package name as valid Go identifier 4. Check against list of Go reserved words 5. For decl names, convert to Go-style names (TitleCase), check against existing decl bindgen, internal/go: WIP cmd/wit-bindgen-go: add --map wit=go ... flag bindgen, cmd/wit-bindgen-go: implement generated by for DO NOT EDIT comment internal/design: stab at what a generated interface for wasi:clocks/wall-clock could look like _design: multiple Go modules _design: WIP for imported and exported type _design/import-and-export: add README _design/import-and-export: fix typo bindgen, wit: WIP remove go.work and secondary go.mod file _design -> design, with go:build tags wasm/cm: importable Component Model primitive types design/wasi/io/poll: hand-rolled example for wasi:io/poll design/wasi/io/poll: right ABI? design/import-and-export: remove build tags where not necessary design/wasi/io: update WIP design/wasi/io/poll: improve comments design/wasi/io/poll: wasmexport methods should call the real methods on the type design/wasi/io: add world.wit source design: reorganized design/{export,import}: further explorations design/export/wasi/io/poll: exploring own/borrow semantics wasm/cm: Resource, Handle, Own, Borrow types wasm/cm: Resource, Handle, Own, Borrow types design: further experimentation cabi, design: post-return function to free allocated memory wasm/cabi: combine cabi and wasm/cm packages wasm/cabi: update README links cmd/wit-bindgen-go/cmd/generate: update to github.com/urfave/cli/v3 API changes cabi, design: move cabi back out of wasm directory cabi: add some TODOs wit: rename PackageName to ID; add extension (world, interface) bindgen, wit: update use of ID wit, testdata: ID -> Ident internal/go/gen: fix test wit: move Ident to ident.go and add tests bidngen, internal/go/gen: start generating Go names bindgen, internal/go/gen: more Go code generation; WIP cmd/wit-bindgen-go/cmd/generate, internal/go/gen: PackagePath function to load go.mod file cmd/wit-bindgen-go/cmd/generate: add -o flag internal/go/gen: Unique name generator internal/go/gen: add package, file, import manipulation bindgen, cmd/wit-bindgen-go/cmd/generate: PackageRoot option bindgen, wit: generate multiple Go packages design/wasi/io/streams: try version directories bindgen: WIP on package path and name generation bindgen: update comments bindgen: WIP bindgen, cmd/wit-bindgen-go/cmd/generate: remove - from Go package paths wit: fix typo bindgen: WIP emitting Go names for types in correct packages bindgen: emit functions; WIP bindgen: remove packageForWorld method bindgen: fake wasmimport lines bindgen: add TODO about mapping WIT functions and typedefs to Go decls internal/go/gen: replace Imports type with Imports func bindgen: export Go name helpers bindgen: rename isSep to notLetterDigit internal/go/gen: rename AddImport to Import bindgen, internal/go/gen: update Unique function internal/go/gen: NewFile -> File bindgen, internal/go/gen: update AddDecl bindgen, internal/go/gen: Decl returns Decl{} bindgen: map wit.TypeDef and wit.Function to gen.Decl bindgen: update comments cmd/wit-bindgen-go/cmd/generate: note generated package list internal/go/gen: remove File.ImportDecls internal/go/gen: FormatDocComments bindgen, cmd/wit-bindgen-go/cmd/generate, internal/go/gen: generate Go code into individual files in packages Write doc comments from WIT into files; set type aliases to any // TODO bindgen: serialize WIT docs into Go doc comments for types and functions bindgen: start breaking out type generation bindgen: rearrange deck chairs bindgen: stub out option internal/go/gen: use golang.org/x/mod/modfile internal/go/gen: require IsGo for HasPackageDocs internal/go/gen: reorganize wit: omit doc comments when ctx == nil bindgen: print WIT definition in doc comments for each type wit: use tab indentation instead of 4 spaces This is necessary for Go doc comments that embed original WIT definition. testdata: regenerate with tab indentation bindgen: declare types before defining them wit: test that all TypeDef roots have named owners Anonymous interfaces can use types, but should point to a type owned by a named interface. design/wasi/io/poll/exports: update design for exported interfaces cabi: tweak --- cabi/README.md | 10 +- cabi/memory.go | 35 + cabi/primitive.go | 17 + cabi/resource.go | 36 ++ cmd/wit-bindgen-go/cmd/syntax/syntax.go | 25 - design/README.md | 3 + design/import-and-export/README.md | 5 + .../wasi/clocks/wallclock/exports.go | 22 + .../wasi/clocks/wallclock/imports.go | 25 + .../wasi/clocks/wallclock/types.go | 13 + design/import-and-export/world.wit | 15 + design/import-and-export/world.wit.json | 82 +++ design/wasi/io/poll/exports/exports.go | 54 ++ design/wasi/io/poll/imports/imports.go | 48 ++ design/wasi/io/poll/types.go | 10 + design/wasi/io/streams/v0.2.0/example.go | 3 + design/wasi/io/world.wit | 49 ++ design/wasi/io/world.wit.json | 596 ++++++++++++++++++ 18 files changed, 1021 insertions(+), 27 deletions(-) create mode 100644 cabi/memory.go create mode 100644 cabi/primitive.go create mode 100644 cabi/resource.go delete mode 100644 cmd/wit-bindgen-go/cmd/syntax/syntax.go create mode 100644 design/README.md create mode 100644 design/import-and-export/README.md create mode 100644 design/import-and-export/wasi/clocks/wallclock/exports.go create mode 100644 design/import-and-export/wasi/clocks/wallclock/imports.go create mode 100644 design/import-and-export/wasi/clocks/wallclock/types.go create mode 100644 design/import-and-export/world.wit create mode 100644 design/import-and-export/world.wit.json create mode 100644 design/wasi/io/poll/exports/exports.go create mode 100644 design/wasi/io/poll/imports/imports.go create mode 100644 design/wasi/io/poll/types.go create mode 100644 design/wasi/io/streams/v0.2.0/example.go create mode 100644 design/wasi/io/world.wit create mode 100644 design/wasi/io/world.wit.json diff --git a/cabi/README.md b/cabi/README.md index d9e5f0878..3efed1547 100644 --- a/cabi/README.md +++ b/cabi/README.md @@ -1,6 +1,12 @@ -### Usage +# Canonical ABI -The `cabi` package contains a single exported WebAssembly function `cabi_realloc` ([Canonical ABI] realloc). To use, import this package with `_`: +## Types + +Package `cabi` declares a number of types, including [Component Model](https://component-model.bytecodealliance.org/) [primitive types](https://component-model.bytecodealliance.org/design/wit.html#primitive-types), along with resource and handle types. + +## cabi_realloc + +The `cabi` package contains an exported WebAssembly function `cabi_realloc` ([Canonical ABI] realloc). To use, import this package with `_`: ``` import _ "github.com/ydnar/wasm-tools-go/cabi" diff --git a/cabi/memory.go b/cabi/memory.go new file mode 100644 index 000000000..f7f880d69 --- /dev/null +++ b/cabi/memory.go @@ -0,0 +1,35 @@ +package cabi + +import ( + "sync" + "unsafe" +) + +// TODO: remove this or move it to package cm? + +var ( + mu sync.Mutex + pointers = make(map[unsafe.Pointer]int) +) + +// KeepAlive reference counts a pointer. +// TODO: prove this works. +func KeepAlive(ptr unsafe.Pointer) { + mu.Lock() + n := pointers[ptr] + pointers[ptr] = n + 1 + mu.Unlock() +} + +// Drop drops a reference to ptr. +// TODO: prove this works. +func Drop(ptr unsafe.Pointer) { + mu.Lock() + n := pointers[ptr] + n -= 1 + // TODO: panic if n < 0? + if n <= 0 { + delete(pointers, ptr) + } + mu.Unlock() +} diff --git a/cabi/primitive.go b/cabi/primitive.go new file mode 100644 index 000000000..b4ab2b962 --- /dev/null +++ b/cabi/primitive.go @@ -0,0 +1,17 @@ +package cabi + +// TODO: remove this or move it to package cm. + +type Bool bool +type S8 int8 +type U8 uint8 +type S16 int16 +type U16 uint16 +type S32 int32 +type U32 uint32 +type S64 int64 +type U64 uint64 +type F32 float32 +type F64 float64 +type Char rune +type String string diff --git a/cabi/resource.go b/cabi/resource.go new file mode 100644 index 000000000..e240b8dcf --- /dev/null +++ b/cabi/resource.go @@ -0,0 +1,36 @@ +package cabi + +// TODO: remove this or move it to package cm. + +// Resource is the interface implemented by all [resource] types. +type Resource[T any] interface { + ResourceHandle() Handle[T] + // BorrowResource() Borrow[T] + // OwnResource() Own[T] +} + +// Handle is an opaque handle to a [resource]. +type Handle[T any] uint32 + +// Own is a handle to an owned [resource]. +type Own[T any] Handle[T] + +func (o Own[T]) Rep() T { + return Rep(Handle[T](o)) +} + +// Borrow is a handle to a borrowed [resource]. +type Borrow[T any] Handle[T] + +func (b Borrow[T]) Rep() T { + return Rep(Handle[T](b)) +} + +// TODO: can we use finalizers for dropping handles? + +// Rep returns the representation of handle, if any. +func Rep[T any, H Handle[T]](handle H) T { + // TODO: extract the actual representation from a table + var v T + return v +} diff --git a/cmd/wit-bindgen-go/cmd/syntax/syntax.go b/cmd/wit-bindgen-go/cmd/syntax/syntax.go deleted file mode 100644 index 8397adb09..000000000 --- a/cmd/wit-bindgen-go/cmd/syntax/syntax.go +++ /dev/null @@ -1,25 +0,0 @@ -package syntax - -import ( - "context" - "fmt" - - "github.com/urfave/cli/v3" - "github.com/ydnar/wasm-tools-go/internal/witcli" -) - -// Command is the CLI command for wit. -var Command = &cli.Command{ - Name: "wit", - Usage: "reverses a WIT JSON file into WIT syntax", - Action: action, -} - -func action(ctx context.Context, cmd *cli.Command) error { - res, err := witcli.LoadOne(cmd.Args().Slice()...) - if err != nil { - return err - } - fmt.Println(res.WIT(nil, "")) - return nil -} diff --git a/design/README.md b/design/README.md new file mode 100644 index 000000000..68359f79b --- /dev/null +++ b/design/README.md @@ -0,0 +1,3 @@ +# Design + +This directory contains hand-written Go packages that correspond to WIT definitions for the purposes of fleshing out a viable design. None of these packages should be imported or used. diff --git a/design/import-and-export/README.md b/design/import-and-export/README.md new file mode 100644 index 000000000..928289e1b --- /dev/null +++ b/design/import-and-export/README.md @@ -0,0 +1,5 @@ +# import-and-export + +This design example contains a subset of the `wasi:clocks` package with a world that both *imports* and *exports* the `wasi:clocks/wall-clock` interface. The purpose of this example is to sketch out a mechanism for generating Go code whereby an interface (and types) can simultaneously be imported and exported. + +The source WIT file is [world.wit](./world.wit). diff --git a/design/import-and-export/wasi/clocks/wallclock/exports.go b/design/import-and-export/wasi/clocks/wallclock/exports.go new file mode 100644 index 000000000..4edd78439 --- /dev/null +++ b/design/import-and-export/wasi/clocks/wallclock/exports.go @@ -0,0 +1,22 @@ +//go:build wasm + +package wallclock + +// Instance is the sole global instance of the +// WIT interface "wasi:clocks/wall-clock". +// Assign it to accept calls to this interface. +var Instance Interface + +// FIXME: correct type for struct return values +// +//go:wasmexport wasi:clocks/wall-clock now +func wasmexport_now() DateTime { + return Instance.Now() +} + +// FIXME: correct type for struct return values +// +//go:wasmexport wasi:clocks/wall-clock resolution +func wasmexport_resolution() DateTime { + return Instance.Resolution() +} diff --git a/design/import-and-export/wasi/clocks/wallclock/imports.go b/design/import-and-export/wasi/clocks/wallclock/imports.go new file mode 100644 index 000000000..0de970c76 --- /dev/null +++ b/design/import-and-export/wasi/clocks/wallclock/imports.go @@ -0,0 +1,25 @@ +//go:build wasm + +package wallclock + +// Now returns a DateTime for the current wall clock, corresponding to +// the Component Model function "wasi:clocks/wall-clock.now". +func Now() DateTime { + return wasmimport_now() +} + +// FIXME: correct type for struct return values +// +//go:wasmimport wasi:clocks/wall-clock now +func wasmimport_now() DateTime + +// Resolution returns the resolution of the current wall clock, corresponding to +// the Component Model function "wasi:clocks/wall-clock.resolution". +func Resolution() DateTime { + return wasmimport_resolution() +} + +// FIXME: correct type for struct return values +// +//go:wasmimport wasi:clocks/wall-clock resolution +func wasmimport_resolution() DateTime diff --git a/design/import-and-export/wasi/clocks/wallclock/types.go b/design/import-and-export/wasi/clocks/wallclock/types.go new file mode 100644 index 000000000..11def3665 --- /dev/null +++ b/design/import-and-export/wasi/clocks/wallclock/types.go @@ -0,0 +1,13 @@ +package wallclock + +// Interface is the Go implementation of WIT interface "wasi:clocks/wall-clock". +type Interface interface { + Now() DateTime + Resolution() DateTime +} + +// DateTime is a Go implementation of WIT type "wasi:clocks/wall-clock.datetime". +type DateTime struct { + Seconds uint64 + Nanonseconds uint32 +} diff --git a/design/import-and-export/world.wit b/design/import-and-export/world.wit new file mode 100644 index 000000000..5cadfa88a --- /dev/null +++ b/design/import-and-export/world.wit @@ -0,0 +1,15 @@ +package wasi:clocks; + +interface wall-clock { + record datetime { + seconds: u64, + nanoseconds: u32 + } + now: func() -> datetime; + resolution: func() -> datetime; +} + +world import-and-export { + import wall-clock; + export wall-clock; +} diff --git a/design/import-and-export/world.wit.json b/design/import-and-export/world.wit.json new file mode 100644 index 000000000..7be5ca114 --- /dev/null +++ b/design/import-and-export/world.wit.json @@ -0,0 +1,82 @@ +{ + "worlds": [ + { + "name": "import-and-export", + "imports": { + "interface-0": { + "interface": 0 + } + }, + "exports": { + "interface-0": { + "interface": 0 + } + }, + "package": 0 + } + ], + "interfaces": [ + { + "name": "wall-clock", + "types": { + "datetime": 0 + }, + "functions": { + "now": { + "name": "now", + "kind": "freestanding", + "params": [], + "results": [ + { + "type": 0 + } + ] + }, + "resolution": { + "name": "resolution", + "kind": "freestanding", + "params": [], + "results": [ + { + "type": 0 + } + ] + } + }, + "package": 0 + } + ], + "types": [ + { + "name": "datetime", + "kind": { + "record": { + "fields": [ + { + "name": "seconds", + "type": "u64" + }, + { + "name": "nanoseconds", + "type": "u32" + } + ] + } + }, + "owner": { + "interface": 0 + } + } + ], + "packages": [ + { + "name": "wasi:clocks", + "interfaces": { + "wall-clock": 0 + }, + "worlds": { + "import-and-export": 0 + } + } + ] +} \ No newline at end of file diff --git a/design/wasi/io/poll/exports/exports.go b/design/wasi/io/poll/exports/exports.go new file mode 100644 index 000000000..81a954866 --- /dev/null +++ b/design/wasi/io/poll/exports/exports.go @@ -0,0 +1,54 @@ +package exports + +import ( + "unsafe" + + "github.com/ydnar/wasm-tools-go/cabi" + "github.com/ydnar/wasm-tools-go/cm" +) + +// Interface implements the Component Model interface "wasi:io/poll". +type Interface interface { + Poll(in cm.List[cabi.Borrow[Pollable]]) cm.List[uint32] + Pollable() interface { + // constructor, static functions would go here + } +} + +// Export registers a concrete implementation of "wasi:io/poll". +func Export(i Interface) { + impl = i +} + +// TODO: make a default implementation that panics with a helpful message on all function calls. +var impl Interface + +//go:wasmexport wasi:io/poll#poll +func poll(in cm.List[cabi.Borrow[Pollable]], result *cm.List[uint32]) { + *result = impl.Poll(in) + // sData := unsafe.SliceData(s.Slice()) + // cabi.KeepAlive(unsafe.Pointer(sData)) +} + +//go:wasmexport wasi:io/poll#cabi_post_poll +func cabi_post_poll(result *cm.List[uint32]) { + // Is this necessary if the Go GC runs after the wasmexport call? + cabi.Drop(unsafe.Pointer(result.Data())) +} + +//go:wasmexport wasi:io/poll#[method]pollable.block +func method_pollable_block(self cabi.Borrow[Pollable]) { + self.Rep().Block() +} + +//go:wasmexport wasi:io/poll#[method]pollable.ready +func method_pollable_ready(self cabi.Borrow[Pollable]) bool { + return self.Rep().Ready() +} + +// Pollable represents the Component Model type "wasi:io/poll.pollable". +type Pollable interface { + Block() + Ready() bool + cabi.Resource[Pollable] +} diff --git a/design/wasi/io/poll/imports/imports.go b/design/wasi/io/poll/imports/imports.go new file mode 100644 index 000000000..9ad20a3f8 --- /dev/null +++ b/design/wasi/io/poll/imports/imports.go @@ -0,0 +1,48 @@ +//go:build wasm + +package imports + +import ( + "unsafe" + + "github.com/ydnar/wasm-tools-go/cabi" + "github.com/ydnar/wasm-tools-go/design/wasi/io/poll" +) + +// Pollable represents the Component Model type "wasi:io/poll.pollable". +type Pollable cabi.Handle[poll.Pollable] + +var _ poll.Pollable = Pollable(0) + +// Poll imports Component Model func "wasi:io/poll.poll". +func Poll(in []poll.Pollable) []uint32 { + in_ := make([]Pollable, len(in)) + for i := range in { + in_[i] = Pollable(in[i].ResourceHandle()) + } + ptr, size := wasmimport_poll(unsafe.SliceData(in_), uint32(len(in_))) + return unsafe.Slice(ptr, size) +} + +func (self Pollable) ResourceHandle() cabi.Handle[poll.Pollable] { + return cabi.Handle[poll.Pollable](self) +} + +//go:wasmimport wasi:io/poll poll +func wasmimport_poll(data *Pollable, size uint32) (*uint32, int32) + +// Block imports Component Model method "wasi:io/poll.pollable.block". +func (self Pollable) Block() { + wasmimport_pollable_block(self) +} + +//go:wasmimport wasi:io/poll [method]pollable.block +func wasmimport_pollable_block(self Pollable) + +// Ready imports Component Model method "wasi:io/poll.pollable.ready". +func (self Pollable) Ready() bool { + return wasmimport_pollable_ready(self) +} + +//go:wasmimport wasi:io/poll [method]pollable.ready +func wasmimport_pollable_ready(self Pollable) bool diff --git a/design/wasi/io/poll/types.go b/design/wasi/io/poll/types.go new file mode 100644 index 000000000..b1539df91 --- /dev/null +++ b/design/wasi/io/poll/types.go @@ -0,0 +1,10 @@ +package poll + +import "github.com/ydnar/wasm-tools-go/cabi" + +// Pollable represents the Component Model type "wasi:io/poll.pollable". +type Pollable interface { + Block() + Ready() bool + cabi.Resource[Pollable] +} diff --git a/design/wasi/io/streams/v0.2.0/example.go b/design/wasi/io/streams/v0.2.0/example.go new file mode 100644 index 000000000..8aecaafdc --- /dev/null +++ b/design/wasi/io/streams/v0.2.0/example.go @@ -0,0 +1,3 @@ +package streams + +const Version = "0.2.0" diff --git a/design/wasi/io/world.wit b/design/wasi/io/world.wit new file mode 100644 index 000000000..6ee210c8d --- /dev/null +++ b/design/wasi/io/world.wit @@ -0,0 +1,49 @@ +package wasi:io; + +interface poll { + resource pollable { + block: func(); + ready: func() -> bool; + } + poll: func(in: list>) -> list; +} + +interface streams { + resource error { + to-debug-string: func() -> string; + } + resource input-stream { + blocking-read: func(len: u64) -> result, stream-error>; + blocking-skip: func(len: u64) -> result; + read: func(len: u64) -> result, stream-error>; + skip: func(len: u64) -> result; + subscribe: func() -> own; + } + resource output-stream { + blocking-flush: func() -> result<_, stream-error>; + blocking-splice: func(src: borrow, len: u64) -> result; + blocking-write-and-flush: func(contents: list) -> result<_, stream-error>; + blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>; + check-write: func() -> result; + flush: func() -> result<_, stream-error>; + splice: func(src: borrow, len: u64) -> result; + subscribe: func() -> own; + write: func(contents: list) -> result<_, stream-error>; + write-zeroes: func(len: u64) -> result<_, stream-error>; + } + use poll.{pollable}; + variant stream-error { + last-operation-failed(own), + closed + } +} + +world imports { + import poll; + import streams; +} + +world exports { + export poll; + export streams; +} diff --git a/design/wasi/io/world.wit.json b/design/wasi/io/world.wit.json new file mode 100644 index 000000000..1f514cc6a --- /dev/null +++ b/design/wasi/io/world.wit.json @@ -0,0 +1,596 @@ +{ + "worlds": [ + { + "name": "imports", + "imports": { + "interface-0": { + "interface": 0 + }, + "interface-1": { + "interface": 1 + } + }, + "exports": {}, + "package": 0 + }, + { + "name": "exports", + "imports": {}, + "exports": { + "interface-0": { + "interface": 0 + }, + "interface-1": { + "interface": 1 + } + }, + "package": 0 + } + ], + "interfaces": [ + { + "name": "poll", + "types": { + "pollable": 0 + }, + "functions": { + "[method]pollable.block": { + "name": "[method]pollable.block", + "kind": { + "method": 0 + }, + "params": [ + { + "name": "self", + "type": 1 + } + ], + "results": [] + }, + "[method]pollable.ready": { + "name": "[method]pollable.ready", + "kind": { + "method": 0 + }, + "params": [ + { + "name": "self", + "type": 1 + } + ], + "results": [ + { + "type": "bool" + } + ] + }, + "poll": { + "name": "poll", + "kind": "freestanding", + "params": [ + { + "name": "in", + "type": 2 + } + ], + "results": [ + { + "type": 3 + } + ] + } + }, + "package": 0 + }, + { + "name": "streams", + "types": { + "pollable": 4, + "error": 5, + "input-stream": 6, + "output-stream": 7, + "stream-error": 9 + }, + "functions": { + "[method]error.to-debug-string": { + "name": "[method]error.to-debug-string", + "kind": { + "method": 5 + }, + "params": [ + { + "name": "self", + "type": 10 + } + ], + "results": [ + { + "type": "string" + } + ] + }, + "[method]input-stream.blocking-read": { + "name": "[method]input-stream.blocking-read", + "kind": { + "method": 6 + }, + "params": [ + { + "name": "self", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 13 + } + ] + }, + "[method]input-stream.blocking-skip": { + "name": "[method]input-stream.blocking-skip", + "kind": { + "method": 6 + }, + "params": [ + { + "name": "self", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 14 + } + ] + }, + "[method]input-stream.read": { + "name": "[method]input-stream.read", + "kind": { + "method": 6 + }, + "params": [ + { + "name": "self", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 13 + } + ] + }, + "[method]input-stream.skip": { + "name": "[method]input-stream.skip", + "kind": { + "method": 6 + }, + "params": [ + { + "name": "self", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 14 + } + ] + }, + "[method]input-stream.subscribe": { + "name": "[method]input-stream.subscribe", + "kind": { + "method": 6 + }, + "params": [ + { + "name": "self", + "type": 11 + } + ], + "results": [ + { + "type": 17 + } + ] + }, + "[method]output-stream.blocking-flush": { + "name": "[method]output-stream.blocking-flush", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + } + ], + "results": [ + { + "type": 16 + } + ] + }, + "[method]output-stream.blocking-splice": { + "name": "[method]output-stream.blocking-splice", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "src", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 14 + } + ] + }, + "[method]output-stream.blocking-write-and-flush": { + "name": "[method]output-stream.blocking-write-and-flush", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "contents", + "type": 12 + } + ], + "results": [ + { + "type": 16 + } + ] + }, + "[method]output-stream.blocking-write-zeroes-and-flush": { + "name": "[method]output-stream.blocking-write-zeroes-and-flush", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 16 + } + ] + }, + "[method]output-stream.check-write": { + "name": "[method]output-stream.check-write", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + } + ], + "results": [ + { + "type": 14 + } + ] + }, + "[method]output-stream.flush": { + "name": "[method]output-stream.flush", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + } + ], + "results": [ + { + "type": 16 + } + ] + }, + "[method]output-stream.splice": { + "name": "[method]output-stream.splice", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "src", + "type": 11 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 14 + } + ] + }, + "[method]output-stream.subscribe": { + "name": "[method]output-stream.subscribe", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + } + ], + "results": [ + { + "type": 17 + } + ] + }, + "[method]output-stream.write": { + "name": "[method]output-stream.write", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "contents", + "type": 12 + } + ], + "results": [ + { + "type": 16 + } + ] + }, + "[method]output-stream.write-zeroes": { + "name": "[method]output-stream.write-zeroes", + "kind": { + "method": 7 + }, + "params": [ + { + "name": "self", + "type": 15 + }, + { + "name": "len", + "type": "u64" + } + ], + "results": [ + { + "type": 16 + } + ] + } + }, + "package": 0 + } + ], + "types": [ + { + "name": "pollable", + "kind": "resource", + "owner": { + "interface": 0 + } + }, + { + "name": null, + "kind": { + "handle": { + "borrow": 0 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "list": 1 + }, + "owner": null + }, + { + "name": null, + "kind": { + "list": "u32" + }, + "owner": null + }, + { + "name": "pollable", + "kind": { + "type": 0 + }, + "owner": { + "interface": 1 + } + }, + { + "name": "error", + "kind": "resource", + "owner": { + "interface": 1 + } + }, + { + "name": "input-stream", + "kind": "resource", + "owner": { + "interface": 1 + } + }, + { + "name": "output-stream", + "kind": "resource", + "owner": { + "interface": 1 + } + }, + { + "name": null, + "kind": { + "handle": { + "own": 5 + } + }, + "owner": null + }, + { + "name": "stream-error", + "kind": { + "variant": { + "cases": [ + { + "name": "last-operation-failed", + "type": 8 + }, + { + "name": "closed", + "type": null + } + ] + } + }, + "owner": { + "interface": 1 + } + }, + { + "name": null, + "kind": { + "handle": { + "borrow": 5 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "handle": { + "borrow": 6 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "list": "u8" + }, + "owner": null + }, + { + "name": null, + "kind": { + "result": { + "ok": 12, + "err": 9 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "result": { + "ok": "u64", + "err": 9 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "handle": { + "borrow": 7 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "result": { + "ok": null, + "err": 9 + } + }, + "owner": null + }, + { + "name": null, + "kind": { + "handle": { + "own": 4 + } + }, + "owner": null + } + ], + "packages": [ + { + "name": "wasi:io", + "interfaces": { + "poll": 0, + "streams": 1 + }, + "worlds": { + "imports": 0, + "exports": 1 + } + } + ] +} \ No newline at end of file