// Go support for Protocol Buffers - Google's data interchange format//// Copyright 2012 The Go Authors. All rights reserved.// https://github.com/golang/protobuf//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.// +build !purego,!appengine,!js// This file contains the implementation of the proto field accesses using package unsafe.package protoimport ()const unsafeAllowed = true// A field identifies a field in a struct, accessible from a pointer.// In this implementation, a field is identified by its byte offset from the start of the struct.type field uintptr// toField returns a field equivalent to the given reflect field.func toField( *reflect.StructField) field {returnfield(.Offset)}// invalidField is an invalid field identifier.const invalidField = ^field(0)// zeroField is a noop when calling pointer.offset.const zeroField = field(0)// IsValid reports whether the field identifier is valid.func ( field) () bool {return != invalidField}// The pointer type below is for the new table-driven encoder/decoder.// The implementation here uses unsafe.Pointer to create a generic pointer.// In pointer_reflect.go we use reflect instead of unsafe to implement// the same (but slower) interface.type pointer struct { p unsafe.Pointer}// size of pointervar ptrSize = unsafe.Sizeof(uintptr(0))// toPointer converts an interface of pointer type to a pointer// that points to the same target.func toPointer( *Message) pointer {// Super-tricky - read pointer out of data word of interface value. // Saves ~25ns over the equivalent: // return valToPointer(reflect.ValueOf(*i))returnpointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer())[1]}}// toAddrPointer converts an interface to a pointer that points to// the interface data.func toAddrPointer( *interface{}, bool) pointer {// Super-tricky - read or get the address of data word of interface value.if {// The interface is of pointer type, thus it is a direct interface. // The data word is the pointer data itself. We take its address.returnpointer{p: unsafe.Pointer(uintptr(unsafe.Pointer()) + ptrSize)} }// The interface is not of pointer type. The data word is the pointer // to the data.returnpointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer())[1]}}// valToPointer converts v to a pointer. v must be of pointer type.func valToPointer( reflect.Value) pointer {returnpointer{p: unsafe.Pointer(.Pointer())}}// offset converts from a pointer to a structure to a pointer to// one of its fields.func ( pointer) ( field) pointer {// For safety, we should panic if !f.IsValid, however calling panic causes // this to no longer be inlineable, which is a serious performance cost. /* if !f.IsValid() { panic("invalid field") } */returnpointer{p: unsafe.Pointer(uintptr(.p) + uintptr())}}func ( pointer) () bool {return .p == nil}func ( pointer) () *int64 {return (*int64)(.p)}func ( pointer) () **int64 {return (**int64)(.p)}func ( pointer) () *[]int64 {return (*[]int64)(.p)}func ( pointer) () *int32 {return (*int32)(.p)}// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist./* func (p pointer) toInt32Ptr() **int32 { return (**int32)(p.p) } func (p pointer) toInt32Slice() *[]int32 { return (*[]int32)(p.p) }*/func ( pointer) () *int32 {return *(**int32)(.p)}func ( pointer) ( int32) { *(**int32)(.p) = &}// getInt32Slice loads a []int32 from p.// The value returned is aliased with the original slice.// This behavior differs from the implementation in pointer_reflect.go.func ( pointer) () []int32 {return *(*[]int32)(.p)}// setInt32Slice stores a []int32 to p.// The value set is aliased with the input slice.// This behavior differs from the implementation in pointer_reflect.go.func ( pointer) ( []int32) { *(*[]int32)(.p) = }// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?func ( pointer) ( int32) { := (*[]int32)(.p) * = append(*, )}func ( pointer) () *uint64 {return (*uint64)(.p)}func ( pointer) () **uint64 {return (**uint64)(.p)}func ( pointer) () *[]uint64 {return (*[]uint64)(.p)}func ( pointer) () *uint32 {return (*uint32)(.p)}func ( pointer) () **uint32 {return (**uint32)(.p)}func ( pointer) () *[]uint32 {return (*[]uint32)(.p)}func ( pointer) () *bool {return (*bool)(.p)}func ( pointer) () **bool {return (**bool)(.p)}func ( pointer) () *[]bool {return (*[]bool)(.p)}func ( pointer) () *float64 {return (*float64)(.p)}func ( pointer) () **float64 {return (**float64)(.p)}func ( pointer) () *[]float64 {return (*[]float64)(.p)}func ( pointer) () *float32 {return (*float32)(.p)}func ( pointer) () **float32 {return (**float32)(.p)}func ( pointer) () *[]float32 {return (*[]float32)(.p)}func ( pointer) () *string {return (*string)(.p)}func ( pointer) () **string {return (**string)(.p)}func ( pointer) () *[]string {return (*[]string)(.p)}func ( pointer) () *[]byte {return (*[]byte)(.p)}func ( pointer) () *[][]byte {return (*[][]byte)(.p)}func ( pointer) () *XXX_InternalExtensions {return (*XXX_InternalExtensions)(.p)}func ( pointer) () *map[int32]Extension {return (*map[int32]Extension)(.p)}// getPointerSlice loads []*T from p as a []pointer.// The value returned is aliased with the original slice.// This behavior differs from the implementation in pointer_reflect.go.func ( pointer) () []pointer {// Super-tricky - p should point to a []*T where T is a // message type. We load it as []pointer.return *(*[]pointer)(.p)}// setPointerSlice stores []pointer into p as a []*T.// The value set is aliased with the input slice.// This behavior differs from the implementation in pointer_reflect.go.func ( pointer) ( []pointer) {// Super-tricky - p should point to a []*T where T is a // message type. We store it as []pointer. *(*[]pointer)(.p) = }// getPointer loads the pointer at p and returns it.func ( pointer) () pointer {returnpointer{p: *(*unsafe.Pointer)(.p)}}// setPointer stores the pointer q at p.func ( pointer) ( pointer) { *(*unsafe.Pointer)(.p) = .p}// append q to the slice pointed to by p.func ( pointer) ( pointer) { := (*[]unsafe.Pointer)(.p) * = append(*, .p)}// getInterfacePointer returns a pointer that points to the// interface data of the interface pointed by p.func ( pointer) () pointer {// Super-tricky - read pointer out of data word of interface value.returnpointer{p: (*(*[2]unsafe.Pointer)(.p))[1]}}// asPointerTo returns a reflect.Value that is a pointer to an// object of type t stored at p.func ( pointer) ( reflect.Type) reflect.Value {returnreflect.NewAt(, .p)}func atomicLoadUnmarshalInfo( **unmarshalInfo) *unmarshalInfo {return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer())))}func atomicStoreUnmarshalInfo( **unmarshalInfo, *unmarshalInfo) {atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer()), unsafe.Pointer())}func atomicLoadMarshalInfo( **marshalInfo) *marshalInfo {return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer())))}func atomicStoreMarshalInfo( **marshalInfo, *marshalInfo) {atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer()), unsafe.Pointer())}func atomicLoadMergeInfo( **mergeInfo) *mergeInfo {return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer())))}func atomicStoreMergeInfo( **mergeInfo, *mergeInfo) {atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer()), unsafe.Pointer())}func atomicLoadDiscardInfo( **discardInfo) *discardInfo {return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer())))}func atomicStoreDiscardInfo( **discardInfo, *discardInfo) {atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer()), unsafe.Pointer())}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.