diff options
Diffstat (limited to 'vendor/github.com/golang/protobuf/proto/pointer_unsafe.go')
-rw-r--r-- | vendor/github.com/golang/protobuf/proto/pointer_unsafe.go | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go new file mode 100644 index 0000000..d55a335 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go | |||
@@ -0,0 +1,308 @@ | |||
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 !purego,!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 | "sync/atomic" | ||
41 | "unsafe" | ||
42 | ) | ||
43 | |||
44 | const unsafeAllowed = true | ||
45 | |||
46 | // A field identifies a field in a struct, accessible from a pointer. | ||
47 | // In this implementation, a field is identified by its byte offset from the start of the struct. | ||
48 | type field uintptr | ||
49 | |||
50 | // toField returns a field equivalent to the given reflect field. | ||
51 | func toField(f *reflect.StructField) field { | ||
52 | return field(f.Offset) | ||
53 | } | ||
54 | |||
55 | // invalidField is an invalid field identifier. | ||
56 | const invalidField = ^field(0) | ||
57 | |||
58 | // zeroField is a noop when calling pointer.offset. | ||
59 | const zeroField = field(0) | ||
60 | |||
61 | // IsValid reports whether the field identifier is valid. | ||
62 | func (f field) IsValid() bool { | ||
63 | return f != invalidField | ||
64 | } | ||
65 | |||
66 | // The pointer type below is for the new table-driven encoder/decoder. | ||
67 | // The implementation here uses unsafe.Pointer to create a generic pointer. | ||
68 | // In pointer_reflect.go we use reflect instead of unsafe to implement | ||
69 | // the same (but slower) interface. | ||
70 | type pointer struct { | ||
71 | p unsafe.Pointer | ||
72 | } | ||
73 | |||
74 | // size of pointer | ||
75 | var ptrSize = unsafe.Sizeof(uintptr(0)) | ||
76 | |||
77 | // toPointer converts an interface of pointer type to a pointer | ||
78 | // that points to the same target. | ||
79 | func toPointer(i *Message) pointer { | ||
80 | // Super-tricky - read pointer out of data word of interface value. | ||
81 | // Saves ~25ns over the equivalent: | ||
82 | // return valToPointer(reflect.ValueOf(*i)) | ||
83 | return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} | ||
84 | } | ||
85 | |||
86 | // toAddrPointer converts an interface to a pointer that points to | ||
87 | // the interface data. | ||
88 | func toAddrPointer(i *interface{}, isptr bool) pointer { | ||
89 | // Super-tricky - read or get the address of data word of interface value. | ||
90 | if isptr { | ||
91 | // The interface is of pointer type, thus it is a direct interface. | ||
92 | // The data word is the pointer data itself. We take its address. | ||
93 | return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} | ||
94 | } | ||
95 | // The interface is not of pointer type. The data word is the pointer | ||
96 | // to the data. | ||
97 | return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} | ||
98 | } | ||
99 | |||
100 | // valToPointer converts v to a pointer. v must be of pointer type. | ||
101 | func valToPointer(v reflect.Value) pointer { | ||
102 | return pointer{p: unsafe.Pointer(v.Pointer())} | ||
103 | } | ||
104 | |||
105 | // offset converts from a pointer to a structure to a pointer to | ||
106 | // one of its fields. | ||
107 | func (p pointer) offset(f field) pointer { | ||
108 | // For safety, we should panic if !f.IsValid, however calling panic causes | ||
109 | // this to no longer be inlineable, which is a serious performance cost. | ||
110 | /* | ||
111 | if !f.IsValid() { | ||
112 | panic("invalid field") | ||
113 | } | ||
114 | */ | ||
115 | return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} | ||
116 | } | ||
117 | |||
118 | func (p pointer) isNil() bool { | ||
119 | return p.p == nil | ||
120 | } | ||
121 | |||
122 | func (p pointer) toInt64() *int64 { | ||
123 | return (*int64)(p.p) | ||
124 | } | ||
125 | func (p pointer) toInt64Ptr() **int64 { | ||
126 | return (**int64)(p.p) | ||
127 | } | ||
128 | func (p pointer) toInt64Slice() *[]int64 { | ||
129 | return (*[]int64)(p.p) | ||
130 | } | ||
131 | func (p pointer) toInt32() *int32 { | ||
132 | return (*int32)(p.p) | ||
133 | } | ||
134 | |||
135 | // See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist. | ||
136 | /* | ||
137 | func (p pointer) toInt32Ptr() **int32 { | ||
138 | return (**int32)(p.p) | ||
139 | } | ||
140 | func (p pointer) toInt32Slice() *[]int32 { | ||
141 | return (*[]int32)(p.p) | ||
142 | } | ||
143 | */ | ||
144 | func (p pointer) getInt32Ptr() *int32 { | ||
145 | return *(**int32)(p.p) | ||
146 | } | ||
147 | func (p pointer) setInt32Ptr(v int32) { | ||
148 | *(**int32)(p.p) = &v | ||
149 | } | ||
150 | |||
151 | // getInt32Slice loads a []int32 from p. | ||
152 | // The value returned is aliased with the original slice. | ||
153 | // This behavior differs from the implementation in pointer_reflect.go. | ||
154 | func (p pointer) getInt32Slice() []int32 { | ||
155 | return *(*[]int32)(p.p) | ||
156 | } | ||
157 | |||
158 | // setInt32Slice stores a []int32 to p. | ||
159 | // The value set is aliased with the input slice. | ||
160 | // This behavior differs from the implementation in pointer_reflect.go. | ||
161 | func (p pointer) setInt32Slice(v []int32) { | ||
162 | *(*[]int32)(p.p) = v | ||
163 | } | ||
164 | |||
165 | // TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead? | ||
166 | func (p pointer) appendInt32Slice(v int32) { | ||
167 | s := (*[]int32)(p.p) | ||
168 | *s = append(*s, v) | ||
169 | } | ||
170 | |||
171 | func (p pointer) toUint64() *uint64 { | ||
172 | return (*uint64)(p.p) | ||
173 | } | ||
174 | func (p pointer) toUint64Ptr() **uint64 { | ||
175 | return (**uint64)(p.p) | ||
176 | } | ||
177 | func (p pointer) toUint64Slice() *[]uint64 { | ||
178 | return (*[]uint64)(p.p) | ||
179 | } | ||
180 | func (p pointer) toUint32() *uint32 { | ||
181 | return (*uint32)(p.p) | ||
182 | } | ||
183 | func (p pointer) toUint32Ptr() **uint32 { | ||
184 | return (**uint32)(p.p) | ||
185 | } | ||
186 | func (p pointer) toUint32Slice() *[]uint32 { | ||
187 | return (*[]uint32)(p.p) | ||
188 | } | ||
189 | func (p pointer) toBool() *bool { | ||
190 | return (*bool)(p.p) | ||
191 | } | ||
192 | func (p pointer) toBoolPtr() **bool { | ||
193 | return (**bool)(p.p) | ||
194 | } | ||
195 | func (p pointer) toBoolSlice() *[]bool { | ||
196 | return (*[]bool)(p.p) | ||
197 | } | ||
198 | func (p pointer) toFloat64() *float64 { | ||
199 | return (*float64)(p.p) | ||
200 | } | ||
201 | func (p pointer) toFloat64Ptr() **float64 { | ||
202 | return (**float64)(p.p) | ||
203 | } | ||
204 | func (p pointer) toFloat64Slice() *[]float64 { | ||
205 | return (*[]float64)(p.p) | ||
206 | } | ||
207 | func (p pointer) toFloat32() *float32 { | ||
208 | return (*float32)(p.p) | ||
209 | } | ||
210 | func (p pointer) toFloat32Ptr() **float32 { | ||
211 | return (**float32)(p.p) | ||
212 | } | ||
213 | func (p pointer) toFloat32Slice() *[]float32 { | ||
214 | return (*[]float32)(p.p) | ||
215 | } | ||
216 | func (p pointer) toString() *string { | ||
217 | return (*string)(p.p) | ||
218 | } | ||
219 | func (p pointer) toStringPtr() **string { | ||
220 | return (**string)(p.p) | ||
221 | } | ||
222 | func (p pointer) toStringSlice() *[]string { | ||
223 | return (*[]string)(p.p) | ||
224 | } | ||
225 | func (p pointer) toBytes() *[]byte { | ||
226 | return (*[]byte)(p.p) | ||
227 | } | ||
228 | func (p pointer) toBytesSlice() *[][]byte { | ||
229 | return (*[][]byte)(p.p) | ||
230 | } | ||
231 | func (p pointer) toExtensions() *XXX_InternalExtensions { | ||
232 | return (*XXX_InternalExtensions)(p.p) | ||
233 | } | ||
234 | func (p pointer) toOldExtensions() *map[int32]Extension { | ||
235 | return (*map[int32]Extension)(p.p) | ||
236 | } | ||
237 | |||
238 | // getPointerSlice loads []*T from p as a []pointer. | ||
239 | // The value returned is aliased with the original slice. | ||
240 | // This behavior differs from the implementation in pointer_reflect.go. | ||
241 | func (p pointer) getPointerSlice() []pointer { | ||
242 | // Super-tricky - p should point to a []*T where T is a | ||
243 | // message type. We load it as []pointer. | ||
244 | return *(*[]pointer)(p.p) | ||
245 | } | ||
246 | |||
247 | // setPointerSlice stores []pointer into p as a []*T. | ||
248 | // The value set is aliased with the input slice. | ||
249 | // This behavior differs from the implementation in pointer_reflect.go. | ||
250 | func (p pointer) setPointerSlice(v []pointer) { | ||
251 | // Super-tricky - p should point to a []*T where T is a | ||
252 | // message type. We store it as []pointer. | ||
253 | *(*[]pointer)(p.p) = v | ||
254 | } | ||
255 | |||
256 | // getPointer loads the pointer at p and returns it. | ||
257 | func (p pointer) getPointer() pointer { | ||
258 | return pointer{p: *(*unsafe.Pointer)(p.p)} | ||
259 | } | ||
260 | |||
261 | // setPointer stores the pointer q at p. | ||
262 | func (p pointer) setPointer(q pointer) { | ||
263 | *(*unsafe.Pointer)(p.p) = q.p | ||
264 | } | ||
265 | |||
266 | // append q to the slice pointed to by p. | ||
267 | func (p pointer) appendPointer(q pointer) { | ||
268 | s := (*[]unsafe.Pointer)(p.p) | ||
269 | *s = append(*s, q.p) | ||
270 | } | ||
271 | |||
272 | // getInterfacePointer returns a pointer that points to the | ||
273 | // interface data of the interface pointed by p. | ||
274 | func (p pointer) getInterfacePointer() pointer { | ||
275 | // Super-tricky - read pointer out of data word of interface value. | ||
276 | return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]} | ||
277 | } | ||
278 | |||
279 | // asPointerTo returns a reflect.Value that is a pointer to an | ||
280 | // object of type t stored at p. | ||
281 | func (p pointer) asPointerTo(t reflect.Type) reflect.Value { | ||
282 | return reflect.NewAt(t, p.p) | ||
283 | } | ||
284 | |||
285 | func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { | ||
286 | return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) | ||
287 | } | ||
288 | func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { | ||
289 | atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) | ||
290 | } | ||
291 | func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { | ||
292 | return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) | ||
293 | } | ||
294 | func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { | ||
295 | atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) | ||
296 | } | ||
297 | func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { | ||
298 | return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) | ||
299 | } | ||
300 | func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { | ||
301 | atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) | ||
302 | } | ||
303 | func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { | ||
304 | return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) | ||
305 | } | ||
306 | func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { | ||
307 | atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v)) | ||
308 | } | ||