|  | // Go support for Protocol Buffers - Google's data interchange format | 
|  | // | 
|  | // Copyright 2012 The Go Authors.  All rights reserved. | 
|  | // https://github.com/golang/protobuf | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are | 
|  | // met: | 
|  | // | 
|  | //     * Redistributions of source code must retain the above copyright | 
|  | // notice, this list of conditions and the following disclaimer. | 
|  | //     * Redistributions in binary form must reproduce the above | 
|  | // copyright notice, this list of conditions and the following disclaimer | 
|  | // in the documentation and/or other materials provided with the | 
|  | // distribution. | 
|  | //     * Neither the name of Google Inc. nor the names of its | 
|  | // contributors may be used to endorse or promote products derived from | 
|  | // this software without specific prior written permission. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  | // +build appengine js | 
|  |  | 
|  | // This file contains an implementation of proto field accesses using package reflect. | 
|  | // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can | 
|  | // be used on App Engine. | 
|  |  | 
|  | package proto | 
|  |  | 
|  | import ( | 
|  | "math" | 
|  | "reflect" | 
|  | ) | 
|  |  | 
|  | // A structPointer is a pointer to a struct. | 
|  | type structPointer struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | // toStructPointer returns a structPointer equivalent to the given reflect value. | 
|  | // The reflect value must itself be a pointer to a struct. | 
|  | func toStructPointer(v reflect.Value) structPointer { | 
|  | return structPointer{v} | 
|  | } | 
|  |  | 
|  | // IsNil reports whether p is nil. | 
|  | func structPointer_IsNil(p structPointer) bool { | 
|  | return p.v.IsNil() | 
|  | } | 
|  |  | 
|  | // Interface returns the struct pointer as an interface value. | 
|  | func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { | 
|  | return p.v.Interface() | 
|  | } | 
|  |  | 
|  | // A field identifies a field in a struct, accessible from a structPointer. | 
|  | // In this implementation, a field is identified by the sequence of field indices | 
|  | // passed to reflect's FieldByIndex. | 
|  | type field []int | 
|  |  | 
|  | // toField returns a field equivalent to the given reflect field. | 
|  | func toField(f *reflect.StructField) field { | 
|  | return f.Index | 
|  | } | 
|  |  | 
|  | // invalidField is an invalid field identifier. | 
|  | var invalidField = field(nil) | 
|  |  | 
|  | // IsValid reports whether the field identifier is valid. | 
|  | func (f field) IsValid() bool { return f != nil } | 
|  |  | 
|  | // field returns the given field in the struct as a reflect value. | 
|  | func structPointer_field(p structPointer, f field) reflect.Value { | 
|  | // Special case: an extension map entry with a value of type T | 
|  | // passes a *T to the struct-handling code with a zero field, | 
|  | // expecting that it will be treated as equivalent to *struct{ X T }, | 
|  | // which has the same memory layout. We have to handle that case | 
|  | // specially, because reflect will panic if we call FieldByIndex on a | 
|  | // non-struct. | 
|  | if f == nil { | 
|  | return p.v.Elem() | 
|  | } | 
|  |  | 
|  | return p.v.Elem().FieldByIndex(f) | 
|  | } | 
|  |  | 
|  | // ifield returns the given field in the struct as an interface value. | 
|  | func structPointer_ifield(p structPointer, f field) interface{} { | 
|  | return structPointer_field(p, f).Addr().Interface() | 
|  | } | 
|  |  | 
|  | // Bytes returns the address of a []byte field in the struct. | 
|  | func structPointer_Bytes(p structPointer, f field) *[]byte { | 
|  | return structPointer_ifield(p, f).(*[]byte) | 
|  | } | 
|  |  | 
|  | // BytesSlice returns the address of a [][]byte field in the struct. | 
|  | func structPointer_BytesSlice(p structPointer, f field) *[][]byte { | 
|  | return structPointer_ifield(p, f).(*[][]byte) | 
|  | } | 
|  |  | 
|  | // Bool returns the address of a *bool field in the struct. | 
|  | func structPointer_Bool(p structPointer, f field) **bool { | 
|  | return structPointer_ifield(p, f).(**bool) | 
|  | } | 
|  |  | 
|  | // BoolVal returns the address of a bool field in the struct. | 
|  | func structPointer_BoolVal(p structPointer, f field) *bool { | 
|  | return structPointer_ifield(p, f).(*bool) | 
|  | } | 
|  |  | 
|  | // BoolSlice returns the address of a []bool field in the struct. | 
|  | func structPointer_BoolSlice(p structPointer, f field) *[]bool { | 
|  | return structPointer_ifield(p, f).(*[]bool) | 
|  | } | 
|  |  | 
|  | // String returns the address of a *string field in the struct. | 
|  | func structPointer_String(p structPointer, f field) **string { | 
|  | return structPointer_ifield(p, f).(**string) | 
|  | } | 
|  |  | 
|  | // StringVal returns the address of a string field in the struct. | 
|  | func structPointer_StringVal(p structPointer, f field) *string { | 
|  | return structPointer_ifield(p, f).(*string) | 
|  | } | 
|  |  | 
|  | // StringSlice returns the address of a []string field in the struct. | 
|  | func structPointer_StringSlice(p structPointer, f field) *[]string { | 
|  | return structPointer_ifield(p, f).(*[]string) | 
|  | } | 
|  |  | 
|  | // Extensions returns the address of an extension map field in the struct. | 
|  | func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { | 
|  | return structPointer_ifield(p, f).(*XXX_InternalExtensions) | 
|  | } | 
|  |  | 
|  | // ExtMap returns the address of an extension map field in the struct. | 
|  | func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { | 
|  | return structPointer_ifield(p, f).(*map[int32]Extension) | 
|  | } | 
|  |  | 
|  | // NewAt returns the reflect.Value for a pointer to a field in the struct. | 
|  | func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { | 
|  | return structPointer_field(p, f).Addr() | 
|  | } | 
|  |  | 
|  | // SetStructPointer writes a *struct field in the struct. | 
|  | func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { | 
|  | structPointer_field(p, f).Set(q.v) | 
|  | } | 
|  |  | 
|  | // GetStructPointer reads a *struct field in the struct. | 
|  | func structPointer_GetStructPointer(p structPointer, f field) structPointer { | 
|  | return structPointer{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // StructPointerSlice the address of a []*struct field in the struct. | 
|  | func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { | 
|  | return structPointerSlice{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // A structPointerSlice represents the address of a slice of pointers to structs | 
|  | // (themselves messages or groups). That is, v.Type() is *[]*struct{...}. | 
|  | type structPointerSlice struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | func (p structPointerSlice) Len() int                  { return p.v.Len() } | 
|  | func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } | 
|  | func (p structPointerSlice) Append(q structPointer) { | 
|  | p.v.Set(reflect.Append(p.v, q.v)) | 
|  | } | 
|  |  | 
|  | var ( | 
|  | int32Type   = reflect.TypeOf(int32(0)) | 
|  | uint32Type  = reflect.TypeOf(uint32(0)) | 
|  | float32Type = reflect.TypeOf(float32(0)) | 
|  | int64Type   = reflect.TypeOf(int64(0)) | 
|  | uint64Type  = reflect.TypeOf(uint64(0)) | 
|  | float64Type = reflect.TypeOf(float64(0)) | 
|  | ) | 
|  |  | 
|  | // A word32 represents a field of type *int32, *uint32, *float32, or *enum. | 
|  | // That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. | 
|  | type word32 struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | // IsNil reports whether p is nil. | 
|  | func word32_IsNil(p word32) bool { | 
|  | return p.v.IsNil() | 
|  | } | 
|  |  | 
|  | // Set sets p to point at a newly allocated word with bits set to x. | 
|  | func word32_Set(p word32, o *Buffer, x uint32) { | 
|  | t := p.v.Type().Elem() | 
|  | switch t { | 
|  | case int32Type: | 
|  | if len(o.int32s) == 0 { | 
|  | o.int32s = make([]int32, uint32PoolSize) | 
|  | } | 
|  | o.int32s[0] = int32(x) | 
|  | p.v.Set(reflect.ValueOf(&o.int32s[0])) | 
|  | o.int32s = o.int32s[1:] | 
|  | return | 
|  | case uint32Type: | 
|  | if len(o.uint32s) == 0 { | 
|  | o.uint32s = make([]uint32, uint32PoolSize) | 
|  | } | 
|  | o.uint32s[0] = x | 
|  | p.v.Set(reflect.ValueOf(&o.uint32s[0])) | 
|  | o.uint32s = o.uint32s[1:] | 
|  | return | 
|  | case float32Type: | 
|  | if len(o.float32s) == 0 { | 
|  | o.float32s = make([]float32, uint32PoolSize) | 
|  | } | 
|  | o.float32s[0] = math.Float32frombits(x) | 
|  | p.v.Set(reflect.ValueOf(&o.float32s[0])) | 
|  | o.float32s = o.float32s[1:] | 
|  | return | 
|  | } | 
|  |  | 
|  | // must be enum | 
|  | p.v.Set(reflect.New(t)) | 
|  | p.v.Elem().SetInt(int64(int32(x))) | 
|  | } | 
|  |  | 
|  | // Get gets the bits pointed at by p, as a uint32. | 
|  | func word32_Get(p word32) uint32 { | 
|  | elem := p.v.Elem() | 
|  | switch elem.Kind() { | 
|  | case reflect.Int32: | 
|  | return uint32(elem.Int()) | 
|  | case reflect.Uint32: | 
|  | return uint32(elem.Uint()) | 
|  | case reflect.Float32: | 
|  | return math.Float32bits(float32(elem.Float())) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | // Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. | 
|  | func structPointer_Word32(p structPointer, f field) word32 { | 
|  | return word32{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // A word32Val represents a field of type int32, uint32, float32, or enum. | 
|  | // That is, v.Type() is int32, uint32, float32, or enum and v is assignable. | 
|  | type word32Val struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | // Set sets *p to x. | 
|  | func word32Val_Set(p word32Val, x uint32) { | 
|  | switch p.v.Type() { | 
|  | case int32Type: | 
|  | p.v.SetInt(int64(x)) | 
|  | return | 
|  | case uint32Type: | 
|  | p.v.SetUint(uint64(x)) | 
|  | return | 
|  | case float32Type: | 
|  | p.v.SetFloat(float64(math.Float32frombits(x))) | 
|  | return | 
|  | } | 
|  |  | 
|  | // must be enum | 
|  | p.v.SetInt(int64(int32(x))) | 
|  | } | 
|  |  | 
|  | // Get gets the bits pointed at by p, as a uint32. | 
|  | func word32Val_Get(p word32Val) uint32 { | 
|  | elem := p.v | 
|  | switch elem.Kind() { | 
|  | case reflect.Int32: | 
|  | return uint32(elem.Int()) | 
|  | case reflect.Uint32: | 
|  | return uint32(elem.Uint()) | 
|  | case reflect.Float32: | 
|  | return math.Float32bits(float32(elem.Float())) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | // Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. | 
|  | func structPointer_Word32Val(p structPointer, f field) word32Val { | 
|  | return word32Val{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // A word32Slice is a slice of 32-bit values. | 
|  | // That is, v.Type() is []int32, []uint32, []float32, or []enum. | 
|  | type word32Slice struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | func (p word32Slice) Append(x uint32) { | 
|  | n, m := p.v.Len(), p.v.Cap() | 
|  | if n < m { | 
|  | p.v.SetLen(n + 1) | 
|  | } else { | 
|  | t := p.v.Type().Elem() | 
|  | p.v.Set(reflect.Append(p.v, reflect.Zero(t))) | 
|  | } | 
|  | elem := p.v.Index(n) | 
|  | switch elem.Kind() { | 
|  | case reflect.Int32: | 
|  | elem.SetInt(int64(int32(x))) | 
|  | case reflect.Uint32: | 
|  | elem.SetUint(uint64(x)) | 
|  | case reflect.Float32: | 
|  | elem.SetFloat(float64(math.Float32frombits(x))) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (p word32Slice) Len() int { | 
|  | return p.v.Len() | 
|  | } | 
|  |  | 
|  | func (p word32Slice) Index(i int) uint32 { | 
|  | elem := p.v.Index(i) | 
|  | switch elem.Kind() { | 
|  | case reflect.Int32: | 
|  | return uint32(elem.Int()) | 
|  | case reflect.Uint32: | 
|  | return uint32(elem.Uint()) | 
|  | case reflect.Float32: | 
|  | return math.Float32bits(float32(elem.Float())) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | // Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. | 
|  | func structPointer_Word32Slice(p structPointer, f field) word32Slice { | 
|  | return word32Slice{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // word64 is like word32 but for 64-bit values. | 
|  | type word64 struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | func word64_Set(p word64, o *Buffer, x uint64) { | 
|  | t := p.v.Type().Elem() | 
|  | switch t { | 
|  | case int64Type: | 
|  | if len(o.int64s) == 0 { | 
|  | o.int64s = make([]int64, uint64PoolSize) | 
|  | } | 
|  | o.int64s[0] = int64(x) | 
|  | p.v.Set(reflect.ValueOf(&o.int64s[0])) | 
|  | o.int64s = o.int64s[1:] | 
|  | return | 
|  | case uint64Type: | 
|  | if len(o.uint64s) == 0 { | 
|  | o.uint64s = make([]uint64, uint64PoolSize) | 
|  | } | 
|  | o.uint64s[0] = x | 
|  | p.v.Set(reflect.ValueOf(&o.uint64s[0])) | 
|  | o.uint64s = o.uint64s[1:] | 
|  | return | 
|  | case float64Type: | 
|  | if len(o.float64s) == 0 { | 
|  | o.float64s = make([]float64, uint64PoolSize) | 
|  | } | 
|  | o.float64s[0] = math.Float64frombits(x) | 
|  | p.v.Set(reflect.ValueOf(&o.float64s[0])) | 
|  | o.float64s = o.float64s[1:] | 
|  | return | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func word64_IsNil(p word64) bool { | 
|  | return p.v.IsNil() | 
|  | } | 
|  |  | 
|  | func word64_Get(p word64) uint64 { | 
|  | elem := p.v.Elem() | 
|  | switch elem.Kind() { | 
|  | case reflect.Int64: | 
|  | return uint64(elem.Int()) | 
|  | case reflect.Uint64: | 
|  | return elem.Uint() | 
|  | case reflect.Float64: | 
|  | return math.Float64bits(elem.Float()) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func structPointer_Word64(p structPointer, f field) word64 { | 
|  | return word64{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | // word64Val is like word32Val but for 64-bit values. | 
|  | type word64Val struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | func word64Val_Set(p word64Val, o *Buffer, x uint64) { | 
|  | switch p.v.Type() { | 
|  | case int64Type: | 
|  | p.v.SetInt(int64(x)) | 
|  | return | 
|  | case uint64Type: | 
|  | p.v.SetUint(x) | 
|  | return | 
|  | case float64Type: | 
|  | p.v.SetFloat(math.Float64frombits(x)) | 
|  | return | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func word64Val_Get(p word64Val) uint64 { | 
|  | elem := p.v | 
|  | switch elem.Kind() { | 
|  | case reflect.Int64: | 
|  | return uint64(elem.Int()) | 
|  | case reflect.Uint64: | 
|  | return elem.Uint() | 
|  | case reflect.Float64: | 
|  | return math.Float64bits(elem.Float()) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func structPointer_Word64Val(p structPointer, f field) word64Val { | 
|  | return word64Val{structPointer_field(p, f)} | 
|  | } | 
|  |  | 
|  | type word64Slice struct { | 
|  | v reflect.Value | 
|  | } | 
|  |  | 
|  | func (p word64Slice) Append(x uint64) { | 
|  | n, m := p.v.Len(), p.v.Cap() | 
|  | if n < m { | 
|  | p.v.SetLen(n + 1) | 
|  | } else { | 
|  | t := p.v.Type().Elem() | 
|  | p.v.Set(reflect.Append(p.v, reflect.Zero(t))) | 
|  | } | 
|  | elem := p.v.Index(n) | 
|  | switch elem.Kind() { | 
|  | case reflect.Int64: | 
|  | elem.SetInt(int64(int64(x))) | 
|  | case reflect.Uint64: | 
|  | elem.SetUint(uint64(x)) | 
|  | case reflect.Float64: | 
|  | elem.SetFloat(float64(math.Float64frombits(x))) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (p word64Slice) Len() int { | 
|  | return p.v.Len() | 
|  | } | 
|  |  | 
|  | func (p word64Slice) Index(i int) uint64 { | 
|  | elem := p.v.Index(i) | 
|  | switch elem.Kind() { | 
|  | case reflect.Int64: | 
|  | return uint64(elem.Int()) | 
|  | case reflect.Uint64: | 
|  | return uint64(elem.Uint()) | 
|  | case reflect.Float64: | 
|  | return math.Float64bits(float64(elem.Float())) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func structPointer_Word64Slice(p structPointer, f field) word64Slice { | 
|  | return word64Slice{structPointer_field(p, f)} | 
|  | } |