github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/reflect/swapper.go (about)

     1  package reflect
     2  
     3  import "unsafe"
     4  
     5  // Some of code here has been copied from the Go sources:
     6  //   https://github.com/golang/go/blob/go1.15.2/src/reflect/swapper.go
     7  // It has the following copyright note:
     8  //
     9  // 		Copyright 2016 The Go Authors. All rights reserved.
    10  // 		Use of this source code is governed by a BSD-style
    11  // 		license that can be found in the LICENSE file.
    12  
    13  func Swapper(slice interface{}) func(i, j int) {
    14  	v := ValueOf(slice)
    15  	if v.Kind() != Slice {
    16  		panic(&ValueError{Method: "Swapper"})
    17  	}
    18  
    19  	// Just return Nop func if nothing to swap.
    20  	if v.Len() < 2 {
    21  		return func(i, j int) {}
    22  	}
    23  
    24  	typ := v.typecode.Elem()
    25  	size := typ.Size()
    26  
    27  	header := (*sliceHeader)(v.value)
    28  	tmp := unsafe.Pointer(&make([]byte, size)[0])
    29  
    30  	return func(i, j int) {
    31  		if uint(i) >= uint(header.len) || uint(j) >= uint(header.len) {
    32  			panic("reflect: slice index out of range")
    33  		}
    34  		val1 := unsafe.Add(header.data, uintptr(i)*size)
    35  		val2 := unsafe.Add(header.data, uintptr(j)*size)
    36  		memcpy(tmp, val1, size)
    37  		memcpy(val1, val2, size)
    38  		memcpy(val2, tmp, size)
    39  	}
    40  }