blob: 35d40029c389d80f8213ef60747ac5c5db663cd1 [file] [log] [blame]
Damien Neilc37adef2019-04-01 13:49:56 -07001// 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 (
Damien Neil6e40b322019-10-01 13:05:16 -07008 "fmt"
Damien Neilc37adef2019-04-01 13:49:56 -07009 "reflect"
Joe Tsai6e095992019-08-10 13:56:36 -070010 "sync"
Damien Neilc37adef2019-04-01 13:49:56 -070011
Joe Tsaicd108d02020-02-14 18:08:02 -080012 "google.golang.org/protobuf/encoding/protowire"
Damien Neilc37adef2019-04-01 13:49:56 -070013 "google.golang.org/protobuf/proto"
14 pref "google.golang.org/protobuf/reflect/protoreflect"
Joe Tsai6e095992019-08-10 13:56:36 -070015 preg "google.golang.org/protobuf/reflect/protoregistry"
Damien Neilc600d6c2020-01-21 15:00:33 -080016 piface "google.golang.org/protobuf/runtime/protoiface"
Damien Neilc37adef2019-04-01 13:49:56 -070017)
18
19type errInvalidUTF8 struct{}
20
21func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
22func (errInvalidUTF8) InvalidUTF8() bool { return true }
23
Damien Neilce413af2019-12-05 16:36:28 -080024// 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) {
Damien Neilce413af2019-12-05 16:36:28 -080032 fs := si.oneofsByName[od.Name()]
33 ft := fs.Type
Damien Neil316febd2020-02-09 12:26:50 -080034 oneofFields := make(map[reflect.Type]*coderFieldInfo)
Damien Neilce413af2019-12-05 16:36:28 -080035 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()
Damien Neil316febd2020-02-09 12:26:50 -080040 // 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]
Damien Neilce413af2019-12-05 16:36:28 -080047 ot := si.oneofWrappersByNumber[num]
Damien Neile8e88752020-02-11 11:25:16 -080048 cf.ft = ot.Field(0).Type
49 cf.mi, cf.funcs = fieldCoder(fd, cf.ft)
Damien Neil316febd2020-02-09 12:26:50 -080050 oneofFields[ot] = &cf
51 if cf.funcs.isInit != nil {
Damien Neilce413af2019-12-05 16:36:28 -080052 needIsInit = true
53 }
Joe Tsaicd108d02020-02-14 18:08:02 -080054 mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070055 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 }
Damien Neil316febd2020-02-09 12:26:50 -080062 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
Damien Neile91877d2019-06-27 10:54:42 -070063 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -080064 return out, err
Damien Neilc37adef2019-04-01 13:49:56 -070065 }
Joe Tsai6c286742019-07-11 23:15:05 -070066 vi.Set(vw)
Damien Neilf0831e82020-01-21 14:25:12 -080067 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -070068 }
69 }
Damien Neil316febd2020-02-09 12:26:50 -080070 getInfo := func(p pointer) (pointer, *coderFieldInfo) {
Damien Neilce413af2019-12-05 16:36:28 -080071 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()]
Damien Neil316febd2020-02-09 12:26:50 -080082 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
Damien Neilce413af2019-12-05 16:36:28 -080083 p, info := getInfo(p)
84 if info == nil || info.funcs.size == nil {
85 return 0
86 }
Damien Neil316febd2020-02-09 12:26:50 -080087 return info.funcs.size(p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080088 }
Damien Neil316febd2020-02-09 12:26:50 -080089 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilce413af2019-12-05 16:36:28 -080090 p, info := getInfo(p)
91 if info == nil || info.funcs.marshal == nil {
92 return b, nil
93 }
Damien Neil316febd2020-02-09 12:26:50 -080094 return info.funcs.marshal(b, p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080095 }
Damien Neile8e88752020-02-11 11:25:16 -080096 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 }
Damien Neilce413af2019-12-05 16:36:28 -0800108 if needIsInit {
Damien Neil316febd2020-02-09 12:26:50 -0800109 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
Damien Neilce413af2019-12-05 16:36:28 -0800110 p, info := getInfo(p)
111 if info == nil || info.funcs.isInit == nil {
112 return nil
113 }
Damien Neil316febd2020-02-09 12:26:50 -0800114 return info.funcs.isInit(p, info)
Damien Neilce413af2019-12-05 16:36:28 -0800115 }
116 }
Damien Neilc37adef2019-04-01 13:49:56 -0700117}
118
Joe Tsai6e095992019-08-10 13:56:36 -0700119func 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
Joe Tsai6e095992019-08-10 13:56:36 -0700129 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800130 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neile8e88752020-02-11 11:25:16 -0800131 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700132 if !ok {
133 return 0
134 }
Damien Neil6e40b322019-10-01 13:05:16 -0700135 lazyInit()
136 if messageType == nil {
137 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
138 }
Damien Neil316febd2020-02-09 12:26:50 -0800139 return sizeMessage(m, f.tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700140 },
Damien Neil316febd2020-02-09 12:26:50 -0800141 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neile8e88752020-02-11 11:25:16 -0800142 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700143 if !ok {
144 return b, nil
145 }
Damien Neil6e40b322019-10-01 13:05:16 -0700146 lazyInit()
147 if messageType == nil {
148 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
149 }
Damien Neil316febd2020-02-09 12:26:50 -0800150 return appendMessage(b, m, f.wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700151 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800152 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6e095992019-08-10 13:56:36 -0700153 fs := p.WeakFields()
Damien Neile8e88752020-02-11 11:25:16 -0800154 m, ok := fs.get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700155 if !ok {
156 lazyInit()
157 if messageType == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800158 return unmarshalOutput{}, errUnknown
Joe Tsai6e095992019-08-10 13:56:36 -0700159 }
Damien Neil6e40b322019-10-01 13:05:16 -0700160 m = messageType.New().Interface()
Damien Neile8e88752020-02-11 11:25:16 -0800161 fs.set(f.num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700162 }
Damien Neil6e40b322019-10-01 13:05:16 -0700163 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700164 },
Damien Neil316febd2020-02-09 12:26:50 -0800165 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neile8e88752020-02-11 11:25:16 -0800166 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700167 if !ok {
168 return nil
169 }
Joe Tsaif26a9e72020-02-20 10:05:37 -0800170 return proto.CheckInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700171 },
Damien Neile8e88752020-02-11 11:25:16 -0800172 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 },
Joe Tsai6e095992019-08-10 13:56:36 -0700188 }
189}
190
Damien Neilc37adef2019-04-01 13:49:56 -0700191func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700192 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800193 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800194 size: sizeMessageInfo,
195 marshal: appendMessageInfo,
196 unmarshal: consumeMessageInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800197 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700198 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800199 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800200 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800201 }
202 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700203 } else {
204 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800205 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700206 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800207 return sizeMessage(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700208 },
Damien Neil316febd2020-02-09 12:26:50 -0800209 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700210 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800211 return appendMessage(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700212 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800213 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700214 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 },
Damien Neil316febd2020-02-09 12:26:50 -0800220 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700221 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800222 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700223 },
Damien Neile8e88752020-02-11 11:25:16 -0800224 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700225 }
226 }
227}
228
Damien Neil316febd2020-02-09 12:26:50 -0800229func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Joe Tsaicd108d02020-02-14 18:08:02 -0800230 return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700231}
232
Damien Neil316febd2020-02-09 12:26:50 -0800233func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800234 b = protowire.AppendVarint(b, f.wiretag)
235 b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
Damien Neil316febd2020-02-09 12:26:50 -0800236 return f.mi.marshalAppendPointer(b, p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700237}
238
Joe Tsaicd108d02020-02-14 18:08:02 -0800239func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
240 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800241 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700242 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800243 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700244 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700245 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700246 }
247 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800248 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700249 }
Damien Neil316febd2020-02-09 12:26:50 -0800250 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800251 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800252 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700253 }
Damien Neilf0831e82020-01-21 14:25:12 -0800254 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800255 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800256 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700257}
258
Damien Neil316febd2020-02-09 12:26:50 -0800259func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800260 return f.mi.checkInitializedPointer(p.Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800261}
262
Damien Neilc37adef2019-04-01 13:49:56 -0700263func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
Joe Tsaicd108d02020-02-14 18:08:02 -0800264 return protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700265}
266
267func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800268 b = protowire.AppendVarint(b, wiretag)
269 b = protowire.AppendVarint(b, uint64(proto.Size(m)))
Damien Neilc37adef2019-04-01 13:49:56 -0700270 return opts.Options().MarshalAppend(b, m)
271}
272
Joe Tsaicd108d02020-02-14 18:08:02 -0800273func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
274 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800275 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700276 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800277 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700278 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700279 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700280 }
Joe Tsaie05f7892020-03-09 12:01:52 -0700281 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
282 Buf: v,
283 Message: m.ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800284 })
285 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800286 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700287 }
Damien Neilf0831e82020-01-21 14:25:12 -0800288 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800289 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800290 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700291}
292
Damien Neil68b81c32019-08-22 11:41:32 -0700293func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
294 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700295 return sizeMessage(m, tagsize, opts)
296}
297
Damien Neil68b81c32019-08-22 11:41:32 -0700298func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
299 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700300 return appendMessage(b, m, wiretag, opts)
301}
302
Joe Tsaicd108d02020-02-14 18:08:02 -0800303func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700304 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800305 out, err := consumeMessage(b, m, wtyp, opts)
306 return v, out, err
Damien Neile91877d2019-06-27 10:54:42 -0700307}
308
Damien Neil68b81c32019-08-22 11:41:32 -0700309func isInitMessageValue(v pref.Value) error {
310 m := v.Message().Interface()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800311 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700312}
313
Damien Neil68b81c32019-08-22 11:41:32 -0700314var coderMessageValue = valueCoderFuncs{
315 size: sizeMessageValue,
316 marshal: appendMessageValue,
317 unmarshal: consumeMessageValue,
318 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800319 merge: mergeMessageValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700320}
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
Joe Tsaicd108d02020-02-14 18:08:02 -0800332func consumeGroupValue(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700333 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800334 out, err := consumeGroup(b, m, num, wtyp, opts)
335 return v, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700336}
337
338var coderGroupValue = valueCoderFuncs{
339 size: sizeGroupValue,
340 marshal: appendGroupValue,
341 unmarshal: consumeGroupValue,
342 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800343 merge: mergeMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700344}
345
346func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700347 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700348 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800349 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800350 size: sizeGroupType,
351 marshal: appendGroupType,
352 unmarshal: consumeGroupType,
Damien Neile8e88752020-02-11 11:25:16 -0800353 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700354 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800355 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800356 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800357 }
358 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700359 } else {
360 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800361 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700362 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800363 return sizeGroup(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700364 },
Damien Neil316febd2020-02-09 12:26:50 -0800365 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700366 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800367 return appendGroup(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700368 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800369 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700370 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 },
Damien Neil316febd2020-02-09 12:26:50 -0800376 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700377 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800378 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700379 },
Damien Neile8e88752020-02-11 11:25:16 -0800380 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700381 }
382 }
383}
384
Damien Neil316febd2020-02-09 12:26:50 -0800385func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
386 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700387}
388
Damien Neil316febd2020-02-09 12:26:50 -0800389func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800390 b = protowire.AppendVarint(b, f.wiretag) // start group
Damien Neil316febd2020-02-09 12:26:50 -0800391 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800392 b = protowire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700393 return b, err
394}
395
Joe Tsaicd108d02020-02-14 18:08:02 -0800396func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
397 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800398 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700399 }
400 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800401 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700402 }
Damien Neil316febd2020-02-09 12:26:50 -0800403 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700404}
405
Damien Neilc37adef2019-04-01 13:49:56 -0700406func 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) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800411 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neilc37adef2019-04-01 13:49:56 -0700412 b, err := opts.Options().MarshalAppend(b, m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800413 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700414 return b, err
415}
416
Joe Tsaicd108d02020-02-14 18:08:02 -0800417func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
418 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800419 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700420 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800421 b, n := protowire.ConsumeGroup(num, b)
Damien Neile91877d2019-06-27 10:54:42 -0700422 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700423 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700424 }
Joe Tsaie05f7892020-03-09 12:01:52 -0700425 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
426 Buf: b,
427 Message: m.ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800428 })
429 if err != nil {
430 return out, err
431 }
Damien Neilf0831e82020-01-21 14:25:12 -0800432 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800433 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilc600d6c2020-01-21 15:00:33 -0800434 return out, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700435}
436
Damien Neilc37adef2019-04-01 13:49:56 -0700437func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700438 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800439 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800440 size: sizeMessageSliceInfo,
441 marshal: appendMessageSliceInfo,
442 unmarshal: consumeMessageSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800443 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700444 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800445 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800446 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800447 }
448 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700449 }
450 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800451 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
452 return sizeMessageSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700453 },
Damien Neil316febd2020-02-09 12:26:50 -0800454 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
455 return appendMessageSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700456 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800457 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700458 return consumeMessageSlice(b, p, ft, wtyp, opts)
459 },
Damien Neil316febd2020-02-09 12:26:50 -0800460 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700461 return isInitMessageSlice(p, ft)
462 },
Damien Neile8e88752020-02-11 11:25:16 -0800463 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700464 }
465}
466
Damien Neil316febd2020-02-09 12:26:50 -0800467func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700468 s := p.PointerSlice()
469 n := 0
470 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800471 n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700472 }
473 return n
474}
475
Damien Neil316febd2020-02-09 12:26:50 -0800476func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700477 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700478 var err error
479 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800480 b = protowire.AppendVarint(b, f.wiretag)
Damien Neil316febd2020-02-09 12:26:50 -0800481 siz := f.mi.sizePointer(v, opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800482 b = protowire.AppendVarint(b, uint64(siz))
Damien Neil316febd2020-02-09 12:26:50 -0800483 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700484 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700485 return b, err
486 }
487 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700488 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700489}
490
Joe Tsaicd108d02020-02-14 18:08:02 -0800491func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
492 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800493 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700494 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800495 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700496 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700497 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700498 }
Damien Neil316febd2020-02-09 12:26:50 -0800499 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700500 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800501 o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800502 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800503 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700504 }
505 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800506 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800507 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800508 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700509}
510
Damien Neil316febd2020-02-09 12:26:50 -0800511func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700512 s := p.PointerSlice()
513 for _, v := range s {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800514 if err := f.mi.checkInitializedPointer(v); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700515 return err
516 }
517 }
518 return nil
519}
520
Damien Neilc37adef2019-04-01 13:49:56 -0700521func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
522 s := p.PointerSlice()
523 n := 0
524 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700525 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800526 n += protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700527 }
528 return n
529}
530
531func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
532 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700533 var err error
534 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700535 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800536 b = protowire.AppendVarint(b, wiretag)
Damien Neilc37adef2019-04-01 13:49:56 -0700537 siz := proto.Size(m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800538 b = protowire.AppendVarint(b, uint64(siz))
Damien Neilc37adef2019-04-01 13:49:56 -0700539 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700540 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700541 return b, err
542 }
543 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700544 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700545}
546
Joe Tsaicd108d02020-02-14 18:08:02 -0800547func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
548 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800549 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700550 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800551 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700552 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700553 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700554 }
555 mp := reflect.New(goType.Elem())
Joe Tsaie05f7892020-03-09 12:01:52 -0700556 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
557 Buf: v,
558 Message: asMessage(mp).ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800559 })
560 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800561 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700562 }
563 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800564 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800565 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800566 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700567}
568
Damien Neil5322bdb2019-04-09 15:57:05 -0700569func isInitMessageSlice(p pointer, goType reflect.Type) error {
570 s := p.PointerSlice()
571 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700572 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaif26a9e72020-02-20 10:05:37 -0800573 if err := proto.CheckInitialized(m); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700574 return err
575 }
576 }
577 return nil
578}
579
Damien Neilc37adef2019-04-01 13:49:56 -0700580// Slices of messages
581
Damien Neil68b81c32019-08-22 11:41:32 -0700582func 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()
Joe Tsaicd108d02020-02-14 18:08:02 -0800587 n += protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neil68b81c32019-08-22 11:41:32 -0700588 }
589 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700590}
591
Damien Neil68b81c32019-08-22 11:41:32 -0700592func 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()
Joe Tsaicd108d02020-02-14 18:08:02 -0800597 b = protowire.AppendVarint(b, wiretag)
Damien Neil68b81c32019-08-22 11:41:32 -0700598 siz := proto.Size(m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800599 b = protowire.AppendVarint(b, uint64(siz))
Damien Neil68b81c32019-08-22 11:41:32 -0700600 var err error
601 b, err = mopts.MarshalAppend(b, m)
602 if err != nil {
603 return b, err
604 }
605 }
606 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700607}
608
Joe Tsaicd108d02020-02-14 18:08:02 -0800609func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700610 list := listv.List()
Joe Tsaicd108d02020-02-14 18:08:02 -0800611 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800612 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700613 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800614 v, n := protowire.ConsumeBytes(b)
Damien Neil68b81c32019-08-22 11:41:32 -0700615 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700616 return pref.Value{}, out, errDecode
Damien Neil68b81c32019-08-22 11:41:32 -0700617 }
618 m := list.NewElement()
Joe Tsaie05f7892020-03-09 12:01:52 -0700619 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
620 Buf: v,
621 Message: m.Message(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800622 })
623 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800624 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700625 }
626 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800627 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800628 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800629 return listv, out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700630}
631
Damien Neil68b81c32019-08-22 11:41:32 -0700632func 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()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800636 if err := proto.CheckInitialized(m); err != nil {
Damien Neil68b81c32019-08-22 11:41:32 -0700637 return err
638 }
639 }
640 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700641}
642
Damien Neil68b81c32019-08-22 11:41:32 -0700643var coderMessageSliceValue = valueCoderFuncs{
644 size: sizeMessageSliceValue,
645 marshal: appendMessageSliceValue,
646 unmarshal: consumeMessageSliceValue,
647 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800648 merge: mergeMessageListValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700649}
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()
Joe Tsaicd108d02020-02-14 18:08:02 -0800666 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neil68b81c32019-08-22 11:41:32 -0700667 var err error
668 b, err = mopts.MarshalAppend(b, m)
669 if err != nil {
670 return b, err
671 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800672 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neil68b81c32019-08-22 11:41:32 -0700673 }
674 return b, nil
675}
676
Joe Tsaicd108d02020-02-14 18:08:02 -0800677func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700678 list := listv.List()
Joe Tsaicd108d02020-02-14 18:08:02 -0800679 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800680 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700681 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800682 b, n := protowire.ConsumeGroup(num, b)
Damien Neil68b81c32019-08-22 11:41:32 -0700683 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700684 return pref.Value{}, out, errDecode
Damien Neil68b81c32019-08-22 11:41:32 -0700685 }
686 m := list.NewElement()
Joe Tsaie05f7892020-03-09 12:01:52 -0700687 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
688 Buf: b,
689 Message: m.Message(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800690 })
691 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800692 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700693 }
694 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800695 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800696 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800697 return listv, out, nil
Damien Neil68b81c32019-08-22 11:41:32 -0700698}
699
700var coderGroupSliceValue = valueCoderFuncs{
701 size: sizeGroupSliceValue,
702 marshal: appendGroupSliceValue,
703 unmarshal: consumeGroupSliceValue,
704 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800705 merge: mergeMessageListValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700706}
707
708func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700709 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700710 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800711 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800712 size: sizeGroupSliceInfo,
713 marshal: appendGroupSliceInfo,
714 unmarshal: consumeGroupSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800715 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700716 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800717 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800718 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800719 }
720 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700721 }
722 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800723 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
724 return sizeGroupSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700725 },
Damien Neil316febd2020-02-09 12:26:50 -0800726 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
727 return appendGroupSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700728 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800729 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700730 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
731 },
Damien Neil316febd2020-02-09 12:26:50 -0800732 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700733 return isInitMessageSlice(p, ft)
734 },
Damien Neile8e88752020-02-11 11:25:16 -0800735 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700736 }
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 {
Damien Neile91877d2019-06-27 10:54:42 -0700743 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700744 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()
Damien Neilc37adef2019-04-01 13:49:56 -0700751 var err error
752 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700753 m := asMessage(v.AsValueOf(messageType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800754 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neilc37adef2019-04-01 13:49:56 -0700755 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700756 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700757 return b, err
758 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800759 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700760 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700761 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700762}
763
Joe Tsaicd108d02020-02-14 18:08:02 -0800764func 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 {
Damien Neilf0831e82020-01-21 14:25:12 -0800766 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700767 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800768 b, n := protowire.ConsumeGroup(num, b)
Damien Neile91877d2019-06-27 10:54:42 -0700769 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700770 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700771 }
772 mp := reflect.New(goType.Elem())
Joe Tsaie05f7892020-03-09 12:01:52 -0700773 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
774 Buf: b,
775 Message: asMessage(mp).ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800776 })
777 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800778 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700779 }
780 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800781 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800782 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800783 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700784}
785
Damien Neil316febd2020-02-09 12:26:50 -0800786func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700787 s := p.PointerSlice()
788 n := 0
789 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800790 n += 2*f.tagsize + f.mi.sizePointer(v, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700791 }
792 return n
793}
794
Damien Neil316febd2020-02-09 12:26:50 -0800795func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700796 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700797 var err error
798 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800799 b = protowire.AppendVarint(b, f.wiretag) // start group
Damien Neil316febd2020-02-09 12:26:50 -0800800 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700801 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700802 return b, err
803 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800804 b = protowire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700805 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700806 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700807}
808
Joe Tsaicd108d02020-02-14 18:08:02 -0800809func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
810 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800811 return unmarshalOutput{}, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700812 }
Damien Neil316febd2020-02-09 12:26:50 -0800813 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700814 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800815 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700816 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800817 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700818 }
819 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800820 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700821}
822
Damien Neil5b6d0472019-06-14 11:54:07 -0700823func asMessage(v reflect.Value) pref.ProtoMessage {
824 if m, ok := v.Interface().(pref.ProtoMessage); ok {
825 return m
826 }
Joe Tsaia75c9142020-04-01 11:47:49 -0700827 return legacyWrapMessage(v).Interface()
Damien Neil5b6d0472019-06-14 11:54:07 -0700828}