slice_js.go (2778B)
1 // Copyright 2019 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package jsutil 16 17 import ( 18 "fmt" 19 "reflect" 20 "runtime" 21 "syscall/js" 22 "unsafe" 23 ) 24 25 func Uint8ArrayToSlice(value js.Value, length int) []byte { 26 if l := value.Get("byteLength").Int(); length > l { 27 length = l 28 } 29 s := make([]byte, length) 30 js.CopyBytesToGo(s, value) 31 return s 32 } 33 34 func sliceToByteSlice(s interface{}) (bs []byte) { 35 switch s := s.(type) { 36 case []int8: 37 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 38 bs = *(*[]byte)(unsafe.Pointer(h)) 39 runtime.KeepAlive(s) 40 case []int16: 41 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 42 h.Len *= 2 43 h.Cap *= 2 44 bs = *(*[]byte)(unsafe.Pointer(h)) 45 runtime.KeepAlive(s) 46 case []int32: 47 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 48 h.Len *= 4 49 h.Cap *= 4 50 bs = *(*[]byte)(unsafe.Pointer(h)) 51 runtime.KeepAlive(s) 52 case []int64: 53 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 54 h.Len *= 8 55 h.Cap *= 8 56 bs = *(*[]byte)(unsafe.Pointer(h)) 57 runtime.KeepAlive(s) 58 case []uint8: 59 return s 60 case []uint16: 61 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 62 h.Len *= 2 63 h.Cap *= 2 64 bs = *(*[]byte)(unsafe.Pointer(h)) 65 runtime.KeepAlive(s) 66 case []uint32: 67 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 68 h.Len *= 4 69 h.Cap *= 4 70 bs = *(*[]byte)(unsafe.Pointer(h)) 71 runtime.KeepAlive(s) 72 case []uint64: 73 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 74 h.Len *= 8 75 h.Cap *= 8 76 bs = *(*[]byte)(unsafe.Pointer(h)) 77 runtime.KeepAlive(s) 78 case []float32: 79 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 80 h.Len *= 4 81 h.Cap *= 4 82 bs = *(*[]byte)(unsafe.Pointer(h)) 83 runtime.KeepAlive(s) 84 case []float64: 85 h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 86 h.Len *= 8 87 h.Cap *= 8 88 bs = *(*[]byte)(unsafe.Pointer(h)) 89 runtime.KeepAlive(s) 90 default: 91 panic(fmt.Sprintf("jsutil: unexpected value at sliceToBytesSlice: %T", s)) 92 } 93 return 94 } 95 96 func copySliceToTemporaryArrayBuffer(src interface{}) { 97 switch s := src.(type) { 98 case []uint8: 99 js.CopyBytesToJS(temporaryUint8Array, s) 100 case []int8, []int16, []int32, []uint16, []uint32, []float32, []float64: 101 js.CopyBytesToJS(temporaryUint8Array, sliceToByteSlice(s)) 102 default: 103 panic(fmt.Sprintf("jsutil: unexpected value at CopySliceToJS: %T", s)) 104 } 105 }