| // 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 |
| |
| // 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) |
| } |
| |
| // 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) |
| } |
| |
| // Map returns the reflect.Value for the address of a map field in the struct. |
| func structPointer_Map(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)} |
| } |