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) }