1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 "internal/unsafeheader"
13 // Swapper returns a function that swaps the elements in the provided
16 // Swapper panics if the provided interface is not a slice.
17 func Swapper(slice any
) func(i
, j
int) {
19 if v
.Kind() != Slice
{
20 panic(&ValueError
{Method
: "Swapper", Kind
: v
.Kind()})
22 // Fast path for slices of size 0 and 1. Nothing to swap.
25 return func(i
, j
int) { panic("reflect: slice index out of range") }
27 return func(i
, j
int) {
29 panic("reflect: slice index out of range")
34 typ
:= v
.Type().Elem().(*rtype
)
36 hasPtr
:= typ
.ptrdata
!= 0
38 // Some common & small cases, without using memmove:
40 if size
== goarch
.PtrSize
{
41 ps
:= *(*[]unsafe
.Pointer
)(v
.ptr
)
42 return func(i
, j
int) { ps
[i
], ps
[j
] = ps
[j
], ps
[i
] }
44 if typ
.Kind() == String
{
45 ss
:= *(*[]string)(v
.ptr
)
46 return func(i
, j
int) { ss
[i
], ss
[j
] = ss
[j
], ss
[i
] }
51 is
:= *(*[]int64)(v
.ptr
)
52 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
54 is
:= *(*[]int32)(v
.ptr
)
55 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
57 is
:= *(*[]int16)(v
.ptr
)
58 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
60 is
:= *(*[]int8)(v
.ptr
)
61 return func(i
, j
int) { is
[i
], is
[j
] = is
[j
], is
[i
] }
65 s
:= (*unsafeheader
.Slice
)(v
.ptr
)
66 tmp
:= unsafe_New(typ
) // swap scratch space
68 return func(i
, j
int) {
69 if uint(i
) >= uint(s
.Len
) ||
uint(j
) >= uint(s
.Len
) {
70 panic("reflect: slice index out of range")
72 val1
:= arrayAt(s
.Data
, i
, size
, "i < s.Len")
73 val2
:= arrayAt(s
.Data
, j
, size
, "j < s.Len")
74 typedmemmove(typ
, tmp
, val1
)
75 typedmemmove(typ
, val1
, val2
)
76 typedmemmove(typ
, val2
, tmp
)