package sys
import (
"errors"
"fmt"
"io"
"net"
"time"
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
"github.com/tetratelabs/wazero/internal/platform"
"github.com/tetratelabs/wazero/sys"
)
type Context struct {
args, environ [][]byte
argsSize, environSize uint32
walltime sys .Walltime
walltimeResolution sys .ClockResolution
nanotime sys .Nanotime
nanotimeResolution sys .ClockResolution
nanosleep sys .Nanosleep
osyield sys .Osyield
randSource io .Reader
fsc FSContext
}
func (c *Context ) Args () [][]byte {
return c .args
}
func (c *Context ) ArgsSize () uint32 {
return c .argsSize
}
func (c *Context ) Environ () [][]byte {
return c .environ
}
func (c *Context ) EnvironSize () uint32 {
return c .environSize
}
func (c *Context ) Walltime () (sec int64 , nsec int32 ) {
return c .walltime ()
}
func (c *Context ) WalltimeNanos () int64 {
sec , nsec := c .Walltime ()
return (sec * time .Second .Nanoseconds ()) + int64 (nsec )
}
func (c *Context ) WalltimeResolution () sys .ClockResolution {
return c .walltimeResolution
}
func (c *Context ) Nanotime () int64 {
return c .nanotime ()
}
func (c *Context ) NanotimeResolution () sys .ClockResolution {
return c .nanotimeResolution
}
func (c *Context ) Nanosleep (ns int64 ) {
c .nanosleep (ns )
}
func (c *Context ) Osyield () {
c .osyield ()
}
func (c *Context ) FS () *FSContext {
return &c .fsc
}
func (c *Context ) RandSource () io .Reader {
return c .randSource
}
func DefaultContext (fs experimentalsys .FS ) *Context {
if sysCtx , err := NewContext (0 , nil , nil , nil , nil , nil , nil , nil , 0 , nil , 0 , nil , nil , []experimentalsys .FS {fs }, []string {"" }, nil ); err != nil {
panic (fmt .Errorf ("BUG: DefaultContext should never error: %w" , err ))
} else {
return sysCtx
}
}
func NewContext (
max uint32 ,
args , environ [][]byte ,
stdin io .Reader ,
stdout , stderr io .Writer ,
randSource io .Reader ,
walltime sys .Walltime ,
walltimeResolution sys .ClockResolution ,
nanotime sys .Nanotime ,
nanotimeResolution sys .ClockResolution ,
nanosleep sys .Nanosleep ,
osyield sys .Osyield ,
fs []experimentalsys .FS , guestPaths []string ,
tcpListeners []*net .TCPListener ,
) (sysCtx *Context , err error ) {
sysCtx = &Context {args : args , environ : environ }
if sysCtx .argsSize , err = nullTerminatedByteCount (max , args ); err != nil {
return nil , fmt .Errorf ("args invalid: %w" , err )
}
if sysCtx .environSize , err = nullTerminatedByteCount (max , environ ); err != nil {
return nil , fmt .Errorf ("environ invalid: %w" , err )
}
if randSource == nil {
sysCtx .randSource = platform .NewFakeRandSource ()
} else {
sysCtx .randSource = randSource
}
if walltime != nil {
if clockResolutionInvalid (walltimeResolution ) {
return nil , fmt .Errorf ("invalid Walltime resolution: %d" , walltimeResolution )
}
sysCtx .walltime = walltime
sysCtx .walltimeResolution = walltimeResolution
} else {
sysCtx .walltime = platform .NewFakeWalltime ()
sysCtx .walltimeResolution = sys .ClockResolution (time .Microsecond .Nanoseconds ())
}
if nanotime != nil {
if clockResolutionInvalid (nanotimeResolution ) {
return nil , fmt .Errorf ("invalid Nanotime resolution: %d" , nanotimeResolution )
}
sysCtx .nanotime = nanotime
sysCtx .nanotimeResolution = nanotimeResolution
} else {
sysCtx .nanotime = platform .NewFakeNanotime ()
sysCtx .nanotimeResolution = sys .ClockResolution (time .Nanosecond )
}
if nanosleep != nil {
sysCtx .nanosleep = nanosleep
} else {
sysCtx .nanosleep = platform .FakeNanosleep
}
if osyield != nil {
sysCtx .osyield = osyield
} else {
sysCtx .osyield = platform .FakeOsyield
}
err = sysCtx .InitFSContext (stdin , stdout , stderr , fs , guestPaths , tcpListeners )
return
}
func clockResolutionInvalid(resolution sys .ClockResolution ) bool {
return resolution < 1 || resolution > sys .ClockResolution (time .Hour .Nanoseconds ())
}
func nullTerminatedByteCount(max uint32 , elements [][]byte ) (uint32 , error ) {
count := uint32 (len (elements ))
if count > max {
return 0 , errors .New ("exceeds maximum count" )
}
bufSize , maxSize := uint64 (count ), uint64 (max )
for _ , e := range elements {
for _ , c := range e {
if c == 0 {
return 0 , errors .New ("contains NUL character" )
}
}
nextSize := bufSize + uint64 (len (e ))
if nextSize > maxSize {
return 0 , errors .New ("exceeds maximum size" )
}
bufSize = nextSize
}
return uint32 (bufSize ), nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .