blob: cb4b482d166f5571887f5584b345764a82e336a0 [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 Neila0f95d52020-07-24 14:25:43 -070013 "google.golang.org/protobuf/internal/errors"
Damien Neilc37adef2019-04-01 13:49:56 -070014 "google.golang.org/protobuf/proto"
15 pref "google.golang.org/protobuf/reflect/protoreflect"
Joe Tsai6e095992019-08-10 13:56:36 -070016 preg "google.golang.org/protobuf/reflect/protoregistry"
Damien Neilc600d6c2020-01-21 15:00:33 -080017 piface "google.golang.org/protobuf/runtime/protoiface"
Damien Neilc37adef2019-04-01 13:49:56 -070018)
19
20type errInvalidUTF8 struct{}
21
22func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
23func (errInvalidUTF8) InvalidUTF8() bool { return true }
Damien Neila0f95d52020-07-24 14:25:43 -070024func (errInvalidUTF8) Unwrap() error { return errors.Error }
Damien Neilc37adef2019-04-01 13:49:56 -070025
Damien Neilce413af2019-12-05 16:36:28 -080026// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof.
27//
28// For size, marshal, and isInit operations, functions are set only on the first field
29// in the oneof. The functions are called when the oneof is non-nil, and will dispatch
30// to the appropriate field-specific function as necessary.
31//
32// The unmarshal function is set on each field individually as usual.
33func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) {
Damien Neilce413af2019-12-05 16:36:28 -080034 fs := si.oneofsByName[od.Name()]
35 ft := fs.Type
Damien Neil316febd2020-02-09 12:26:50 -080036 oneofFields := make(map[reflect.Type]*coderFieldInfo)
Damien Neilce413af2019-12-05 16:36:28 -080037 needIsInit := false
38 fields := od.Fields()
39 for i, lim := 0, fields.Len(); i < lim; i++ {
40 fd := od.Fields().Get(i)
41 num := fd.Number()
Damien Neil316febd2020-02-09 12:26:50 -080042 // Make a copy of the original coderFieldInfo for use in unmarshaling.
43 //
44 // oneofFields[oneofType].funcs.marshal is the field-specific marshal function.
45 //
46 // mi.coderFields[num].marshal is set on only the first field in the oneof,
47 // and dispatches to the field-specific marshaler in oneofFields.
48 cf := *mi.coderFields[num]
Damien Neilce413af2019-12-05 16:36:28 -080049 ot := si.oneofWrappersByNumber[num]
Damien Neile8e88752020-02-11 11:25:16 -080050 cf.ft = ot.Field(0).Type
51 cf.mi, cf.funcs = fieldCoder(fd, cf.ft)
Damien Neil316febd2020-02-09 12:26:50 -080052 oneofFields[ot] = &cf
53 if cf.funcs.isInit != nil {
Damien Neilce413af2019-12-05 16:36:28 -080054 needIsInit = true
55 }
Joe Tsaicd108d02020-02-14 18:08:02 -080056 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 -070057 var vw reflect.Value // pointer to wrapper type
58 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
59 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
60 vw = vi.Elem()
61 } else {
62 vw = reflect.New(ot)
63 }
Damien Neil316febd2020-02-09 12:26:50 -080064 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
Damien Neile91877d2019-06-27 10:54:42 -070065 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -080066 return out, err
Damien Neilc37adef2019-04-01 13:49:56 -070067 }
Joe Tsai6c286742019-07-11 23:15:05 -070068 vi.Set(vw)
Damien Neilf0831e82020-01-21 14:25:12 -080069 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -070070 }
71 }
Damien Neil316febd2020-02-09 12:26:50 -080072 getInfo := func(p pointer) (pointer, *coderFieldInfo) {
Damien Neilce413af2019-12-05 16:36:28 -080073 v := p.AsValueOf(ft).Elem()
74 if v.IsNil() {
75 return pointer{}, nil
76 }
77 v = v.Elem() // interface -> *struct
78 if v.IsNil() {
79 return pointer{}, nil
80 }
81 return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()]
82 }
83 first := mi.coderFields[od.Fields().Get(0).Number()]
Damien Neil316febd2020-02-09 12:26:50 -080084 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
Damien Neilce413af2019-12-05 16:36:28 -080085 p, info := getInfo(p)
86 if info == nil || info.funcs.size == nil {
87 return 0
88 }
Damien Neil316febd2020-02-09 12:26:50 -080089 return info.funcs.size(p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080090 }
Damien Neil316febd2020-02-09 12:26:50 -080091 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilce413af2019-12-05 16:36:28 -080092 p, info := getInfo(p)
93 if info == nil || info.funcs.marshal == nil {
94 return b, nil
95 }
Damien Neil316febd2020-02-09 12:26:50 -080096 return info.funcs.marshal(b, p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080097 }
Damien Neile8e88752020-02-11 11:25:16 -080098 first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) {
99 srcp, srcinfo := getInfo(src)
100 if srcinfo == nil || srcinfo.funcs.merge == nil {
101 return
102 }
103 dstp, dstinfo := getInfo(dst)
104 if dstinfo != srcinfo {
105 dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type()))
106 dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset)
107 }
108 srcinfo.funcs.merge(dstp, srcp, srcinfo, opts)
109 }
Damien Neilce413af2019-12-05 16:36:28 -0800110 if needIsInit {
Damien Neil316febd2020-02-09 12:26:50 -0800111 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
Damien Neilce413af2019-12-05 16:36:28 -0800112 p, info := getInfo(p)
113 if info == nil || info.funcs.isInit == nil {
114 return nil
115 }
Damien Neil316febd2020-02-09 12:26:50 -0800116 return info.funcs.isInit(p, info)
Damien Neilce413af2019-12-05 16:36:28 -0800117 }
118 }
Damien Neilc37adef2019-04-01 13:49:56 -0700119}
120
Joe Tsai6e095992019-08-10 13:56:36 -0700121func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
122 var once sync.Once
123 var messageType pref.MessageType
124 lazyInit := func() {
125 once.Do(func() {
126 messageName := fd.Message().FullName()
127 messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
128 })
129 }
130
Joe Tsai6e095992019-08-10 13:56:36 -0700131 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800132 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neile8e88752020-02-11 11:25:16 -0800133 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700134 if !ok {
135 return 0
136 }
Damien Neil6e40b322019-10-01 13:05:16 -0700137 lazyInit()
138 if messageType == nil {
139 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
140 }
Damien Neil316febd2020-02-09 12:26:50 -0800141 return sizeMessage(m, f.tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700142 },
Damien Neil316febd2020-02-09 12:26:50 -0800143 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neile8e88752020-02-11 11:25:16 -0800144 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700145 if !ok {
146 return b, nil
147 }
Damien Neil6e40b322019-10-01 13:05:16 -0700148 lazyInit()
149 if messageType == nil {
150 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
151 }
Damien Neil316febd2020-02-09 12:26:50 -0800152 return appendMessage(b, m, f.wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700153 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800154 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6e095992019-08-10 13:56:36 -0700155 fs := p.WeakFields()
Damien Neile8e88752020-02-11 11:25:16 -0800156 m, ok := fs.get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700157 if !ok {
158 lazyInit()
159 if messageType == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800160 return unmarshalOutput{}, errUnknown
Joe Tsai6e095992019-08-10 13:56:36 -0700161 }
Damien Neil6e40b322019-10-01 13:05:16 -0700162 m = messageType.New().Interface()
Damien Neile8e88752020-02-11 11:25:16 -0800163 fs.set(f.num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700164 }
Damien Neil6e40b322019-10-01 13:05:16 -0700165 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700166 },
Damien Neil316febd2020-02-09 12:26:50 -0800167 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neile8e88752020-02-11 11:25:16 -0800168 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700169 if !ok {
170 return nil
171 }
Joe Tsaif26a9e72020-02-20 10:05:37 -0800172 return proto.CheckInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700173 },
Damien Neile8e88752020-02-11 11:25:16 -0800174 merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
175 sm, ok := src.WeakFields().get(f.num)
176 if !ok {
177 return
178 }
179 dm, ok := dst.WeakFields().get(f.num)
180 if !ok {
181 lazyInit()
182 if messageType == nil {
183 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
184 }
185 dm = messageType.New().Interface()
186 dst.WeakFields().set(f.num, dm)
187 }
188 opts.Merge(dm, sm)
189 },
Joe Tsai6e095992019-08-10 13:56:36 -0700190 }
191}
192
Damien Neilc37adef2019-04-01 13:49:56 -0700193func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700194 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800195 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800196 size: sizeMessageInfo,
197 marshal: appendMessageInfo,
198 unmarshal: consumeMessageInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800199 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700200 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800201 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800202 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800203 }
204 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700205 } else {
206 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800207 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700208 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800209 return sizeMessage(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700210 },
Damien Neil316febd2020-02-09 12:26:50 -0800211 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700212 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800213 return appendMessage(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700214 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800215 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700216 mp := p.AsValueOf(ft).Elem()
217 if mp.IsNil() {
218 mp.Set(reflect.New(ft.Elem()))
219 }
220 return consumeMessage(b, asMessage(mp), wtyp, opts)
221 },
Damien Neil316febd2020-02-09 12:26:50 -0800222 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700223 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800224 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700225 },
Damien Neile8e88752020-02-11 11:25:16 -0800226 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700227 }
228 }
229}
230
Damien Neil316febd2020-02-09 12:26:50 -0800231func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Joe Tsaicd108d02020-02-14 18:08:02 -0800232 return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700233}
234
Damien Neil316febd2020-02-09 12:26:50 -0800235func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800236 b = protowire.AppendVarint(b, f.wiretag)
237 b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
Damien Neil316febd2020-02-09 12:26:50 -0800238 return f.mi.marshalAppendPointer(b, p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700239}
240
Joe Tsaicd108d02020-02-14 18:08:02 -0800241func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
242 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800243 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700244 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800245 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700246 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700247 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700248 }
249 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800250 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700251 }
Damien Neil316febd2020-02-09 12:26:50 -0800252 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800253 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800254 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700255 }
Damien Neilf0831e82020-01-21 14:25:12 -0800256 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800257 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800258 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700259}
260
Damien Neil316febd2020-02-09 12:26:50 -0800261func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800262 return f.mi.checkInitializedPointer(p.Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800263}
264
Damien Neilc37adef2019-04-01 13:49:56 -0700265func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
Joe Tsaicd108d02020-02-14 18:08:02 -0800266 return protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700267}
268
269func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800270 b = protowire.AppendVarint(b, wiretag)
271 b = protowire.AppendVarint(b, uint64(proto.Size(m)))
Damien Neilc37adef2019-04-01 13:49:56 -0700272 return opts.Options().MarshalAppend(b, m)
273}
274
Joe Tsaicd108d02020-02-14 18:08:02 -0800275func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
276 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800277 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700278 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800279 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700280 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700281 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700282 }
Joe Tsaie05f7892020-03-09 12:01:52 -0700283 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
284 Buf: v,
285 Message: m.ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800286 })
287 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800288 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700289 }
Damien Neilf0831e82020-01-21 14:25:12 -0800290 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800291 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800292 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700293}
294
Damien Neil68b81c32019-08-22 11:41:32 -0700295func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
296 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700297 return sizeMessage(m, tagsize, opts)
298}
299
Damien Neil68b81c32019-08-22 11:41:32 -0700300func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
301 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700302 return appendMessage(b, m, wiretag, opts)
303}
304
Joe Tsaicd108d02020-02-14 18:08:02 -0800305func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700306 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800307 out, err := consumeMessage(b, m, wtyp, opts)
308 return v, out, err
Damien Neile91877d2019-06-27 10:54:42 -0700309}
310
Damien Neil68b81c32019-08-22 11:41:32 -0700311func isInitMessageValue(v pref.Value) error {
312 m := v.Message().Interface()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800313 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700314}
315
Damien Neil68b81c32019-08-22 11:41:32 -0700316var coderMessageValue = valueCoderFuncs{
317 size: sizeMessageValue,
318 marshal: appendMessageValue,
319 unmarshal: consumeMessageValue,
320 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800321 merge: mergeMessageValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700322}
323
324func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
325 m := v.Message().Interface()
326 return sizeGroup(m, tagsize, opts)
327}
328
329func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
330 m := v.Message().Interface()
331 return appendGroup(b, m, wiretag, opts)
332}
333
Joe Tsaicd108d02020-02-14 18:08:02 -0800334func 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 -0700335 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800336 out, err := consumeGroup(b, m, num, wtyp, opts)
337 return v, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700338}
339
340var coderGroupValue = valueCoderFuncs{
341 size: sizeGroupValue,
342 marshal: appendGroupValue,
343 unmarshal: consumeGroupValue,
344 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800345 merge: mergeMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700346}
347
348func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700349 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700350 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800351 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800352 size: sizeGroupType,
353 marshal: appendGroupType,
354 unmarshal: consumeGroupType,
Damien Neile8e88752020-02-11 11:25:16 -0800355 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700356 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800357 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800358 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800359 }
360 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700361 } else {
362 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800363 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700364 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800365 return sizeGroup(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700366 },
Damien Neil316febd2020-02-09 12:26:50 -0800367 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700368 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800369 return appendGroup(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700370 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800371 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700372 mp := p.AsValueOf(ft).Elem()
373 if mp.IsNil() {
374 mp.Set(reflect.New(ft.Elem()))
375 }
376 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
377 },
Damien Neil316febd2020-02-09 12:26:50 -0800378 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700379 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800380 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700381 },
Damien Neile8e88752020-02-11 11:25:16 -0800382 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700383 }
384 }
385}
386
Damien Neil316febd2020-02-09 12:26:50 -0800387func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
388 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700389}
390
Damien Neil316febd2020-02-09 12:26:50 -0800391func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800392 b = protowire.AppendVarint(b, f.wiretag) // start group
Damien Neil316febd2020-02-09 12:26:50 -0800393 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800394 b = protowire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700395 return b, err
396}
397
Joe Tsaicd108d02020-02-14 18:08:02 -0800398func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
399 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800400 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700401 }
402 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800403 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700404 }
Damien Neil316febd2020-02-09 12:26:50 -0800405 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700406}
407
Damien Neilc37adef2019-04-01 13:49:56 -0700408func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
409 return 2*tagsize + proto.Size(m)
410}
411
412func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsaicd108d02020-02-14 18:08:02 -0800413 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neilc37adef2019-04-01 13:49:56 -0700414 b, err := opts.Options().MarshalAppend(b, m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800415 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700416 return b, err
417}
418
Joe Tsaicd108d02020-02-14 18:08:02 -0800419func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
420 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800421 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700422 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800423 b, n := protowire.ConsumeGroup(num, b)
Damien Neile91877d2019-06-27 10:54:42 -0700424 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700425 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700426 }
Joe Tsaie05f7892020-03-09 12:01:52 -0700427 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
428 Buf: b,
429 Message: m.ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800430 })
431 if err != nil {
432 return out, err
433 }
Damien Neilf0831e82020-01-21 14:25:12 -0800434 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800435 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilc600d6c2020-01-21 15:00:33 -0800436 return out, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700437}
438
Damien Neilc37adef2019-04-01 13:49:56 -0700439func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700440 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800441 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800442 size: sizeMessageSliceInfo,
443 marshal: appendMessageSliceInfo,
444 unmarshal: consumeMessageSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800445 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700446 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800447 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800448 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800449 }
450 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700451 }
452 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800453 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
454 return sizeMessageSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700455 },
Damien Neil316febd2020-02-09 12:26:50 -0800456 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
457 return appendMessageSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700458 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800459 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700460 return consumeMessageSlice(b, p, ft, wtyp, opts)
461 },
Damien Neil316febd2020-02-09 12:26:50 -0800462 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700463 return isInitMessageSlice(p, ft)
464 },
Damien Neile8e88752020-02-11 11:25:16 -0800465 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700466 }
467}
468
Damien Neil316febd2020-02-09 12:26:50 -0800469func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700470 s := p.PointerSlice()
471 n := 0
472 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800473 n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700474 }
475 return n
476}
477
Damien Neil316febd2020-02-09 12:26:50 -0800478func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700479 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700480 var err error
481 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800482 b = protowire.AppendVarint(b, f.wiretag)
Damien Neil316febd2020-02-09 12:26:50 -0800483 siz := f.mi.sizePointer(v, opts)
Joe Tsaicd108d02020-02-14 18:08:02 -0800484 b = protowire.AppendVarint(b, uint64(siz))
Damien Neil316febd2020-02-09 12:26:50 -0800485 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700486 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700487 return b, err
488 }
489 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700490 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700491}
492
Joe Tsaicd108d02020-02-14 18:08:02 -0800493func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
494 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800495 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700496 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800497 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700498 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700499 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700500 }
Damien Neil316febd2020-02-09 12:26:50 -0800501 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700502 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800503 o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800504 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800505 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700506 }
507 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800508 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800509 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800510 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700511}
512
Damien Neil316febd2020-02-09 12:26:50 -0800513func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700514 s := p.PointerSlice()
515 for _, v := range s {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800516 if err := f.mi.checkInitializedPointer(v); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700517 return err
518 }
519 }
520 return nil
521}
522
Damien Neilc37adef2019-04-01 13:49:56 -0700523func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
524 s := p.PointerSlice()
525 n := 0
526 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700527 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800528 n += protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700529 }
530 return n
531}
532
533func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
534 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700535 var err error
536 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700537 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800538 b = protowire.AppendVarint(b, wiretag)
Damien Neilc37adef2019-04-01 13:49:56 -0700539 siz := proto.Size(m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800540 b = protowire.AppendVarint(b, uint64(siz))
Damien Neilc37adef2019-04-01 13:49:56 -0700541 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700542 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700543 return b, err
544 }
545 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700546 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700547}
548
Joe Tsaicd108d02020-02-14 18:08:02 -0800549func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
550 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800551 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700552 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800553 v, n := protowire.ConsumeBytes(b)
Damien Neile91877d2019-06-27 10:54:42 -0700554 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700555 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700556 }
557 mp := reflect.New(goType.Elem())
Joe Tsaie05f7892020-03-09 12:01:52 -0700558 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
559 Buf: v,
560 Message: asMessage(mp).ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800561 })
562 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800563 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700564 }
565 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800566 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800567 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800568 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700569}
570
Damien Neil5322bdb2019-04-09 15:57:05 -0700571func isInitMessageSlice(p pointer, goType reflect.Type) error {
572 s := p.PointerSlice()
573 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700574 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaif26a9e72020-02-20 10:05:37 -0800575 if err := proto.CheckInitialized(m); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700576 return err
577 }
578 }
579 return nil
580}
581
Damien Neilc37adef2019-04-01 13:49:56 -0700582// Slices of messages
583
Damien Neil68b81c32019-08-22 11:41:32 -0700584func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
585 list := listv.List()
586 n := 0
587 for i, llen := 0, list.Len(); i < llen; i++ {
588 m := list.Get(i).Message().Interface()
Joe Tsaicd108d02020-02-14 18:08:02 -0800589 n += protowire.SizeBytes(proto.Size(m)) + tagsize
Damien Neil68b81c32019-08-22 11:41:32 -0700590 }
591 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700592}
593
Damien Neil68b81c32019-08-22 11:41:32 -0700594func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
595 list := listv.List()
596 mopts := opts.Options()
597 for i, llen := 0, list.Len(); i < llen; i++ {
598 m := list.Get(i).Message().Interface()
Joe Tsaicd108d02020-02-14 18:08:02 -0800599 b = protowire.AppendVarint(b, wiretag)
Damien Neil68b81c32019-08-22 11:41:32 -0700600 siz := proto.Size(m)
Joe Tsaicd108d02020-02-14 18:08:02 -0800601 b = protowire.AppendVarint(b, uint64(siz))
Damien Neil68b81c32019-08-22 11:41:32 -0700602 var err error
603 b, err = mopts.MarshalAppend(b, m)
604 if err != nil {
605 return b, err
606 }
607 }
608 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700609}
610
Joe Tsaicd108d02020-02-14 18:08:02 -0800611func 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 -0700612 list := listv.List()
Joe Tsaicd108d02020-02-14 18:08:02 -0800613 if wtyp != protowire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800614 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700615 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800616 v, n := protowire.ConsumeBytes(b)
Damien Neil68b81c32019-08-22 11:41:32 -0700617 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700618 return pref.Value{}, out, errDecode
Damien Neil68b81c32019-08-22 11:41:32 -0700619 }
620 m := list.NewElement()
Joe Tsaie05f7892020-03-09 12:01:52 -0700621 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
622 Buf: v,
623 Message: m.Message(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800624 })
625 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800626 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700627 }
628 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800629 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800630 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800631 return listv, out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700632}
633
Damien Neil68b81c32019-08-22 11:41:32 -0700634func isInitMessageSliceValue(listv pref.Value) error {
635 list := listv.List()
636 for i, llen := 0, list.Len(); i < llen; i++ {
637 m := list.Get(i).Message().Interface()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800638 if err := proto.CheckInitialized(m); err != nil {
Damien Neil68b81c32019-08-22 11:41:32 -0700639 return err
640 }
641 }
642 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700643}
644
Damien Neil68b81c32019-08-22 11:41:32 -0700645var coderMessageSliceValue = valueCoderFuncs{
646 size: sizeMessageSliceValue,
647 marshal: appendMessageSliceValue,
648 unmarshal: consumeMessageSliceValue,
649 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800650 merge: mergeMessageListValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700651}
652
653func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
654 list := listv.List()
655 n := 0
656 for i, llen := 0, list.Len(); i < llen; i++ {
657 m := list.Get(i).Message().Interface()
658 n += 2*tagsize + proto.Size(m)
659 }
660 return n
661}
662
663func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
664 list := listv.List()
665 mopts := opts.Options()
666 for i, llen := 0, list.Len(); i < llen; i++ {
667 m := list.Get(i).Message().Interface()
Joe Tsaicd108d02020-02-14 18:08:02 -0800668 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neil68b81c32019-08-22 11:41:32 -0700669 var err error
670 b, err = mopts.MarshalAppend(b, m)
671 if err != nil {
672 return b, err
673 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800674 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neil68b81c32019-08-22 11:41:32 -0700675 }
676 return b, nil
677}
678
Joe Tsaicd108d02020-02-14 18:08:02 -0800679func 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 -0700680 list := listv.List()
Joe Tsaicd108d02020-02-14 18:08:02 -0800681 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800682 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700683 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800684 b, n := protowire.ConsumeGroup(num, b)
Damien Neil68b81c32019-08-22 11:41:32 -0700685 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700686 return pref.Value{}, out, errDecode
Damien Neil68b81c32019-08-22 11:41:32 -0700687 }
688 m := list.NewElement()
Joe Tsaie05f7892020-03-09 12:01:52 -0700689 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
690 Buf: b,
691 Message: m.Message(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800692 })
693 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800694 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700695 }
696 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800697 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800698 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800699 return listv, out, nil
Damien Neil68b81c32019-08-22 11:41:32 -0700700}
701
702var coderGroupSliceValue = valueCoderFuncs{
703 size: sizeGroupSliceValue,
704 marshal: appendGroupSliceValue,
705 unmarshal: consumeGroupSliceValue,
706 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800707 merge: mergeMessageListValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700708}
709
710func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700711 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700712 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800713 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800714 size: sizeGroupSliceInfo,
715 marshal: appendGroupSliceInfo,
716 unmarshal: consumeGroupSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800717 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700718 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800719 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800720 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800721 }
722 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700723 }
724 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800725 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
726 return sizeGroupSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700727 },
Damien Neil316febd2020-02-09 12:26:50 -0800728 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
729 return appendGroupSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700730 },
Joe Tsaicd108d02020-02-14 18:08:02 -0800731 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700732 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
733 },
Damien Neil316febd2020-02-09 12:26:50 -0800734 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700735 return isInitMessageSlice(p, ft)
736 },
Damien Neile8e88752020-02-11 11:25:16 -0800737 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700738 }
739}
740
741func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
742 s := p.PointerSlice()
743 n := 0
744 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700745 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700746 n += 2*tagsize + proto.Size(m)
747 }
748 return n
749}
750
751func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
752 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700753 var err error
754 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700755 m := asMessage(v.AsValueOf(messageType.Elem()))
Joe Tsaicd108d02020-02-14 18:08:02 -0800756 b = protowire.AppendVarint(b, wiretag) // start group
Damien Neilc37adef2019-04-01 13:49:56 -0700757 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700758 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700759 return b, err
760 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800761 b = protowire.AppendVarint(b, wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700762 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700763 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700764}
765
Joe Tsaicd108d02020-02-14 18:08:02 -0800766func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
767 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800768 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700769 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800770 b, n := protowire.ConsumeGroup(num, b)
Damien Neile91877d2019-06-27 10:54:42 -0700771 if n < 0 {
Damien Neilb5523e32020-07-22 09:10:20 -0700772 return out, errDecode
Damien Neile91877d2019-06-27 10:54:42 -0700773 }
774 mp := reflect.New(goType.Elem())
Joe Tsaie05f7892020-03-09 12:01:52 -0700775 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
776 Buf: b,
777 Message: asMessage(mp).ProtoReflect(),
Damien Neilc600d6c2020-01-21 15:00:33 -0800778 })
779 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800780 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700781 }
782 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800783 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800784 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800785 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700786}
787
Damien Neil316febd2020-02-09 12:26:50 -0800788func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700789 s := p.PointerSlice()
790 n := 0
791 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800792 n += 2*f.tagsize + f.mi.sizePointer(v, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700793 }
794 return n
795}
796
Damien Neil316febd2020-02-09 12:26:50 -0800797func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700798 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700799 var err error
800 for _, v := range s {
Joe Tsaicd108d02020-02-14 18:08:02 -0800801 b = protowire.AppendVarint(b, f.wiretag) // start group
Damien Neil316febd2020-02-09 12:26:50 -0800802 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700803 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700804 return b, err
805 }
Joe Tsaicd108d02020-02-14 18:08:02 -0800806 b = protowire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700807 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700808 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700809}
810
Joe Tsaicd108d02020-02-14 18:08:02 -0800811func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
812 if wtyp != protowire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800813 return unmarshalOutput{}, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700814 }
Damien Neil316febd2020-02-09 12:26:50 -0800815 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700816 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800817 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700818 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800819 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700820 }
821 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800822 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700823}
824
Damien Neil5b6d0472019-06-14 11:54:07 -0700825func asMessage(v reflect.Value) pref.ProtoMessage {
826 if m, ok := v.Interface().(pref.ProtoMessage); ok {
827 return m
828 }
Joe Tsaia75c9142020-04-01 11:47:49 -0700829 return legacyWrapMessage(v).Interface()
Damien Neil5b6d0472019-06-14 11:54:07 -0700830}