blob: 366034c62c59fbc9e84cec7df3a7938988ec8c57 [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 Neilc37adef2019-04-01 13:49:56 -0700167 return pointerCoderFuncs{
168 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 Neil5322bdb2019-04-09 15:57:05 -0700177 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700178 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700179 },
Damien Neilc37adef2019-04-01 13:49:56 -0700180 }
181 } else {
182 return pointerCoderFuncs{
183 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700184 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700185 return sizeMessage(m, tagsize, opts)
186 },
187 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700188 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700189 return appendMessage(b, m, wiretag, opts)
190 },
Damien Neile91877d2019-06-27 10:54:42 -0700191 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
192 mp := p.AsValueOf(ft).Elem()
193 if mp.IsNil() {
194 mp.Set(reflect.New(ft.Elem()))
195 }
196 return consumeMessage(b, asMessage(mp), wtyp, opts)
197 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700198 isInit: func(p pointer) error {
199 m := asMessage(p.AsValueOf(ft).Elem())
200 return proto.IsInitialized(m)
201 },
Damien Neilc37adef2019-04-01 13:49:56 -0700202 }
203 }
204}
205
Joe Tsai4fe96632019-05-22 05:12:36 -0400206func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700207 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
208}
209
Joe Tsai4fe96632019-05-22 05:12:36 -0400210func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700211 b = wire.AppendVarint(b, wiretag)
212 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
213 return mi.marshalAppendPointer(b, p.Elem(), opts)
214}
215
Damien Neile91877d2019-06-27 10:54:42 -0700216func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
217 if wtyp != wire.BytesType {
218 return 0, errUnknown
219 }
220 v, n := wire.ConsumeBytes(b)
221 if n < 0 {
222 return 0, wire.ParseError(n)
223 }
224 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700225 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700226 }
227 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
228 return 0, err
229 }
230 return n, nil
231}
232
Damien Neilc37adef2019-04-01 13:49:56 -0700233func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
234 return wire.SizeBytes(proto.Size(m)) + tagsize
235}
236
237func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
238 b = wire.AppendVarint(b, wiretag)
239 b = wire.AppendVarint(b, uint64(proto.Size(m)))
240 return opts.Options().MarshalAppend(b, m)
241}
242
Damien Neile91877d2019-06-27 10:54:42 -0700243func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
244 if wtyp != wire.BytesType {
245 return 0, errUnknown
246 }
247 v, n := wire.ConsumeBytes(b)
248 if n < 0 {
249 return 0, wire.ParseError(n)
250 }
251 if err := opts.Options().Unmarshal(v, m); err != nil {
252 return 0, err
253 }
254 return n, nil
255}
256
Damien Neil68b81c32019-08-22 11:41:32 -0700257func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
258 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700259 return sizeMessage(m, tagsize, opts)
260}
261
Damien Neil68b81c32019-08-22 11:41:32 -0700262func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
263 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700264 return appendMessage(b, m, wiretag, opts)
265}
266
Damien Neil68b81c32019-08-22 11:41:32 -0700267func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
268 m := v.Message().Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700269 n, err := consumeMessage(b, m, wtyp, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700270 return v, n, err
Damien Neile91877d2019-06-27 10:54:42 -0700271}
272
Damien Neil68b81c32019-08-22 11:41:32 -0700273func isInitMessageValue(v pref.Value) error {
274 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700275 return proto.IsInitialized(m)
276}
277
Damien Neil68b81c32019-08-22 11:41:32 -0700278var coderMessageValue = valueCoderFuncs{
279 size: sizeMessageValue,
280 marshal: appendMessageValue,
281 unmarshal: consumeMessageValue,
282 isInit: isInitMessageValue,
283}
284
285func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
286 m := v.Message().Interface()
287 return sizeGroup(m, tagsize, opts)
288}
289
290func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
291 m := v.Message().Interface()
292 return appendGroup(b, m, wiretag, opts)
293}
294
295func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
296 m := v.Message().Interface()
297 n, err := consumeGroup(b, m, num, wtyp, opts)
298 return v, n, err
299}
300
301var coderGroupValue = valueCoderFuncs{
302 size: sizeGroupValue,
303 marshal: appendGroupValue,
304 unmarshal: consumeGroupValue,
305 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700306}
307
308func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700309 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700310 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700311 return pointerCoderFuncs{
312 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700313 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700314 },
315 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700316 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700317 },
Damien Neile91877d2019-06-27 10:54:42 -0700318 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700319 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700320 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700321 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700322 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700323 },
Damien Neilc37adef2019-04-01 13:49:56 -0700324 }
325 } else {
326 return pointerCoderFuncs{
327 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700328 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700329 return sizeGroup(m, tagsize, opts)
330 },
331 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700332 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700333 return appendGroup(b, m, wiretag, opts)
334 },
Damien Neile91877d2019-06-27 10:54:42 -0700335 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
336 mp := p.AsValueOf(ft).Elem()
337 if mp.IsNil() {
338 mp.Set(reflect.New(ft.Elem()))
339 }
340 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
341 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700342 isInit: func(p pointer) error {
343 m := asMessage(p.AsValueOf(ft).Elem())
344 return proto.IsInitialized(m)
345 },
Damien Neilc37adef2019-04-01 13:49:56 -0700346 }
347 }
348}
349
Joe Tsai4fe96632019-05-22 05:12:36 -0400350func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700351 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
352}
353
Joe Tsai4fe96632019-05-22 05:12:36 -0400354func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700355 b = wire.AppendVarint(b, wiretag) // start group
356 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
357 b = wire.AppendVarint(b, wiretag+1) // end group
358 return b, err
359}
360
Damien Neile91877d2019-06-27 10:54:42 -0700361func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
362 if wtyp != wire.StartGroupType {
363 return 0, errUnknown
364 }
365 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700366 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700367 }
368 return mi.unmarshalPointer(b, p.Elem(), num, opts)
369}
370
Damien Neilc37adef2019-04-01 13:49:56 -0700371func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
372 return 2*tagsize + proto.Size(m)
373}
374
375func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
376 b = wire.AppendVarint(b, wiretag) // start group
377 b, err := opts.Options().MarshalAppend(b, m)
378 b = wire.AppendVarint(b, wiretag+1) // end group
379 return b, err
380}
381
Damien Neile91877d2019-06-27 10:54:42 -0700382func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
383 if wtyp != wire.StartGroupType {
384 return 0, errUnknown
385 }
386 b, n := wire.ConsumeGroup(num, b)
387 if n < 0 {
388 return 0, wire.ParseError(n)
389 }
390 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700391}
392
Damien Neilc37adef2019-04-01 13:49:56 -0700393func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700394 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700395 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700396 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700397 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700398 },
Damien Neilc37adef2019-04-01 13:49:56 -0700399 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700400 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700401 },
Damien Neile91877d2019-06-27 10:54:42 -0700402 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700403 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700404 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700405 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700406 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700407 },
Damien Neilc37adef2019-04-01 13:49:56 -0700408 }
409 }
410 return pointerCoderFuncs{
411 size: func(p pointer, tagsize int, opts marshalOptions) int {
412 return sizeMessageSlice(p, ft, tagsize, opts)
413 },
414 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
415 return appendMessageSlice(b, p, wiretag, ft, opts)
416 },
Damien Neile91877d2019-06-27 10:54:42 -0700417 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
418 return consumeMessageSlice(b, p, ft, wtyp, opts)
419 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700420 isInit: func(p pointer) error {
421 return isInitMessageSlice(p, ft)
422 },
Damien Neilc37adef2019-04-01 13:49:56 -0700423 }
424}
425
Joe Tsai4fe96632019-05-22 05:12:36 -0400426func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700427 s := p.PointerSlice()
428 n := 0
429 for _, v := range s {
430 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
431 }
432 return n
433}
434
Joe Tsai4fe96632019-05-22 05:12:36 -0400435func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700436 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700437 var err error
438 for _, v := range s {
439 b = wire.AppendVarint(b, wiretag)
440 siz := mi.sizePointer(v, opts)
441 b = wire.AppendVarint(b, uint64(siz))
442 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700443 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700444 return b, err
445 }
446 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700447 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700448}
449
Damien Neile91877d2019-06-27 10:54:42 -0700450func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
451 if wtyp != wire.BytesType {
452 return 0, errUnknown
453 }
454 v, n := wire.ConsumeBytes(b)
455 if n < 0 {
456 return 0, wire.ParseError(n)
457 }
Damien Neil16163b42019-08-06 15:43:25 -0700458 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700459 mp := pointerOfIface(m)
460 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
461 return 0, err
462 }
463 p.AppendPointerSlice(mp)
464 return n, nil
465}
466
Damien Neil5322bdb2019-04-09 15:57:05 -0700467func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
468 s := p.PointerSlice()
469 for _, v := range s {
470 if err := mi.isInitializedPointer(v); err != nil {
471 return err
472 }
473 }
474 return nil
475}
476
Damien Neilc37adef2019-04-01 13:49:56 -0700477func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
478 s := p.PointerSlice()
479 n := 0
480 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700481 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700482 n += wire.SizeBytes(proto.Size(m)) + tagsize
483 }
484 return n
485}
486
487func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
488 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700489 var err error
490 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700491 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700492 b = wire.AppendVarint(b, wiretag)
493 siz := proto.Size(m)
494 b = wire.AppendVarint(b, uint64(siz))
495 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700496 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700497 return b, err
498 }
499 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700500 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700501}
502
Damien Neile91877d2019-06-27 10:54:42 -0700503func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
504 if wtyp != wire.BytesType {
505 return 0, errUnknown
506 }
507 v, n := wire.ConsumeBytes(b)
508 if n < 0 {
509 return 0, wire.ParseError(n)
510 }
511 mp := reflect.New(goType.Elem())
512 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
513 return 0, err
514 }
515 p.AppendPointerSlice(pointerOfValue(mp))
516 return n, nil
517}
518
Damien Neil5322bdb2019-04-09 15:57:05 -0700519func isInitMessageSlice(p pointer, goType reflect.Type) error {
520 s := p.PointerSlice()
521 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700522 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700523 if err := proto.IsInitialized(m); err != nil {
524 return err
525 }
526 }
527 return nil
528}
529
Damien Neilc37adef2019-04-01 13:49:56 -0700530// Slices of messages
531
Damien Neil68b81c32019-08-22 11:41:32 -0700532func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
533 list := listv.List()
534 n := 0
535 for i, llen := 0, list.Len(); i < llen; i++ {
536 m := list.Get(i).Message().Interface()
537 n += wire.SizeBytes(proto.Size(m)) + tagsize
538 }
539 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700540}
541
Damien Neil68b81c32019-08-22 11:41:32 -0700542func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
543 list := listv.List()
544 mopts := opts.Options()
545 for i, llen := 0, list.Len(); i < llen; i++ {
546 m := list.Get(i).Message().Interface()
547 b = wire.AppendVarint(b, wiretag)
548 siz := proto.Size(m)
549 b = wire.AppendVarint(b, uint64(siz))
550 var err error
551 b, err = mopts.MarshalAppend(b, m)
552 if err != nil {
553 return b, err
554 }
555 }
556 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700557}
558
Damien Neil68b81c32019-08-22 11:41:32 -0700559func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
560 list := listv.List()
561 if wtyp != wire.BytesType {
562 return pref.Value{}, 0, errUnknown
563 }
564 v, n := wire.ConsumeBytes(b)
565 if n < 0 {
566 return pref.Value{}, 0, wire.ParseError(n)
567 }
568 m := list.NewElement()
569 if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
570 return pref.Value{}, 0, err
571 }
572 list.Append(m)
573 return listv, n, nil
Damien Neile91877d2019-06-27 10:54:42 -0700574}
575
Damien Neil68b81c32019-08-22 11:41:32 -0700576func isInitMessageSliceValue(listv pref.Value) error {
577 list := listv.List()
578 for i, llen := 0, list.Len(); i < llen; i++ {
579 m := list.Get(i).Message().Interface()
580 if err := proto.IsInitialized(m); err != nil {
581 return err
582 }
583 }
584 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700585}
586
Damien Neil68b81c32019-08-22 11:41:32 -0700587var coderMessageSliceValue = valueCoderFuncs{
588 size: sizeMessageSliceValue,
589 marshal: appendMessageSliceValue,
590 unmarshal: consumeMessageSliceValue,
591 isInit: isInitMessageSliceValue,
592}
593
594func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
595 list := listv.List()
596 n := 0
597 for i, llen := 0, list.Len(); i < llen; i++ {
598 m := list.Get(i).Message().Interface()
599 n += 2*tagsize + proto.Size(m)
600 }
601 return n
602}
603
604func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
605 list := listv.List()
606 mopts := opts.Options()
607 for i, llen := 0, list.Len(); i < llen; i++ {
608 m := list.Get(i).Message().Interface()
609 b = wire.AppendVarint(b, wiretag) // start group
610 var err error
611 b, err = mopts.MarshalAppend(b, m)
612 if err != nil {
613 return b, err
614 }
615 b = wire.AppendVarint(b, wiretag+1) // end group
616 }
617 return b, nil
618}
619
620func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
621 list := listv.List()
622 if wtyp != wire.StartGroupType {
623 return pref.Value{}, 0, errUnknown
624 }
625 b, n := wire.ConsumeGroup(num, b)
626 if n < 0 {
627 return pref.Value{}, 0, wire.ParseError(n)
628 }
629 m := list.NewElement()
630 if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
631 return pref.Value{}, 0, err
632 }
633 list.Append(m)
634 return listv, n, nil
635}
636
637var coderGroupSliceValue = valueCoderFuncs{
638 size: sizeGroupSliceValue,
639 marshal: appendGroupSliceValue,
640 unmarshal: consumeGroupSliceValue,
641 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700642}
643
644func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700645 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700646 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700647 return pointerCoderFuncs{
648 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700649 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700650 },
651 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700652 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700653 },
Damien Neile91877d2019-06-27 10:54:42 -0700654 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700655 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700656 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700657 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700658 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700659 },
Damien Neilc37adef2019-04-01 13:49:56 -0700660 }
661 }
662 return pointerCoderFuncs{
663 size: func(p pointer, tagsize int, opts marshalOptions) int {
664 return sizeGroupSlice(p, ft, tagsize, opts)
665 },
666 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
667 return appendGroupSlice(b, p, wiretag, ft, opts)
668 },
Damien Neile91877d2019-06-27 10:54:42 -0700669 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
670 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
671 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700672 isInit: func(p pointer) error {
673 return isInitMessageSlice(p, ft)
674 },
Damien Neilc37adef2019-04-01 13:49:56 -0700675 }
676}
677
678func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
679 s := p.PointerSlice()
680 n := 0
681 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700682 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700683 n += 2*tagsize + proto.Size(m)
684 }
685 return n
686}
687
688func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
689 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700690 var err error
691 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700692 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700693 b = wire.AppendVarint(b, wiretag) // start group
694 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700695 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700696 return b, err
697 }
698 b = wire.AppendVarint(b, wiretag+1) // end group
699 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700700 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700701}
702
Damien Neile91877d2019-06-27 10:54:42 -0700703func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
704 if wtyp != wire.StartGroupType {
705 return 0, errUnknown
706 }
707 b, n := wire.ConsumeGroup(num, b)
708 if n < 0 {
709 return 0, wire.ParseError(n)
710 }
711 mp := reflect.New(goType.Elem())
712 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
713 return 0, err
714 }
715 p.AppendPointerSlice(pointerOfValue(mp))
716 return n, nil
717}
718
Joe Tsai4fe96632019-05-22 05:12:36 -0400719func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700720 s := p.PointerSlice()
721 n := 0
722 for _, v := range s {
723 n += 2*tagsize + mi.sizePointer(v, opts)
724 }
725 return n
726}
727
Joe Tsai4fe96632019-05-22 05:12:36 -0400728func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700729 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700730 var err error
731 for _, v := range s {
732 b = wire.AppendVarint(b, wiretag) // start group
733 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700734 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700735 return b, err
736 }
737 b = wire.AppendVarint(b, wiretag+1) // end group
738 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700739 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700740}
741
Damien Neile91877d2019-06-27 10:54:42 -0700742func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
743 if wtyp != wire.StartGroupType {
744 return 0, errUnknown
745 }
Damien Neil16163b42019-08-06 15:43:25 -0700746 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700747 mp := pointerOfIface(m)
748 n, err := mi.unmarshalPointer(b, mp, num, opts)
749 if err != nil {
750 return 0, err
751 }
752 p.AppendPointerSlice(mp)
753 return n, nil
754}
755
Damien Neil5b6d0472019-06-14 11:54:07 -0700756func asMessage(v reflect.Value) pref.ProtoMessage {
757 if m, ok := v.Interface().(pref.ProtoMessage); ok {
758 return m
759 }
760 return legacyWrapMessage(v)
761}