github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/proto/pointer_reflect.go (about)

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2012 The Go Authors.  All rights reserved.
     4  // https://yougam/libraries/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 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  	"math"
    42  	"reflect"
    43  )
    44  
    45  // A structPointer is a pointer to a struct.
    46  type structPointer struct {
    47  	v reflect.Value
    48  }
    49  
    50  // toStructPointer returns a structPointer equivalent to the given reflect value.
    51  // The reflect value must itself be a pointer to a struct.
    52  func toStructPointer(v reflect.Value) structPointer {
    53  	return structPointer{v}
    54  }
    55  
    56  // IsNil reports whether p is nil.
    57  func structPointer_IsNil(p structPointer) bool {
    58  	return p.v.IsNil()
    59  }
    60  
    61  // Interface returns the struct pointer as an interface value.
    62  func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
    63  	return p.v.Interface()
    64  }
    65  
    66  // A field identifies a field in a struct, accessible from a structPointer.
    67  // In this implementation, a field is identified by the sequence of field indices
    68  // passed to reflect's FieldByIndex.
    69  type field []int
    70  
    71  // toField returns a field equivalent to the given reflect field.
    72  func toField(f *reflect.StructField) field {
    73  	return f.Index
    74  }
    75  
    76  // invalidField is an invalid field identifier.
    77  var invalidField = field(nil)
    78  
    79  // IsValid reports whether the field identifier is valid.
    80  func (f field) IsValid() bool { return f != nil }
    81  
    82  // field returns the given field in the struct as a reflect value.
    83  func structPointer_field(p structPointer, f field) reflect.Value {
    84  	// Special case: an extension map entry with a value of type T
    85  	// passes a *T to the struct-handling code with a zero field,
    86  	// expecting that it will be treated as equivalent to *struct{ X T },
    87  	// which has the same memory layout. We have to handle that case
    88  	// specially, because reflect will panic if we call FieldByIndex on a
    89  	// non-struct.
    90  	if f == nil {
    91  		return p.v.Elem()
    92  	}
    93  
    94  	return p.v.Elem().FieldByIndex(f)
    95  }
    96  
    97  // ifield returns the given field in the struct as an interface value.
    98  func structPointer_ifield(p structPointer, f field) interface{} {
    99  	return structPointer_field(p, f).Addr().Interface()
   100  }
   101  
   102  // Bytes returns the address of a []byte field in the struct.
   103  func structPointer_Bytes(p structPointer, f field) *[]byte {
   104  	return structPointer_ifield(p, f).(*[]byte)
   105  }
   106  
   107  // BytesSlice returns the address of a [][]byte field in the struct.
   108  func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
   109  	return structPointer_ifield(p, f).(*[][]byte)
   110  }
   111  
   112  // Bool returns the address of a *bool field in the struct.
   113  func structPointer_Bool(p structPointer, f field) **bool {
   114  	return structPointer_ifield(p, f).(**bool)
   115  }
   116  
   117  // BoolVal returns the address of a bool field in the struct.
   118  func structPointer_BoolVal(p structPointer, f field) *bool {
   119  	return structPointer_ifield(p, f).(*bool)
   120  }
   121  
   122  // BoolSlice returns the address of a []bool field in the struct.
   123  func structPointer_BoolSlice(p structPointer, f field) *[]bool {
   124  	return structPointer_ifield(p, f).(*[]bool)
   125  }
   126  
   127  // String returns the address of a *string field in the struct.
   128  func structPointer_String(p structPointer, f field) **string {
   129  	return structPointer_ifield(p, f).(**string)
   130  }
   131  
   132  // StringVal returns the address of a string field in the struct.
   133  func structPointer_StringVal(p structPointer, f field) *string {
   134  	return structPointer_ifield(p, f).(*string)
   135  }
   136  
   137  // StringSlice returns the address of a []string field in the struct.
   138  func structPointer_StringSlice(p structPointer, f field) *[]string {
   139  	return structPointer_ifield(p, f).(*[]string)
   140  }
   141  
   142  // ExtMap returns the address of an extension map field in the struct.
   143  func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
   144  	return structPointer_ifield(p, f).(*map[int32]Extension)
   145  }
   146  
   147  // NewAt returns the reflect.Value for a pointer to a field in the struct.
   148  func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
   149  	return structPointer_field(p, f).Addr()
   150  }
   151  
   152  // SetStructPointer writes a *struct field in the struct.
   153  func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
   154  	structPointer_field(p, f).Set(q.v)
   155  }
   156  
   157  // GetStructPointer reads a *struct field in the struct.
   158  func structPointer_GetStructPointer(p structPointer, f field) structPointer {
   159  	return structPointer{structPointer_field(p, f)}
   160  }
   161  
   162  // StructPointerSlice the address of a []*struct field in the struct.
   163  func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
   164  	return structPointerSlice{structPointer_field(p, f)}
   165  }
   166  
   167  // A structPointerSlice represents the address of a slice of pointers to structs
   168  // (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
   169  type structPointerSlice struct {
   170  	v reflect.Value
   171  }
   172  
   173  func (p structPointerSlice) Len() int                  { return p.v.Len() }
   174  func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
   175  func (p structPointerSlice) Append(q structPointer) {
   176  	p.v.Set(reflect.Append(p.v, q.v))
   177  }
   178  
   179  var (
   180  	int32Type   = reflect.TypeOf(int32(0))
   181  	uint32Type  = reflect.TypeOf(uint32(0))
   182  	float32Type = reflect.TypeOf(float32(0))
   183  	int64Type   = reflect.TypeOf(int64(0))
   184  	uint64Type  = reflect.TypeOf(uint64(0))
   185  	float64Type = reflect.TypeOf(float64(0))
   186  )
   187  
   188  // A word32 represents a field of type *int32, *uint32, *float32, or *enum.
   189  // That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
   190  type word32 struct {
   191  	v reflect.Value
   192  }
   193  
   194  // IsNil reports whether p is nil.
   195  func word32_IsNil(p word32) bool {
   196  	return p.v.IsNil()
   197  }
   198  
   199  // Set sets p to point at a newly allocated word with bits set to x.
   200  func word32_Set(p word32, o *Buffer, x uint32) {
   201  	t := p.v.Type().Elem()
   202  	switch t {
   203  	case int32Type:
   204  		if len(o.int32s) == 0 {
   205  			o.int32s = make([]int32, uint32PoolSize)
   206  		}
   207  		o.int32s[0] = int32(x)
   208  		p.v.Set(reflect.ValueOf(&o.int32s[0]))
   209  		o.int32s = o.int32s[1:]
   210  		return
   211  	case uint32Type:
   212  		if len(o.uint32s) == 0 {
   213  			o.uint32s = make([]uint32, uint32PoolSize)
   214  		}
   215  		o.uint32s[0] = x
   216  		p.v.Set(reflect.ValueOf(&o.uint32s[0]))
   217  		o.uint32s = o.uint32s[1:]
   218  		return
   219  	case float32Type:
   220  		if len(o.float32s) == 0 {
   221  			o.float32s = make([]float32, uint32PoolSize)
   222  		}
   223  		o.float32s[0] = math.Float32frombits(x)
   224  		p.v.Set(reflect.ValueOf(&o.float32s[0]))
   225  		o.float32s = o.float32s[1:]
   226  		return
   227  	}
   228  
   229  	// must be enum
   230  	p.v.Set(reflect.New(t))
   231  	p.v.Elem().SetInt(int64(int32(x)))
   232  }
   233  
   234  // Get gets the bits pointed at by p, as a uint32.
   235  func word32_Get(p word32) uint32 {
   236  	elem := p.v.Elem()
   237  	switch elem.Kind() {
   238  	case reflect.Int32:
   239  		return uint32(elem.Int())
   240  	case reflect.Uint32:
   241  		return uint32(elem.Uint())
   242  	case reflect.Float32:
   243  		return math.Float32bits(float32(elem.Float()))
   244  	}
   245  	panic("unreachable")
   246  }
   247  
   248  // Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
   249  func structPointer_Word32(p structPointer, f field) word32 {
   250  	return word32{structPointer_field(p, f)}
   251  }
   252  
   253  // A word32Val represents a field of type int32, uint32, float32, or enum.
   254  // That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
   255  type word32Val struct {
   256  	v reflect.Value
   257  }
   258  
   259  // Set sets *p to x.
   260  func word32Val_Set(p word32Val, x uint32) {
   261  	switch p.v.Type() {
   262  	case int32Type:
   263  		p.v.SetInt(int64(x))
   264  		return
   265  	case uint32Type:
   266  		p.v.SetUint(uint64(x))
   267  		return
   268  	case float32Type:
   269  		p.v.SetFloat(float64(math.Float32frombits(x)))
   270  		return
   271  	}
   272  
   273  	// must be enum
   274  	p.v.SetInt(int64(int32(x)))
   275  }
   276  
   277  // Get gets the bits pointed at by p, as a uint32.
   278  func word32Val_Get(p word32Val) uint32 {
   279  	elem := p.v
   280  	switch elem.Kind() {
   281  	case reflect.Int32:
   282  		return uint32(elem.Int())
   283  	case reflect.Uint32:
   284  		return uint32(elem.Uint())
   285  	case reflect.Float32:
   286  		return math.Float32bits(float32(elem.Float()))
   287  	}
   288  	panic("unreachable")
   289  }
   290  
   291  // Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
   292  func structPointer_Word32Val(p structPointer, f field) word32Val {
   293  	return word32Val{structPointer_field(p, f)}
   294  }
   295  
   296  // A word32Slice is a slice of 32-bit values.
   297  // That is, v.Type() is []int32, []uint32, []float32, or []enum.
   298  type word32Slice struct {
   299  	v reflect.Value
   300  }
   301  
   302  func (p word32Slice) Append(x uint32) {
   303  	n, m := p.v.Len(), p.v.Cap()
   304  	if n < m {
   305  		p.v.SetLen(n + 1)
   306  	} else {
   307  		t := p.v.Type().Elem()
   308  		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
   309  	}
   310  	elem := p.v.Index(n)
   311  	switch elem.Kind() {
   312  	case reflect.Int32:
   313  		elem.SetInt(int64(int32(x)))
   314  	case reflect.Uint32:
   315  		elem.SetUint(uint64(x))
   316  	case reflect.Float32:
   317  		elem.SetFloat(float64(math.Float32frombits(x)))
   318  	}
   319  }
   320  
   321  func (p word32Slice) Len() int {
   322  	return p.v.Len()
   323  }
   324  
   325  func (p word32Slice) Index(i int) uint32 {
   326  	elem := p.v.Index(i)
   327  	switch elem.Kind() {
   328  	case reflect.Int32:
   329  		return uint32(elem.Int())
   330  	case reflect.Uint32:
   331  		return uint32(elem.Uint())
   332  	case reflect.Float32:
   333  		return math.Float32bits(float32(elem.Float()))
   334  	}
   335  	panic("unreachable")
   336  }
   337  
   338  // Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
   339  func structPointer_Word32Slice(p structPointer, f field) word32Slice {
   340  	return word32Slice{structPointer_field(p, f)}
   341  }
   342  
   343  // word64 is like word32 but for 64-bit values.
   344  type word64 struct {
   345  	v reflect.Value
   346  }
   347  
   348  func word64_Set(p word64, o *Buffer, x uint64) {
   349  	t := p.v.Type().Elem()
   350  	switch t {
   351  	case int64Type:
   352  		if len(o.int64s) == 0 {
   353  			o.int64s = make([]int64, uint64PoolSize)
   354  		}
   355  		o.int64s[0] = int64(x)
   356  		p.v.Set(reflect.ValueOf(&o.int64s[0]))
   357  		o.int64s = o.int64s[1:]
   358  		return
   359  	case uint64Type:
   360  		if len(o.uint64s) == 0 {
   361  			o.uint64s = make([]uint64, uint64PoolSize)
   362  		}
   363  		o.uint64s[0] = x
   364  		p.v.Set(reflect.ValueOf(&o.uint64s[0]))
   365  		o.uint64s = o.uint64s[1:]
   366  		return
   367  	case float64Type:
   368  		if len(o.float64s) == 0 {
   369  			o.float64s = make([]float64, uint64PoolSize)
   370  		}
   371  		o.float64s[0] = math.Float64frombits(x)
   372  		p.v.Set(reflect.ValueOf(&o.float64s[0]))
   373  		o.float64s = o.float64s[1:]
   374  		return
   375  	}
   376  	panic("unreachable")
   377  }
   378  
   379  func word64_IsNil(p word64) bool {
   380  	return p.v.IsNil()
   381  }
   382  
   383  func word64_Get(p word64) uint64 {
   384  	elem := p.v.Elem()
   385  	switch elem.Kind() {
   386  	case reflect.Int64:
   387  		return uint64(elem.Int())
   388  	case reflect.Uint64:
   389  		return elem.Uint()
   390  	case reflect.Float64:
   391  		return math.Float64bits(elem.Float())
   392  	}
   393  	panic("unreachable")
   394  }
   395  
   396  func structPointer_Word64(p structPointer, f field) word64 {
   397  	return word64{structPointer_field(p, f)}
   398  }
   399  
   400  // word64Val is like word32Val but for 64-bit values.
   401  type word64Val struct {
   402  	v reflect.Value
   403  }
   404  
   405  func word64Val_Set(p word64Val, o *Buffer, x uint64) {
   406  	switch p.v.Type() {
   407  	case int64Type:
   408  		p.v.SetInt(int64(x))
   409  		return
   410  	case uint64Type:
   411  		p.v.SetUint(x)
   412  		return
   413  	case float64Type:
   414  		p.v.SetFloat(math.Float64frombits(x))
   415  		return
   416  	}
   417  	panic("unreachable")
   418  }
   419  
   420  func word64Val_Get(p word64Val) uint64 {
   421  	elem := p.v
   422  	switch elem.Kind() {
   423  	case reflect.Int64:
   424  		return uint64(elem.Int())
   425  	case reflect.Uint64:
   426  		return elem.Uint()
   427  	case reflect.Float64:
   428  		return math.Float64bits(elem.Float())
   429  	}
   430  	panic("unreachable")
   431  }
   432  
   433  func structPointer_Word64Val(p structPointer, f field) word64Val {
   434  	return word64Val{structPointer_field(p, f)}
   435  }
   436  
   437  type word64Slice struct {
   438  	v reflect.Value
   439  }
   440  
   441  func (p word64Slice) Append(x uint64) {
   442  	n, m := p.v.Len(), p.v.Cap()
   443  	if n < m {
   444  		p.v.SetLen(n + 1)
   445  	} else {
   446  		t := p.v.Type().Elem()
   447  		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
   448  	}
   449  	elem := p.v.Index(n)
   450  	switch elem.Kind() {
   451  	case reflect.Int64:
   452  		elem.SetInt(int64(int64(x)))
   453  	case reflect.Uint64:
   454  		elem.SetUint(uint64(x))
   455  	case reflect.Float64:
   456  		elem.SetFloat(float64(math.Float64frombits(x)))
   457  	}
   458  }
   459  
   460  func (p word64Slice) Len() int {
   461  	return p.v.Len()
   462  }
   463  
   464  func (p word64Slice) Index(i int) uint64 {
   465  	elem := p.v.Index(i)
   466  	switch elem.Kind() {
   467  	case reflect.Int64:
   468  		return uint64(elem.Int())
   469  	case reflect.Uint64:
   470  		return uint64(elem.Uint())
   471  	case reflect.Float64:
   472  		return math.Float64bits(float64(elem.Float()))
   473  	}
   474  	panic("unreachable")
   475  }
   476  
   477  func structPointer_Word64Slice(p structPointer, f field) word64Slice {
   478  	return word64Slice{structPointer_field(p, f)}
   479  }