github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/google.golang.org/protobuf/internal/strs/strings_unsafe.go (about)

     1  // Copyright 2018 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.
     4  
     5  //go:build !purego && !appengine
     6  // +build !purego,!appengine
     7  
     8  package strs
     9  
    10  import (
    11  	"unsafe"
    12  
    13  	"google.golang.org/protobuf/reflect/protoreflect"
    14  )
    15  
    16  type (
    17  	stringHeader struct {
    18  		Data unsafe.Pointer
    19  		Len  int
    20  	}
    21  	sliceHeader struct {
    22  		Data unsafe.Pointer
    23  		Len  int
    24  		Cap  int
    25  	}
    26  )
    27  
    28  // UnsafeString returns an unsafe string reference of b.
    29  // The caller must treat the input slice as immutable.
    30  //
    31  // WARNING: Use carefully. The returned result must not leak to the end user
    32  // unless the input slice is provably immutable.
    33  func UnsafeString(b []byte) (s string) {
    34  	src := (*sliceHeader)(unsafe.Pointer(&b))
    35  	dst := (*stringHeader)(unsafe.Pointer(&s))
    36  	dst.Data = src.Data
    37  	dst.Len = src.Len
    38  	return s
    39  }
    40  
    41  // UnsafeBytes returns an unsafe bytes slice reference of s.
    42  // The caller must treat returned slice as immutable.
    43  //
    44  // WARNING: Use carefully. The returned result must not leak to the end user.
    45  func UnsafeBytes(s string) (b []byte) {
    46  	src := (*stringHeader)(unsafe.Pointer(&s))
    47  	dst := (*sliceHeader)(unsafe.Pointer(&b))
    48  	dst.Data = src.Data
    49  	dst.Len = src.Len
    50  	dst.Cap = src.Len
    51  	return b
    52  }
    53  
    54  // Builder builds a set of strings with shared lifetime.
    55  // This differs from strings.Builder, which is for building a single string.
    56  type Builder struct {
    57  	buf []byte
    58  }
    59  
    60  // AppendFullName is equivalent to protoreflect.FullName.Append,
    61  // but optimized for large batches where each name has a shared lifetime.
    62  func (sb *Builder) AppendFullName(prefix protoreflect.FullName, name protoreflect.Name) protoreflect.FullName {
    63  	n := len(prefix) + len(".") + len(name)
    64  	if len(prefix) == 0 {
    65  		n -= len(".")
    66  	}
    67  	sb.grow(n)
    68  	sb.buf = append(sb.buf, prefix...)
    69  	sb.buf = append(sb.buf, '.')
    70  	sb.buf = append(sb.buf, name...)
    71  	return protoreflect.FullName(sb.last(n))
    72  }
    73  
    74  // MakeString is equivalent to string(b), but optimized for large batches
    75  // with a shared lifetime.
    76  func (sb *Builder) MakeString(b []byte) string {
    77  	sb.grow(len(b))
    78  	sb.buf = append(sb.buf, b...)
    79  	return sb.last(len(b))
    80  }
    81  
    82  func (sb *Builder) grow(n int) {
    83  	if cap(sb.buf)-len(sb.buf) >= n {
    84  		return
    85  	}
    86  
    87  	// Unlike strings.Builder, we do not need to copy over the contents
    88  	// of the old buffer since our builder provides no API for
    89  	// retrieving previously created strings.
    90  	sb.buf = make([]byte, 0, 2*(cap(sb.buf)+n))
    91  }
    92  
    93  func (sb *Builder) last(n int) string {
    94  	return UnsafeString(sb.buf[len(sb.buf)-n:])
    95  }