blob: 38bd392ff947084dd829cde3ab5c0d5ca545f86c [file] [log] [blame]
Damien Neilc37adef2019-04-01 13:49:56 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
8 "fmt"
9 "reflect"
10
11 pref "google.golang.org/protobuf/reflect/protoreflect"
12)
13
14// pointerCoderFuncs is a set of pointer encoding functions.
15type pointerCoderFuncs struct {
16 size func(p pointer, tagsize int, opts marshalOptions) int
17 marshal func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
18}
19
20// ifaceCoderFuncs is a set of interface{} encoding functions.
21type ifaceCoderFuncs struct {
22 size func(ival interface{}, tagsize int, opts marshalOptions) int
23 marshal func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
24}
25
26// fieldCoder returns pointer functions for a field, used for operating on
27// struct fields.
28func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
29 switch {
30 case fd.Cardinality() == pref.Repeated && !fd.IsPacked():
31 // Repeated fields (not packed).
32 if ft.Kind() != reflect.Slice {
33 break
34 }
35 ft := ft.Elem()
36 switch fd.Kind() {
37 case pref.BoolKind:
38 if ft.Kind() == reflect.Bool {
39 return coderBoolSlice
40 }
41 case pref.EnumKind:
42 if ft.Kind() == reflect.Int32 {
43 return coderEnumSlice
44 }
45 case pref.Int32Kind:
46 if ft.Kind() == reflect.Int32 {
47 return coderInt32Slice
48 }
49 case pref.Sint32Kind:
50 if ft.Kind() == reflect.Int32 {
51 return coderSint32Slice
52 }
53 case pref.Uint32Kind:
54 if ft.Kind() == reflect.Uint32 {
55 return coderUint32Slice
56 }
57 case pref.Int64Kind:
58 if ft.Kind() == reflect.Int64 {
59 return coderInt64Slice
60 }
61 case pref.Sint64Kind:
62 if ft.Kind() == reflect.Int64 {
63 return coderSint64Slice
64 }
65 case pref.Uint64Kind:
66 if ft.Kind() == reflect.Uint64 {
67 return coderUint64Slice
68 }
69 case pref.Sfixed32Kind:
70 if ft.Kind() == reflect.Int32 {
71 return coderSfixed32Slice
72 }
73 case pref.Fixed32Kind:
74 if ft.Kind() == reflect.Uint32 {
75 return coderFixed32Slice
76 }
77 case pref.FloatKind:
78 if ft.Kind() == reflect.Float32 {
79 return coderFloatSlice
80 }
81 case pref.Sfixed64Kind:
82 if ft.Kind() == reflect.Int64 {
83 return coderSfixed64Slice
84 }
85 case pref.Fixed64Kind:
86 if ft.Kind() == reflect.Uint64 {
87 return coderFixed64Slice
88 }
89 case pref.DoubleKind:
90 if ft.Kind() == reflect.Float64 {
91 return coderDoubleSlice
92 }
93 case pref.StringKind:
94 if ft.Kind() == reflect.String && fd.Syntax() == pref.Proto3 {
95 return coderStringSliceValidateUTF8
96 }
97 if ft.Kind() == reflect.String {
98 return coderStringSlice
99 }
100 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
101 return coderBytesSlice
102 }
103 case pref.BytesKind:
104 if ft.Kind() == reflect.String {
105 return coderStringSlice
106 }
107 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
108 return coderBytesSlice
109 }
110 case pref.MessageKind:
111 return makeMessageSliceFieldCoder(fd, ft)
112 case pref.GroupKind:
113 return makeGroupSliceFieldCoder(fd, ft)
114 }
115 case fd.Cardinality() == pref.Repeated && fd.IsPacked():
116 // Packed repeated fields.
117 //
118 // Only repeated fields of primitive numeric types
119 // (Varint, Fixed32, or Fixed64 wire type) can be packed.
120 if ft.Kind() != reflect.Slice {
121 break
122 }
123 ft := ft.Elem()
124 switch fd.Kind() {
125 case pref.BoolKind:
126 if ft.Kind() == reflect.Bool {
127 return coderBoolPackedSlice
128 }
129 case pref.EnumKind:
130 if ft.Kind() == reflect.Int32 {
131 return coderEnumPackedSlice
132 }
133 case pref.Int32Kind:
134 if ft.Kind() == reflect.Int32 {
135 return coderInt32PackedSlice
136 }
137 case pref.Sint32Kind:
138 if ft.Kind() == reflect.Int32 {
139 return coderSint32PackedSlice
140 }
141 case pref.Uint32Kind:
142 if ft.Kind() == reflect.Uint32 {
143 return coderUint32PackedSlice
144 }
145 case pref.Int64Kind:
146 if ft.Kind() == reflect.Int64 {
147 return coderInt64PackedSlice
148 }
149 case pref.Sint64Kind:
150 if ft.Kind() == reflect.Int64 {
151 return coderSint64PackedSlice
152 }
153 case pref.Uint64Kind:
154 if ft.Kind() == reflect.Uint64 {
155 return coderUint64PackedSlice
156 }
157 case pref.Sfixed32Kind:
158 if ft.Kind() == reflect.Int32 {
159 return coderSfixed32PackedSlice
160 }
161 case pref.Fixed32Kind:
162 if ft.Kind() == reflect.Uint32 {
163 return coderFixed32PackedSlice
164 }
165 case pref.FloatKind:
166 if ft.Kind() == reflect.Float32 {
167 return coderFloatPackedSlice
168 }
169 case pref.Sfixed64Kind:
170 if ft.Kind() == reflect.Int64 {
171 return coderSfixed64PackedSlice
172 }
173 case pref.Fixed64Kind:
174 if ft.Kind() == reflect.Uint64 {
175 return coderFixed64PackedSlice
176 }
177 case pref.DoubleKind:
178 if ft.Kind() == reflect.Float64 {
179 return coderDoublePackedSlice
180 }
181 }
182 case fd.Kind() == pref.MessageKind:
183 return makeMessageFieldCoder(fd, ft)
184 case fd.Kind() == pref.GroupKind:
185 return makeGroupFieldCoder(fd, ft)
186 case fd.Syntax() == pref.Proto3 && fd.ContainingOneof() == nil:
187 // Populated oneof fields always encode even if set to the zero value,
188 // which normally are not encoded in proto3.
189 switch fd.Kind() {
190 case pref.BoolKind:
191 if ft.Kind() == reflect.Bool {
192 return coderBoolNoZero
193 }
194 case pref.EnumKind:
195 if ft.Kind() == reflect.Int32 {
196 return coderEnumNoZero
197 }
198 case pref.Int32Kind:
199 if ft.Kind() == reflect.Int32 {
200 return coderInt32NoZero
201 }
202 case pref.Sint32Kind:
203 if ft.Kind() == reflect.Int32 {
204 return coderSint32NoZero
205 }
206 case pref.Uint32Kind:
207 if ft.Kind() == reflect.Uint32 {
208 return coderUint32NoZero
209 }
210 case pref.Int64Kind:
211 if ft.Kind() == reflect.Int64 {
212 return coderInt64NoZero
213 }
214 case pref.Sint64Kind:
215 if ft.Kind() == reflect.Int64 {
216 return coderSint64NoZero
217 }
218 case pref.Uint64Kind:
219 if ft.Kind() == reflect.Uint64 {
220 return coderUint64NoZero
221 }
222 case pref.Sfixed32Kind:
223 if ft.Kind() == reflect.Int32 {
224 return coderSfixed32NoZero
225 }
226 case pref.Fixed32Kind:
227 if ft.Kind() == reflect.Uint32 {
228 return coderFixed32NoZero
229 }
230 case pref.FloatKind:
231 if ft.Kind() == reflect.Float32 {
232 return coderFloatNoZero
233 }
234 case pref.Sfixed64Kind:
235 if ft.Kind() == reflect.Int64 {
236 return coderSfixed64NoZero
237 }
238 case pref.Fixed64Kind:
239 if ft.Kind() == reflect.Uint64 {
240 return coderFixed64NoZero
241 }
242 case pref.DoubleKind:
243 if ft.Kind() == reflect.Float64 {
244 return coderDoubleNoZero
245 }
246 case pref.StringKind:
247 if ft.Kind() == reflect.String {
248 return coderStringNoZeroValidateUTF8
249 }
250 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
251 return coderBytesNoZero
252 }
253 case pref.BytesKind:
254 if ft.Kind() == reflect.String {
255 return coderStringNoZero
256 }
257 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
258 return coderBytesNoZero
259 }
260 }
261 case ft.Kind() == reflect.Ptr:
262 ft := ft.Elem()
263 switch fd.Kind() {
264 case pref.BoolKind:
265 if ft.Kind() == reflect.Bool {
266 return coderBoolPtr
267 }
268 case pref.EnumKind:
269 if ft.Kind() == reflect.Int32 {
270 return coderEnumPtr
271 }
272 case pref.Int32Kind:
273 if ft.Kind() == reflect.Int32 {
274 return coderInt32Ptr
275 }
276 case pref.Sint32Kind:
277 if ft.Kind() == reflect.Int32 {
278 return coderSint32Ptr
279 }
280 case pref.Uint32Kind:
281 if ft.Kind() == reflect.Uint32 {
282 return coderUint32Ptr
283 }
284 case pref.Int64Kind:
285 if ft.Kind() == reflect.Int64 {
286 return coderInt64Ptr
287 }
288 case pref.Sint64Kind:
289 if ft.Kind() == reflect.Int64 {
290 return coderSint64Ptr
291 }
292 case pref.Uint64Kind:
293 if ft.Kind() == reflect.Uint64 {
294 return coderUint64Ptr
295 }
296 case pref.Sfixed32Kind:
297 if ft.Kind() == reflect.Int32 {
298 return coderSfixed32Ptr
299 }
300 case pref.Fixed32Kind:
301 if ft.Kind() == reflect.Uint32 {
302 return coderFixed32Ptr
303 }
304 case pref.FloatKind:
305 if ft.Kind() == reflect.Float32 {
306 return coderFloatPtr
307 }
308 case pref.Sfixed64Kind:
309 if ft.Kind() == reflect.Int64 {
310 return coderSfixed64Ptr
311 }
312 case pref.Fixed64Kind:
313 if ft.Kind() == reflect.Uint64 {
314 return coderFixed64Ptr
315 }
316 case pref.DoubleKind:
317 if ft.Kind() == reflect.Float64 {
318 return coderDoublePtr
319 }
320 case pref.StringKind:
321 if ft.Kind() == reflect.String {
322 return coderStringPtr
323 }
324 case pref.BytesKind:
325 if ft.Kind() == reflect.String {
326 return coderStringPtr
327 }
328 }
329 default:
330 switch fd.Kind() {
331 case pref.BoolKind:
332 if ft.Kind() == reflect.Bool {
333 return coderBool
334 }
335 case pref.EnumKind:
336 if ft.Kind() == reflect.Int32 {
337 return coderEnum
338 }
339 case pref.Int32Kind:
340 if ft.Kind() == reflect.Int32 {
341 return coderInt32
342 }
343 case pref.Sint32Kind:
344 if ft.Kind() == reflect.Int32 {
345 return coderSint32
346 }
347 case pref.Uint32Kind:
348 if ft.Kind() == reflect.Uint32 {
349 return coderUint32
350 }
351 case pref.Int64Kind:
352 if ft.Kind() == reflect.Int64 {
353 return coderInt64
354 }
355 case pref.Sint64Kind:
356 if ft.Kind() == reflect.Int64 {
357 return coderSint64
358 }
359 case pref.Uint64Kind:
360 if ft.Kind() == reflect.Uint64 {
361 return coderUint64
362 }
363 case pref.Sfixed32Kind:
364 if ft.Kind() == reflect.Int32 {
365 return coderSfixed32
366 }
367 case pref.Fixed32Kind:
368 if ft.Kind() == reflect.Uint32 {
369 return coderFixed32
370 }
371 case pref.FloatKind:
372 if ft.Kind() == reflect.Float32 {
373 return coderFloat
374 }
375 case pref.Sfixed64Kind:
376 if ft.Kind() == reflect.Int64 {
377 return coderSfixed64
378 }
379 case pref.Fixed64Kind:
380 if ft.Kind() == reflect.Uint64 {
381 return coderFixed64
382 }
383 case pref.DoubleKind:
384 if ft.Kind() == reflect.Float64 {
385 return coderDouble
386 }
387 case pref.StringKind:
388 if fd.Syntax() == pref.Proto3 && ft.Kind() == reflect.String {
389 return coderStringValidateUTF8
390 }
391 if ft.Kind() == reflect.String {
392 return coderString
393 }
394 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
395 return coderBytes
396 }
397 case pref.BytesKind:
398 if ft.Kind() == reflect.String {
399 return coderString
400 }
401 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
402 return coderBytes
403 }
404 }
405 }
406 panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))
407}
408
409// encoderFuncsForValue returns interface{} value functions for a field, used for
410// extension values and map encoding.
411func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
412 switch {
413 case fd.Cardinality() == pref.Repeated && !fd.IsPacked():
414 if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
415 break
416 }
417 ft := ft.Elem().Elem()
418 switch fd.Kind() {
419 case pref.BoolKind:
420 if ft.Kind() == reflect.Bool {
421 return coderBoolSliceIface
422 }
423 case pref.EnumKind:
424 if ft.Kind() == reflect.Int32 {
425 return coderEnumSliceIface
426 }
427 case pref.Int32Kind:
428 if ft.Kind() == reflect.Int32 {
429 return coderInt32SliceIface
430 }
431 case pref.Sint32Kind:
432 if ft.Kind() == reflect.Int32 {
433 return coderSint32SliceIface
434 }
435 case pref.Uint32Kind:
436 if ft.Kind() == reflect.Uint32 {
437 return coderUint32SliceIface
438 }
439 case pref.Int64Kind:
440 if ft.Kind() == reflect.Int64 {
441 return coderInt64SliceIface
442 }
443 case pref.Sint64Kind:
444 if ft.Kind() == reflect.Int64 {
445 return coderSint64SliceIface
446 }
447 case pref.Uint64Kind:
448 if ft.Kind() == reflect.Uint64 {
449 return coderUint64SliceIface
450 }
451 case pref.Sfixed32Kind:
452 if ft.Kind() == reflect.Int32 {
453 return coderSfixed32SliceIface
454 }
455 case pref.Fixed32Kind:
456 if ft.Kind() == reflect.Uint32 {
457 return coderFixed32SliceIface
458 }
459 case pref.FloatKind:
460 if ft.Kind() == reflect.Float32 {
461 return coderFloatSliceIface
462 }
463 case pref.Sfixed64Kind:
464 if ft.Kind() == reflect.Int64 {
465 return coderSfixed64SliceIface
466 }
467 case pref.Fixed64Kind:
468 if ft.Kind() == reflect.Uint64 {
469 return coderFixed64SliceIface
470 }
471 case pref.DoubleKind:
472 if ft.Kind() == reflect.Float64 {
473 return coderDoubleSliceIface
474 }
475 case pref.StringKind:
476 if ft.Kind() == reflect.String {
477 return coderStringSliceIface
478 }
479 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
480 return coderBytesSliceIface
481 }
482 case pref.BytesKind:
483 if ft.Kind() == reflect.String {
484 return coderStringSliceIface
485 }
486 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
487 return coderBytesSliceIface
488 }
489 case pref.MessageKind:
490 return coderMessageSliceIface
491 case pref.GroupKind:
492 return coderGroupSliceIface
493 }
494 case fd.Cardinality() == pref.Repeated && fd.IsPacked():
495 default:
496 switch fd.Kind() {
497 case pref.BoolKind:
498 if ft.Kind() == reflect.Bool {
499 return coderBoolIface
500 }
501 case pref.EnumKind:
502 if ft.Kind() == reflect.Int32 {
503 return coderEnumIface
504 }
505 case pref.Int32Kind:
506 if ft.Kind() == reflect.Int32 {
507 return coderInt32Iface
508 }
509 case pref.Sint32Kind:
510 if ft.Kind() == reflect.Int32 {
511 return coderSint32Iface
512 }
513 case pref.Uint32Kind:
514 if ft.Kind() == reflect.Uint32 {
515 return coderUint32Iface
516 }
517 case pref.Int64Kind:
518 if ft.Kind() == reflect.Int64 {
519 return coderInt64Iface
520 }
521 case pref.Sint64Kind:
522 if ft.Kind() == reflect.Int64 {
523 return coderSint64Iface
524 }
525 case pref.Uint64Kind:
526 if ft.Kind() == reflect.Uint64 {
527 return coderUint64Iface
528 }
529 case pref.Sfixed32Kind:
530 if ft.Kind() == reflect.Int32 {
531 return coderSfixed32Iface
532 }
533 case pref.Fixed32Kind:
534 if ft.Kind() == reflect.Uint32 {
535 return coderFixed32Iface
536 }
537 case pref.FloatKind:
538 if ft.Kind() == reflect.Float32 {
539 return coderFloatIface
540 }
541 case pref.Sfixed64Kind:
542 if ft.Kind() == reflect.Int64 {
543 return coderSfixed64Iface
544 }
545 case pref.Fixed64Kind:
546 if ft.Kind() == reflect.Uint64 {
547 return coderFixed64Iface
548 }
549 case pref.DoubleKind:
550 if ft.Kind() == reflect.Float64 {
551 return coderDoubleIface
552 }
553 case pref.StringKind:
554 if fd.Syntax() == pref.Proto3 && ft.Kind() == reflect.String {
555 return coderStringIfaceValidateUTF8
556 }
557 if ft.Kind() == reflect.String {
558 return coderStringIface
559 }
560 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
561 return coderBytesIface
562 }
563 case pref.BytesKind:
564 if ft.Kind() == reflect.String {
565 return coderStringIface
566 }
567 if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
568 return coderBytesIface
569 }
570 case pref.MessageKind:
571 return coderMessageIface
572 case pref.GroupKind:
573 return coderGroupIface
574 }
575 }
576 panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))
577}