1 // Copyright 2023 The gVisor Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 15 //go:build go1.13 && !go1.20
16 // +build go1.13,!go1.20
17 18 // TODO(go.dev/issue/8422): Remove this file once Go 1.19 is no longer
19 // supported.
20 21 package gohacks
22 23 import (
24 "unsafe"
25 )
26 27 // stringHeader is equivalent to reflect.StringHeader, but represents the
28 // pointer to the underlying array as unsafe.Pointer rather than uintptr,
29 // allowing StringHeaders to be directly converted to strings.
30 type stringHeader struct {
31 Data unsafe.Pointer
32 Len int
33 }
34 35 // ImmutableBytesFromString is equivalent to []byte(s), except that it uses the
36 // same memory backing s instead of making a heap-allocated copy. This is only
37 // valid if the returned slice is never mutated.
38 func ImmutableBytesFromString(s string) []byte {
39 shdr := (*stringHeader)(unsafe.Pointer(&s))
40 return Slice((*byte)(shdr.Data), shdr.Len)
41 }
42 43 // StringFromImmutableBytes is equivalent to string(bs), except that it uses
44 // the same memory backing bs instead of making a heap-allocated copy. This is
45 // only valid if bs is never mutated after StringFromImmutableBytes returns.
46 func StringFromImmutableBytes(bs []byte) string {
47 // This is cheaper than messing with StringHeader and SliceHeader, which as
48 // of this writing produces many dead stores of zeroes. Compare
49 // strings.Builder.String().
50 return *(*string)(unsafe.Pointer(&bs))
51 }
52