blob: 3f3957ce4aab7413f374cd43d1e77c33081bc7e9 [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
12 "google.golang.org/protobuf/internal/encoding/wire"
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 Neilc37adef2019-04-01 13:49:56 -070016)
17
18type errInvalidUTF8 struct{}
19
20func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
21func (errInvalidUTF8) InvalidUTF8() bool { return true }
22
Damien Neilce413af2019-12-05 16:36:28 -080023// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof.
24//
25// For size, marshal, and isInit operations, functions are set only on the first field
26// in the oneof. The functions are called when the oneof is non-nil, and will dispatch
27// to the appropriate field-specific function as necessary.
28//
29// The unmarshal function is set on each field individually as usual.
30func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) {
31 type oneofFieldInfo struct {
32 wiretag uint64 // field tag (number + wire type)
33 tagsize int // size of the varint-encoded tag
34 funcs pointerCoderFuncs
Damien Neil5322bdb2019-04-09 15:57:05 -070035 }
Damien Neilce413af2019-12-05 16:36:28 -080036 fs := si.oneofsByName[od.Name()]
37 ft := fs.Type
38 oneofFields := make(map[reflect.Type]*oneofFieldInfo)
39 needIsInit := false
40 fields := od.Fields()
41 for i, lim := 0, fields.Len(); i < lim; i++ {
42 fd := od.Fields().Get(i)
43 num := fd.Number()
44 cf := mi.coderFields[num]
45 ot := si.oneofWrappersByNumber[num]
46 funcs := fieldCoder(fd, ot.Field(0).Type)
47 oneofFields[ot] = &oneofFieldInfo{
48 wiretag: cf.wiretag,
49 tagsize: cf.tagsize,
50 funcs: funcs,
51 }
52 if funcs.isInit != nil {
53 needIsInit = true
54 }
55 cf.funcs.unmarshal = func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070056 var vw reflect.Value // pointer to wrapper type
57 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
58 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
59 vw = vi.Elem()
60 } else {
61 vw = reflect.New(ot)
62 }
63 n, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070064 if err != nil {
65 return 0, err
Damien Neilc37adef2019-04-01 13:49:56 -070066 }
Joe Tsai6c286742019-07-11 23:15:05 -070067 vi.Set(vw)
Damien Neile91877d2019-06-27 10:54:42 -070068 return n, nil
Damien Neile91877d2019-06-27 10:54:42 -070069 }
70 }
Damien Neilce413af2019-12-05 16:36:28 -080071 getInfo := func(p pointer) (pointer, *oneofFieldInfo) {
72 v := p.AsValueOf(ft).Elem()
73 if v.IsNil() {
74 return pointer{}, nil
75 }
76 v = v.Elem() // interface -> *struct
77 if v.IsNil() {
78 return pointer{}, nil
79 }
80 return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()]
81 }
82 first := mi.coderFields[od.Fields().Get(0).Number()]
83 first.funcs.size = func(p pointer, tagsize int, opts marshalOptions) int {
84 p, info := getInfo(p)
85 if info == nil || info.funcs.size == nil {
86 return 0
87 }
88 return info.funcs.size(p, info.tagsize, opts)
89 }
90 first.funcs.marshal = func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
91 p, info := getInfo(p)
92 if info == nil || info.funcs.marshal == nil {
93 return b, nil
94 }
95 return info.funcs.marshal(b, p, info.wiretag, opts)
96 }
97 if needIsInit {
98 first.funcs.isInit = func(p pointer) error {
99 p, info := getInfo(p)
100 if info == nil || info.funcs.isInit == nil {
101 return nil
102 }
103 return info.funcs.isInit(p)
104 }
105 }
Damien Neilc37adef2019-04-01 13:49:56 -0700106}
107
Joe Tsai6e095992019-08-10 13:56:36 -0700108func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
109 var once sync.Once
110 var messageType pref.MessageType
111 lazyInit := func() {
112 once.Do(func() {
113 messageName := fd.Message().FullName()
114 messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
115 })
116 }
117
Damien Neil6e40b322019-10-01 13:05:16 -0700118 num := fd.Number()
Joe Tsai6e095992019-08-10 13:56:36 -0700119 return pointerCoderFuncs{
120 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil6e40b322019-10-01 13:05:16 -0700121 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700122 if !ok {
123 return 0
124 }
Damien Neil6e40b322019-10-01 13:05:16 -0700125 lazyInit()
126 if messageType == nil {
127 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
128 }
129 return sizeMessage(m, tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700130 },
131 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil6e40b322019-10-01 13:05:16 -0700132 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700133 if !ok {
134 return b, nil
135 }
Damien Neil6e40b322019-10-01 13:05:16 -0700136 lazyInit()
137 if messageType == nil {
138 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
139 }
140 return appendMessage(b, m, wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700141 },
142 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
143 fs := p.WeakFields()
Damien Neil6e40b322019-10-01 13:05:16 -0700144 m, ok := fs.get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700145 if !ok {
146 lazyInit()
147 if messageType == nil {
148 return 0, errUnknown
149 }
Damien Neil6e40b322019-10-01 13:05:16 -0700150 m = messageType.New().Interface()
151 fs.set(num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700152 }
Damien Neil6e40b322019-10-01 13:05:16 -0700153 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700154 },
155 isInit: func(p pointer) error {
Damien Neil6e40b322019-10-01 13:05:16 -0700156 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700157 if !ok {
158 return nil
159 }
Damien Neil6e40b322019-10-01 13:05:16 -0700160 return proto.IsInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700161 },
162 }
163}
164
Damien Neilc37adef2019-04-01 13:49:56 -0700165func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700166 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800167 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700168 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700169 return sizeMessageInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700170 },
171 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700172 return appendMessageInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700173 },
Damien Neile91877d2019-06-27 10:54:42 -0700174 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700175 return consumeMessageInfo(b, p, mi, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700176 },
Damien Neilc37adef2019-04-01 13:49:56 -0700177 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800178 if needsInitCheck(mi.Desc) {
179 funcs.isInit = func(p pointer) error {
180 return mi.isInitializedPointer(p.Elem())
181 }
182 }
183 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700184 } else {
185 return pointerCoderFuncs{
186 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700187 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700188 return sizeMessage(m, tagsize, opts)
189 },
190 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700191 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700192 return appendMessage(b, m, wiretag, opts)
193 },
Damien Neile91877d2019-06-27 10:54:42 -0700194 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
195 mp := p.AsValueOf(ft).Elem()
196 if mp.IsNil() {
197 mp.Set(reflect.New(ft.Elem()))
198 }
199 return consumeMessage(b, asMessage(mp), wtyp, opts)
200 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700201 isInit: func(p pointer) error {
202 m := asMessage(p.AsValueOf(ft).Elem())
203 return proto.IsInitialized(m)
204 },
Damien Neilc37adef2019-04-01 13:49:56 -0700205 }
206 }
207}
208
Joe Tsai4fe96632019-05-22 05:12:36 -0400209func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700210 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
211}
212
Joe Tsai4fe96632019-05-22 05:12:36 -0400213func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700214 b = wire.AppendVarint(b, wiretag)
215 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
216 return mi.marshalAppendPointer(b, p.Elem(), opts)
217}
218
Damien Neile91877d2019-06-27 10:54:42 -0700219func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
220 if wtyp != wire.BytesType {
221 return 0, errUnknown
222 }
223 v, n := wire.ConsumeBytes(b)
224 if n < 0 {
225 return 0, wire.ParseError(n)
226 }
227 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700228 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700229 }
230 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
231 return 0, err
232 }
233 return n, nil
234}
235
Damien Neilc37adef2019-04-01 13:49:56 -0700236func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
237 return wire.SizeBytes(proto.Size(m)) + tagsize
238}
239
240func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
241 b = wire.AppendVarint(b, wiretag)
242 b = wire.AppendVarint(b, uint64(proto.Size(m)))
243 return opts.Options().MarshalAppend(b, m)
244}
245
Damien Neile91877d2019-06-27 10:54:42 -0700246func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
247 if wtyp != wire.BytesType {
248 return 0, errUnknown
249 }
250 v, n := wire.ConsumeBytes(b)
251 if n < 0 {
252 return 0, wire.ParseError(n)
253 }
254 if err := opts.Options().Unmarshal(v, m); err != nil {
255 return 0, err
256 }
257 return n, nil
258}
259
Damien Neil68b81c32019-08-22 11:41:32 -0700260func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
261 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700262 return sizeMessage(m, tagsize, opts)
263}
264
Damien Neil68b81c32019-08-22 11:41:32 -0700265func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
266 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700267 return appendMessage(b, m, wiretag, opts)
268}
269
Damien Neil68b81c32019-08-22 11:41:32 -0700270func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
271 m := v.Message().Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700272 n, err := consumeMessage(b, m, wtyp, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700273 return v, n, err
Damien Neile91877d2019-06-27 10:54:42 -0700274}
275
Damien Neil68b81c32019-08-22 11:41:32 -0700276func isInitMessageValue(v pref.Value) error {
277 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700278 return proto.IsInitialized(m)
279}
280
Damien Neil68b81c32019-08-22 11:41:32 -0700281var coderMessageValue = valueCoderFuncs{
282 size: sizeMessageValue,
283 marshal: appendMessageValue,
284 unmarshal: consumeMessageValue,
285 isInit: isInitMessageValue,
286}
287
288func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
289 m := v.Message().Interface()
290 return sizeGroup(m, tagsize, opts)
291}
292
293func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
294 m := v.Message().Interface()
295 return appendGroup(b, m, wiretag, opts)
296}
297
298func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
299 m := v.Message().Interface()
300 n, err := consumeGroup(b, m, num, wtyp, opts)
301 return v, n, err
302}
303
304var coderGroupValue = valueCoderFuncs{
305 size: sizeGroupValue,
306 marshal: appendGroupValue,
307 unmarshal: consumeGroupValue,
308 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700309}
310
311func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700312 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700313 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800314 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700315 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700316 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700317 },
318 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700319 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700320 },
Damien Neile91877d2019-06-27 10:54:42 -0700321 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700322 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700323 },
Damien Neilc37adef2019-04-01 13:49:56 -0700324 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800325 if needsInitCheck(mi.Desc) {
326 funcs.isInit = func(p pointer) error {
327 return mi.isInitializedPointer(p.Elem())
328 }
329 }
330 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700331 } else {
332 return pointerCoderFuncs{
333 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700334 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700335 return sizeGroup(m, tagsize, opts)
336 },
337 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700338 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700339 return appendGroup(b, m, wiretag, opts)
340 },
Damien Neile91877d2019-06-27 10:54:42 -0700341 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
342 mp := p.AsValueOf(ft).Elem()
343 if mp.IsNil() {
344 mp.Set(reflect.New(ft.Elem()))
345 }
346 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
347 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700348 isInit: func(p pointer) error {
349 m := asMessage(p.AsValueOf(ft).Elem())
350 return proto.IsInitialized(m)
351 },
Damien Neilc37adef2019-04-01 13:49:56 -0700352 }
353 }
354}
355
Joe Tsai4fe96632019-05-22 05:12:36 -0400356func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700357 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
358}
359
Joe Tsai4fe96632019-05-22 05:12:36 -0400360func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700361 b = wire.AppendVarint(b, wiretag) // start group
362 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
363 b = wire.AppendVarint(b, wiretag+1) // end group
364 return b, err
365}
366
Damien Neile91877d2019-06-27 10:54:42 -0700367func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
368 if wtyp != wire.StartGroupType {
369 return 0, errUnknown
370 }
371 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700372 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700373 }
374 return mi.unmarshalPointer(b, p.Elem(), num, opts)
375}
376
Damien Neilc37adef2019-04-01 13:49:56 -0700377func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
378 return 2*tagsize + proto.Size(m)
379}
380
381func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
382 b = wire.AppendVarint(b, wiretag) // start group
383 b, err := opts.Options().MarshalAppend(b, m)
384 b = wire.AppendVarint(b, wiretag+1) // end group
385 return b, err
386}
387
Damien Neile91877d2019-06-27 10:54:42 -0700388func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
389 if wtyp != wire.StartGroupType {
390 return 0, errUnknown
391 }
392 b, n := wire.ConsumeGroup(num, b)
393 if n < 0 {
394 return 0, wire.ParseError(n)
395 }
396 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700397}
398
Damien Neilc37adef2019-04-01 13:49:56 -0700399func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700400 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800401 funcs := pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700402 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700403 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700404 },
Damien Neilc37adef2019-04-01 13:49:56 -0700405 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700406 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700407 },
Damien Neile91877d2019-06-27 10:54:42 -0700408 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700409 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700410 },
411 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800412 if needsInitCheck(mi.Desc) {
413 funcs.isInit = func(p pointer) error {
414 return isInitMessageSliceInfo(p, mi)
415 }
416 }
417 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700418 }
419 return pointerCoderFuncs{
420 size: func(p pointer, tagsize int, opts marshalOptions) int {
421 return sizeMessageSlice(p, ft, tagsize, opts)
422 },
423 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
424 return appendMessageSlice(b, p, wiretag, ft, opts)
425 },
Damien Neile91877d2019-06-27 10:54:42 -0700426 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
427 return consumeMessageSlice(b, p, ft, wtyp, opts)
428 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700429 isInit: func(p pointer) error {
430 return isInitMessageSlice(p, ft)
431 },
Damien Neilc37adef2019-04-01 13:49:56 -0700432 }
433}
434
Joe Tsai4fe96632019-05-22 05:12:36 -0400435func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700436 s := p.PointerSlice()
437 n := 0
438 for _, v := range s {
439 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
440 }
441 return n
442}
443
Joe Tsai4fe96632019-05-22 05:12:36 -0400444func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700445 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700446 var err error
447 for _, v := range s {
448 b = wire.AppendVarint(b, wiretag)
449 siz := mi.sizePointer(v, opts)
450 b = wire.AppendVarint(b, uint64(siz))
451 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700452 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700453 return b, err
454 }
455 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700456 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700457}
458
Damien Neile91877d2019-06-27 10:54:42 -0700459func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
460 if wtyp != wire.BytesType {
461 return 0, errUnknown
462 }
463 v, n := wire.ConsumeBytes(b)
464 if n < 0 {
465 return 0, wire.ParseError(n)
466 }
Damien Neil16163b42019-08-06 15:43:25 -0700467 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700468 mp := pointerOfIface(m)
469 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
470 return 0, err
471 }
472 p.AppendPointerSlice(mp)
473 return n, nil
474}
475
Damien Neil5322bdb2019-04-09 15:57:05 -0700476func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
477 s := p.PointerSlice()
478 for _, v := range s {
479 if err := mi.isInitializedPointer(v); err != nil {
480 return err
481 }
482 }
483 return nil
484}
485
Damien Neilc37adef2019-04-01 13:49:56 -0700486func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
487 s := p.PointerSlice()
488 n := 0
489 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700490 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700491 n += wire.SizeBytes(proto.Size(m)) + tagsize
492 }
493 return n
494}
495
496func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
497 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700498 var err error
499 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700500 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700501 b = wire.AppendVarint(b, wiretag)
502 siz := proto.Size(m)
503 b = wire.AppendVarint(b, uint64(siz))
504 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700505 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700506 return b, err
507 }
508 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700509 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700510}
511
Damien Neile91877d2019-06-27 10:54:42 -0700512func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
513 if wtyp != wire.BytesType {
514 return 0, errUnknown
515 }
516 v, n := wire.ConsumeBytes(b)
517 if n < 0 {
518 return 0, wire.ParseError(n)
519 }
520 mp := reflect.New(goType.Elem())
521 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
522 return 0, err
523 }
524 p.AppendPointerSlice(pointerOfValue(mp))
525 return n, nil
526}
527
Damien Neil5322bdb2019-04-09 15:57:05 -0700528func isInitMessageSlice(p pointer, goType reflect.Type) error {
529 s := p.PointerSlice()
530 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700531 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700532 if err := proto.IsInitialized(m); err != nil {
533 return err
534 }
535 }
536 return nil
537}
538
Damien Neilc37adef2019-04-01 13:49:56 -0700539// Slices of messages
540
Damien Neil68b81c32019-08-22 11:41:32 -0700541func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
542 list := listv.List()
543 n := 0
544 for i, llen := 0, list.Len(); i < llen; i++ {
545 m := list.Get(i).Message().Interface()
546 n += wire.SizeBytes(proto.Size(m)) + tagsize
547 }
548 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700549}
550
Damien Neil68b81c32019-08-22 11:41:32 -0700551func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
552 list := listv.List()
553 mopts := opts.Options()
554 for i, llen := 0, list.Len(); i < llen; i++ {
555 m := list.Get(i).Message().Interface()
556 b = wire.AppendVarint(b, wiretag)
557 siz := proto.Size(m)
558 b = wire.AppendVarint(b, uint64(siz))
559 var err error
560 b, err = mopts.MarshalAppend(b, m)
561 if err != nil {
562 return b, err
563 }
564 }
565 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700566}
567
Damien Neil68b81c32019-08-22 11:41:32 -0700568func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
569 list := listv.List()
570 if wtyp != wire.BytesType {
571 return pref.Value{}, 0, errUnknown
572 }
573 v, n := wire.ConsumeBytes(b)
574 if n < 0 {
575 return pref.Value{}, 0, wire.ParseError(n)
576 }
577 m := list.NewElement()
578 if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
579 return pref.Value{}, 0, err
580 }
581 list.Append(m)
582 return listv, n, nil
Damien Neile91877d2019-06-27 10:54:42 -0700583}
584
Damien Neil68b81c32019-08-22 11:41:32 -0700585func isInitMessageSliceValue(listv pref.Value) error {
586 list := listv.List()
587 for i, llen := 0, list.Len(); i < llen; i++ {
588 m := list.Get(i).Message().Interface()
589 if err := proto.IsInitialized(m); err != nil {
590 return err
591 }
592 }
593 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700594}
595
Damien Neil68b81c32019-08-22 11:41:32 -0700596var coderMessageSliceValue = valueCoderFuncs{
597 size: sizeMessageSliceValue,
598 marshal: appendMessageSliceValue,
599 unmarshal: consumeMessageSliceValue,
600 isInit: isInitMessageSliceValue,
601}
602
603func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
604 list := listv.List()
605 n := 0
606 for i, llen := 0, list.Len(); i < llen; i++ {
607 m := list.Get(i).Message().Interface()
608 n += 2*tagsize + proto.Size(m)
609 }
610 return n
611}
612
613func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
614 list := listv.List()
615 mopts := opts.Options()
616 for i, llen := 0, list.Len(); i < llen; i++ {
617 m := list.Get(i).Message().Interface()
618 b = wire.AppendVarint(b, wiretag) // start group
619 var err error
620 b, err = mopts.MarshalAppend(b, m)
621 if err != nil {
622 return b, err
623 }
624 b = wire.AppendVarint(b, wiretag+1) // end group
625 }
626 return b, nil
627}
628
629func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
630 list := listv.List()
631 if wtyp != wire.StartGroupType {
632 return pref.Value{}, 0, errUnknown
633 }
634 b, n := wire.ConsumeGroup(num, b)
635 if n < 0 {
636 return pref.Value{}, 0, wire.ParseError(n)
637 }
638 m := list.NewElement()
639 if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
640 return pref.Value{}, 0, err
641 }
642 list.Append(m)
643 return listv, n, nil
644}
645
646var coderGroupSliceValue = valueCoderFuncs{
647 size: sizeGroupSliceValue,
648 marshal: appendGroupSliceValue,
649 unmarshal: consumeGroupSliceValue,
650 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700651}
652
653func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700654 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700655 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800656 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700657 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700658 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700659 },
660 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700661 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700662 },
Damien Neile91877d2019-06-27 10:54:42 -0700663 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700664 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700665 },
Damien Neilc37adef2019-04-01 13:49:56 -0700666 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800667 if needsInitCheck(mi.Desc) {
668 funcs.isInit = func(p pointer) error {
669 return isInitMessageSliceInfo(p, mi)
670 }
671 }
672 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700673 }
674 return pointerCoderFuncs{
675 size: func(p pointer, tagsize int, opts marshalOptions) int {
676 return sizeGroupSlice(p, ft, tagsize, opts)
677 },
678 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
679 return appendGroupSlice(b, p, wiretag, ft, opts)
680 },
Damien Neile91877d2019-06-27 10:54:42 -0700681 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
682 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
683 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700684 isInit: func(p pointer) error {
685 return isInitMessageSlice(p, ft)
686 },
Damien Neilc37adef2019-04-01 13:49:56 -0700687 }
688}
689
690func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
691 s := p.PointerSlice()
692 n := 0
693 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700694 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700695 n += 2*tagsize + proto.Size(m)
696 }
697 return n
698}
699
700func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
701 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700702 var err error
703 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700704 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700705 b = wire.AppendVarint(b, wiretag) // start group
706 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700707 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700708 return b, err
709 }
710 b = wire.AppendVarint(b, wiretag+1) // end group
711 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700712 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700713}
714
Damien Neile91877d2019-06-27 10:54:42 -0700715func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
716 if wtyp != wire.StartGroupType {
717 return 0, errUnknown
718 }
719 b, n := wire.ConsumeGroup(num, b)
720 if n < 0 {
721 return 0, wire.ParseError(n)
722 }
723 mp := reflect.New(goType.Elem())
724 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
725 return 0, err
726 }
727 p.AppendPointerSlice(pointerOfValue(mp))
728 return n, nil
729}
730
Joe Tsai4fe96632019-05-22 05:12:36 -0400731func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700732 s := p.PointerSlice()
733 n := 0
734 for _, v := range s {
735 n += 2*tagsize + mi.sizePointer(v, opts)
736 }
737 return n
738}
739
Joe Tsai4fe96632019-05-22 05:12:36 -0400740func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700741 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700742 var err error
743 for _, v := range s {
744 b = wire.AppendVarint(b, wiretag) // start group
745 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700746 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700747 return b, err
748 }
749 b = wire.AppendVarint(b, wiretag+1) // end group
750 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700751 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700752}
753
Damien Neile91877d2019-06-27 10:54:42 -0700754func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
755 if wtyp != wire.StartGroupType {
756 return 0, errUnknown
757 }
Damien Neil16163b42019-08-06 15:43:25 -0700758 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700759 mp := pointerOfIface(m)
760 n, err := mi.unmarshalPointer(b, mp, num, opts)
761 if err != nil {
762 return 0, err
763 }
764 p.AppendPointerSlice(mp)
765 return n, nil
766}
767
Damien Neil5b6d0472019-06-14 11:54:07 -0700768func asMessage(v reflect.Value) pref.ProtoMessage {
769 if m, ok := v.Interface().(pref.ProtoMessage); ok {
770 return m
771 }
772 return legacyWrapMessage(v)
773}