abi.mx raw

   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