...

Source file src/github.com/cespare/xxhash/v2/xxhash_unsafe.go

Documentation: github.com/cespare/xxhash/v2

     1  //go:build !appengine
     2  // +build !appengine
     3  
     4  // This file encapsulates usage of unsafe.
     5  // xxhash_safe.go contains the safe implementations.
     6  
     7  package xxhash
     8  
     9  import (
    10  	"unsafe"
    11  )
    12  
    13  // In the future it's possible that compiler optimizations will make these
    14  // XxxString functions unnecessary by realizing that calls such as
    15  // Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205.
    16  // If that happens, even if we keep these functions they can be replaced with
    17  // the trivial safe code.
    18  
    19  // NOTE: The usual way of doing an unsafe string-to-[]byte conversion is:
    20  //
    21  //   var b []byte
    22  //   bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    23  //   bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
    24  //   bh.Len = len(s)
    25  //   bh.Cap = len(s)
    26  //
    27  // Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough
    28  // weight to this sequence of expressions that any function that uses it will
    29  // not be inlined. Instead, the functions below use a different unsafe
    30  // conversion designed to minimize the inliner weight and allow both to be
    31  // inlined. There is also a test (TestInlining) which verifies that these are
    32  // inlined.
    33  //
    34  // See https://github.com/golang/go/issues/42739 for discussion.
    35  
    36  // Sum64String computes the 64-bit xxHash digest of s with a zero seed.
    37  // It may be faster than Sum64([]byte(s)) by avoiding a copy.
    38  func Sum64String(s string) uint64 {
    39  	b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
    40  	return Sum64(b)
    41  }
    42  
    43  // WriteString adds more data to d. It always returns len(s), nil.
    44  // It may be faster than Write([]byte(s)) by avoiding a copy.
    45  func (d *Digest) WriteString(s string) (n int, err error) {
    46  	d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})))
    47  	// d.Write always returns len(s), nil.
    48  	// Ignoring the return output and returning these fixed values buys a
    49  	// savings of 6 in the inliner's cost model.
    50  	return len(s), nil
    51  }
    52  
    53  // sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout
    54  // of the first two words is the same as the layout of a string.
    55  type sliceHeader struct {
    56  	s   string
    57  	cap int
    58  }
    59  

View as plain text