.github
alerting
client
config
controller
core
docs
example
jsonpath
k8s
k8stest
metric
pattern
security
storage
util
vendor
cloud.google.com
github.com
go.etcd.io
golang.org
google.golang.org
appengine
protobuf
encoding
internal
descfmt
descopts
detrand
encoding
errors
fieldsort
filedesc
filetype
flags
genid
impl
mapsort
pragma
set
strs
strings.go
strings_pure.go
strings_unsafe.go
version
proto
reflect
runtime
types
AUTHORS
CONTRIBUTORS
LICENSE
PATENTS
gopkg.in
k8s.io
lukechampine.com
modernc.org
sigs.k8s.io
modules.txt
watchdog
web
.dockerignore
.gitattributes
.gitignore
Dockerfile
LICENSE.md
Makefile
README.md
config.yaml
go.mod
go.sum
main.go
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build !purego,!appengine
|
|
|
|
package strs
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
type (
|
|
stringHeader struct {
|
|
Data unsafe.Pointer
|
|
Len int
|
|
}
|
|
sliceHeader struct {
|
|
Data unsafe.Pointer
|
|
Len int
|
|
Cap int
|
|
}
|
|
)
|
|
|
|
// UnsafeString returns an unsafe string reference of b.
|
|
// The caller must treat the input slice as immutable.
|
|
//
|
|
// WARNING: Use carefully. The returned result must not leak to the end user
|
|
// unless the input slice is provably immutable.
|
|
func UnsafeString(b []byte) (s string) {
|
|
src := (*sliceHeader)(unsafe.Pointer(&b))
|
|
dst := (*stringHeader)(unsafe.Pointer(&s))
|
|
dst.Data = src.Data
|
|
dst.Len = src.Len
|
|
return s
|
|
}
|
|
|
|
// UnsafeBytes returns an unsafe bytes slice reference of s.
|
|
// The caller must treat returned slice as immutable.
|
|
//
|
|
// WARNING: Use carefully. The returned result must not leak to the end user.
|
|
func UnsafeBytes(s string) (b []byte) {
|
|
src := (*stringHeader)(unsafe.Pointer(&s))
|
|
dst := (*sliceHeader)(unsafe.Pointer(&b))
|
|
dst.Data = src.Data
|
|
dst.Len = src.Len
|
|
dst.Cap = src.Len
|
|
return b
|
|
}
|
|
|
|
// Builder builds a set of strings with shared lifetime.
|
|
// This differs from strings.Builder, which is for building a single string.
|
|
type Builder struct {
|
|
buf []byte
|
|
}
|
|
|
|
// AppendFullName is equivalent to protoreflect.FullName.Append,
|
|
// but optimized for large batches where each name has a shared lifetime.
|
|
func (sb *Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName {
|
|
n := len(prefix) + len(".") + len(name)
|
|
if len(prefix) == 0 {
|
|
n -= len(".")
|
|
}
|
|
sb.grow(n)
|
|
sb.buf = append(sb.buf, prefix...)
|
|
sb.buf = append(sb.buf, '.')
|
|
sb.buf = append(sb.buf, name...)
|
|
return pref.FullName(sb.last(n))
|
|
}
|
|
|
|
// MakeString is equivalent to string(b), but optimized for large batches
|
|
// with a shared lifetime.
|
|
func (sb *Builder) MakeString(b []byte) string {
|
|
sb.grow(len(b))
|
|
sb.buf = append(sb.buf, b...)
|
|
return sb.last(len(b))
|
|
}
|
|
|
|
func (sb *Builder) grow(n int) {
|
|
if cap(sb.buf)-len(sb.buf) >= n {
|
|
return
|
|
}
|
|
|
|
// Unlike strings.Builder, we do not need to copy over the contents
|
|
// of the old buffer since our builder provides no API for
|
|
// retrieving previously created strings.
|
|
sb.buf = make([]byte, 2*(cap(sb.buf)+n))
|
|
}
|
|
|
|
func (sb *Builder) last(n int) string {
|
|
return UnsafeString(sb.buf[len(sb.buf)-n:])
|
|
}
|