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 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 38package proto 39 40import ( 41 "math" 42 "reflect" 43) 44 45// A structPointer is a pointer to a struct. 46type 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. 52func toStructPointer(v reflect.Value) structPointer { 53 return structPointer{v} 54} 55 56// IsNil reports whether p is nil. 57func structPointer_IsNil(p structPointer) bool { 58 return p.v.IsNil() 59} 60 61// Interface returns the struct pointer as an interface value. 62func 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. 69type field []int 70 71// toField returns a field equivalent to the given reflect field. 72func toField(f *reflect.StructField) field { 73 return f.Index 74} 75 76// invalidField is an invalid field identifier. 77var invalidField = field(nil) 78 79// IsValid reports whether the field identifier is valid. 80func (f field) IsValid() bool { return f != nil } 81 82// field returns the given field in the struct as a reflect value. 83func 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. 98func 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. 103func 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. 108func 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. 113func 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. 118func 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. 123func 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. 128func 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. 133func 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. 138func 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. 143func 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. 148func 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. 153func 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. 158func 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. 163func 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{...}. 169type structPointerSlice struct { 170 v reflect.Value 171} 172 173func (p structPointerSlice) Len() int { return p.v.Len() } 174func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } 175func (p structPointerSlice) Append(q structPointer) { 176 p.v.Set(reflect.Append(p.v, q.v)) 177} 178 179var ( 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. 190type word32 struct { 191 v reflect.Value 192} 193 194// IsNil reports whether p is nil. 195func 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. 200func 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. 235func 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. 249func 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. 255type word32Val struct { 256 v reflect.Value 257} 258 259// Set sets *p to x. 260func 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. 278func 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. 292func 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. 298type word32Slice struct { 299 v reflect.Value 300} 301 302func (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 321func (p word32Slice) Len() int { 322 return p.v.Len() 323} 324 325func (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. 339func 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. 344type word64 struct { 345 v reflect.Value 346} 347 348func 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 379func word64_IsNil(p word64) bool { 380 return p.v.IsNil() 381} 382 383func 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 396func 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. 401type word64Val struct { 402 v reflect.Value 403} 404 405func 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 420func 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 433func structPointer_Word64Val(p structPointer, f field) word64Val { 434 return word64Val{structPointer_field(p, f)} 435} 436 437type word64Slice struct { 438 v reflect.Value 439} 440 441func (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 460func (p word64Slice) Len() int { 461 return p.v.Len() 462} 463 464func (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 477func structPointer_Word64Slice(p structPointer, f field) word64Slice { 478 return word64Slice{structPointer_field(p, f)} 479} 480