wa-lang.org/wazero@v1.0.2/imports/wasi_snapshot_preview1/random.go (about)

     1  package wasi_snapshot_preview1
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  
     7  	"wa-lang.org/wazero/api"
     8  	"wa-lang.org/wazero/internal/wasm"
     9  )
    10  
    11  const functionRandomGet = "random_get"
    12  
    13  // randomGet is the WASI function named functionRandomGet which writes random
    14  // data to a buffer.
    15  //
    16  // # Parameters
    17  //
    18  //   - buf: api.Memory offset to write random values
    19  //   - bufLen: size of random data in bytes
    20  //
    21  // Result (Errno)
    22  //
    23  // The return value is ErrnoSuccess except the following error conditions:
    24  //   - ErrnoFault: `buf` or `bufLen` point to an offset out of memory
    25  //   - ErrnoIo: a file system error
    26  //
    27  // For example, if underlying random source was seeded like
    28  // `rand.NewSource(42)`, we expect api.Memory to contain:
    29  //
    30  //	                   bufLen (5)
    31  //	          +--------------------------+
    32  //	          |                        	 |
    33  //	[]byte{?, 0x53, 0x8c, 0x7f, 0x96, 0xb1, ?}
    34  //	    buf --^
    35  //
    36  // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-bufLen-size---errno
    37  var randomGet = &wasm.HostFunc{
    38  	ExportNames: []string{functionRandomGet},
    39  	Name:        functionRandomGet,
    40  	ParamTypes:  []api.ValueType{i32, i32},
    41  	ParamNames:  []string{"buf", "buf_len"},
    42  	ResultTypes: []api.ValueType{i32},
    43  	Code: &wasm.Code{
    44  		IsHostFunction: true,
    45  		GoFunc:         wasiFunc(randomGetFn),
    46  	},
    47  }
    48  
    49  func randomGetFn(ctx context.Context, mod api.Module, params []uint64) Errno {
    50  	sysCtx := mod.(*wasm.CallContext).Sys
    51  	randSource := sysCtx.RandSource()
    52  	buf, bufLen := uint32(params[0]), uint32(params[1])
    53  
    54  	randomBytes, ok := mod.Memory().Read(ctx, buf, bufLen)
    55  	if !ok { // out-of-range
    56  		return ErrnoFault
    57  	}
    58  
    59  	// We can ignore the returned n as it only != byteCount on error
    60  	if _, err := io.ReadAtLeast(randSource, randomBytes, int(bufLen)); err != nil {
    61  		return ErrnoIo
    62  	}
    63  
    64  	return ErrnoSuccess
    65  }