Home | History | Annotate | Download | only in 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 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 // Extensions returns the address of an extension map field in the struct.
    143 func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
    144 	return structPointer_ifield(p, f).(*XXX_InternalExtensions)
    145 }
    146 
    147 // ExtMap returns the address of an extension map field in the struct.
    148 func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
    149 	return structPointer_ifield(p, f).(*map[int32]Extension)
    150 }
    151 
    152 // NewAt returns the reflect.Value for a pointer to a field in the struct.
    153 func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
    154 	return structPointer_field(p, f).Addr()
    155 }
    156 
    157 // SetStructPointer writes a *struct field in the struct.
    158 func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
    159 	structPointer_field(p, f).Set(q.v)
    160 }
    161 
    162 // GetStructPointer reads a *struct field in the struct.
    163 func structPointer_GetStructPointer(p structPointer, f field) structPointer {
    164 	return structPointer{structPointer_field(p, f)}
    165 }
    166 
    167 // StructPointerSlice the address of a []*struct field in the struct.
    168 func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
    169 	return structPointerSlice{structPointer_field(p, f)}
    170 }
    171 
    172 // A structPointerSlice represents the address of a slice of pointers to structs
    173 // (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
    174 type structPointerSlice struct {
    175 	v reflect.Value
    176 }
    177 
    178 func (p structPointerSlice) Len() int                  { return p.v.Len() }
    179 func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
    180 func (p structPointerSlice) Append(q structPointer) {
    181 	p.v.Set(reflect.Append(p.v, q.v))
    182 }
    183 
    184 var (
    185 	int32Type   = reflect.TypeOf(int32(0))
    186 	uint32Type  = reflect.TypeOf(uint32(0))
    187 	float32Type = reflect.TypeOf(float32(0))
    188 	int64Type   = reflect.TypeOf(int64(0))
    189 	uint64Type  = reflect.TypeOf(uint64(0))
    190 	float64Type = reflect.TypeOf(float64(0))
    191 )
    192 
    193 // A word32 represents a field of type *int32, *uint32, *float32, or *enum.
    194 // That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
    195 type word32 struct {
    196 	v reflect.Value
    197 }
    198 
    199 // IsNil reports whether p is nil.
    200 func word32_IsNil(p word32) bool {
    201 	return p.v.IsNil()
    202 }
    203 
    204 // Set sets p to point at a newly allocated word with bits set to x.
    205 func word32_Set(p word32, o *Buffer, x uint32) {
    206 	t := p.v.Type().Elem()
    207 	switch t {
    208 	case int32Type:
    209 		if len(o.int32s) == 0 {
    210 			o.int32s = make([]int32, uint32PoolSize)
    211 		}
    212 		o.int32s[0] = int32(x)
    213 		p.v.Set(reflect.ValueOf(&o.int32s[0]))
    214 		o.int32s = o.int32s[1:]
    215 		return
    216 	case uint32Type:
    217 		if len(o.uint32s) == 0 {
    218 			o.uint32s = make([]uint32, uint32PoolSize)
    219 		}
    220 		o.uint32s[0] = x
    221 		p.v.Set(reflect.ValueOf(&o.uint32s[0]))
    222 		o.uint32s = o.uint32s[1:]
    223 		return
    224 	case float32Type:
    225 		if len(o.float32s) == 0 {
    226 			o.float32s = make([]float32, uint32PoolSize)
    227 		}
    228 		o.float32s[0] = math.Float32frombits(x)
    229 		p.v.Set(reflect.ValueOf(&o.float32s[0]))
    230 		o.float32s = o.float32s[1:]
    231 		return
    232 	}
    233 
    234 	// must be enum
    235 	p.v.Set(reflect.New(t))
    236 	p.v.Elem().SetInt(int64(int32(x)))
    237 }
    238 
    239 // Get gets the bits pointed at by p, as a uint32.
    240 func word32_Get(p word32) uint32 {
    241 	elem := p.v.Elem()
    242 	switch elem.Kind() {
    243 	case reflect.Int32:
    244 		return uint32(elem.Int())
    245 	case reflect.Uint32:
    246 		return uint32(elem.Uint())
    247 	case reflect.Float32:
    248 		return math.Float32bits(float32(elem.Float()))
    249 	}
    250 	panic("unreachable")
    251 }
    252 
    253 // Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
    254 func structPointer_Word32(p structPointer, f field) word32 {
    255 	return word32{structPointer_field(p, f)}
    256 }
    257 
    258 // A word32Val represents a field of type int32, uint32, float32, or enum.
    259 // That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
    260 type word32Val struct {
    261 	v reflect.Value
    262 }
    263 
    264 // Set sets *p to x.
    265 func word32Val_Set(p word32Val, x uint32) {
    266 	switch p.v.Type() {
    267 	case int32Type:
    268 		p.v.SetInt(int64(x))
    269 		return
    270 	case uint32Type:
    271 		p.v.SetUint(uint64(x))
    272 		return
    273 	case float32Type:
    274 		p.v.SetFloat(float64(math.Float32frombits(x)))
    275 		return
    276 	}
    277 
    278 	// must be enum
    279 	p.v.SetInt(int64(int32(x)))
    280 }
    281 
    282 // Get gets the bits pointed at by p, as a uint32.
    283 func word32Val_Get(p word32Val) uint32 {
    284 	elem := p.v
    285 	switch elem.Kind() {
    286 	case reflect.Int32:
    287 		return uint32(elem.Int())
    288 	case reflect.Uint32:
    289 		return uint32(elem.Uint())
    290 	case reflect.Float32:
    291 		return math.Float32bits(float32(elem.Float()))
    292 	}
    293 	panic("unreachable")
    294 }
    295 
    296 // Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
    297 func structPointer_Word32Val(p structPointer, f field) word32Val {
    298 	return word32Val{structPointer_field(p, f)}
    299 }
    300 
    301 // A word32Slice is a slice of 32-bit values.
    302 // That is, v.Type() is []int32, []uint32, []float32, or []enum.
    303 type word32Slice struct {
    304 	v reflect.Value
    305 }
    306 
    307 func (p word32Slice) Append(x uint32) {
    308 	n, m := p.v.Len(), p.v.Cap()
    309 	if n < m {
    310 		p.v.SetLen(n + 1)
    311 	} else {
    312 		t := p.v.Type().Elem()
    313 		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
    314 	}
    315 	elem := p.v.Index(n)
    316 	switch elem.Kind() {
    317 	case reflect.Int32:
    318 		elem.SetInt(int64(int32(x)))
    319 	case reflect.Uint32:
    320 		elem.SetUint(uint64(x))
    321 	case reflect.Float32:
    322 		elem.SetFloat(float64(math.Float32frombits(x)))
    323 	}
    324 }
    325 
    326 func (p word32Slice) Len() int {
    327 	return p.v.Len()
    328 }
    329 
    330 func (p word32Slice) Index(i int) uint32 {
    331 	elem := p.v.Index(i)
    332 	switch elem.Kind() {
    333 	case reflect.Int32:
    334 		return uint32(elem.Int())
    335 	case reflect.Uint32:
    336 		return uint32(elem.Uint())
    337 	case reflect.Float32:
    338 		return math.Float32bits(float32(elem.Float()))
    339 	}
    340 	panic("unreachable")
    341 }
    342 
    343 // Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
    344 func structPointer_Word32Slice(p structPointer, f field) word32Slice {
    345 	return word32Slice{structPointer_field(p, f)}
    346 }
    347 
    348 // word64 is like word32 but for 64-bit values.
    349 type word64 struct {
    350 	v reflect.Value
    351 }
    352 
    353 func word64_Set(p word64, o *Buffer, x uint64) {
    354 	t := p.v.Type().Elem()
    355 	switch t {
    356 	case int64Type:
    357 		if len(o.int64s) == 0 {
    358 			o.int64s = make([]int64, uint64PoolSize)
    359 		}
    360 		o.int64s[0] = int64(x)
    361 		p.v.Set(reflect.ValueOf(&o.int64s[0]))
    362 		o.int64s = o.int64s[1:]
    363 		return
    364 	case uint64Type:
    365 		if len(o.uint64s) == 0 {
    366 			o.uint64s = make([]uint64, uint64PoolSize)
    367 		}
    368 		o.uint64s[0] = x
    369 		p.v.Set(reflect.ValueOf(&o.uint64s[0]))
    370 		o.uint64s = o.uint64s[1:]
    371 		return
    372 	case float64Type:
    373 		if len(o.float64s) == 0 {
    374 			o.float64s = make([]float64, uint64PoolSize)
    375 		}
    376 		o.float64s[0] = math.Float64frombits(x)
    377 		p.v.Set(reflect.ValueOf(&o.float64s[0]))
    378 		o.float64s = o.float64s[1:]
    379 		return
    380 	}
    381 	panic("unreachable")
    382 }
    383 
    384 func word64_IsNil(p word64) bool {
    385 	return p.v.IsNil()
    386 }
    387 
    388 func word64_Get(p word64) uint64 {
    389 	elem := p.v.Elem()
    390 	switch elem.Kind() {
    391 	case reflect.Int64:
    392 		return uint64(elem.Int())
    393 	case reflect.Uint64:
    394 		return elem.Uint()
    395 	case reflect.Float64:
    396 		return math.Float64bits(elem.Float())
    397 	}
    398 	panic("unreachable")
    399 }
    400 
    401 func structPointer_Word64(p structPointer, f field) word64 {
    402 	return word64{structPointer_field(p, f)}
    403 }
    404 
    405 // word64Val is like word32Val but for 64-bit values.
    406 type word64Val struct {
    407 	v reflect.Value
    408 }
    409 
    410 func word64Val_Set(p word64Val, o *Buffer, x uint64) {
    411 	switch p.v.Type() {
    412 	case int64Type:
    413 		p.v.SetInt(int64(x))
    414 		return
    415 	case uint64Type:
    416 		p.v.SetUint(x)
    417 		return
    418 	case float64Type:
    419 		p.v.SetFloat(math.Float64frombits(x))
    420 		return
    421 	}
    422 	panic("unreachable")
    423 }
    424 
    425 func word64Val_Get(p word64Val) uint64 {
    426 	elem := p.v
    427 	switch elem.Kind() {
    428 	case reflect.Int64:
    429 		return uint64(elem.Int())
    430 	case reflect.Uint64:
    431 		return elem.Uint()
    432 	case reflect.Float64:
    433 		return math.Float64bits(elem.Float())
    434 	}
    435 	panic("unreachable")
    436 }
    437 
    438 func structPointer_Word64Val(p structPointer, f field) word64Val {
    439 	return word64Val{structPointer_field(p, f)}
    440 }
    441 
    442 type word64Slice struct {
    443 	v reflect.Value
    444 }
    445 
    446 func (p word64Slice) Append(x uint64) {
    447 	n, m := p.v.Len(), p.v.Cap()
    448 	if n < m {
    449 		p.v.SetLen(n + 1)
    450 	} else {
    451 		t := p.v.Type().Elem()
    452 		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
    453 	}
    454 	elem := p.v.Index(n)
    455 	switch elem.Kind() {
    456 	case reflect.Int64:
    457 		elem.SetInt(int64(int64(x)))
    458 	case reflect.Uint64:
    459 		elem.SetUint(uint64(x))
    460 	case reflect.Float64:
    461 		elem.SetFloat(float64(math.Float64frombits(x)))
    462 	}
    463 }
    464 
    465 func (p word64Slice) Len() int {
    466 	return p.v.Len()
    467 }
    468 
    469 func (p word64Slice) Index(i int) uint64 {
    470 	elem := p.v.Index(i)
    471 	switch elem.Kind() {
    472 	case reflect.Int64:
    473 		return uint64(elem.Int())
    474 	case reflect.Uint64:
    475 		return uint64(elem.Uint())
    476 	case reflect.Float64:
    477 		return math.Float64bits(float64(elem.Float()))
    478 	}
    479 	panic("unreachable")
    480 }
    481 
    482 func structPointer_Word64Slice(p structPointer, f field) word64Slice {
    483 	return word64Slice{structPointer_field(p, f)}
    484 }
    485