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