Source file
src/reflect/swapper.go
1
2
3
4
5 package reflect
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "internal/unsafeheader"
11 "unsafe"
12 )
13
14
15
16
17
18 func Swapper(slice any) func(i, j int) {
19 v := ValueOf(slice)
20 if v.Kind() != Slice {
21 panic(&ValueError{Method: "Swapper", Kind: v.Kind()})
22 }
23
24 switch v.Len() {
25 case 0:
26 return func(i, j int) { panic("reflect: slice index out of range") }
27 case 1:
28 return func(i, j int) {
29 if i != 0 || j != 0 {
30 panic("reflect: slice index out of range")
31 }
32 }
33 }
34
35 typ := v.Type().Elem().common()
36 size := typ.Size()
37 hasPtr := typ.Pointers()
38
39
40 if hasPtr {
41 if size == goarch.PtrSize {
42 ps := *(*[]unsafe.Pointer)(v.ptr)
43 return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
44 }
45 if typ.Kind() == abi.String {
46 ss := *(*[]string)(v.ptr)
47 return func(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
48 }
49 } else {
50 switch size {
51 case 8:
52 is := *(*[]int64)(v.ptr)
53 return func(i, j int) { is[i], is[j] = is[j], is[i] }
54 case 4:
55 is := *(*[]int32)(v.ptr)
56 return func(i, j int) { is[i], is[j] = is[j], is[i] }
57 case 2:
58 is := *(*[]int16)(v.ptr)
59 return func(i, j int) { is[i], is[j] = is[j], is[i] }
60 case 1:
61 is := *(*[]int8)(v.ptr)
62 return func(i, j int) { is[i], is[j] = is[j], is[i] }
63 }
64 }
65
66 s := (*unsafeheader.Slice)(v.ptr)
67 tmp := unsafe_New(typ)
68
69 return func(i, j int) {
70 if uint(i) >= uint(s.Len) || uint(j) >= uint(s.Len) {
71 panic("reflect: slice index out of range")
72 }
73 val1 := arrayAt(s.Data, i, size, "i < s.Len")
74 val2 := arrayAt(s.Data, j, size, "j < s.Len")
75 typedmemmove(typ, tmp, val1)
76 typedmemmove(typ, val1, val2)
77 typedmemmove(typ, val2, tmp)
78 }
79 }
80
View as plain text