1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsen//go:build purego || appengine 6*1c12ee1eSDan Willemsen// +build purego appengine 7*1c12ee1eSDan Willemsen 8*1c12ee1eSDan Willemsenpackage impl 9*1c12ee1eSDan Willemsen 10*1c12ee1eSDan Willemsenimport ( 11*1c12ee1eSDan Willemsen "fmt" 12*1c12ee1eSDan Willemsen "reflect" 13*1c12ee1eSDan Willemsen "sync" 14*1c12ee1eSDan Willemsen) 15*1c12ee1eSDan Willemsen 16*1c12ee1eSDan Willemsenconst UnsafeEnabled = false 17*1c12ee1eSDan Willemsen 18*1c12ee1eSDan Willemsen// Pointer is an opaque pointer type. 19*1c12ee1eSDan Willemsentype Pointer interface{} 20*1c12ee1eSDan Willemsen 21*1c12ee1eSDan Willemsen// offset represents the offset to a struct field, accessible from a pointer. 22*1c12ee1eSDan Willemsen// The offset is the field index into a struct. 23*1c12ee1eSDan Willemsentype offset struct { 24*1c12ee1eSDan Willemsen index int 25*1c12ee1eSDan Willemsen export exporter 26*1c12ee1eSDan Willemsen} 27*1c12ee1eSDan Willemsen 28*1c12ee1eSDan Willemsen// offsetOf returns a field offset for the struct field. 29*1c12ee1eSDan Willemsenfunc offsetOf(f reflect.StructField, x exporter) offset { 30*1c12ee1eSDan Willemsen if len(f.Index) != 1 { 31*1c12ee1eSDan Willemsen panic("embedded structs are not supported") 32*1c12ee1eSDan Willemsen } 33*1c12ee1eSDan Willemsen if f.PkgPath == "" { 34*1c12ee1eSDan Willemsen return offset{index: f.Index[0]} // field is already exported 35*1c12ee1eSDan Willemsen } 36*1c12ee1eSDan Willemsen if x == nil { 37*1c12ee1eSDan Willemsen panic("exporter must be provided for unexported field") 38*1c12ee1eSDan Willemsen } 39*1c12ee1eSDan Willemsen return offset{index: f.Index[0], export: x} 40*1c12ee1eSDan Willemsen} 41*1c12ee1eSDan Willemsen 42*1c12ee1eSDan Willemsen// IsValid reports whether the offset is valid. 43*1c12ee1eSDan Willemsenfunc (f offset) IsValid() bool { return f.index >= 0 } 44*1c12ee1eSDan Willemsen 45*1c12ee1eSDan Willemsen// invalidOffset is an invalid field offset. 46*1c12ee1eSDan Willemsenvar invalidOffset = offset{index: -1} 47*1c12ee1eSDan Willemsen 48*1c12ee1eSDan Willemsen// zeroOffset is a noop when calling pointer.Apply. 49*1c12ee1eSDan Willemsenvar zeroOffset = offset{index: 0} 50*1c12ee1eSDan Willemsen 51*1c12ee1eSDan Willemsen// pointer is an abstract representation of a pointer to a struct or field. 52*1c12ee1eSDan Willemsentype pointer struct{ v reflect.Value } 53*1c12ee1eSDan Willemsen 54*1c12ee1eSDan Willemsen// pointerOf returns p as a pointer. 55*1c12ee1eSDan Willemsenfunc pointerOf(p Pointer) pointer { 56*1c12ee1eSDan Willemsen return pointerOfIface(p) 57*1c12ee1eSDan Willemsen} 58*1c12ee1eSDan Willemsen 59*1c12ee1eSDan Willemsen// pointerOfValue returns v as a pointer. 60*1c12ee1eSDan Willemsenfunc pointerOfValue(v reflect.Value) pointer { 61*1c12ee1eSDan Willemsen return pointer{v: v} 62*1c12ee1eSDan Willemsen} 63*1c12ee1eSDan Willemsen 64*1c12ee1eSDan Willemsen// pointerOfIface returns the pointer portion of an interface. 65*1c12ee1eSDan Willemsenfunc pointerOfIface(v interface{}) pointer { 66*1c12ee1eSDan Willemsen return pointer{v: reflect.ValueOf(v)} 67*1c12ee1eSDan Willemsen} 68*1c12ee1eSDan Willemsen 69*1c12ee1eSDan Willemsen// IsNil reports whether the pointer is nil. 70*1c12ee1eSDan Willemsenfunc (p pointer) IsNil() bool { 71*1c12ee1eSDan Willemsen return p.v.IsNil() 72*1c12ee1eSDan Willemsen} 73*1c12ee1eSDan Willemsen 74*1c12ee1eSDan Willemsen// Apply adds an offset to the pointer to derive a new pointer 75*1c12ee1eSDan Willemsen// to a specified field. The current pointer must be pointing at a struct. 76*1c12ee1eSDan Willemsenfunc (p pointer) Apply(f offset) pointer { 77*1c12ee1eSDan Willemsen if f.export != nil { 78*1c12ee1eSDan Willemsen if v := reflect.ValueOf(f.export(p.v.Interface(), f.index)); v.IsValid() { 79*1c12ee1eSDan Willemsen return pointer{v: v} 80*1c12ee1eSDan Willemsen } 81*1c12ee1eSDan Willemsen } 82*1c12ee1eSDan Willemsen return pointer{v: p.v.Elem().Field(f.index).Addr()} 83*1c12ee1eSDan Willemsen} 84*1c12ee1eSDan Willemsen 85*1c12ee1eSDan Willemsen// AsValueOf treats p as a pointer to an object of type t and returns the value. 86*1c12ee1eSDan Willemsen// It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) 87*1c12ee1eSDan Willemsenfunc (p pointer) AsValueOf(t reflect.Type) reflect.Value { 88*1c12ee1eSDan Willemsen if got := p.v.Type().Elem(); got != t { 89*1c12ee1eSDan Willemsen panic(fmt.Sprintf("invalid type: got %v, want %v", got, t)) 90*1c12ee1eSDan Willemsen } 91*1c12ee1eSDan Willemsen return p.v 92*1c12ee1eSDan Willemsen} 93*1c12ee1eSDan Willemsen 94*1c12ee1eSDan Willemsen// AsIfaceOf treats p as a pointer to an object of type t and returns the value. 95*1c12ee1eSDan Willemsen// It is equivalent to p.AsValueOf(t).Interface() 96*1c12ee1eSDan Willemsenfunc (p pointer) AsIfaceOf(t reflect.Type) interface{} { 97*1c12ee1eSDan Willemsen return p.AsValueOf(t).Interface() 98*1c12ee1eSDan Willemsen} 99*1c12ee1eSDan Willemsen 100*1c12ee1eSDan Willemsenfunc (p pointer) Bool() *bool { return p.v.Interface().(*bool) } 101*1c12ee1eSDan Willemsenfunc (p pointer) BoolPtr() **bool { return p.v.Interface().(**bool) } 102*1c12ee1eSDan Willemsenfunc (p pointer) BoolSlice() *[]bool { return p.v.Interface().(*[]bool) } 103*1c12ee1eSDan Willemsenfunc (p pointer) Int32() *int32 { return p.v.Interface().(*int32) } 104*1c12ee1eSDan Willemsenfunc (p pointer) Int32Ptr() **int32 { return p.v.Interface().(**int32) } 105*1c12ee1eSDan Willemsenfunc (p pointer) Int32Slice() *[]int32 { return p.v.Interface().(*[]int32) } 106*1c12ee1eSDan Willemsenfunc (p pointer) Int64() *int64 { return p.v.Interface().(*int64) } 107*1c12ee1eSDan Willemsenfunc (p pointer) Int64Ptr() **int64 { return p.v.Interface().(**int64) } 108*1c12ee1eSDan Willemsenfunc (p pointer) Int64Slice() *[]int64 { return p.v.Interface().(*[]int64) } 109*1c12ee1eSDan Willemsenfunc (p pointer) Uint32() *uint32 { return p.v.Interface().(*uint32) } 110*1c12ee1eSDan Willemsenfunc (p pointer) Uint32Ptr() **uint32 { return p.v.Interface().(**uint32) } 111*1c12ee1eSDan Willemsenfunc (p pointer) Uint32Slice() *[]uint32 { return p.v.Interface().(*[]uint32) } 112*1c12ee1eSDan Willemsenfunc (p pointer) Uint64() *uint64 { return p.v.Interface().(*uint64) } 113*1c12ee1eSDan Willemsenfunc (p pointer) Uint64Ptr() **uint64 { return p.v.Interface().(**uint64) } 114*1c12ee1eSDan Willemsenfunc (p pointer) Uint64Slice() *[]uint64 { return p.v.Interface().(*[]uint64) } 115*1c12ee1eSDan Willemsenfunc (p pointer) Float32() *float32 { return p.v.Interface().(*float32) } 116*1c12ee1eSDan Willemsenfunc (p pointer) Float32Ptr() **float32 { return p.v.Interface().(**float32) } 117*1c12ee1eSDan Willemsenfunc (p pointer) Float32Slice() *[]float32 { return p.v.Interface().(*[]float32) } 118*1c12ee1eSDan Willemsenfunc (p pointer) Float64() *float64 { return p.v.Interface().(*float64) } 119*1c12ee1eSDan Willemsenfunc (p pointer) Float64Ptr() **float64 { return p.v.Interface().(**float64) } 120*1c12ee1eSDan Willemsenfunc (p pointer) Float64Slice() *[]float64 { return p.v.Interface().(*[]float64) } 121*1c12ee1eSDan Willemsenfunc (p pointer) String() *string { return p.v.Interface().(*string) } 122*1c12ee1eSDan Willemsenfunc (p pointer) StringPtr() **string { return p.v.Interface().(**string) } 123*1c12ee1eSDan Willemsenfunc (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) } 124*1c12ee1eSDan Willemsenfunc (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) } 125*1c12ee1eSDan Willemsenfunc (p pointer) BytesPtr() **[]byte { return p.v.Interface().(**[]byte) } 126*1c12ee1eSDan Willemsenfunc (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } 127*1c12ee1eSDan Willemsenfunc (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) } 128*1c12ee1eSDan Willemsenfunc (p pointer) Extensions() *map[int32]ExtensionField { 129*1c12ee1eSDan Willemsen return p.v.Interface().(*map[int32]ExtensionField) 130*1c12ee1eSDan Willemsen} 131*1c12ee1eSDan Willemsen 132*1c12ee1eSDan Willemsenfunc (p pointer) Elem() pointer { 133*1c12ee1eSDan Willemsen return pointer{v: p.v.Elem()} 134*1c12ee1eSDan Willemsen} 135*1c12ee1eSDan Willemsen 136*1c12ee1eSDan Willemsen// PointerSlice copies []*T from p as a new []pointer. 137*1c12ee1eSDan Willemsen// This behavior differs from the implementation in pointer_unsafe.go. 138*1c12ee1eSDan Willemsenfunc (p pointer) PointerSlice() []pointer { 139*1c12ee1eSDan Willemsen // TODO: reconsider this 140*1c12ee1eSDan Willemsen if p.v.IsNil() { 141*1c12ee1eSDan Willemsen return nil 142*1c12ee1eSDan Willemsen } 143*1c12ee1eSDan Willemsen n := p.v.Elem().Len() 144*1c12ee1eSDan Willemsen s := make([]pointer, n) 145*1c12ee1eSDan Willemsen for i := 0; i < n; i++ { 146*1c12ee1eSDan Willemsen s[i] = pointer{v: p.v.Elem().Index(i)} 147*1c12ee1eSDan Willemsen } 148*1c12ee1eSDan Willemsen return s 149*1c12ee1eSDan Willemsen} 150*1c12ee1eSDan Willemsen 151*1c12ee1eSDan Willemsen// AppendPointerSlice appends v to p, which must be a []*T. 152*1c12ee1eSDan Willemsenfunc (p pointer) AppendPointerSlice(v pointer) { 153*1c12ee1eSDan Willemsen sp := p.v.Elem() 154*1c12ee1eSDan Willemsen sp.Set(reflect.Append(sp, v.v)) 155*1c12ee1eSDan Willemsen} 156*1c12ee1eSDan Willemsen 157*1c12ee1eSDan Willemsen// SetPointer sets *p to v. 158*1c12ee1eSDan Willemsenfunc (p pointer) SetPointer(v pointer) { 159*1c12ee1eSDan Willemsen p.v.Elem().Set(v.v) 160*1c12ee1eSDan Willemsen} 161*1c12ee1eSDan Willemsen 162*1c12ee1eSDan Willemsenfunc (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } 163*1c12ee1eSDan Willemsenfunc (ms *messageState) pointer() pointer { panic("not supported") } 164*1c12ee1eSDan Willemsenfunc (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } 165*1c12ee1eSDan Willemsenfunc (ms *messageState) LoadMessageInfo() *MessageInfo { panic("not supported") } 166*1c12ee1eSDan Willemsenfunc (ms *messageState) StoreMessageInfo(mi *MessageInfo) { panic("not supported") } 167*1c12ee1eSDan Willemsen 168*1c12ee1eSDan Willemsentype atomicNilMessage struct { 169*1c12ee1eSDan Willemsen once sync.Once 170*1c12ee1eSDan Willemsen m messageReflectWrapper 171*1c12ee1eSDan Willemsen} 172*1c12ee1eSDan Willemsen 173*1c12ee1eSDan Willemsenfunc (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { 174*1c12ee1eSDan Willemsen m.once.Do(func() { 175*1c12ee1eSDan Willemsen m.m.p = pointerOfIface(reflect.Zero(mi.GoReflectType).Interface()) 176*1c12ee1eSDan Willemsen m.m.mi = mi 177*1c12ee1eSDan Willemsen }) 178*1c12ee1eSDan Willemsen return &m.m 179*1c12ee1eSDan Willemsen} 180