mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-08 13:03:39 +00:00
c02a8141c7
* internal/wasm-tools, internal/cm: update wasm-tools-go to v0.3.1 and regenerate bindings * syscall: use new (cm.Result).Result() method instead of OK() and Err()
130 lines
3.7 KiB
Go
130 lines
3.7 KiB
Go
package cm
|
|
|
|
import "unsafe"
|
|
|
|
const (
|
|
// ResultOK represents the OK case of a result.
|
|
ResultOK = false
|
|
|
|
// ResultErr represents the error case of a result.
|
|
ResultErr = true
|
|
)
|
|
|
|
// BoolResult represents a result with no OK or error type.
|
|
// False represents the OK case and true represents the error case.
|
|
type BoolResult bool
|
|
|
|
// Result represents a result sized to hold the Shape type.
|
|
// The size of the Shape type must be greater than or equal to the size of OK and Err types.
|
|
// For results with two zero-length types, use [BoolResult].
|
|
type Result[Shape, OK, Err any] struct {
|
|
_ HostLayout
|
|
result[Shape, OK, Err]
|
|
}
|
|
|
|
// AnyResult is a type constraint for generic functions that accept any [Result] type.
|
|
type AnyResult[Shape, OK, Err any] interface {
|
|
~struct {
|
|
_ HostLayout
|
|
result[Shape, OK, Err]
|
|
}
|
|
}
|
|
|
|
// result represents the internal representation of a Component Model result type.
|
|
type result[Shape, OK, Err any] struct {
|
|
_ HostLayout
|
|
isErr bool
|
|
_ [0]OK
|
|
_ [0]Err
|
|
data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
|
|
}
|
|
|
|
// IsOK returns true if r represents the OK case.
|
|
func (r *result[Shape, OK, Err]) IsOK() bool {
|
|
r.validate()
|
|
return !r.isErr
|
|
}
|
|
|
|
// IsErr returns true if r represents the error case.
|
|
func (r *result[Shape, OK, Err]) IsErr() bool {
|
|
r.validate()
|
|
return r.isErr
|
|
}
|
|
|
|
// OK returns a non-nil *OK pointer if r represents the OK case.
|
|
// If r represents an error, then it returns nil.
|
|
func (r *result[Shape, OK, Err]) OK() *OK {
|
|
r.validate()
|
|
if r.isErr {
|
|
return nil
|
|
}
|
|
return (*OK)(unsafe.Pointer(&r.data))
|
|
}
|
|
|
|
// Err returns a non-nil *Err pointer if r represents the error case.
|
|
// If r represents the OK case, then it returns nil.
|
|
func (r *result[Shape, OK, Err]) Err() *Err {
|
|
r.validate()
|
|
if !r.isErr {
|
|
return nil
|
|
}
|
|
return (*Err)(unsafe.Pointer(&r.data))
|
|
}
|
|
|
|
// Result returns (OK, zero value of Err, false) if r represents the OK case,
|
|
// or (zero value of OK, Err, true) if r represents the error case.
|
|
// This does not have a pointer receiver, so it can be chained.
|
|
func (r result[Shape, OK, Err]) Result() (ok OK, err Err, isErr bool) {
|
|
if r.isErr {
|
|
return ok, *(*Err)(unsafe.Pointer(&r.data)), true
|
|
}
|
|
return *(*OK)(unsafe.Pointer(&r.data)), err, false
|
|
}
|
|
|
|
// This function is sized so it can be inlined and optimized away.
|
|
func (r *result[Shape, OK, Err]) validate() {
|
|
var shape Shape
|
|
var ok OK
|
|
var err Err
|
|
|
|
// Check if size of Shape is greater than both OK and Err
|
|
if unsafe.Sizeof(shape) > unsafe.Sizeof(ok) && unsafe.Sizeof(shape) > unsafe.Sizeof(err) {
|
|
panic("result: size of data type > OK and Err types")
|
|
}
|
|
|
|
// Check if size of OK is greater than Shape
|
|
if unsafe.Sizeof(ok) > unsafe.Sizeof(shape) {
|
|
panic("result: size of OK type > data type")
|
|
}
|
|
|
|
// Check if size of Err is greater than Shape
|
|
if unsafe.Sizeof(err) > unsafe.Sizeof(shape) {
|
|
panic("result: size of Err type > data type")
|
|
}
|
|
|
|
// Check if Shape is zero-sized, but size of result != 1
|
|
if unsafe.Sizeof(shape) == 0 && unsafe.Sizeof(*r) != 1 {
|
|
panic("result: size of data type == 0, but result size != 1")
|
|
}
|
|
}
|
|
|
|
// OK returns an OK result with shape Shape and type OK and Err.
|
|
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
|
func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
|
|
var r Result[Shape, OK, Err]
|
|
r.validate()
|
|
r.isErr = ResultOK
|
|
*((*OK)(unsafe.Pointer(&r.data))) = ok
|
|
return R(r)
|
|
}
|
|
|
|
// Err returns an error result with shape Shape and type OK and Err.
|
|
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
|
func Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {
|
|
var r Result[Shape, OK, Err]
|
|
r.validate()
|
|
r.isErr = ResultErr
|
|
*((*Err)(unsafe.Pointer(&r.data))) = err
|
|
return R(r)
|
|
}
|