Skip to content

Commit 42a69de

Browse files
committed
internal/reflectlite: do not use the reflect package
This avoids a dependency on the reflect package. I've tried to deduplicate as much as reasonably possible, while keeping the code clean. Especially some tricky methods for the reflect.Type type have a shared implementation (using //go:linkname). In other cases, I've simply used the same type using a type alias, in the other direction (the reflect package now imports the internal/reflectlite package).
1 parent 38e3d55 commit 42a69de

File tree

8 files changed

+503
-253
lines changed

8 files changed

+503
-253
lines changed

src/internal/reflectlite/error.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package reflectlite
2+
3+
type TypeError struct {
4+
Method string
5+
}
6+
7+
func (e *TypeError) Error() string {
8+
return "reflect: call of reflect.Type." + e.Method + " on invalid type"
9+
}
10+
11+
var (
12+
errTypeElem = &TypeError{"Elem"}
13+
)
14+
15+
type ValueError struct {
16+
Method string
17+
Kind Kind
18+
}
19+
20+
func (e *ValueError) Error() string {
21+
if e.Kind == 0 {
22+
return "reflect: call of " + e.Method + " on zero Value"
23+
}
24+
return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
25+
}

src/internal/reflectlite/reflect.go

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/internal/reflectlite/swapper.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package reflectlite
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+
}

0 commit comments

Comments
 (0)