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