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