...

Source file src/github.com/gogo/protobuf/proto/pointer_reflect.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 an implementation of proto field accesses using package reflect.
    35  // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
    36  // be used on App Engine.
    37  
    38  package proto
    39  
    40  import (
    41  	"reflect"
    42  	"sync"
    43  )
    44  
    45  const unsafeAllowed = false
    46  
    47  // A field identifies a field in a struct, accessible from a pointer.
    48  // In this implementation, a field is identified by the sequence of field indices
    49  // passed to reflect's FieldByIndex.
    50  type field []int
    51  
    52  // toField returns a field equivalent to the given reflect field.
    53  func toField(f *reflect.StructField) field {
    54  	return f.Index
    55  }
    56  
    57  // invalidField is an invalid field identifier.
    58  var invalidField = field(nil)
    59  
    60  // zeroField is a noop when calling pointer.offset.
    61  var zeroField = field([]int{})
    62  
    63  // IsValid reports whether the field identifier is valid.
    64  func (f field) IsValid() bool { return f != nil }
    65  
    66  // The pointer type is for the table-driven decoder.
    67  // The implementation here uses a reflect.Value of pointer type to
    68  // create a generic pointer. In pointer_unsafe.go we use unsafe
    69  // instead of reflect to implement the same (but faster) interface.
    70  type pointer struct {
    71  	v reflect.Value
    72  }
    73  
    74  // toPointer converts an interface of pointer type to a pointer
    75  // that points to the same target.
    76  func toPointer(i *Message) pointer {
    77  	return pointer{v: reflect.ValueOf(*i)}
    78  }
    79  
    80  // toAddrPointer converts an interface to a pointer that points to
    81  // the interface data.
    82  func toAddrPointer(i *interface{}, isptr bool) pointer {
    83  	v := reflect.ValueOf(*i)
    84  	u := reflect.New(v.Type())
    85  	u.Elem().Set(v)
    86  	return pointer{v: u}
    87  }
    88  
    89  // valToPointer converts v to a pointer.  v must be of pointer type.
    90  func valToPointer(v reflect.Value) pointer {
    91  	return pointer{v: v}
    92  }
    93  
    94  // offset converts from a pointer to a structure to a pointer to
    95  // one of its fields.
    96  func (p pointer) offset(f field) pointer {
    97  	return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
    98  }
    99  
   100  func (p pointer) isNil() bool {
   101  	return p.v.IsNil()
   102  }
   103  
   104  // grow updates the slice s in place to make it one element longer.
   105  // s must be addressable.
   106  // Returns the (addressable) new element.
   107  func grow(s reflect.Value) reflect.Value {
   108  	n, m := s.Len(), s.Cap()
   109  	if n < m {
   110  		s.SetLen(n + 1)
   111  	} else {
   112  		s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
   113  	}
   114  	return s.Index(n)
   115  }
   116  
   117  func (p pointer) toInt64() *int64 {
   118  	return p.v.Interface().(*int64)
   119  }
   120  func (p pointer) toInt64Ptr() **int64 {
   121  	return p.v.Interface().(**int64)
   122  }
   123  func (p pointer) toInt64Slice() *[]int64 {
   124  	return p.v.Interface().(*[]int64)
   125  }
   126  
   127  var int32ptr = reflect.TypeOf((*int32)(nil))
   128  
   129  func (p pointer) toInt32() *int32 {
   130  	return p.v.Convert(int32ptr).Interface().(*int32)
   131  }
   132  
   133  // The toInt32Ptr/Slice methods don't work because of enums.
   134  // Instead, we must use set/get methods for the int32ptr/slice case.
   135  /*
   136  	func (p pointer) toInt32Ptr() **int32 {
   137  		return p.v.Interface().(**int32)
   138  }
   139  	func (p pointer) toInt32Slice() *[]int32 {
   140  		return p.v.Interface().(*[]int32)
   141  }
   142  */
   143  func (p pointer) getInt32Ptr() *int32 {
   144  	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
   145  		// raw int32 type
   146  		return p.v.Elem().Interface().(*int32)
   147  	}
   148  	// an enum
   149  	return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
   150  }
   151  func (p pointer) setInt32Ptr(v int32) {
   152  	// Allocate value in a *int32. Possibly convert that to a *enum.
   153  	// Then assign it to a **int32 or **enum.
   154  	// Note: we can convert *int32 to *enum, but we can't convert
   155  	// **int32 to **enum!
   156  	p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
   157  }
   158  
   159  // getInt32Slice copies []int32 from p as a new slice.
   160  // This behavior differs from the implementation in pointer_unsafe.go.
   161  func (p pointer) getInt32Slice() []int32 {
   162  	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
   163  		// raw int32 type
   164  		return p.v.Elem().Interface().([]int32)
   165  	}
   166  	// an enum
   167  	// Allocate a []int32, then assign []enum's values into it.
   168  	// Note: we can't convert []enum to []int32.
   169  	slice := p.v.Elem()
   170  	s := make([]int32, slice.Len())
   171  	for i := 0; i < slice.Len(); i++ {
   172  		s[i] = int32(slice.Index(i).Int())
   173  	}
   174  	return s
   175  }
   176  
   177  // setInt32Slice copies []int32 into p as a new slice.
   178  // This behavior differs from the implementation in pointer_unsafe.go.
   179  func (p pointer) setInt32Slice(v []int32) {
   180  	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
   181  		// raw int32 type
   182  		p.v.Elem().Set(reflect.ValueOf(v))
   183  		return
   184  	}
   185  	// an enum
   186  	// Allocate a []enum, then assign []int32's values into it.
   187  	// Note: we can't convert []enum to []int32.
   188  	slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
   189  	for i, x := range v {
   190  		slice.Index(i).SetInt(int64(x))
   191  	}
   192  	p.v.Elem().Set(slice)
   193  }
   194  func (p pointer) appendInt32Slice(v int32) {
   195  	grow(p.v.Elem()).SetInt(int64(v))
   196  }
   197  
   198  func (p pointer) toUint64() *uint64 {
   199  	return p.v.Interface().(*uint64)
   200  }
   201  func (p pointer) toUint64Ptr() **uint64 {
   202  	return p.v.Interface().(**uint64)
   203  }
   204  func (p pointer) toUint64Slice() *[]uint64 {
   205  	return p.v.Interface().(*[]uint64)
   206  }
   207  func (p pointer) toUint32() *uint32 {
   208  	return p.v.Interface().(*uint32)
   209  }
   210  func (p pointer) toUint32Ptr() **uint32 {
   211  	return p.v.Interface().(**uint32)
   212  }
   213  func (p pointer) toUint32Slice() *[]uint32 {
   214  	return p.v.Interface().(*[]uint32)
   215  }
   216  func (p pointer) toBool() *bool {
   217  	return p.v.Interface().(*bool)
   218  }
   219  func (p pointer) toBoolPtr() **bool {
   220  	return p.v.Interface().(**bool)
   221  }
   222  func (p pointer) toBoolSlice() *[]bool {
   223  	return p.v.Interface().(*[]bool)
   224  }
   225  func (p pointer) toFloat64() *float64 {
   226  	return p.v.Interface().(*float64)
   227  }
   228  func (p pointer) toFloat64Ptr() **float64 {
   229  	return p.v.Interface().(**float64)
   230  }
   231  func (p pointer) toFloat64Slice() *[]float64 {
   232  	return p.v.Interface().(*[]float64)
   233  }
   234  func (p pointer) toFloat32() *float32 {
   235  	return p.v.Interface().(*float32)
   236  }
   237  func (p pointer) toFloat32Ptr() **float32 {
   238  	return p.v.Interface().(**float32)
   239  }
   240  func (p pointer) toFloat32Slice() *[]float32 {
   241  	return p.v.Interface().(*[]float32)
   242  }
   243  func (p pointer) toString() *string {
   244  	return p.v.Interface().(*string)
   245  }
   246  func (p pointer) toStringPtr() **string {
   247  	return p.v.Interface().(**string)
   248  }
   249  func (p pointer) toStringSlice() *[]string {
   250  	return p.v.Interface().(*[]string)
   251  }
   252  func (p pointer) toBytes() *[]byte {
   253  	return p.v.Interface().(*[]byte)
   254  }
   255  func (p pointer) toBytesSlice() *[][]byte {
   256  	return p.v.Interface().(*[][]byte)
   257  }
   258  func (p pointer) toExtensions() *XXX_InternalExtensions {
   259  	return p.v.Interface().(*XXX_InternalExtensions)
   260  }
   261  func (p pointer) toOldExtensions() *map[int32]Extension {
   262  	return p.v.Interface().(*map[int32]Extension)
   263  }
   264  func (p pointer) getPointer() pointer {
   265  	return pointer{v: p.v.Elem()}
   266  }
   267  func (p pointer) setPointer(q pointer) {
   268  	p.v.Elem().Set(q.v)
   269  }
   270  func (p pointer) appendPointer(q pointer) {
   271  	grow(p.v.Elem()).Set(q.v)
   272  }
   273  
   274  // getPointerSlice copies []*T from p as a new []pointer.
   275  // This behavior differs from the implementation in pointer_unsafe.go.
   276  func (p pointer) getPointerSlice() []pointer {
   277  	if p.v.IsNil() {
   278  		return nil
   279  	}
   280  	n := p.v.Elem().Len()
   281  	s := make([]pointer, n)
   282  	for i := 0; i < n; i++ {
   283  		s[i] = pointer{v: p.v.Elem().Index(i)}
   284  	}
   285  	return s
   286  }
   287  
   288  // setPointerSlice copies []pointer into p as a new []*T.
   289  // This behavior differs from the implementation in pointer_unsafe.go.
   290  func (p pointer) setPointerSlice(v []pointer) {
   291  	if v == nil {
   292  		p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
   293  		return
   294  	}
   295  	s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
   296  	for _, p := range v {
   297  		s = reflect.Append(s, p.v)
   298  	}
   299  	p.v.Elem().Set(s)
   300  }
   301  
   302  // getInterfacePointer returns a pointer that points to the
   303  // interface data of the interface pointed by p.
   304  func (p pointer) getInterfacePointer() pointer {
   305  	if p.v.Elem().IsNil() {
   306  		return pointer{v: p.v.Elem()}
   307  	}
   308  	return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
   309  }
   310  
   311  func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
   312  	// TODO: check that p.v.Type().Elem() == t?
   313  	return p.v
   314  }
   315  
   316  func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
   317  	atomicLock.Lock()
   318  	defer atomicLock.Unlock()
   319  	return *p
   320  }
   321  func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
   322  	atomicLock.Lock()
   323  	defer atomicLock.Unlock()
   324  	*p = v
   325  }
   326  func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
   327  	atomicLock.Lock()
   328  	defer atomicLock.Unlock()
   329  	return *p
   330  }
   331  func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
   332  	atomicLock.Lock()
   333  	defer atomicLock.Unlock()
   334  	*p = v
   335  }
   336  func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
   337  	atomicLock.Lock()
   338  	defer atomicLock.Unlock()
   339  	return *p
   340  }
   341  func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
   342  	atomicLock.Lock()
   343  	defer atomicLock.Unlock()
   344  	*p = v
   345  }
   346  func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
   347  	atomicLock.Lock()
   348  	defer atomicLock.Unlock()
   349  	return *p
   350  }
   351  func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
   352  	atomicLock.Lock()
   353  	defer atomicLock.Unlock()
   354  	*p = v
   355  }
   356  
   357  var atomicLock sync.Mutex
   358  

View as plain text