vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go
changeset 256 6d9efbef00a9
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
       
     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 // +build !purego,!appengine
       
     6 
       
     7 package impl
       
     8 
       
     9 import (
       
    10 	"reflect"
       
    11 	"sync/atomic"
       
    12 	"unsafe"
       
    13 )
       
    14 
       
    15 const UnsafeEnabled = true
       
    16 
       
    17 // Pointer is an opaque pointer type.
       
    18 type Pointer unsafe.Pointer
       
    19 
       
    20 // offset represents the offset to a struct field, accessible from a pointer.
       
    21 // The offset is the byte offset to the field from the start of the struct.
       
    22 type offset uintptr
       
    23 
       
    24 // offsetOf returns a field offset for the struct field.
       
    25 func offsetOf(f reflect.StructField, x exporter) offset {
       
    26 	return offset(f.Offset)
       
    27 }
       
    28 
       
    29 // IsValid reports whether the offset is valid.
       
    30 func (f offset) IsValid() bool { return f != invalidOffset }
       
    31 
       
    32 // invalidOffset is an invalid field offset.
       
    33 var invalidOffset = ^offset(0)
       
    34 
       
    35 // zeroOffset is a noop when calling pointer.Apply.
       
    36 var zeroOffset = offset(0)
       
    37 
       
    38 // pointer is a pointer to a message struct or field.
       
    39 type pointer struct{ p unsafe.Pointer }
       
    40 
       
    41 // pointerOf returns p as a pointer.
       
    42 func pointerOf(p Pointer) pointer {
       
    43 	return pointer{p: unsafe.Pointer(p)}
       
    44 }
       
    45 
       
    46 // pointerOfValue returns v as a pointer.
       
    47 func pointerOfValue(v reflect.Value) pointer {
       
    48 	return pointer{p: unsafe.Pointer(v.Pointer())}
       
    49 }
       
    50 
       
    51 // pointerOfIface returns the pointer portion of an interface.
       
    52 func pointerOfIface(v interface{}) pointer {
       
    53 	type ifaceHeader struct {
       
    54 		Type unsafe.Pointer
       
    55 		Data unsafe.Pointer
       
    56 	}
       
    57 	return pointer{p: (*ifaceHeader)(unsafe.Pointer(&v)).Data}
       
    58 }
       
    59 
       
    60 // IsNil reports whether the pointer is nil.
       
    61 func (p pointer) IsNil() bool {
       
    62 	return p.p == nil
       
    63 }
       
    64 
       
    65 // Apply adds an offset to the pointer to derive a new pointer
       
    66 // to a specified field. The pointer must be valid and pointing at a struct.
       
    67 func (p pointer) Apply(f offset) pointer {
       
    68 	if p.IsNil() {
       
    69 		panic("invalid nil pointer")
       
    70 	}
       
    71 	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
       
    72 }
       
    73 
       
    74 // AsValueOf treats p as a pointer to an object of type t and returns the value.
       
    75 // It is equivalent to reflect.ValueOf(p.AsIfaceOf(t))
       
    76 func (p pointer) AsValueOf(t reflect.Type) reflect.Value {
       
    77 	return reflect.NewAt(t, p.p)
       
    78 }
       
    79 
       
    80 // AsIfaceOf treats p as a pointer to an object of type t and returns the value.
       
    81 // It is equivalent to p.AsValueOf(t).Interface()
       
    82 func (p pointer) AsIfaceOf(t reflect.Type) interface{} {
       
    83 	// TODO: Use tricky unsafe magic to directly create ifaceHeader.
       
    84 	return p.AsValueOf(t).Interface()
       
    85 }
       
    86 
       
    87 func (p pointer) Bool() *bool                           { return (*bool)(p.p) }
       
    88 func (p pointer) BoolPtr() **bool                       { return (**bool)(p.p) }
       
    89 func (p pointer) BoolSlice() *[]bool                    { return (*[]bool)(p.p) }
       
    90 func (p pointer) Int32() *int32                         { return (*int32)(p.p) }
       
    91 func (p pointer) Int32Ptr() **int32                     { return (**int32)(p.p) }
       
    92 func (p pointer) Int32Slice() *[]int32                  { return (*[]int32)(p.p) }
       
    93 func (p pointer) Int64() *int64                         { return (*int64)(p.p) }
       
    94 func (p pointer) Int64Ptr() **int64                     { return (**int64)(p.p) }
       
    95 func (p pointer) Int64Slice() *[]int64                  { return (*[]int64)(p.p) }
       
    96 func (p pointer) Uint32() *uint32                       { return (*uint32)(p.p) }
       
    97 func (p pointer) Uint32Ptr() **uint32                   { return (**uint32)(p.p) }
       
    98 func (p pointer) Uint32Slice() *[]uint32                { return (*[]uint32)(p.p) }
       
    99 func (p pointer) Uint64() *uint64                       { return (*uint64)(p.p) }
       
   100 func (p pointer) Uint64Ptr() **uint64                   { return (**uint64)(p.p) }
       
   101 func (p pointer) Uint64Slice() *[]uint64                { return (*[]uint64)(p.p) }
       
   102 func (p pointer) Float32() *float32                     { return (*float32)(p.p) }
       
   103 func (p pointer) Float32Ptr() **float32                 { return (**float32)(p.p) }
       
   104 func (p pointer) Float32Slice() *[]float32              { return (*[]float32)(p.p) }
       
   105 func (p pointer) Float64() *float64                     { return (*float64)(p.p) }
       
   106 func (p pointer) Float64Ptr() **float64                 { return (**float64)(p.p) }
       
   107 func (p pointer) Float64Slice() *[]float64              { return (*[]float64)(p.p) }
       
   108 func (p pointer) String() *string                       { return (*string)(p.p) }
       
   109 func (p pointer) StringPtr() **string                   { return (**string)(p.p) }
       
   110 func (p pointer) StringSlice() *[]string                { return (*[]string)(p.p) }
       
   111 func (p pointer) Bytes() *[]byte                        { return (*[]byte)(p.p) }
       
   112 func (p pointer) BytesPtr() **[]byte                    { return (**[]byte)(p.p) }
       
   113 func (p pointer) BytesSlice() *[][]byte                 { return (*[][]byte)(p.p) }
       
   114 func (p pointer) WeakFields() *weakFields               { return (*weakFields)(p.p) }
       
   115 func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) }
       
   116 
       
   117 func (p pointer) Elem() pointer {
       
   118 	return pointer{p: *(*unsafe.Pointer)(p.p)}
       
   119 }
       
   120 
       
   121 // PointerSlice loads []*T from p as a []pointer.
       
   122 // The value returned is aliased with the original slice.
       
   123 // This behavior differs from the implementation in pointer_reflect.go.
       
   124 func (p pointer) PointerSlice() []pointer {
       
   125 	// Super-tricky - p should point to a []*T where T is a
       
   126 	// message type. We load it as []pointer.
       
   127 	return *(*[]pointer)(p.p)
       
   128 }
       
   129 
       
   130 // AppendPointerSlice appends v to p, which must be a []*T.
       
   131 func (p pointer) AppendPointerSlice(v pointer) {
       
   132 	*(*[]pointer)(p.p) = append(*(*[]pointer)(p.p), v)
       
   133 }
       
   134 
       
   135 // SetPointer sets *p to v.
       
   136 func (p pointer) SetPointer(v pointer) {
       
   137 	*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
       
   138 }
       
   139 
       
   140 // Static check that MessageState does not exceed the size of a pointer.
       
   141 const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{}))
       
   142 
       
   143 func (Export) MessageStateOf(p Pointer) *messageState {
       
   144 	// Super-tricky - see documentation on MessageState.
       
   145 	return (*messageState)(unsafe.Pointer(p))
       
   146 }
       
   147 func (ms *messageState) pointer() pointer {
       
   148 	// Super-tricky - see documentation on MessageState.
       
   149 	return pointer{p: unsafe.Pointer(ms)}
       
   150 }
       
   151 func (ms *messageState) messageInfo() *MessageInfo {
       
   152 	mi := ms.LoadMessageInfo()
       
   153 	if mi == nil {
       
   154 		panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct")
       
   155 	}
       
   156 	return mi
       
   157 }
       
   158 func (ms *messageState) LoadMessageInfo() *MessageInfo {
       
   159 	return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo))))
       
   160 }
       
   161 func (ms *messageState) StoreMessageInfo(mi *MessageInfo) {
       
   162 	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)), unsafe.Pointer(mi))
       
   163 }
       
   164 
       
   165 type atomicNilMessage struct{ p unsafe.Pointer } // p is a *messageReflectWrapper
       
   166 
       
   167 func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper {
       
   168 	if p := atomic.LoadPointer(&m.p); p != nil {
       
   169 		return (*messageReflectWrapper)(p)
       
   170 	}
       
   171 	w := &messageReflectWrapper{mi: mi}
       
   172 	atomic.CompareAndSwapPointer(&m.p, nil, (unsafe.Pointer)(w))
       
   173 	return (*messageReflectWrapper)(atomic.LoadPointer(&m.p))
       
   174 }