|
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 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 "reflect" |
|
42 "sync" |
|
43 ) |
|
44 |
|
45 const unsafeAllowed = false |
|
46 |
|
47 // A field identifies a field in a struct, accessible from a pointer. |
|
48 // In this implementation, a field is identified by the sequence of field indices |
|
49 // passed to reflect's FieldByIndex. |
|
50 type field []int |
|
51 |
|
52 // toField returns a field equivalent to the given reflect field. |
|
53 func toField(f *reflect.StructField) field { |
|
54 return f.Index |
|
55 } |
|
56 |
|
57 // invalidField is an invalid field identifier. |
|
58 var invalidField = field(nil) |
|
59 |
|
60 // zeroField is a noop when calling pointer.offset. |
|
61 var zeroField = field([]int{}) |
|
62 |
|
63 // IsValid reports whether the field identifier is valid. |
|
64 func (f field) IsValid() bool { return f != nil } |
|
65 |
|
66 // The pointer type is for the table-driven decoder. |
|
67 // The implementation here uses a reflect.Value of pointer type to |
|
68 // create a generic pointer. In pointer_unsafe.go we use unsafe |
|
69 // instead of reflect to implement the same (but faster) interface. |
|
70 type pointer struct { |
|
71 v reflect.Value |
|
72 } |
|
73 |
|
74 // toPointer converts an interface of pointer type to a pointer |
|
75 // that points to the same target. |
|
76 func toPointer(i *Message) pointer { |
|
77 return pointer{v: reflect.ValueOf(*i)} |
|
78 } |
|
79 |
|
80 // toAddrPointer converts an interface to a pointer that points to |
|
81 // the interface data. |
|
82 func toAddrPointer(i *interface{}, isptr bool) pointer { |
|
83 v := reflect.ValueOf(*i) |
|
84 u := reflect.New(v.Type()) |
|
85 u.Elem().Set(v) |
|
86 return pointer{v: u} |
|
87 } |
|
88 |
|
89 // valToPointer converts v to a pointer. v must be of pointer type. |
|
90 func valToPointer(v reflect.Value) pointer { |
|
91 return pointer{v: v} |
|
92 } |
|
93 |
|
94 // offset converts from a pointer to a structure to a pointer to |
|
95 // one of its fields. |
|
96 func (p pointer) offset(f field) pointer { |
|
97 return pointer{v: p.v.Elem().FieldByIndex(f).Addr()} |
|
98 } |
|
99 |
|
100 func (p pointer) isNil() bool { |
|
101 return p.v.IsNil() |
|
102 } |
|
103 |
|
104 // grow updates the slice s in place to make it one element longer. |
|
105 // s must be addressable. |
|
106 // Returns the (addressable) new element. |
|
107 func grow(s reflect.Value) reflect.Value { |
|
108 n, m := s.Len(), s.Cap() |
|
109 if n < m { |
|
110 s.SetLen(n + 1) |
|
111 } else { |
|
112 s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem()))) |
|
113 } |
|
114 return s.Index(n) |
|
115 } |
|
116 |
|
117 func (p pointer) toInt64() *int64 { |
|
118 return p.v.Interface().(*int64) |
|
119 } |
|
120 func (p pointer) toInt64Ptr() **int64 { |
|
121 return p.v.Interface().(**int64) |
|
122 } |
|
123 func (p pointer) toInt64Slice() *[]int64 { |
|
124 return p.v.Interface().(*[]int64) |
|
125 } |
|
126 |
|
127 var int32ptr = reflect.TypeOf((*int32)(nil)) |
|
128 |
|
129 func (p pointer) toInt32() *int32 { |
|
130 return p.v.Convert(int32ptr).Interface().(*int32) |
|
131 } |
|
132 |
|
133 // The toInt32Ptr/Slice methods don't work because of enums. |
|
134 // Instead, we must use set/get methods for the int32ptr/slice case. |
|
135 /* |
|
136 func (p pointer) toInt32Ptr() **int32 { |
|
137 return p.v.Interface().(**int32) |
|
138 } |
|
139 func (p pointer) toInt32Slice() *[]int32 { |
|
140 return p.v.Interface().(*[]int32) |
|
141 } |
|
142 */ |
|
143 func (p pointer) getInt32Ptr() *int32 { |
|
144 if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { |
|
145 // raw int32 type |
|
146 return p.v.Elem().Interface().(*int32) |
|
147 } |
|
148 // an enum |
|
149 return p.v.Elem().Convert(int32PtrType).Interface().(*int32) |
|
150 } |
|
151 func (p pointer) setInt32Ptr(v int32) { |
|
152 // Allocate value in a *int32. Possibly convert that to a *enum. |
|
153 // Then assign it to a **int32 or **enum. |
|
154 // Note: we can convert *int32 to *enum, but we can't convert |
|
155 // **int32 to **enum! |
|
156 p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem())) |
|
157 } |
|
158 |
|
159 // getInt32Slice copies []int32 from p as a new slice. |
|
160 // This behavior differs from the implementation in pointer_unsafe.go. |
|
161 func (p pointer) getInt32Slice() []int32 { |
|
162 if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { |
|
163 // raw int32 type |
|
164 return p.v.Elem().Interface().([]int32) |
|
165 } |
|
166 // an enum |
|
167 // Allocate a []int32, then assign []enum's values into it. |
|
168 // Note: we can't convert []enum to []int32. |
|
169 slice := p.v.Elem() |
|
170 s := make([]int32, slice.Len()) |
|
171 for i := 0; i < slice.Len(); i++ { |
|
172 s[i] = int32(slice.Index(i).Int()) |
|
173 } |
|
174 return s |
|
175 } |
|
176 |
|
177 // setInt32Slice copies []int32 into p as a new slice. |
|
178 // This behavior differs from the implementation in pointer_unsafe.go. |
|
179 func (p pointer) setInt32Slice(v []int32) { |
|
180 if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) { |
|
181 // raw int32 type |
|
182 p.v.Elem().Set(reflect.ValueOf(v)) |
|
183 return |
|
184 } |
|
185 // an enum |
|
186 // Allocate a []enum, then assign []int32's values into it. |
|
187 // Note: we can't convert []enum to []int32. |
|
188 slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v)) |
|
189 for i, x := range v { |
|
190 slice.Index(i).SetInt(int64(x)) |
|
191 } |
|
192 p.v.Elem().Set(slice) |
|
193 } |
|
194 func (p pointer) appendInt32Slice(v int32) { |
|
195 grow(p.v.Elem()).SetInt(int64(v)) |
|
196 } |
|
197 |
|
198 func (p pointer) toUint64() *uint64 { |
|
199 return p.v.Interface().(*uint64) |
|
200 } |
|
201 func (p pointer) toUint64Ptr() **uint64 { |
|
202 return p.v.Interface().(**uint64) |
|
203 } |
|
204 func (p pointer) toUint64Slice() *[]uint64 { |
|
205 return p.v.Interface().(*[]uint64) |
|
206 } |
|
207 func (p pointer) toUint32() *uint32 { |
|
208 return p.v.Interface().(*uint32) |
|
209 } |
|
210 func (p pointer) toUint32Ptr() **uint32 { |
|
211 return p.v.Interface().(**uint32) |
|
212 } |
|
213 func (p pointer) toUint32Slice() *[]uint32 { |
|
214 return p.v.Interface().(*[]uint32) |
|
215 } |
|
216 func (p pointer) toBool() *bool { |
|
217 return p.v.Interface().(*bool) |
|
218 } |
|
219 func (p pointer) toBoolPtr() **bool { |
|
220 return p.v.Interface().(**bool) |
|
221 } |
|
222 func (p pointer) toBoolSlice() *[]bool { |
|
223 return p.v.Interface().(*[]bool) |
|
224 } |
|
225 func (p pointer) toFloat64() *float64 { |
|
226 return p.v.Interface().(*float64) |
|
227 } |
|
228 func (p pointer) toFloat64Ptr() **float64 { |
|
229 return p.v.Interface().(**float64) |
|
230 } |
|
231 func (p pointer) toFloat64Slice() *[]float64 { |
|
232 return p.v.Interface().(*[]float64) |
|
233 } |
|
234 func (p pointer) toFloat32() *float32 { |
|
235 return p.v.Interface().(*float32) |
|
236 } |
|
237 func (p pointer) toFloat32Ptr() **float32 { |
|
238 return p.v.Interface().(**float32) |
|
239 } |
|
240 func (p pointer) toFloat32Slice() *[]float32 { |
|
241 return p.v.Interface().(*[]float32) |
|
242 } |
|
243 func (p pointer) toString() *string { |
|
244 return p.v.Interface().(*string) |
|
245 } |
|
246 func (p pointer) toStringPtr() **string { |
|
247 return p.v.Interface().(**string) |
|
248 } |
|
249 func (p pointer) toStringSlice() *[]string { |
|
250 return p.v.Interface().(*[]string) |
|
251 } |
|
252 func (p pointer) toBytes() *[]byte { |
|
253 return p.v.Interface().(*[]byte) |
|
254 } |
|
255 func (p pointer) toBytesSlice() *[][]byte { |
|
256 return p.v.Interface().(*[][]byte) |
|
257 } |
|
258 func (p pointer) toExtensions() *XXX_InternalExtensions { |
|
259 return p.v.Interface().(*XXX_InternalExtensions) |
|
260 } |
|
261 func (p pointer) toOldExtensions() *map[int32]Extension { |
|
262 return p.v.Interface().(*map[int32]Extension) |
|
263 } |
|
264 func (p pointer) getPointer() pointer { |
|
265 return pointer{v: p.v.Elem()} |
|
266 } |
|
267 func (p pointer) setPointer(q pointer) { |
|
268 p.v.Elem().Set(q.v) |
|
269 } |
|
270 func (p pointer) appendPointer(q pointer) { |
|
271 grow(p.v.Elem()).Set(q.v) |
|
272 } |
|
273 |
|
274 // getPointerSlice copies []*T from p as a new []pointer. |
|
275 // This behavior differs from the implementation in pointer_unsafe.go. |
|
276 func (p pointer) getPointerSlice() []pointer { |
|
277 if p.v.IsNil() { |
|
278 return nil |
|
279 } |
|
280 n := p.v.Elem().Len() |
|
281 s := make([]pointer, n) |
|
282 for i := 0; i < n; i++ { |
|
283 s[i] = pointer{v: p.v.Elem().Index(i)} |
|
284 } |
|
285 return s |
|
286 } |
|
287 |
|
288 // setPointerSlice copies []pointer into p as a new []*T. |
|
289 // This behavior differs from the implementation in pointer_unsafe.go. |
|
290 func (p pointer) setPointerSlice(v []pointer) { |
|
291 if v == nil { |
|
292 p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem()) |
|
293 return |
|
294 } |
|
295 s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v)) |
|
296 for _, p := range v { |
|
297 s = reflect.Append(s, p.v) |
|
298 } |
|
299 p.v.Elem().Set(s) |
|
300 } |
|
301 |
|
302 // getInterfacePointer returns a pointer that points to the |
|
303 // interface data of the interface pointed by p. |
|
304 func (p pointer) getInterfacePointer() pointer { |
|
305 if p.v.Elem().IsNil() { |
|
306 return pointer{v: p.v.Elem()} |
|
307 } |
|
308 return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct |
|
309 } |
|
310 |
|
311 func (p pointer) asPointerTo(t reflect.Type) reflect.Value { |
|
312 // TODO: check that p.v.Type().Elem() == t? |
|
313 return p.v |
|
314 } |
|
315 |
|
316 func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo { |
|
317 atomicLock.Lock() |
|
318 defer atomicLock.Unlock() |
|
319 return *p |
|
320 } |
|
321 func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) { |
|
322 atomicLock.Lock() |
|
323 defer atomicLock.Unlock() |
|
324 *p = v |
|
325 } |
|
326 func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo { |
|
327 atomicLock.Lock() |
|
328 defer atomicLock.Unlock() |
|
329 return *p |
|
330 } |
|
331 func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) { |
|
332 atomicLock.Lock() |
|
333 defer atomicLock.Unlock() |
|
334 *p = v |
|
335 } |
|
336 func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo { |
|
337 atomicLock.Lock() |
|
338 defer atomicLock.Unlock() |
|
339 return *p |
|
340 } |
|
341 func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) { |
|
342 atomicLock.Lock() |
|
343 defer atomicLock.Unlock() |
|
344 *p = v |
|
345 } |
|
346 func atomicLoadDiscardInfo(p **discardInfo) *discardInfo { |
|
347 atomicLock.Lock() |
|
348 defer atomicLock.Unlock() |
|
349 return *p |
|
350 } |
|
351 func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) { |
|
352 atomicLock.Lock() |
|
353 defer atomicLock.Unlock() |
|
354 *p = v |
|
355 } |
|
356 |
|
357 var atomicLock sync.Mutex |