github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/imports/wasi_snapshot_preview1/example/cat.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"embed"
     6  	"fmt"
     7  	"io/fs"
     8  	"log"
     9  	"os"
    10  
    11  	"github.com/tetratelabs/wazero"
    12  	"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
    13  	"github.com/tetratelabs/wazero/sys"
    14  )
    15  
    16  // catFS is an embedded filesystem limited to test.txt
    17  //
    18  //go:embed testdata/test.txt
    19  var catFS embed.FS
    20  
    21  // catWasmCargoWasi was compiled from testdata/cargo-wasi/cat.rs
    22  //
    23  //go:embed testdata/cargo-wasi/cat.wasm
    24  var catWasmCargoWasi []byte
    25  
    26  // catWasmTinyGo was compiled from testdata/tinygo/cat.go
    27  //
    28  //go:embed testdata/tinygo/cat.wasm
    29  var catWasmTinyGo []byte
    30  
    31  // catWasmZig was compiled from testdata/zig/cat.zig
    32  //
    33  //go:embed testdata/zig/cat.wasm
    34  var catWasmZig []byte
    35  
    36  // catWasmZigCc was compiled from testdata/zig-cc/cat.c
    37  //
    38  //go:embed testdata/zig-cc/cat.wasm
    39  var catWasmZigCc []byte
    40  
    41  // main writes an input file to stdout, just like `cat`.
    42  //
    43  // This is a basic introduction to the WebAssembly System Interface (WASI).
    44  // See https://github.com/WebAssembly/WASI
    45  func main() {
    46  	// Choose the context to use for function calls.
    47  	ctx := context.Background()
    48  
    49  	// Create a new WebAssembly Runtime.
    50  	r := wazero.NewRuntime(ctx)
    51  	defer r.Close(ctx) // This closes everything this Runtime created.
    52  
    53  	// Since wazero uses fs.FS, we can use standard libraries to do things like trim the leading path.
    54  	rooted, err := fs.Sub(catFS, "testdata")
    55  	if err != nil {
    56  		log.Panicln(err)
    57  	}
    58  
    59  	// Combine the above into our baseline config, overriding defaults.
    60  	config := wazero.NewModuleConfig().
    61  		// By default, I/O streams are discarded and there's no file system.
    62  		WithStdout(os.Stdout).WithStderr(os.Stderr).WithFS(rooted)
    63  
    64  	// Instantiate WASI, which implements system I/O such as console output.
    65  	wasi_snapshot_preview1.MustInstantiate(ctx, r)
    66  
    67  	// Choose the binary we want to test. Most compilers that implement WASI
    68  	// are portable enough to use binaries interchangeably.
    69  	var catWasm []byte
    70  	toolchain := os.Getenv("TOOLCHAIN")
    71  	switch toolchain {
    72  	case "":
    73  		fallthrough // default to TinyGo
    74  	case "cargo-wasi":
    75  		catWasm = catWasmCargoWasi
    76  	case "tinygo":
    77  		catWasm = catWasmTinyGo
    78  	case "zig":
    79  		catWasm = catWasmZig
    80  	case "zig-cc":
    81  		catWasm = catWasmZigCc
    82  	default:
    83  		log.Panicln("unknown toolchain", toolchain)
    84  	}
    85  
    86  	// InstantiateModule runs the "_start" function, WASI's "main".
    87  	// * Set the program name (arg[0]) to "wasi"; arg[1] should be "/test.txt".
    88  	if _, err = r.InstantiateWithConfig(ctx, catWasm, config.WithArgs("wasi", os.Args[1])); err != nil {
    89  		// Note: Most compilers do not exit the module after running "_start",
    90  		// unless there was an error. This allows you to call exported functions.
    91  		if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 {
    92  			fmt.Fprintf(os.Stderr, "exit_code: %d\n", exitErr.ExitCode())
    93  		} else if !ok {
    94  			log.Panicln(err)
    95  		}
    96  	}
    97  }