1// 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 "reflect"
9
10 "google.golang.org/protobuf/encoding/protowire"
11 "google.golang.org/protobuf/internal/errors"
12 "google.golang.org/protobuf/proto"
13 "google.golang.org/protobuf/reflect/protoreflect"
14 "google.golang.org/protobuf/runtime/protoiface"
15)
16
17type errInvalidUTF8 struct{}
18
19func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
20func (errInvalidUTF8) InvalidUTF8() bool { return true }
21func (errInvalidUTF8) Unwrap() error { return errors.Error }
22
23// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof.
24//
25// For size, marshal, and isInit operations, functions are set only on the first field
26// in the oneof. The functions are called when the oneof is non-nil, and will dispatch
27// to the appropriate field-specific function as necessary.
28//
29// The unmarshal function is set on each field individually as usual.
30func (mi *MessageInfo) initOneofFieldCoders(od protoreflect.OneofDescriptor, si structInfo) {
31 fs := si.oneofsByName[od.Name()]
32 ft := fs.Type
33 oneofFields := make(map[reflect.Type]*coderFieldInfo)
34 needIsInit := false
35 fields := od.Fields()
36 for i, lim := 0, fields.Len(); i < lim; i++ {
37 fd := od.Fields().Get(i)
38 num := fd.Number()
39 // Make a copy of the original coderFieldInfo for use in unmarshaling.
40 //
41 // oneofFields[oneofType].funcs.marshal is the field-specific marshal function.
42 //
43 // mi.coderFields[num].marshal is set on only the first field in the oneof,
44 // and dispatches to the field-specific marshaler in oneofFields.
45 cf := *mi.coderFields[num]
46 ot := si.oneofWrappersByNumber[num]
47 cf.ft = ot.Field(0).Type
48 cf.mi, cf.funcs = fieldCoder(fd, cf.ft)
49 oneofFields[ot] = &cf
50 if cf.funcs.isInit != nil {
51 needIsInit = true
52 }
53 mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
54 var vw reflect.Value // pointer to wrapper type
55 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
56 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
57 vw = vi.Elem()
58 } else {
59 vw = reflect.New(ot)
60 }
61 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
62 if err != nil {
63 return out, err
64 }
65 if cf.funcs.isInit == nil {
66 out.initialized = true
67 }
68 vi.Set(vw)
69 return out, nil
70 }
71 }
72 getInfo := func(p pointer) (pointer, *coderFieldInfo) {
73 v := p.AsValueOf(ft).Elem()
74 if v.IsNil() {
75 return pointer{}, nil
76 }
77 v = v.Elem() // interface -> *struct
78 if v.IsNil() {
79 return pointer{}, nil
80 }
81 return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()]
82 }
83 first := mi.coderFields[od.Fields().Get(0).Number()]
84 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
85 p, info := getInfo(p)
86 if info == nil || info.funcs.size == nil {
87 return 0
88 }
89 return info.funcs.size(p, info, opts)
90 }
91 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
92 p, info := getInfo(p)
93 if info == nil || info.funcs.marshal == nil {
94 return b, nil
95 }
96 return info.funcs.marshal(b, p, info, opts)
97 }
98 first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) {
99 srcp, srcinfo := getInfo(src)
100 if srcinfo == nil || srcinfo.funcs.merge == nil {
101 return
102 }
103 dstp, dstinfo := getInfo(dst)
104 if dstinfo != srcinfo {
105 dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type()))
106 dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset)
107 }
108 srcinfo.funcs.merge(dstp, srcp, srcinfo, opts)
109 }
110 if needIsInit {
111 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
112 p, info := getInfo(p)
113 if info == nil || info.funcs.isInit == nil {
114 return nil
115 }
116 return info.funcs.isInit(p, info)
117 }
118 }
119}
120
121func makeMessageFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
122 if mi := getMessageInfo(ft); mi != nil {
123 funcs := pointerCoderFuncs{
124 size: sizeMessageInfo,
125 marshal: appendMessageInfo,
126 unmarshal: consumeMessageInfo,
127 merge: mergeMessage,
128 }
129 if needsInitCheck(mi.Desc) {
130 funcs.isInit = isInitMessageInfo
131 }
132 return funcs
133 } else {
134 return pointerCoderFuncs{
135 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
136 m := asMessage(p.AsValueOf(ft).Elem())
137 return sizeMessage(m, f.tagsize, opts)
138 },
139 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
140 m := asMessage(p.AsValueOf(ft).Elem())
141 return appendMessage(b, m, f.wiretag, opts)
142 },
143 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
144 mp := p.AsValueOf(ft).Elem()
145 if mp.IsNil() {
146 mp.Set(reflect.New(ft.Elem()))
147 }
148 return consumeMessage(b, asMessage(mp), wtyp, opts)
149 },
150 isInit: func(p pointer, f *coderFieldInfo) error {
151 m := asMessage(p.AsValueOf(ft).Elem())
152 return proto.CheckInitialized(m)
153 },
154 merge: mergeMessage,
155 }
156 }
157}
158
159func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
160 return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
161}
162
163func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
164 calculatedSize := f.mi.sizePointer(p.Elem(), opts)
165 b = protowire.AppendVarint(b, f.wiretag)
166 b = protowire.AppendVarint(b, uint64(calculatedSize))
167 before := len(b)
168 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
169 if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil {
170 return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
171 }
172 return b, err
173}
174
175func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
176 if wtyp != protowire.BytesType {
177 return out, errUnknown
178 }
179 v, n := protowire.ConsumeBytes(b)
180 if n < 0 {
181 return out, errDecode
182 }
183 if p.Elem().IsNil() {
184 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
185 }
186 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
187 if err != nil {
188 return out, err
189 }
190 out.n = n
191 out.initialized = o.initialized
192 return out, nil
193}
194
195func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
196 return f.mi.checkInitializedPointer(p.Elem())
197}
198
199func sizeMessage(m proto.Message, tagsize int, opts marshalOptions) int {
200 return protowire.SizeBytes(opts.Options().Size(m)) + tagsize
201}
202
203func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
204 mopts := opts.Options()
205 calculatedSize := mopts.Size(m)
206 b = protowire.AppendVarint(b, wiretag)
207 b = protowire.AppendVarint(b, uint64(calculatedSize))
208 before := len(b)
209 b, err := mopts.MarshalAppend(b, m)
210 if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil {
211 return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize)
212 }
213 return b, err
214}
215
216func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
217 if wtyp != protowire.BytesType {
218 return out, errUnknown
219 }
220 v, n := protowire.ConsumeBytes(b)
221 if n < 0 {
222 return out, errDecode
223 }
224 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
225 Buf: v,
226 Message: m.ProtoReflect(),
227 })
228 if err != nil {
229 return out, err
230 }
231 out.n = n
232 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
233 return out, nil
234}
235
236func sizeMessageValue(v protoreflect.Value, tagsize int, opts marshalOptions) int {
237 m := v.Message().Interface()
238 return sizeMessage(m, tagsize, opts)
239}
240
241func appendMessageValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
242 m := v.Message().Interface()
243 return appendMessage(b, m, wiretag, opts)
244}
245
246func consumeMessageValue(b []byte, v protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (protoreflect.Value, unmarshalOutput, error) {
247 m := v.Message().Interface()
248 out, err := consumeMessage(b, m, wtyp, opts)
249 return v, out, err
250}
251
252func isInitMessageValue(v protoreflect.Value) error {
253 m := v.Message().Interface()
254 return proto.CheckInitialized(m)
255}
256
257var coderMessageValue = valueCoderFuncs{
258 size: sizeMessageValue,
259 marshal: appendMessageValue,
260 unmarshal: consumeMessageValue,
261 isInit: isInitMessageValue,
262 merge: mergeMessageValue,
263}
264
265func sizeGroupValue(v protoreflect.Value, tagsize int, opts marshalOptions) int {
266 m := v.Message().Interface()
267 return sizeGroup(m, tagsize, opts)
268}
269
270func appendGroupValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
271 m := v.Message().Interface()
272 return appendGroup(b, m, wiretag, opts)
273}
274
275func consumeGroupValue(b []byte, v protoreflect.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (protoreflect.Value, unmarshalOutput, error) {
276 m := v.Message().Interface()
277 out, err := consumeGroup(b, m, num, wtyp, opts)
278 return v, out, err
279}
280
281var coderGroupValue = valueCoderFuncs{
282 size: sizeGroupValue,
283 marshal: appendGroupValue,
284 unmarshal: consumeGroupValue,
285 isInit: isInitMessageValue,
286 merge: mergeMessageValue,
287}
288
289func makeGroupFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
290 num := fd.Number()
291 if mi := getMessageInfo(ft); mi != nil {
292 funcs := pointerCoderFuncs{
293 size: sizeGroupType,
294 marshal: appendGroupType,
295 unmarshal: consumeGroupType,
296 merge: mergeMessage,
297 }
298 if needsInitCheck(mi.Desc) {
299 funcs.isInit = isInitMessageInfo
300 }
301 return funcs
302 } else {
303 return pointerCoderFuncs{
304 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
305 m := asMessage(p.AsValueOf(ft).Elem())
306 return sizeGroup(m, f.tagsize, opts)
307 },
308 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
309 m := asMessage(p.AsValueOf(ft).Elem())
310 return appendGroup(b, m, f.wiretag, opts)
311 },
312 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
313 mp := p.AsValueOf(ft).Elem()
314 if mp.IsNil() {
315 mp.Set(reflect.New(ft.Elem()))
316 }
317 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
318 },
319 isInit: func(p pointer, f *coderFieldInfo) error {
320 m := asMessage(p.AsValueOf(ft).Elem())
321 return proto.CheckInitialized(m)
322 },
323 merge: mergeMessage,
324 }
325 }
326}
327
328func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
329 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
330}
331
332func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
333 b = protowire.AppendVarint(b, f.wiretag) // start group
334 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
335 b = protowire.AppendVarint(b, f.wiretag+1) // end group
336 return b, err
337}
338
339func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
340 if wtyp != protowire.StartGroupType {
341 return out, errUnknown
342 }
343 if p.Elem().IsNil() {
344 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
345 }
346 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
347}
348
349func sizeGroup(m proto.Message, tagsize int, opts marshalOptions) int {
350 return 2*tagsize + opts.Options().Size(m)
351}
352
353func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
354 b = protowire.AppendVarint(b, wiretag) // start group
355 b, err := opts.Options().MarshalAppend(b, m)
356 b = protowire.AppendVarint(b, wiretag+1) // end group
357 return b, err
358}
359
360func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
361 if wtyp != protowire.StartGroupType {
362 return out, errUnknown
363 }
364 b, n := protowire.ConsumeGroup(num, b)
365 if n < 0 {
366 return out, errDecode
367 }
368 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
369 Buf: b,
370 Message: m.ProtoReflect(),
371 })
372 if err != nil {
373 return out, err
374 }
375 out.n = n
376 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
377 return out, nil
378}
379
380func makeMessageSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
381 if mi := getMessageInfo(ft); mi != nil {
382 funcs := pointerCoderFuncs{
383 size: sizeMessageSliceInfo,
384 marshal: appendMessageSliceInfo,
385 unmarshal: consumeMessageSliceInfo,
386 merge: mergeMessageSlice,
387 }
388 if needsInitCheck(mi.Desc) {
389 funcs.isInit = isInitMessageSliceInfo
390 }
391 return funcs
392 }
393 return pointerCoderFuncs{
394 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
395 return sizeMessageSlice(p, ft, f.tagsize, opts)
396 },
397 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
398 return appendMessageSlice(b, p, f.wiretag, ft, opts)
399 },
400 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
401 return consumeMessageSlice(b, p, ft, wtyp, opts)
402 },
403 isInit: func(p pointer, f *coderFieldInfo) error {
404 return isInitMessageSlice(p, ft)
405 },
406 merge: mergeMessageSlice,
407 }
408}
409
410func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
411 s := p.PointerSlice()
412 n := 0
413 for _, v := range s {
414 n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
415 }
416 return n
417}
418
419func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
420 s := p.PointerSlice()
421 var err error
422 for _, v := range s {
423 b = protowire.AppendVarint(b, f.wiretag)
424 siz := f.mi.sizePointer(v, opts)
425 b = protowire.AppendVarint(b, uint64(siz))
426 before := len(b)
427 b, err = f.mi.marshalAppendPointer(b, v, opts)
428 if err != nil {
429 return b, err
430 }
431 if measuredSize := len(b) - before; siz != measuredSize {
432 return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
433 }
434 }
435 return b, nil
436}
437
438func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
439 if wtyp != protowire.BytesType {
440 return out, errUnknown
441 }
442 v, n := protowire.ConsumeBytes(b)
443 if n < 0 {
444 return out, errDecode
445 }
446 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
447 mp := pointerOfIface(m)
448 o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
449 if err != nil {
450 return out, err
451 }
452 p.AppendPointerSlice(mp)
453 out.n = n
454 out.initialized = o.initialized
455 return out, nil
456}
457
458func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
459 s := p.PointerSlice()
460 for _, v := range s {
461 if err := f.mi.checkInitializedPointer(v); err != nil {
462 return err
463 }
464 }
465 return nil
466}
467
468func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, opts marshalOptions) int {
469 mopts := opts.Options()
470 s := p.PointerSlice()
471 n := 0
472 for _, v := range s {
473 m := asMessage(v.AsValueOf(goType.Elem()))
474 n += protowire.SizeBytes(mopts.Size(m)) + tagsize
475 }
476 return n
477}
478
479func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
480 mopts := opts.Options()
481 s := p.PointerSlice()
482 var err error
483 for _, v := range s {
484 m := asMessage(v.AsValueOf(goType.Elem()))
485 b = protowire.AppendVarint(b, wiretag)
486 siz := mopts.Size(m)
487 b = protowire.AppendVarint(b, uint64(siz))
488 before := len(b)
489 b, err = mopts.MarshalAppend(b, m)
490 if err != nil {
491 return b, err
492 }
493 if measuredSize := len(b) - before; siz != measuredSize {
494 return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
495 }
496 }
497 return b, nil
498}
499
500func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
501 if wtyp != protowire.BytesType {
502 return out, errUnknown
503 }
504 v, n := protowire.ConsumeBytes(b)
505 if n < 0 {
506 return out, errDecode
507 }
508 mp := reflect.New(goType.Elem())
509 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
510 Buf: v,
511 Message: asMessage(mp).ProtoReflect(),
512 })
513 if err != nil {
514 return out, err
515 }
516 p.AppendPointerSlice(pointerOfValue(mp))
517 out.n = n
518 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
519 return out, nil
520}
521
522func isInitMessageSlice(p pointer, goType reflect.Type) error {
523 s := p.PointerSlice()
524 for _, v := range s {
525 m := asMessage(v.AsValueOf(goType.Elem()))
526 if err := proto.CheckInitialized(m); err != nil {
527 return err
528 }
529 }
530 return nil
531}
532
533// Slices of messages
534
535func sizeMessageSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int {
536 mopts := opts.Options()
537 list := listv.List()
538 n := 0
539 for i, llen := 0, list.Len(); i < llen; i++ {
540 m := list.Get(i).Message().Interface()
541 n += protowire.SizeBytes(mopts.Size(m)) + tagsize
542 }
543 return n
544}
545
546func appendMessageSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
547 list := listv.List()
548 mopts := opts.Options()
549 for i, llen := 0, list.Len(); i < llen; i++ {
550 m := list.Get(i).Message().Interface()
551 b = protowire.AppendVarint(b, wiretag)
552 siz := mopts.Size(m)
553 b = protowire.AppendVarint(b, uint64(siz))
554 before := len(b)
555 var err error
556 b, err = mopts.MarshalAppend(b, m)
557 if err != nil {
558 return b, err
559 }
560 if measuredSize := len(b) - before; siz != measuredSize {
561 return nil, errors.MismatchedSizeCalculation(siz, measuredSize)
562 }
563 }
564 return b, nil
565}
566
567func consumeMessageSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
568 list := listv.List()
569 if wtyp != protowire.BytesType {
570 return protoreflect.Value{}, out, errUnknown
571 }
572 v, n := protowire.ConsumeBytes(b)
573 if n < 0 {
574 return protoreflect.Value{}, out, errDecode
575 }
576 m := list.NewElement()
577 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
578 Buf: v,
579 Message: m.Message(),
580 })
581 if err != nil {
582 return protoreflect.Value{}, out, err
583 }
584 list.Append(m)
585 out.n = n
586 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
587 return listv, out, nil
588}
589
590func isInitMessageSliceValue(listv protoreflect.Value) error {
591 list := listv.List()
592 for i, llen := 0, list.Len(); i < llen; i++ {
593 m := list.Get(i).Message().Interface()
594 if err := proto.CheckInitialized(m); err != nil {
595 return err
596 }
597 }
598 return nil
599}
600
601var coderMessageSliceValue = valueCoderFuncs{
602 size: sizeMessageSliceValue,
603 marshal: appendMessageSliceValue,
604 unmarshal: consumeMessageSliceValue,
605 isInit: isInitMessageSliceValue,
606 merge: mergeMessageListValue,
607}
608
609func sizeGroupSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int {
610 mopts := opts.Options()
611 list := listv.List()
612 n := 0
613 for i, llen := 0, list.Len(); i < llen; i++ {
614 m := list.Get(i).Message().Interface()
615 n += 2*tagsize + mopts.Size(m)
616 }
617 return n
618}
619
620func appendGroupSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
621 list := listv.List()
622 mopts := opts.Options()
623 for i, llen := 0, list.Len(); i < llen; i++ {
624 m := list.Get(i).Message().Interface()
625 b = protowire.AppendVarint(b, wiretag) // start group
626 var err error
627 b, err = mopts.MarshalAppend(b, m)
628 if err != nil {
629 return b, err
630 }
631 b = protowire.AppendVarint(b, wiretag+1) // end group
632 }
633 return b, nil
634}
635
636func consumeGroupSliceValue(b []byte, listv protoreflect.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
637 list := listv.List()
638 if wtyp != protowire.StartGroupType {
639 return protoreflect.Value{}, out, errUnknown
640 }
641 b, n := protowire.ConsumeGroup(num, b)
642 if n < 0 {
643 return protoreflect.Value{}, out, errDecode
644 }
645 m := list.NewElement()
646 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
647 Buf: b,
648 Message: m.Message(),
649 })
650 if err != nil {
651 return protoreflect.Value{}, out, err
652 }
653 list.Append(m)
654 out.n = n
655 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
656 return listv, out, nil
657}
658
659var coderGroupSliceValue = valueCoderFuncs{
660 size: sizeGroupSliceValue,
661 marshal: appendGroupSliceValue,
662 unmarshal: consumeGroupSliceValue,
663 isInit: isInitMessageSliceValue,
664 merge: mergeMessageListValue,
665}
666
667func makeGroupSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
668 num := fd.Number()
669 if mi := getMessageInfo(ft); mi != nil {
670 funcs := pointerCoderFuncs{
671 size: sizeGroupSliceInfo,
672 marshal: appendGroupSliceInfo,
673 unmarshal: consumeGroupSliceInfo,
674 merge: mergeMessageSlice,
675 }
676 if needsInitCheck(mi.Desc) {
677 funcs.isInit = isInitMessageSliceInfo
678 }
679 return funcs
680 }
681 return pointerCoderFuncs{
682 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
683 return sizeGroupSlice(p, ft, f.tagsize, opts)
684 },
685 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
686 return appendGroupSlice(b, p, f.wiretag, ft, opts)
687 },
688 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
689 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
690 },
691 isInit: func(p pointer, f *coderFieldInfo) error {
692 return isInitMessageSlice(p, ft)
693 },
694 merge: mergeMessageSlice,
695 }
696}
697
698func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, opts marshalOptions) int {
699 mopts := opts.Options()
700 s := p.PointerSlice()
701 n := 0
702 for _, v := range s {
703 m := asMessage(v.AsValueOf(messageType.Elem()))
704 n += 2*tagsize + mopts.Size(m)
705 }
706 return n
707}
708
709func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
710 s := p.PointerSlice()
711 var err error
712 for _, v := range s {
713 m := asMessage(v.AsValueOf(messageType.Elem()))
714 b = protowire.AppendVarint(b, wiretag) // start group
715 b, err = opts.Options().MarshalAppend(b, m)
716 if err != nil {
717 return b, err
718 }
719 b = protowire.AppendVarint(b, wiretag+1) // end group
720 }
721 return b, nil
722}
723
724func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
725 if wtyp != protowire.StartGroupType {
726 return out, errUnknown
727 }
728 b, n := protowire.ConsumeGroup(num, b)
729 if n < 0 {
730 return out, errDecode
731 }
732 mp := reflect.New(goType.Elem())
733 o, err := opts.Options().UnmarshalState(protoiface.UnmarshalInput{
734 Buf: b,
735 Message: asMessage(mp).ProtoReflect(),
736 })
737 if err != nil {
738 return out, err
739 }
740 p.AppendPointerSlice(pointerOfValue(mp))
741 out.n = n
742 out.initialized = o.Flags&protoiface.UnmarshalInitialized != 0
743 return out, nil
744}
745
746func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
747 s := p.PointerSlice()
748 n := 0
749 for _, v := range s {
750 n += 2*f.tagsize + f.mi.sizePointer(v, opts)
751 }
752 return n
753}
754
755func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
756 s := p.PointerSlice()
757 var err error
758 for _, v := range s {
759 b = protowire.AppendVarint(b, f.wiretag) // start group
760 b, err = f.mi.marshalAppendPointer(b, v, opts)
761 if err != nil {
762 return b, err
763 }
764 b = protowire.AppendVarint(b, f.wiretag+1) // end group
765 }
766 return b, nil
767}
768
769func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
770 if wtyp != protowire.StartGroupType {
771 return unmarshalOutput{}, errUnknown
772 }
773 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
774 mp := pointerOfIface(m)
775 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
776 if err != nil {
777 return out, err
778 }
779 p.AppendPointerSlice(mp)
780 return out, nil
781}
782
783func asMessage(v reflect.Value) protoreflect.ProtoMessage {
784 if m, ok := v.Interface().(protoreflect.ProtoMessage); ok {
785 return m
786 }
787 return legacyWrapMessage(v).Interface()
788}