1 package cm
2 3 import "unsafe"
4 5 // AnyInteger is a type constraint for any integer type.
6 type AnyInteger interface {
7 ~int | ~uint | ~uintptr | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int64 | ~uint64
8 }
9 10 // Reinterpret reinterprets the bits of type From into type T.
11 // Will panic if the size of From is smaller than the size of To.
12 func Reinterpret[T, From any](from From) (to T) {
13 if unsafe.Sizeof(to) > unsafe.Sizeof(from) {
14 panic("reinterpret: size of to > from")
15 }
16 return *(*T)(unsafe.Pointer(&from))
17 }
18 19 // LowerString lowers a [string] into a pair of Core WebAssembly types.
20 //
21 // [string]: https://pkg.go.dev/builtin#string
22 func LowerString[S ~string](s S) (*byte, uint32) {
23 return unsafe.StringData([]byte(s)), uint32(len(s))
24 }
25 26 // LiftString lifts Core WebAssembly types into a [string].
27 func LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len AnyInteger](data Data, len Len) T {
28 return T(unsafe.String((*uint8)(unsafe.Pointer(data)), int(len)))
29 }
30 31 // LowerList lowers a [List] into a pair of Core WebAssembly types.
32 func LowerList[L AnyList[T], T any](list L) (*T, uint32) {
33 l := (*List[T])(unsafe.Pointer(&list))
34 return l.data, uint32(l.len)
35 }
36 37 // LiftList lifts Core WebAssembly types into a [List].
38 func LiftList[L AnyList[T], T any, Data unsafe.Pointer | uintptr | *T, Len AnyInteger](data Data, len Len) L {
39 return L(NewList((*T)(unsafe.Pointer(data)), len))
40 }
41 42 // BoolToU32 converts a value whose underlying type is [bool] into a [uint32].
43 // Used to lower a [bool] into a Core WebAssembly i32 as specified in the [Canonical ABI].
44 //
45 // [bool]: https://pkg.go.dev/builtin#bool
46 // [uint32]: https://pkg.go.dev/builtin#uint32
47 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
48 func BoolToU32[B ~bool](v B) uint32 { return uint32(*(*uint8)(unsafe.Pointer(&v))) }
49 50 // U32ToBool converts a [uint32] into a [bool].
51 // Used to lift a Core WebAssembly i32 into a [bool] as specified in the [Canonical ABI].
52 //
53 // [uint32]: https://pkg.go.dev/builtin#uint32
54 // [bool]: https://pkg.go.dev/builtin#bool
55 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
56 func U32ToBool(v uint32) bool { tmp := uint8(v); return *(*bool)(unsafe.Pointer(&tmp)) }
57 58 // F32ToU32 maps the bits of a [float32] into a [uint32].
59 // Used to lower a [float32] into a Core WebAssembly i32 as specified in the [Canonical ABI].
60 //
61 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
62 // [float32]: https://pkg.go.dev/builtin#float32
63 // [uint32]: https://pkg.go.dev/builtin#uint32
64 func F32ToU32(v float32) uint32 { return *(*uint32)(unsafe.Pointer(&v)) }
65 66 // U32ToF32 maps the bits of a [uint32] into a [float32].
67 // Used to lift a Core WebAssembly i32 into a [float32] as specified in the [Canonical ABI].
68 //
69 // [uint32]: https://pkg.go.dev/builtin#uint32
70 // [float32]: https://pkg.go.dev/builtin#float32
71 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
72 func U32ToF32(v uint32) float32 { return *(*float32)(unsafe.Pointer(&v)) }
73 74 // F64ToU64 maps the bits of a [float64] into a [uint64].
75 // Used to lower a [float64] into a Core WebAssembly i64 as specified in the [Canonical ABI].
76 //
77 // [float64]: https://pkg.go.dev/builtin#float64
78 // [uint64]: https://pkg.go.dev/builtin#uint64
79 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
80 //
81 // [uint32]: https://pkg.go.dev/builtin#uint32
82 func F64ToU64(v float64) uint64 { return *(*uint64)(unsafe.Pointer(&v)) }
83 84 // U64ToF64 maps the bits of a [uint64] into a [float64].
85 // Used to lift a Core WebAssembly i64 into a [float64] as specified in the [Canonical ABI].
86 //
87 // [uint64]: https://pkg.go.dev/builtin#uint64
88 // [float64]: https://pkg.go.dev/builtin#float64
89 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
90 func U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }
91 92 // F32ToU64 maps the bits of a [float32] into a [uint64].
93 // Used to lower a [float32] into a Core WebAssembly i64 when required by the [Canonical ABI].
94 //
95 // [float32]: https://pkg.go.dev/builtin#float32
96 // [uint64]: https://pkg.go.dev/builtin#uint64
97 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
98 func F32ToU64(v float32) uint64 { return uint64(*(*uint32)(unsafe.Pointer(&v))) }
99 100 // U64ToF32 maps the bits of a [uint64] into a [float32].
101 // Used to lift a Core WebAssembly i64 into a [float32] when required by the [Canonical ABI].
102 //
103 // [uint64]: https://pkg.go.dev/builtin#uint64
104 // [float32]: https://pkg.go.dev/builtin#float32
105 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
106 func U64ToF32(v uint64) float32 {
107 truncated := uint32(v)
108 return *(*float32)(unsafe.Pointer(&truncated))
109 }
110 111 // PointerToU32 converts a pointer of type *T into a [uint32].
112 // Used to lower a pointer into a Core WebAssembly i32 as specified in the [Canonical ABI].
113 //
114 // [uint32]: https://pkg.go.dev/builtin#uint32
115 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
116 func PointerToU32[T any](v *T) uint32 { return uint32(uintptr(unsafe.Pointer(v))) }
117 118 // U32ToPointer converts a [uint32] into a pointer of type *T.
119 // Used to lift a Core WebAssembly i32 into a pointer as specified in the [Canonical ABI].
120 //
121 // [uint32]: https://pkg.go.dev/builtin#uint32
122 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
123 func U32ToPointer[T any](v uint32) *T { return (*T)(unsafePointer(uintptr(v))) }
124 125 // PointerToU64 converts a pointer of type *T into a [uint64].
126 // Used to lower a pointer into a Core WebAssembly i64 as specified in the [Canonical ABI].
127 //
128 // [uint64]: https://pkg.go.dev/builtin#uint64
129 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
130 func PointerToU64[T any](v *T) uint64 { return uint64(uintptr(unsafe.Pointer(v))) }
131 132 // U64ToPointer converts a [uint64] into a pointer of type *T.
133 // Used to lift a Core WebAssembly i64 into a pointer as specified in the [Canonical ABI].
134 //
135 // [uint64]: https://pkg.go.dev/builtin#uint64
136 // [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
137 func U64ToPointer[T any](v uint64) *T { return (*T)(unsafePointer(uintptr(v))) }
138 139 // Appease vet, see https://github.com/golang/go/issues/58625
140 func unsafePointer(p uintptr) unsafe.Pointer {
141 return *(*unsafe.Pointer)(unsafe.Pointer(&p))
142 }
143