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