David K. Bainbridge | 215e024 | 2017-09-05 23:18:24 -0700 | [diff] [blame] | 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 the implementation of the proto field accesses using package unsafe. |
| 35 | |
| 36 | package proto |
| 37 | |
| 38 | import ( |
| 39 | "reflect" |
| 40 | "unsafe" |
| 41 | ) |
| 42 | |
| 43 | // NOTE: These type_Foo functions would more idiomatically be methods, |
| 44 | // but Go does not allow methods on pointer types, and we must preserve |
| 45 | // some pointer type for the garbage collector. We use these |
| 46 | // funcs with clunky names as our poor approximation to methods. |
| 47 | // |
| 48 | // An alternative would be |
| 49 | // type structPointer struct { p unsafe.Pointer } |
| 50 | // but that does not registerize as well. |
| 51 | |
| 52 | // A structPointer is a pointer to a struct. |
| 53 | type structPointer unsafe.Pointer |
| 54 | |
| 55 | // toStructPointer returns a structPointer equivalent to the given reflect value. |
| 56 | func toStructPointer(v reflect.Value) structPointer { |
| 57 | return structPointer(unsafe.Pointer(v.Pointer())) |
| 58 | } |
| 59 | |
| 60 | // IsNil reports whether p is nil. |
| 61 | func structPointer_IsNil(p structPointer) bool { |
| 62 | return p == nil |
| 63 | } |
| 64 | |
| 65 | // Interface returns the struct pointer, assumed to have element type t, |
| 66 | // as an interface value. |
| 67 | func structPointer_Interface(p structPointer, t reflect.Type) interface{} { |
| 68 | return reflect.NewAt(t, unsafe.Pointer(p)).Interface() |
| 69 | } |
| 70 | |
| 71 | // A field identifies a field in a struct, accessible from a structPointer. |
| 72 | // In this implementation, a field is identified by its byte offset from the start of the struct. |
| 73 | type field uintptr |
| 74 | |
| 75 | // toField returns a field equivalent to the given reflect field. |
| 76 | func toField(f *reflect.StructField) field { |
| 77 | return field(f.Offset) |
| 78 | } |
| 79 | |
| 80 | // invalidField is an invalid field identifier. |
| 81 | const invalidField = ^field(0) |
| 82 | |
| 83 | // IsValid reports whether the field identifier is valid. |
| 84 | func (f field) IsValid() bool { |
| 85 | return f != ^field(0) |
| 86 | } |
| 87 | |
| 88 | // Bytes returns the address of a []byte field in the struct. |
| 89 | func structPointer_Bytes(p structPointer, f field) *[]byte { |
| 90 | return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 91 | } |
| 92 | |
| 93 | // BytesSlice returns the address of a [][]byte field in the struct. |
| 94 | func structPointer_BytesSlice(p structPointer, f field) *[][]byte { |
| 95 | return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 96 | } |
| 97 | |
| 98 | // Bool returns the address of a *bool field in the struct. |
| 99 | func structPointer_Bool(p structPointer, f field) **bool { |
| 100 | return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 101 | } |
| 102 | |
| 103 | // BoolVal returns the address of a bool field in the struct. |
| 104 | func structPointer_BoolVal(p structPointer, f field) *bool { |
| 105 | return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 106 | } |
| 107 | |
| 108 | // BoolSlice returns the address of a []bool field in the struct. |
| 109 | func structPointer_BoolSlice(p structPointer, f field) *[]bool { |
| 110 | return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 111 | } |
| 112 | |
| 113 | // String returns the address of a *string field in the struct. |
| 114 | func structPointer_String(p structPointer, f field) **string { |
| 115 | return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 116 | } |
| 117 | |
| 118 | // StringVal returns the address of a string field in the struct. |
| 119 | func structPointer_StringVal(p structPointer, f field) *string { |
| 120 | return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 121 | } |
| 122 | |
| 123 | // StringSlice returns the address of a []string field in the struct. |
| 124 | func structPointer_StringSlice(p structPointer, f field) *[]string { |
| 125 | return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 126 | } |
| 127 | |
| 128 | // ExtMap returns the address of an extension map field in the struct. |
| 129 | func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { |
| 130 | return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 131 | } |
| 132 | |
| 133 | func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { |
| 134 | return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 135 | } |
| 136 | |
| 137 | // NewAt returns the reflect.Value for a pointer to a field in the struct. |
| 138 | func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { |
| 139 | return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) |
| 140 | } |
| 141 | |
| 142 | // SetStructPointer writes a *struct field in the struct. |
| 143 | func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { |
| 144 | *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q |
| 145 | } |
| 146 | |
| 147 | // GetStructPointer reads a *struct field in the struct. |
| 148 | func structPointer_GetStructPointer(p structPointer, f field) structPointer { |
| 149 | return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 150 | } |
| 151 | |
| 152 | // StructPointerSlice the address of a []*struct field in the struct. |
| 153 | func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { |
| 154 | return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 155 | } |
| 156 | |
| 157 | // A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). |
| 158 | type structPointerSlice []structPointer |
| 159 | |
| 160 | func (v *structPointerSlice) Len() int { return len(*v) } |
| 161 | func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } |
| 162 | func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } |
| 163 | |
| 164 | // A word32 is the address of a "pointer to 32-bit value" field. |
| 165 | type word32 **uint32 |
| 166 | |
| 167 | // IsNil reports whether *v is nil. |
| 168 | func word32_IsNil(p word32) bool { |
| 169 | return *p == nil |
| 170 | } |
| 171 | |
| 172 | // Set sets *v to point at a newly allocated word set to x. |
| 173 | func word32_Set(p word32, o *Buffer, x uint32) { |
| 174 | if len(o.uint32s) == 0 { |
| 175 | o.uint32s = make([]uint32, uint32PoolSize) |
| 176 | } |
| 177 | o.uint32s[0] = x |
| 178 | *p = &o.uint32s[0] |
| 179 | o.uint32s = o.uint32s[1:] |
| 180 | } |
| 181 | |
| 182 | // Get gets the value pointed at by *v. |
| 183 | func word32_Get(p word32) uint32 { |
| 184 | return **p |
| 185 | } |
| 186 | |
| 187 | // Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. |
| 188 | func structPointer_Word32(p structPointer, f field) word32 { |
| 189 | return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) |
| 190 | } |
| 191 | |
| 192 | // A word32Val is the address of a 32-bit value field. |
| 193 | type word32Val *uint32 |
| 194 | |
| 195 | // Set sets *p to x. |
| 196 | func word32Val_Set(p word32Val, x uint32) { |
| 197 | *p = x |
| 198 | } |
| 199 | |
| 200 | // Get gets the value pointed at by p. |
| 201 | func word32Val_Get(p word32Val) uint32 { |
| 202 | return *p |
| 203 | } |
| 204 | |
| 205 | // Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. |
| 206 | func structPointer_Word32Val(p structPointer, f field) word32Val { |
| 207 | return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) |
| 208 | } |
| 209 | |
| 210 | // A word32Slice is a slice of 32-bit values. |
| 211 | type word32Slice []uint32 |
| 212 | |
| 213 | func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } |
| 214 | func (v *word32Slice) Len() int { return len(*v) } |
| 215 | func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } |
| 216 | |
| 217 | // Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. |
| 218 | func structPointer_Word32Slice(p structPointer, f field) *word32Slice { |
| 219 | return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 220 | } |
| 221 | |
| 222 | // word64 is like word32 but for 64-bit values. |
| 223 | type word64 **uint64 |
| 224 | |
| 225 | func word64_Set(p word64, o *Buffer, x uint64) { |
| 226 | if len(o.uint64s) == 0 { |
| 227 | o.uint64s = make([]uint64, uint64PoolSize) |
| 228 | } |
| 229 | o.uint64s[0] = x |
| 230 | *p = &o.uint64s[0] |
| 231 | o.uint64s = o.uint64s[1:] |
| 232 | } |
| 233 | |
| 234 | func word64_IsNil(p word64) bool { |
| 235 | return *p == nil |
| 236 | } |
| 237 | |
| 238 | func word64_Get(p word64) uint64 { |
| 239 | return **p |
| 240 | } |
| 241 | |
| 242 | func structPointer_Word64(p structPointer, f field) word64 { |
| 243 | return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) |
| 244 | } |
| 245 | |
| 246 | // word64Val is like word32Val but for 64-bit values. |
| 247 | type word64Val *uint64 |
| 248 | |
| 249 | func word64Val_Set(p word64Val, o *Buffer, x uint64) { |
| 250 | *p = x |
| 251 | } |
| 252 | |
| 253 | func word64Val_Get(p word64Val) uint64 { |
| 254 | return *p |
| 255 | } |
| 256 | |
| 257 | func structPointer_Word64Val(p structPointer, f field) word64Val { |
| 258 | return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) |
| 259 | } |
| 260 | |
| 261 | // word64Slice is like word32Slice but for 64-bit values. |
| 262 | type word64Slice []uint64 |
| 263 | |
| 264 | func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } |
| 265 | func (v *word64Slice) Len() int { return len(*v) } |
| 266 | func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } |
| 267 | |
| 268 | func structPointer_Word64Slice(p structPointer, f field) *word64Slice { |
| 269 | return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) |
| 270 | } |