diff options
Diffstat (limited to 'pkg/gohacks/gohacks_unsafe.go')
-rw-r--r-- | pkg/gohacks/gohacks_unsafe.go | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/pkg/gohacks/gohacks_unsafe.go b/pkg/gohacks/gohacks_unsafe.go index aad675172..d26c1ac05 100644 --- a/pkg/gohacks/gohacks_unsafe.go +++ b/pkg/gohacks/gohacks_unsafe.go @@ -12,14 +12,35 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build go1.13 +// +build !go1.17 + +// Check type signatures when updating Go version. + // Package gohacks contains utilities for subverting the Go compiler. package gohacks import ( - "reflect" "unsafe" ) +// SliceHeader is equivalent to reflect.SliceHeader, but represents the pointer +// to the underlying array as unsafe.Pointer rather than uintptr, allowing +// SliceHeaders to be directly converted to slice objects. +type SliceHeader struct { + Data unsafe.Pointer + Len int + Cap int +} + +// StringHeader is equivalent to reflect.StringHeader, but represents the +// pointer to the underlying array as unsafe.Pointer rather than uintptr, +// allowing StringHeaders to be directly converted to strings. +type StringHeader struct { + Data unsafe.Pointer + Len int +} + // Noescape hides a pointer from escape analysis. Noescape is the identity // function but escape analysis doesn't think the output depends on the input. // Noescape is inlined and currently compiles down to zero instructions. @@ -36,22 +57,21 @@ func Noescape(p unsafe.Pointer) unsafe.Pointer { // ImmutableBytesFromString is equivalent to []byte(s), except that it uses the // same memory backing s instead of making a heap-allocated copy. This is only // valid if the returned slice is never mutated. -func ImmutableBytesFromString(s string) []byte { - shdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - var bs []byte - bshdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs)) +func ImmutableBytesFromString(s string) (bs []byte) { + shdr := (*StringHeader)(unsafe.Pointer(&s)) + bshdr := (*SliceHeader)(unsafe.Pointer(&bs)) bshdr.Data = shdr.Data bshdr.Len = shdr.Len bshdr.Cap = shdr.Len - return bs + return } // StringFromImmutableBytes is equivalent to string(bs), except that it uses // the same memory backing bs instead of making a heap-allocated copy. This is // only valid if bs is never mutated after StringFromImmutableBytes returns. func StringFromImmutableBytes(bs []byte) string { - // This is cheaper than messing with reflect.StringHeader and - // reflect.SliceHeader, which as of this writing produces many dead stores - // of zeroes. Compare strings.Builder.String(). + // This is cheaper than messing with StringHeader and SliceHeader, which as + // of this writing produces many dead stores of zeroes. Compare + // strings.Builder.String(). return *(*string)(unsafe.Pointer(&bs)) } |