blob: a6580cee33ba4025e2389dfc32e9ee2d1ed05974 [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 "unicode/utf8"
11
12 "google.golang.org/protobuf/internal/encoding/wire"
13 "google.golang.org/protobuf/internal/errors"
14 "google.golang.org/protobuf/proto"
15 pref "google.golang.org/protobuf/reflect/protoreflect"
16)
17
18type errInvalidUTF8 struct{}
19
20func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
21func (errInvalidUTF8) InvalidUTF8() bool { return true }
22
23func makeOneofFieldCoder(fs reflect.StructField, od pref.OneofDescriptor, structFields map[pref.FieldNumber]reflect.StructField, otypes map[pref.FieldNumber]reflect.Type) pointerCoderFuncs {
24 type oneofFieldInfo struct {
25 wiretag uint64
26 tagsize int
27 funcs pointerCoderFuncs
28 }
29
30 oneofFieldInfos := make(map[reflect.Type]oneofFieldInfo)
31 for i, fields := 0, od.Fields(); i < fields.Len(); i++ {
32 fd := fields.Get(i)
33 ot := otypes[fd.Number()]
34 wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
35 oneofFieldInfos[ot] = oneofFieldInfo{
36 wiretag: wiretag,
37 tagsize: wire.SizeVarint(wiretag),
38 funcs: fieldCoder(fd, ot.Field(0).Type),
39 }
40 }
41 ft := fs.Type
42 return pointerCoderFuncs{
43 size: func(p pointer, _ int, opts marshalOptions) int {
44 v := p.AsValueOf(ft).Elem()
45 if v.IsNil() {
46 return 0
47 }
48 v = v.Elem() // interface -> *struct
49 telem := v.Elem().Type()
50 info, ok := oneofFieldInfos[telem]
51 if !ok {
52 panic(fmt.Errorf("invalid oneof type %v", telem))
53 }
54 return info.funcs.size(pointerOfValue(v).Apply(zeroOffset), info.tagsize, opts)
55 },
56 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
57 v := p.AsValueOf(ft).Elem()
58 if v.IsNil() {
59 return b, nil
60 }
61 v = v.Elem() // interface -> *struct
62 telem := v.Elem().Type()
63 info, ok := oneofFieldInfos[telem]
64 if !ok {
65 panic(fmt.Errorf("invalid oneof type %v", telem))
66 }
67 return info.funcs.marshal(b, pointerOfValue(v).Apply(zeroOffset), info.wiretag, opts)
68 },
69 }
70}
71
72func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -040073 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -070074 return pointerCoderFuncs{
75 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai4fe96632019-05-22 05:12:36 -040076 return sizeMessageInfo(p, fi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070077 },
78 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai4fe96632019-05-22 05:12:36 -040079 return appendMessageInfo(b, p, wiretag, fi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070080 },
81 }
82 } else {
83 return pointerCoderFuncs{
84 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -070085 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -070086 return sizeMessage(m, tagsize, opts)
87 },
88 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -070089 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -070090 return appendMessage(b, m, wiretag, opts)
91 },
92 }
93 }
94}
95
Joe Tsai4fe96632019-05-22 05:12:36 -040096func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -070097 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
98}
99
Joe Tsai4fe96632019-05-22 05:12:36 -0400100func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700101 b = wire.AppendVarint(b, wiretag)
102 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
103 return mi.marshalAppendPointer(b, p.Elem(), opts)
104}
105
106func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
107 return wire.SizeBytes(proto.Size(m)) + tagsize
108}
109
110func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
111 b = wire.AppendVarint(b, wiretag)
112 b = wire.AppendVarint(b, uint64(proto.Size(m)))
113 return opts.Options().MarshalAppend(b, m)
114}
115
116func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
117 m := Export{}.MessageOf(ival).Interface()
118 return sizeMessage(m, tagsize, opts)
119}
120
121func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
122 m := Export{}.MessageOf(ival).Interface()
123 return appendMessage(b, m, wiretag, opts)
124}
125
126var coderMessageIface = ifaceCoderFuncs{
127 size: sizeMessageIface,
128 marshal: appendMessageIface,
129}
130
131func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -0400132 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700133 return pointerCoderFuncs{
134 size: func(p pointer, tagsize int, opts marshalOptions) int {
135 return sizeGroupType(p, fi, tagsize, opts)
136 },
137 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
138 return appendGroupType(b, p, wiretag, fi, opts)
139 },
140 }
141 } else {
142 return pointerCoderFuncs{
143 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700144 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700145 return sizeGroup(m, tagsize, opts)
146 },
147 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700148 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700149 return appendGroup(b, m, wiretag, opts)
150 },
151 }
152 }
153}
154
Joe Tsai4fe96632019-05-22 05:12:36 -0400155func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700156 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
157}
158
Joe Tsai4fe96632019-05-22 05:12:36 -0400159func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700160 b = wire.AppendVarint(b, wiretag) // start group
161 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
162 b = wire.AppendVarint(b, wiretag+1) // end group
163 return b, err
164}
165
166func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
167 return 2*tagsize + proto.Size(m)
168}
169
170func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
171 b = wire.AppendVarint(b, wiretag) // start group
172 b, err := opts.Options().MarshalAppend(b, m)
173 b = wire.AppendVarint(b, wiretag+1) // end group
174 return b, err
175}
176
177func sizeGroupIface(ival interface{}, tagsize int, opts marshalOptions) int {
178 m := Export{}.MessageOf(ival).Interface()
179 return sizeGroup(m, tagsize, opts)
180}
181
182func appendGroupIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
183 m := Export{}.MessageOf(ival).Interface()
184 return appendGroup(b, m, wiretag, opts)
185}
186
187var coderGroupIface = ifaceCoderFuncs{
188 size: sizeGroupIface,
189 marshal: appendGroupIface,
190}
191
192func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -0400193 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700194 return pointerCoderFuncs{
195 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
196 return appendMessageSliceInfo(b, p, wiretag, fi, opts)
197 },
198 size: func(p pointer, tagsize int, opts marshalOptions) int {
199 return sizeMessageSliceInfo(p, fi, tagsize, opts)
200 },
201 }
202 }
203 return pointerCoderFuncs{
204 size: func(p pointer, tagsize int, opts marshalOptions) int {
205 return sizeMessageSlice(p, ft, tagsize, opts)
206 },
207 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
208 return appendMessageSlice(b, p, wiretag, ft, opts)
209 },
210 }
211}
212
Joe Tsai4fe96632019-05-22 05:12:36 -0400213func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700214 s := p.PointerSlice()
215 n := 0
216 for _, v := range s {
217 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
218 }
219 return n
220}
221
Joe Tsai4fe96632019-05-22 05:12:36 -0400222func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700223 s := p.PointerSlice()
224 var nerr errors.NonFatal
225 var err error
226 for _, v := range s {
227 b = wire.AppendVarint(b, wiretag)
228 siz := mi.sizePointer(v, opts)
229 b = wire.AppendVarint(b, uint64(siz))
230 b, err = mi.marshalAppendPointer(b, v, opts)
231 if !nerr.Merge(err) {
232 return b, err
233 }
234 }
235 return b, nerr.E
236}
237
238func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
239 s := p.PointerSlice()
240 n := 0
241 for _, v := range s {
242 m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
243 n += wire.SizeBytes(proto.Size(m)) + tagsize
244 }
245 return n
246}
247
248func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
249 s := p.PointerSlice()
250 var nerr errors.NonFatal
251 var err error
252 for _, v := range s {
253 m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
254 b = wire.AppendVarint(b, wiretag)
255 siz := proto.Size(m)
256 b = wire.AppendVarint(b, uint64(siz))
257 b, err = opts.Options().MarshalAppend(b, m)
258 if !nerr.Merge(err) {
259 return b, err
260 }
261 }
262 return b, nerr.E
263}
264
265// Slices of messages
266
267func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
268 p := pointerOfIface(ival)
269 return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
270}
271
272func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
273 p := pointerOfIface(ival)
274 return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
275}
276
277var coderMessageSliceIface = ifaceCoderFuncs{
278 size: sizeMessageSliceIface,
279 marshal: appendMessageSliceIface,
280}
281
282func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -0400283 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700284 return pointerCoderFuncs{
285 size: func(p pointer, tagsize int, opts marshalOptions) int {
286 return sizeGroupSliceInfo(p, fi, tagsize, opts)
287 },
288 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
289 return appendGroupSliceInfo(b, p, wiretag, fi, opts)
290 },
291 }
292 }
293 return pointerCoderFuncs{
294 size: func(p pointer, tagsize int, opts marshalOptions) int {
295 return sizeGroupSlice(p, ft, tagsize, opts)
296 },
297 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
298 return appendGroupSlice(b, p, wiretag, ft, opts)
299 },
300 }
301}
302
303func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
304 s := p.PointerSlice()
305 n := 0
306 for _, v := range s {
307 m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
308 n += 2*tagsize + proto.Size(m)
309 }
310 return n
311}
312
313func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
314 s := p.PointerSlice()
315 var nerr errors.NonFatal
316 var err error
317 for _, v := range s {
318 m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
319 b = wire.AppendVarint(b, wiretag) // start group
320 b, err = opts.Options().MarshalAppend(b, m)
321 if !nerr.Merge(err) {
322 return b, err
323 }
324 b = wire.AppendVarint(b, wiretag+1) // end group
325 }
326 return b, nerr.E
327}
328
Joe Tsai4fe96632019-05-22 05:12:36 -0400329func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700330 s := p.PointerSlice()
331 n := 0
332 for _, v := range s {
333 n += 2*tagsize + mi.sizePointer(v, opts)
334 }
335 return n
336}
337
Joe Tsai4fe96632019-05-22 05:12:36 -0400338func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700339 s := p.PointerSlice()
340 var nerr errors.NonFatal
341 var err error
342 for _, v := range s {
343 b = wire.AppendVarint(b, wiretag) // start group
344 b, err = mi.marshalAppendPointer(b, v, opts)
345 if !nerr.Merge(err) {
346 return b, err
347 }
348 b = wire.AppendVarint(b, wiretag+1) // end group
349 }
350 return b, nerr.E
351}
352
353func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
354 p := pointerOfIface(ival)
355 return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
356}
357
358func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
359 p := pointerOfIface(ival)
360 return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
361}
362
363var coderGroupSliceIface = ifaceCoderFuncs{
364 size: sizeGroupSliceIface,
365 marshal: appendGroupSliceIface,
366}
367
368// Enums
369
370func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
371 v := reflect.ValueOf(ival).Int()
372 return wire.SizeVarint(uint64(v)) + tagsize
373}
374
375func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
376 v := reflect.ValueOf(ival).Int()
377 b = wire.AppendVarint(b, wiretag)
378 b = wire.AppendVarint(b, uint64(v))
379 return b, nil
380}
381
382var coderEnumIface = ifaceCoderFuncs{
383 size: sizeEnumIface,
384 marshal: appendEnumIface,
385}
386
387func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
388 return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
389}
390
391func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
392 for i, llen := 0, s.Len(); i < llen; i++ {
393 size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
394 }
395 return size
396}
397
398func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
399 return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
400}
401
402func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
403 for i, llen := 0, s.Len(); i < llen; i++ {
404 b = wire.AppendVarint(b, wiretag)
405 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
406 }
407 return b, nil
408}
409
410var coderEnumSliceIface = ifaceCoderFuncs{
411 size: sizeEnumSliceIface,
412 marshal: appendEnumSliceIface,
413}
414
415// Strings with UTF8 validation.
416
417func appendStringValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
418 v := *p.String()
419 b = wire.AppendVarint(b, wiretag)
420 b = wire.AppendBytes(b, []byte(v))
421 if !utf8.ValidString(v) {
422 return b, errInvalidUTF8{}
423 }
424 return b, nil
425}
426
427var coderStringValidateUTF8 = pointerCoderFuncs{
428 size: sizeString,
429 marshal: appendStringValidateUTF8,
430}
431
432func appendStringNoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
433 v := *p.String()
434 if len(v) == 0 {
435 return b, nil
436 }
437 b = wire.AppendVarint(b, wiretag)
438 b = wire.AppendBytes(b, []byte(v))
439 if !utf8.ValidString(v) {
440 return b, errInvalidUTF8{}
441 }
442 return b, nil
443}
444
445var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{
446 size: sizeStringNoZero,
447 marshal: appendStringNoZeroValidateUTF8,
448}
449
450func sizeStringSliceValidateUTF8(p pointer, tagsize int, _ marshalOptions) (size int) {
451 s := *p.StringSlice()
452 for _, v := range s {
453 size += tagsize + wire.SizeBytes(len([]byte(v)))
454 }
455 return size
456}
457
458func appendStringSliceValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
459 s := *p.StringSlice()
460 var err error
461 for _, v := range s {
462 b = wire.AppendVarint(b, wiretag)
463 b = wire.AppendBytes(b, []byte(v))
464 if !utf8.ValidString(v) {
465 err = errInvalidUTF8{}
466 }
467 }
468 return b, err
469}
470
471var coderStringSliceValidateUTF8 = pointerCoderFuncs{
472 size: sizeStringSliceValidateUTF8,
473 marshal: appendStringSliceValidateUTF8,
474}
475
476func sizeStringIfaceValidateUTF8(ival interface{}, tagsize int, _ marshalOptions) int {
477 v := ival.(string)
478 return tagsize + wire.SizeBytes(len([]byte(v)))
479}
480
481func appendStringIfaceValidateUTF8(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
482 v := ival.(string)
483 b = wire.AppendVarint(b, wiretag)
484 b = wire.AppendBytes(b, []byte(v))
485 if !utf8.ValidString(v) {
486 return b, errInvalidUTF8{}
487 }
488 return b, nil
489}
490
491var coderStringIfaceValidateUTF8 = ifaceCoderFuncs{
492 size: sizeStringIfaceValidateUTF8,
493 marshal: appendStringIfaceValidateUTF8,
494}
Damien Neil5b6d0472019-06-14 11:54:07 -0700495
496func asMessage(v reflect.Value) pref.ProtoMessage {
497 if m, ok := v.Interface().(pref.ProtoMessage); ok {
498 return m
499 }
500 return legacyWrapMessage(v)
501}