wasm.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // +build wasm
  2. // +build go1.13
  3. package wasm
  4. import (
  5. "reflect"
  6. "runtime"
  7. "syscall/js"
  8. "unsafe"
  9. )
  10. func sliceToByteSlice(s interface{}) []byte {
  11. switch s := s.(type) {
  12. case []int8:
  13. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  14. return *(*[]byte)(unsafe.Pointer(h))
  15. case []int16:
  16. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  17. h.Len *= 2
  18. h.Cap *= 2
  19. return *(*[]byte)(unsafe.Pointer(h))
  20. case []int32:
  21. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  22. h.Len *= 4
  23. h.Cap *= 4
  24. return *(*[]byte)(unsafe.Pointer(h))
  25. case []int64:
  26. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  27. h.Len *= 8
  28. h.Cap *= 8
  29. return *(*[]byte)(unsafe.Pointer(h))
  30. case []uint8:
  31. return s
  32. case []uint16:
  33. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  34. h.Len *= 2
  35. h.Cap *= 2
  36. return *(*[]byte)(unsafe.Pointer(h))
  37. case []uint32:
  38. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  39. h.Len *= 4
  40. h.Cap *= 4
  41. return *(*[]byte)(unsafe.Pointer(h))
  42. case []uint64:
  43. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  44. h.Len *= 8
  45. h.Cap *= 8
  46. return *(*[]byte)(unsafe.Pointer(h))
  47. case []float32:
  48. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  49. h.Len *= 4
  50. h.Cap *= 4
  51. return *(*[]byte)(unsafe.Pointer(h))
  52. case []float64:
  53. h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
  54. h.Len *= 8
  55. h.Cap *= 8
  56. return *(*[]byte)(unsafe.Pointer(h))
  57. default:
  58. panic("jsutil: unexpected value at sliceToBytesSlice()")
  59. }
  60. }
  61. func SliceToTypedArray(s interface{}) (val js.Value, free func()) {
  62. free = func() {}
  63. switch s := s.(type) {
  64. case []int8:
  65. a := js.Global().Get("Uint8Array").New(len(s))
  66. js.CopyBytesToJS(a, sliceToByteSlice(s))
  67. runtime.KeepAlive(s)
  68. buf := a.Get("buffer")
  69. return js.Global().Get("Int8Array").New(buf, a.Get("byteOffset"), a.Get("byteLength")), free
  70. case []int16:
  71. a := js.Global().Get("Uint8Array").New(len(s) * 2)
  72. js.CopyBytesToJS(a, sliceToByteSlice(s))
  73. runtime.KeepAlive(s)
  74. buf := a.Get("buffer")
  75. return js.Global().Get("Int16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), free
  76. case []int32:
  77. a := js.Global().Get("Uint8Array").New(len(s) * 4)
  78. js.CopyBytesToJS(a, sliceToByteSlice(s))
  79. runtime.KeepAlive(s)
  80. buf := a.Get("buffer")
  81. return js.Global().Get("Int32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
  82. case []uint8:
  83. a := js.Global().Get("Uint8Array").New(len(s))
  84. js.CopyBytesToJS(a, s)
  85. runtime.KeepAlive(s)
  86. return a, free
  87. case []uint16:
  88. a := js.Global().Get("Uint8Array").New(len(s) * 2)
  89. js.CopyBytesToJS(a, sliceToByteSlice(s))
  90. runtime.KeepAlive(s)
  91. buf := a.Get("buffer")
  92. return js.Global().Get("Uint16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), free
  93. case []uint32:
  94. a := js.Global().Get("Uint8Array").New(len(s) * 4)
  95. js.CopyBytesToJS(a, sliceToByteSlice(s))
  96. runtime.KeepAlive(s)
  97. buf := a.Get("buffer")
  98. return js.Global().Get("Uint32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
  99. case []float32:
  100. a := js.Global().Get("Uint8Array").New(len(s) * 4)
  101. js.CopyBytesToJS(a, sliceToByteSlice(s))
  102. runtime.KeepAlive(s)
  103. buf := a.Get("buffer")
  104. return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), free
  105. case []float64:
  106. a := js.Global().Get("Uint8Array").New(len(s) * 8)
  107. js.CopyBytesToJS(a, sliceToByteSlice(s))
  108. runtime.KeepAlive(s)
  109. buf := a.Get("buffer")
  110. return js.Global().Get("Float64Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/8), free
  111. default:
  112. panic("jsutil: unexpected value at SliceToTypedArray()")
  113. }
  114. }
  115. func Equal(a, b js.Value) bool {
  116. return a.Equal(b)
  117. }