github.com/matm/etcd@v0.3.1-0.20140328024009-5b4a473f1453/third_party/code.google.com/p/gogoprotobuf/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 // http://code.google.com/p/goprotobuf/ 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 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 // BoolSlice returns the address of a []bool field in the struct. 118 func structPointer_BoolSlice(p structPointer, f field) *[]bool { 119 return structPointer_ifield(p, f).(*[]bool) 120 } 121 122 // String returns the address of a *string field in the struct. 123 func structPointer_String(p structPointer, f field) **string { 124 return structPointer_ifield(p, f).(**string) 125 } 126 127 // StringSlice returns the address of a []string field in the struct. 128 func structPointer_StringSlice(p structPointer, f field) *[]string { 129 return structPointer_ifield(p, f).(*[]string) 130 } 131 132 // ExtMap returns the address of an extension map field in the struct. 133 func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { 134 return structPointer_ifield(p, f).(*map[int32]Extension) 135 } 136 137 // SetStructPointer writes a *struct field in the struct. 138 func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { 139 structPointer_field(p, f).Set(q.v) 140 } 141 142 // GetStructPointer reads a *struct field in the struct. 143 func structPointer_GetStructPointer(p structPointer, f field) structPointer { 144 return structPointer{structPointer_field(p, f)} 145 } 146 147 // StructPointerSlice the address of a []*struct field in the struct. 148 func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { 149 return structPointerSlice{structPointer_field(p, f)} 150 } 151 152 // A structPointerSlice represents the address of a slice of pointers to structs 153 // (themselves messages or groups). That is, v.Type() is *[]*struct{...}. 154 type structPointerSlice struct { 155 v reflect.Value 156 } 157 158 func (p structPointerSlice) Len() int { return p.v.Len() } 159 func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } 160 func (p structPointerSlice) Append(q structPointer) { 161 p.v.Set(reflect.Append(p.v, q.v)) 162 } 163 164 var ( 165 int32Type = reflect.TypeOf(int32(0)) 166 uint32Type = reflect.TypeOf(uint32(0)) 167 float32Type = reflect.TypeOf(float32(0)) 168 int64Type = reflect.TypeOf(int64(0)) 169 uint64Type = reflect.TypeOf(uint64(0)) 170 float64Type = reflect.TypeOf(float64(0)) 171 ) 172 173 // A word32 represents a field of type *int32, *uint32, *float32, or *enum. 174 // That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. 175 type word32 struct { 176 v reflect.Value 177 } 178 179 // IsNil reports whether p is nil. 180 func word32_IsNil(p word32) bool { 181 return p.v.IsNil() 182 } 183 184 // Set sets p to point at a newly allocated word with bits set to x. 185 func word32_Set(p word32, o *Buffer, x uint32) { 186 t := p.v.Type().Elem() 187 switch t { 188 case int32Type: 189 if len(o.int32s) == 0 { 190 o.int32s = make([]int32, uint32PoolSize) 191 } 192 o.int32s[0] = int32(x) 193 p.v.Set(reflect.ValueOf(&o.int32s[0])) 194 o.int32s = o.int32s[1:] 195 return 196 case uint32Type: 197 if len(o.uint32s) == 0 { 198 o.uint32s = make([]uint32, uint32PoolSize) 199 } 200 o.uint32s[0] = x 201 p.v.Set(reflect.ValueOf(&o.uint32s[0])) 202 o.uint32s = o.uint32s[1:] 203 return 204 case float32Type: 205 if len(o.float32s) == 0 { 206 o.float32s = make([]float32, uint32PoolSize) 207 } 208 o.float32s[0] = math.Float32frombits(x) 209 p.v.Set(reflect.ValueOf(&o.float32s[0])) 210 o.float32s = o.float32s[1:] 211 return 212 } 213 214 // must be enum 215 p.v.Set(reflect.New(t)) 216 p.v.Elem().SetInt(int64(int32(x))) 217 } 218 219 // Get gets the bits pointed at by p, as a uint32. 220 func word32_Get(p word32) uint32 { 221 elem := p.v.Elem() 222 switch elem.Kind() { 223 case reflect.Int32: 224 return uint32(elem.Int()) 225 case reflect.Uint32: 226 return uint32(elem.Uint()) 227 case reflect.Float32: 228 return math.Float32bits(float32(elem.Float())) 229 } 230 panic("unreachable") 231 } 232 233 // Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. 234 func structPointer_Word32(p structPointer, f field) word32 { 235 return word32{structPointer_field(p, f)} 236 } 237 238 // A word32Slice is a slice of 32-bit values. 239 // That is, v.Type() is []int32, []uint32, []float32, or []enum. 240 type word32Slice struct { 241 v reflect.Value 242 } 243 244 func (p word32Slice) Append(x uint32) { 245 n, m := p.v.Len(), p.v.Cap() 246 if n < m { 247 p.v.SetLen(n + 1) 248 } else { 249 t := p.v.Type().Elem() 250 p.v.Set(reflect.Append(p.v, reflect.Zero(t))) 251 } 252 elem := p.v.Index(n) 253 switch elem.Kind() { 254 case reflect.Int32: 255 elem.SetInt(int64(int32(x))) 256 case reflect.Uint32: 257 elem.SetUint(uint64(x)) 258 case reflect.Float32: 259 elem.SetFloat(float64(math.Float32frombits(x))) 260 } 261 } 262 263 func (p word32Slice) Len() int { 264 return p.v.Len() 265 } 266 267 func (p word32Slice) Index(i int) uint32 { 268 elem := p.v.Index(i) 269 switch elem.Kind() { 270 case reflect.Int32: 271 return uint32(elem.Int()) 272 case reflect.Uint32: 273 return uint32(elem.Uint()) 274 case reflect.Float32: 275 return math.Float32bits(float32(elem.Float())) 276 } 277 panic("unreachable") 278 } 279 280 // Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. 281 func structPointer_Word32Slice(p structPointer, f field) word32Slice { 282 return word32Slice{structPointer_field(p, f)} 283 } 284 285 // word64 is like word32 but for 64-bit values. 286 type word64 struct { 287 v reflect.Value 288 } 289 290 func word64_Set(p word64, o *Buffer, x uint64) { 291 t := p.v.Type().Elem() 292 switch t { 293 case int64Type: 294 if len(o.int64s) == 0 { 295 o.int64s = make([]int64, uint64PoolSize) 296 } 297 o.int64s[0] = int64(x) 298 p.v.Set(reflect.ValueOf(&o.int64s[0])) 299 o.int64s = o.int64s[1:] 300 return 301 case uint64Type: 302 if len(o.uint64s) == 0 { 303 o.uint64s = make([]uint64, uint64PoolSize) 304 } 305 o.uint64s[0] = x 306 p.v.Set(reflect.ValueOf(&o.uint64s[0])) 307 o.uint64s = o.uint64s[1:] 308 return 309 case float64Type: 310 if len(o.float64s) == 0 { 311 o.float64s = make([]float64, uint64PoolSize) 312 } 313 o.float64s[0] = math.Float64frombits(x) 314 p.v.Set(reflect.ValueOf(&o.float64s[0])) 315 o.float64s = o.float64s[1:] 316 return 317 } 318 panic("unreachable") 319 } 320 321 func word64_IsNil(p word64) bool { 322 return p.v.IsNil() 323 } 324 325 func word64_Get(p word64) uint64 { 326 elem := p.v.Elem() 327 switch elem.Kind() { 328 case reflect.Int64: 329 return uint64(elem.Int()) 330 case reflect.Uint64: 331 return elem.Uint() 332 case reflect.Float64: 333 return math.Float64bits(elem.Float()) 334 } 335 panic("unreachable") 336 } 337 338 func structPointer_Word64(p structPointer, f field) word64 { 339 return word64{structPointer_field(p, f)} 340 } 341 342 type word64Slice struct { 343 v reflect.Value 344 } 345 346 func (p word64Slice) Append(x uint64) { 347 n, m := p.v.Len(), p.v.Cap() 348 if n < m { 349 p.v.SetLen(n + 1) 350 } else { 351 t := p.v.Type().Elem() 352 p.v.Set(reflect.Append(p.v, reflect.Zero(t))) 353 } 354 elem := p.v.Index(n) 355 switch elem.Kind() { 356 case reflect.Int64: 357 elem.SetInt(int64(int64(x))) 358 case reflect.Uint64: 359 elem.SetUint(uint64(x)) 360 case reflect.Float64: 361 elem.SetFloat(float64(math.Float64frombits(x))) 362 } 363 } 364 365 func (p word64Slice) Len() int { 366 return p.v.Len() 367 } 368 369 func (p word64Slice) Index(i int) uint64 { 370 elem := p.v.Index(i) 371 switch elem.Kind() { 372 case reflect.Int64: 373 return uint64(elem.Int()) 374 case reflect.Uint64: 375 return uint64(elem.Uint()) 376 case reflect.Float64: 377 return math.Float64bits(float64(elem.Float())) 378 } 379 panic("unreachable") 380 } 381 382 func structPointer_Word64Slice(p structPointer, f field) word64Slice { 383 return word64Slice{structPointer_field(p, f)} 384 }