1 package cm
2 3 import "unsafe"
4 5 const (
6 // ResultOK represents the OK case of a result.
7 ResultOK = false
8 9 // ResultErr represents the error case of a result.
10 ResultErr = true
11 )
12 13 // BoolResult represents a result with no OK or error type.
14 // False represents the OK case and true represents the error case.
15 type BoolResult bool
16 17 // Result represents a result sized to hold the Shape type.
18 // The size of the Shape type must be greater than or equal to the size of OK and Err types.
19 // For results with two zero-length types, use [BoolResult].
20 type Result[Shape, OK, Err any] struct {
21 _ HostLayout
22 result[Shape, OK, Err]
23 }
24 25 // AnyResult is a type constraint for generic functions that accept any [Result] type.
26 type AnyResult[Shape, OK, Err any] interface {
27 ~struct {
28 _ HostLayout
29 result[Shape, OK, Err]
30 }
31 }
32 33 // result represents the internal representation of a Component Model result type.
34 type result[Shape, OK, Err any] struct {
35 _ HostLayout
36 isErr bool
37 _ [0]OK
38 _ [0]Err
39 data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
40 }
41 42 // IsOK returns true if r represents the OK case.
43 func (r *result[Shape, OK, Err]) IsOK() bool {
44 r.validate()
45 return !r.isErr
46 }
47 48 // IsErr returns true if r represents the error case.
49 func (r *result[Shape, OK, Err]) IsErr() bool {
50 r.validate()
51 return r.isErr
52 }
53 54 // OK returns a non-nil *OK pointer if r represents the OK case.
55 // If r represents an error, then it returns nil.
56 func (r *result[Shape, OK, Err]) OK() *OK {
57 r.validate()
58 if r.isErr {
59 return nil
60 }
61 return (*OK)(unsafe.Pointer(&r.data))
62 }
63 64 // Err returns a non-nil *Err pointer if r represents the error case.
65 // If r represents the OK case, then it returns nil.
66 func (r *result[Shape, OK, Err]) Err() *Err {
67 r.validate()
68 if !r.isErr {
69 return nil
70 }
71 return (*Err)(unsafe.Pointer(&r.data))
72 }
73 74 // Result returns (OK, zero value of Err, false) if r represents the OK case,
75 // or (zero value of OK, Err, true) if r represents the error case.
76 // This does not have a pointer receiver, so it can be chained.
77 func (r result[Shape, OK, Err]) Result() (ok OK, err Err, isErr bool) {
78 if r.isErr {
79 return ok, *(*Err)(unsafe.Pointer(&r.data)), true
80 }
81 return *(*OK)(unsafe.Pointer(&r.data)), err, false
82 }
83 84 // This function is sized so it can be inlined and optimized away.
85 func (r *result[Shape, OK, Err]) validate() {
86 var shape Shape
87 var ok OK
88 var err Err
89 90 // Check if size of Shape is greater than both OK and Err
91 if unsafe.Sizeof(shape) > unsafe.Sizeof(ok) && unsafe.Sizeof(shape) > unsafe.Sizeof(err) {
92 panic("result: size of data type > OK and Err types")
93 }
94 95 // Check if size of OK is greater than Shape
96 if unsafe.Sizeof(ok) > unsafe.Sizeof(shape) {
97 panic("result: size of OK type > data type")
98 }
99 100 // Check if size of Err is greater than Shape
101 if unsafe.Sizeof(err) > unsafe.Sizeof(shape) {
102 panic("result: size of Err type > data type")
103 }
104 105 // Check if Shape is zero-sized, but size of result != 1
106 if unsafe.Sizeof(shape) == 0 && unsafe.Sizeof(*r) != 1 {
107 panic("result: size of data type == 0, but result size != 1")
108 }
109 }
110 111 // OK returns an OK result with shape Shape and type OK and Err.
112 // Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
113 func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
114 var r Result[Shape, OK, Err]
115 r.validate()
116 r.isErr = ResultOK
117 *((*OK)(unsafe.Pointer(&r.data))) = ok
118 return R(r)
119 }
120 121 // Err returns an error result with shape Shape and type OK and Err.
122 // Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
123 func Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {
124 var r Result[Shape, OK, Err]
125 r.validate()
126 r.isErr = ResultErr
127 *((*Err)(unsafe.Pointer(&r.data))) = err
128 return R(r)
129 }
130