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