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