codec_field.go

  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}