...

Source file src/github.com/gogo/protobuf/proto/pointer_unsafe.go

Documentation: github.com/gogo/protobuf/proto

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2012 The Go Authors.  All rights reserved.
     4  // https://github.com/golang/protobuf
     5  //
     6  // Redistribution and use in source and binary forms, with or without
     7  // modification, are permitted provided that the following conditions are
     8  // met:
     9  //
    10  //     * Redistributions of source code must retain the above copyright
    11  // notice, this list of conditions and the following disclaimer.
    12  //     * Redistributions in binary form must reproduce the above
    13  // copyright notice, this list of conditions and the following disclaimer
    14  // in the documentation and/or other materials provided with the
    15  // distribution.
    16  //     * Neither the name of Google Inc. nor the names of its
    17  // contributors may be used to endorse or promote products derived from
    18  // this software without specific prior written permission.
    19  //
    20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  
    32  // +build !purego,!appengine,!js
    33  
    34  // This file contains the implementation of the proto field accesses using package unsafe.
    35  
    36  package proto
    37  
    38  import (
    39  	"reflect"
    40  	"sync/atomic"
    41  	"unsafe"
    42  )
    43  
    44  const unsafeAllowed = true
    45  
    46  // A field identifies a field in a struct, accessible from a pointer.
    47  // In this implementation, a field is identified by its byte offset from the start of the struct.
    48  type field uintptr
    49  
    50  // toField returns a field equivalent to the given reflect field.
    51  func toField(f *reflect.StructField) field {
    52  	return field(f.Offset)
    53  }
    54  
    55  // invalidField is an invalid field identifier.
    56  const invalidField = ^field(0)
    57  
    58  // zeroField is a noop when calling pointer.offset.
    59  const zeroField = field(0)
    60  
    61  // IsValid reports whether the field identifier is valid.
    62  func (f field) IsValid() bool {
    63  	return f != invalidField
    64  }
    65  
    66  // The pointer type below is for the new table-driven encoder/decoder.
    67  // The implementation here uses unsafe.Pointer to create a generic pointer.
    68  // In pointer_reflect.go we use reflect instead of unsafe to implement
    69  // the same (but slower) interface.
    70  type pointer struct {
    71  	p unsafe.Pointer
    72  }
    73  
    74  // size of pointer
    75  var ptrSize = unsafe.Sizeof(uintptr(0))
    76  
    77  // toPointer converts an interface of pointer type to a pointer
    78  // that points to the same target.
    79  func toPointer(i *Message) pointer {
    80  	// Super-tricky - read pointer out of data word of interface value.
    81  	// Saves ~25ns over the equivalent:
    82  	// return valToPointer(reflect.ValueOf(*i))
    83  	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
    84  }
    85  
    86  // toAddrPointer converts an interface to a pointer that points to
    87  // the interface data.
    88  func toAddrPointer(i *interface{}, isptr bool) pointer {
    89  	// Super-tricky - read or get the address of data word of interface value.
    90  	if isptr {
    91  		// The interface is of pointer type, thus it is a direct interface.
    92  		// The data word is the pointer data itself. We take its address.
    93  		return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
    94  	}
    95  	// The interface is not of pointer type. The data word is the pointer
    96  	// to the data.
    97  	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
    98  }
    99  
   100  // valToPointer converts v to a pointer. v must be of pointer type.
   101  func valToPointer(v reflect.Value) pointer {
   102  	return pointer{p: unsafe.Pointer(v.Pointer())}
   103  }
   104  
   105  // offset converts from a pointer to a structure to a pointer to
   106  // one of its fields.
   107  func (p pointer) offset(f field) pointer {
   108  	// For safety, we should panic if !f.IsValid, however calling panic causes
   109  	// this to no longer be inlineable, which is a serious performance cost.
   110  	/*
   111  		if !f.IsValid() {
   112  			panic("invalid field")
   113  		}
   114  	*/
   115  	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
   116  }
   117  
   118  func (p pointer) isNil() bool {
   119  	return p.p == nil
   120  }
   121  
   122  func (p pointer) toInt64() *int64 {
   123  	return (*int64)(p.p)
   124  }
   125  func (p pointer) toInt64Ptr() **int64 {
   126  	return (**int64)(p.p)
   127  }
   128  func (p pointer) toInt64Slice() *[]int64 {
   129  	return (*[]int64)(p.p)
   130  }
   131  func (p pointer) toInt32() *int32 {
   132  	return (*int32)(p.p)
   133  }
   134  
   135  // See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
   136  /*
   137  	func (p pointer) toInt32Ptr() **int32 {
   138  		return (**int32)(p.p)
   139  	}
   140  	func (p pointer) toInt32Slice() *[]int32 {
   141  		return (*[]int32)(p.p)
   142  	}
   143  */
   144  func (p pointer) getInt32Ptr() *int32 {
   145  	return *(**int32)(p.p)
   146  }
   147  func (p pointer) setInt32Ptr(v int32) {
   148  	*(**int32)(p.p) = &v
   149  }
   150  
   151  // getInt32Slice loads a []int32 from p.
   152  // The value returned is aliased with the original slice.
   153  // This behavior differs from the implementation in pointer_reflect.go.
   154  func (p pointer) getInt32Slice() []int32 {
   155  	return *(*[]int32)(p.p)
   156  }
   157  
   158  // setInt32Slice stores a []int32 to p.
   159  // The value set is aliased with the input slice.
   160  // This behavior differs from the implementation in pointer_reflect.go.
   161  func (p pointer) setInt32Slice(v []int32) {
   162  	*(*[]int32)(p.p) = v
   163  }
   164  
   165  // TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
   166  func (p pointer) appendInt32Slice(v int32) {
   167  	s := (*[]int32)(p.p)
   168  	*s = append(*s, v)
   169  }
   170  
   171  func (p pointer) toUint64() *uint64 {
   172  	return (*uint64)(p.p)
   173  }
   174  func (p pointer) toUint64Ptr() **uint64 {
   175  	return (**uint64)(p.p)
   176  }
   177  func (p pointer) toUint64Slice() *[]uint64 {
   178  	return (*[]uint64)(p.p)
   179  }
   180  func (p pointer) toUint32() *uint32 {
   181  	return (*uint32)(p.p)
   182  }
   183  func (p pointer) toUint32Ptr() **uint32 {
   184  	return (**uint32)(p.p)
   185  }
   186  func (p pointer) toUint32Slice() *[]uint32 {
   187  	return (*[]uint32)(p.p)
   188  }
   189  func (p pointer) toBool() *bool {
   190  	return (*bool)(p.p)
   191  }
   192  func (p pointer) toBoolPtr() **bool {
   193  	return (**bool)(p.p)
   194  }
   195  func (p pointer) toBoolSlice() *[]bool {
   196  	return (*[]bool)(p.p)
   197  }
   198  func (p pointer) toFloat64() *float64 {
   199  	return (*float64)(p.p)
   200  }
   201  func (p pointer) toFloat64Ptr() **float64 {
   202  	return (**float64)(p.p)
   203  }
   204  func (p pointer) toFloat64Slice() *[]float64 {
   205  	return (*[]float64)(p.p)
   206  }
   207  func (p pointer) toFloat32() *float32 {
   208  	return (*float32)(p.p)
   209  }
   210  func (p pointer) toFloat32Ptr() **float32 {
   211  	return (**float32)(p.p)
   212  }
   213  func (p pointer) toFloat32Slice() *[]float32 {
   214  	return (*[]float32)(p.p)
   215  }
   216  func (p pointer) toString() *string {
   217  	return (*string)(p.p)
   218  }
   219  func (p pointer) toStringPtr() **string {
   220  	return (**string)(p.p)
   221  }
   222  func (p pointer) toStringSlice() *[]string {
   223  	return (*[]string)(p.p)
   224  }
   225  func (p pointer) toBytes() *[]byte {
   226  	return (*[]byte)(p.p)
   227  }
   228  func (p pointer) toBytesSlice() *[][]byte {
   229  	return (*[][]byte)(p.p)
   230  }
   231  func (p pointer) toExtensions() *XXX_InternalExtensions {
   232  	return (*XXX_InternalExtensions)(p.p)
   233  }
   234  func (p pointer) toOldExtensions() *map[int32]Extension {
   235  	return (*map[int32]Extension)(p.p)
   236  }
   237  
   238  // getPointerSlice loads []*T from p as a []pointer.
   239  // The value returned is aliased with the original slice.
   240  // This behavior differs from the implementation in pointer_reflect.go.
   241  func (p pointer) getPointerSlice() []pointer {
   242  	// Super-tricky - p should point to a []*T where T is a
   243  	// message type. We load it as []pointer.
   244  	return *(*[]pointer)(p.p)
   245  }
   246  
   247  // setPointerSlice stores []pointer into p as a []*T.
   248  // The value set is aliased with the input slice.
   249  // This behavior differs from the implementation in pointer_reflect.go.
   250  func (p pointer) setPointerSlice(v []pointer) {
   251  	// Super-tricky - p should point to a []*T where T is a
   252  	// message type. We store it as []pointer.
   253  	*(*[]pointer)(p.p) = v
   254  }
   255  
   256  // getPointer loads the pointer at p and returns it.
   257  func (p pointer) getPointer() pointer {
   258  	return pointer{p: *(*unsafe.Pointer)(p.p)}
   259  }
   260  
   261  // setPointer stores the pointer q at p.
   262  func (p pointer) setPointer(q pointer) {
   263  	*(*unsafe.Pointer)(p.p) = q.p
   264  }
   265  
   266  // append q to the slice pointed to by p.
   267  func (p pointer) appendPointer(q pointer) {
   268  	s := (*[]unsafe.Pointer)(p.p)
   269  	*s = append(*s, q.p)
   270  }
   271  
   272  // getInterfacePointer returns a pointer that points to the
   273  // interface data of the interface pointed by p.
   274  func (p pointer) getInterfacePointer() pointer {
   275  	// Super-tricky - read pointer out of data word of interface value.
   276  	return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
   277  }
   278  
   279  // asPointerTo returns a reflect.Value that is a pointer to an
   280  // object of type t stored at p.
   281  func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
   282  	return reflect.NewAt(t, p.p)
   283  }
   284  
   285  func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
   286  	return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
   287  }
   288  func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
   289  	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
   290  }
   291  func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
   292  	return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
   293  }
   294  func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
   295  	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
   296  }
   297  func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
   298  	return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
   299  }
   300  func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
   301  	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
   302  }
   303  func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
   304  	return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
   305  }
   306  func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
   307  	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
   308  }
   309  

View as plain text