blob: cb4b482d166f5571887f5584b345764a82e336a0 [file] [log] [blame]
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +00001// 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 (
8 "fmt"
9 "reflect"
10 "sync"
11
12 "google.golang.org/protobuf/encoding/protowire"
13 "google.golang.org/protobuf/internal/errors"
14 "google.golang.org/protobuf/proto"
15 pref "google.golang.org/protobuf/reflect/protoreflect"
16 preg "google.golang.org/protobuf/reflect/protoregistry"
17 piface "google.golang.org/protobuf/runtime/protoiface"
18)
19
20type errInvalidUTF8 struct{}
21
22func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
23func (errInvalidUTF8) InvalidUTF8() bool { return true }
24func (errInvalidUTF8) Unwrap() error { return errors.Error }
25
26// 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) {
34 fs := si.oneofsByName[od.Name()]
35 ft := fs.Type
36 oneofFields := make(map[reflect.Type]*coderFieldInfo)
37 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()
42 // 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]
49 ot := si.oneofWrappersByNumber[num]
50 cf.ft = ot.Field(0).Type
51 cf.mi, cf.funcs = fieldCoder(fd, cf.ft)
52 oneofFields[ot] = &cf
53 if cf.funcs.isInit != nil {
54 needIsInit = true
55 }
56 mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
57 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 }
64 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
65 if err != nil {
66 return out, err
67 }
68 vi.Set(vw)
69 return out, nil
70 }
71 }
72 getInfo := func(p pointer) (pointer, *coderFieldInfo) {
73 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()]
84 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
85 p, info := getInfo(p)
86 if info == nil || info.funcs.size == nil {
87 return 0
88 }
89 return info.funcs.size(p, info, opts)
90 }
91 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
92 p, info := getInfo(p)
93 if info == nil || info.funcs.marshal == nil {
94 return b, nil
95 }
96 return info.funcs.marshal(b, p, info, opts)
97 }
98 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 }
110 if needIsInit {
111 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
112 p, info := getInfo(p)
113 if info == nil || info.funcs.isInit == nil {
114 return nil
115 }
116 return info.funcs.isInit(p, info)
117 }
118 }
119}
120
121func 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
131 return pointerCoderFuncs{
132 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
133 m, ok := p.WeakFields().get(f.num)
134 if !ok {
135 return 0
136 }
137 lazyInit()
138 if messageType == nil {
139 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
140 }
141 return sizeMessage(m, f.tagsize, opts)
142 },
143 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
144 m, ok := p.WeakFields().get(f.num)
145 if !ok {
146 return b, nil
147 }
148 lazyInit()
149 if messageType == nil {
150 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
151 }
152 return appendMessage(b, m, f.wiretag, opts)
153 },
154 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
155 fs := p.WeakFields()
156 m, ok := fs.get(f.num)
157 if !ok {
158 lazyInit()
159 if messageType == nil {
160 return unmarshalOutput{}, errUnknown
161 }
162 m = messageType.New().Interface()
163 fs.set(f.num, m)
164 }
165 return consumeMessage(b, m, wtyp, opts)
166 },
167 isInit: func(p pointer, f *coderFieldInfo) error {
168 m, ok := p.WeakFields().get(f.num)
169 if !ok {
170 return nil
171 }
172 return proto.CheckInitialized(m)
173 },
174 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 },
190 }
191}
192
193func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
194 if mi := getMessageInfo(ft); mi != nil {
195 funcs := pointerCoderFuncs{
196 size: sizeMessageInfo,
197 marshal: appendMessageInfo,
198 unmarshal: consumeMessageInfo,
199 merge: mergeMessage,
200 }
201 if needsInitCheck(mi.Desc) {
202 funcs.isInit = isInitMessageInfo
203 }
204 return funcs
205 } else {
206 return pointerCoderFuncs{
207 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
208 m := asMessage(p.AsValueOf(ft).Elem())
209 return sizeMessage(m, f.tagsize, opts)
210 },
211 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
212 m := asMessage(p.AsValueOf(ft).Elem())
213 return appendMessage(b, m, f.wiretag, opts)
214 },
215 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
216 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 },
222 isInit: func(p pointer, f *coderFieldInfo) error {
223 m := asMessage(p.AsValueOf(ft).Elem())
224 return proto.CheckInitialized(m)
225 },
226 merge: mergeMessage,
227 }
228 }
229}
230
231func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
232 return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
233}
234
235func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
236 b = protowire.AppendVarint(b, f.wiretag)
237 b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
238 return f.mi.marshalAppendPointer(b, p.Elem(), opts)
239}
240
241func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
242 if wtyp != protowire.BytesType {
243 return out, errUnknown
244 }
245 v, n := protowire.ConsumeBytes(b)
246 if n < 0 {
247 return out, errDecode
248 }
249 if p.Elem().IsNil() {
250 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
251 }
252 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
253 if err != nil {
254 return out, err
255 }
256 out.n = n
257 out.initialized = o.initialized
258 return out, nil
259}
260
261func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
262 return f.mi.checkInitializedPointer(p.Elem())
263}
264
265func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
266 return protowire.SizeBytes(proto.Size(m)) + tagsize
267}
268
269func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
270 b = protowire.AppendVarint(b, wiretag)
271 b = protowire.AppendVarint(b, uint64(proto.Size(m)))
272 return opts.Options().MarshalAppend(b, m)
273}
274
275func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
276 if wtyp != protowire.BytesType {
277 return out, errUnknown
278 }
279 v, n := protowire.ConsumeBytes(b)
280 if n < 0 {
281 return out, errDecode
282 }
283 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
284 Buf: v,
285 Message: m.ProtoReflect(),
286 })
287 if err != nil {
288 return out, err
289 }
290 out.n = n
291 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
292 return out, nil
293}
294
295func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
296 m := v.Message().Interface()
297 return sizeMessage(m, tagsize, opts)
298}
299
300func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
301 m := v.Message().Interface()
302 return appendMessage(b, m, wiretag, opts)
303}
304
305func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
306 m := v.Message().Interface()
307 out, err := consumeMessage(b, m, wtyp, opts)
308 return v, out, err
309}
310
311func isInitMessageValue(v pref.Value) error {
312 m := v.Message().Interface()
313 return proto.CheckInitialized(m)
314}
315
316var coderMessageValue = valueCoderFuncs{
317 size: sizeMessageValue,
318 marshal: appendMessageValue,
319 unmarshal: consumeMessageValue,
320 isInit: isInitMessageValue,
321 merge: mergeMessageValue,
322}
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
334func consumeGroupValue(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
335 m := v.Message().Interface()
336 out, err := consumeGroup(b, m, num, wtyp, opts)
337 return v, out, err
338}
339
340var coderGroupValue = valueCoderFuncs{
341 size: sizeGroupValue,
342 marshal: appendGroupValue,
343 unmarshal: consumeGroupValue,
344 isInit: isInitMessageValue,
345 merge: mergeMessageValue,
346}
347
348func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
349 num := fd.Number()
350 if mi := getMessageInfo(ft); mi != nil {
351 funcs := pointerCoderFuncs{
352 size: sizeGroupType,
353 marshal: appendGroupType,
354 unmarshal: consumeGroupType,
355 merge: mergeMessage,
356 }
357 if needsInitCheck(mi.Desc) {
358 funcs.isInit = isInitMessageInfo
359 }
360 return funcs
361 } else {
362 return pointerCoderFuncs{
363 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
364 m := asMessage(p.AsValueOf(ft).Elem())
365 return sizeGroup(m, f.tagsize, opts)
366 },
367 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
368 m := asMessage(p.AsValueOf(ft).Elem())
369 return appendGroup(b, m, f.wiretag, opts)
370 },
371 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
372 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 },
378 isInit: func(p pointer, f *coderFieldInfo) error {
379 m := asMessage(p.AsValueOf(ft).Elem())
380 return proto.CheckInitialized(m)
381 },
382 merge: mergeMessage,
383 }
384 }
385}
386
387func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
388 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
389}
390
391func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
392 b = protowire.AppendVarint(b, f.wiretag) // start group
393 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
394 b = protowire.AppendVarint(b, f.wiretag+1) // end group
395 return b, err
396}
397
398func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
399 if wtyp != protowire.StartGroupType {
400 return out, errUnknown
401 }
402 if p.Elem().IsNil() {
403 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
404 }
405 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
406}
407
408func 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) {
413 b = protowire.AppendVarint(b, wiretag) // start group
414 b, err := opts.Options().MarshalAppend(b, m)
415 b = protowire.AppendVarint(b, wiretag+1) // end group
416 return b, err
417}
418
419func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
420 if wtyp != protowire.StartGroupType {
421 return out, errUnknown
422 }
423 b, n := protowire.ConsumeGroup(num, b)
424 if n < 0 {
425 return out, errDecode
426 }
427 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
428 Buf: b,
429 Message: m.ProtoReflect(),
430 })
431 if err != nil {
432 return out, err
433 }
434 out.n = n
435 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
436 return out, nil
437}
438
439func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
440 if mi := getMessageInfo(ft); mi != nil {
441 funcs := pointerCoderFuncs{
442 size: sizeMessageSliceInfo,
443 marshal: appendMessageSliceInfo,
444 unmarshal: consumeMessageSliceInfo,
445 merge: mergeMessageSlice,
446 }
447 if needsInitCheck(mi.Desc) {
448 funcs.isInit = isInitMessageSliceInfo
449 }
450 return funcs
451 }
452 return pointerCoderFuncs{
453 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
454 return sizeMessageSlice(p, ft, f.tagsize, opts)
455 },
456 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
457 return appendMessageSlice(b, p, f.wiretag, ft, opts)
458 },
459 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
460 return consumeMessageSlice(b, p, ft, wtyp, opts)
461 },
462 isInit: func(p pointer, f *coderFieldInfo) error {
463 return isInitMessageSlice(p, ft)
464 },
465 merge: mergeMessageSlice,
466 }
467}
468
469func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
470 s := p.PointerSlice()
471 n := 0
472 for _, v := range s {
473 n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
474 }
475 return n
476}
477
478func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
479 s := p.PointerSlice()
480 var err error
481 for _, v := range s {
482 b = protowire.AppendVarint(b, f.wiretag)
483 siz := f.mi.sizePointer(v, opts)
484 b = protowire.AppendVarint(b, uint64(siz))
485 b, err = f.mi.marshalAppendPointer(b, v, opts)
486 if err != nil {
487 return b, err
488 }
489 }
490 return b, nil
491}
492
493func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
494 if wtyp != protowire.BytesType {
495 return out, errUnknown
496 }
497 v, n := protowire.ConsumeBytes(b)
498 if n < 0 {
499 return out, errDecode
500 }
501 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
502 mp := pointerOfIface(m)
503 o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
504 if err != nil {
505 return out, err
506 }
507 p.AppendPointerSlice(mp)
508 out.n = n
509 out.initialized = o.initialized
510 return out, nil
511}
512
513func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
514 s := p.PointerSlice()
515 for _, v := range s {
516 if err := f.mi.checkInitializedPointer(v); err != nil {
517 return err
518 }
519 }
520 return nil
521}
522
523func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
524 s := p.PointerSlice()
525 n := 0
526 for _, v := range s {
527 m := asMessage(v.AsValueOf(goType.Elem()))
528 n += protowire.SizeBytes(proto.Size(m)) + tagsize
529 }
530 return n
531}
532
533func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
534 s := p.PointerSlice()
535 var err error
536 for _, v := range s {
537 m := asMessage(v.AsValueOf(goType.Elem()))
538 b = protowire.AppendVarint(b, wiretag)
539 siz := proto.Size(m)
540 b = protowire.AppendVarint(b, uint64(siz))
541 b, err = opts.Options().MarshalAppend(b, m)
542 if err != nil {
543 return b, err
544 }
545 }
546 return b, nil
547}
548
549func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
550 if wtyp != protowire.BytesType {
551 return out, errUnknown
552 }
553 v, n := protowire.ConsumeBytes(b)
554 if n < 0 {
555 return out, errDecode
556 }
557 mp := reflect.New(goType.Elem())
558 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
559 Buf: v,
560 Message: asMessage(mp).ProtoReflect(),
561 })
562 if err != nil {
563 return out, err
564 }
565 p.AppendPointerSlice(pointerOfValue(mp))
566 out.n = n
567 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
568 return out, nil
569}
570
571func isInitMessageSlice(p pointer, goType reflect.Type) error {
572 s := p.PointerSlice()
573 for _, v := range s {
574 m := asMessage(v.AsValueOf(goType.Elem()))
575 if err := proto.CheckInitialized(m); err != nil {
576 return err
577 }
578 }
579 return nil
580}
581
582// Slices of messages
583
584func 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()
589 n += protowire.SizeBytes(proto.Size(m)) + tagsize
590 }
591 return n
592}
593
594func 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()
599 b = protowire.AppendVarint(b, wiretag)
600 siz := proto.Size(m)
601 b = protowire.AppendVarint(b, uint64(siz))
602 var err error
603 b, err = mopts.MarshalAppend(b, m)
604 if err != nil {
605 return b, err
606 }
607 }
608 return b, nil
609}
610
611func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
612 list := listv.List()
613 if wtyp != protowire.BytesType {
614 return pref.Value{}, out, errUnknown
615 }
616 v, n := protowire.ConsumeBytes(b)
617 if n < 0 {
618 return pref.Value{}, out, errDecode
619 }
620 m := list.NewElement()
621 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
622 Buf: v,
623 Message: m.Message(),
624 })
625 if err != nil {
626 return pref.Value{}, out, err
627 }
628 list.Append(m)
629 out.n = n
630 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
631 return listv, out, nil
632}
633
634func 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()
638 if err := proto.CheckInitialized(m); err != nil {
639 return err
640 }
641 }
642 return nil
643}
644
645var coderMessageSliceValue = valueCoderFuncs{
646 size: sizeMessageSliceValue,
647 marshal: appendMessageSliceValue,
648 unmarshal: consumeMessageSliceValue,
649 isInit: isInitMessageSliceValue,
650 merge: mergeMessageListValue,
651}
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()
668 b = protowire.AppendVarint(b, wiretag) // start group
669 var err error
670 b, err = mopts.MarshalAppend(b, m)
671 if err != nil {
672 return b, err
673 }
674 b = protowire.AppendVarint(b, wiretag+1) // end group
675 }
676 return b, nil
677}
678
679func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
680 list := listv.List()
681 if wtyp != protowire.StartGroupType {
682 return pref.Value{}, out, errUnknown
683 }
684 b, n := protowire.ConsumeGroup(num, b)
685 if n < 0 {
686 return pref.Value{}, out, errDecode
687 }
688 m := list.NewElement()
689 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
690 Buf: b,
691 Message: m.Message(),
692 })
693 if err != nil {
694 return pref.Value{}, out, err
695 }
696 list.Append(m)
697 out.n = n
698 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
699 return listv, out, nil
700}
701
702var coderGroupSliceValue = valueCoderFuncs{
703 size: sizeGroupSliceValue,
704 marshal: appendGroupSliceValue,
705 unmarshal: consumeGroupSliceValue,
706 isInit: isInitMessageSliceValue,
707 merge: mergeMessageListValue,
708}
709
710func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
711 num := fd.Number()
712 if mi := getMessageInfo(ft); mi != nil {
713 funcs := pointerCoderFuncs{
714 size: sizeGroupSliceInfo,
715 marshal: appendGroupSliceInfo,
716 unmarshal: consumeGroupSliceInfo,
717 merge: mergeMessageSlice,
718 }
719 if needsInitCheck(mi.Desc) {
720 funcs.isInit = isInitMessageSliceInfo
721 }
722 return funcs
723 }
724 return pointerCoderFuncs{
725 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
726 return sizeGroupSlice(p, ft, f.tagsize, opts)
727 },
728 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
729 return appendGroupSlice(b, p, f.wiretag, ft, opts)
730 },
731 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
732 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
733 },
734 isInit: func(p pointer, f *coderFieldInfo) error {
735 return isInitMessageSlice(p, ft)
736 },
737 merge: mergeMessageSlice,
738 }
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 {
745 m := asMessage(v.AsValueOf(messageType.Elem()))
746 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()
753 var err error
754 for _, v := range s {
755 m := asMessage(v.AsValueOf(messageType.Elem()))
756 b = protowire.AppendVarint(b, wiretag) // start group
757 b, err = opts.Options().MarshalAppend(b, m)
758 if err != nil {
759 return b, err
760 }
761 b = protowire.AppendVarint(b, wiretag+1) // end group
762 }
763 return b, nil
764}
765
766func 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 {
768 return out, errUnknown
769 }
770 b, n := protowire.ConsumeGroup(num, b)
771 if n < 0 {
772 return out, errDecode
773 }
774 mp := reflect.New(goType.Elem())
775 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{
776 Buf: b,
777 Message: asMessage(mp).ProtoReflect(),
778 })
779 if err != nil {
780 return out, err
781 }
782 p.AppendPointerSlice(pointerOfValue(mp))
783 out.n = n
784 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
785 return out, nil
786}
787
788func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
789 s := p.PointerSlice()
790 n := 0
791 for _, v := range s {
792 n += 2*f.tagsize + f.mi.sizePointer(v, opts)
793 }
794 return n
795}
796
797func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
798 s := p.PointerSlice()
799 var err error
800 for _, v := range s {
801 b = protowire.AppendVarint(b, f.wiretag) // start group
802 b, err = f.mi.marshalAppendPointer(b, v, opts)
803 if err != nil {
804 return b, err
805 }
806 b = protowire.AppendVarint(b, f.wiretag+1) // end group
807 }
808 return b, nil
809}
810
811func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
812 if wtyp != protowire.StartGroupType {
813 return unmarshalOutput{}, errUnknown
814 }
815 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
816 mp := pointerOfIface(m)
817 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
818 if err != nil {
819 return out, err
820 }
821 p.AppendPointerSlice(mp)
822 return out, nil
823}
824
825func asMessage(v reflect.Value) pref.ProtoMessage {
826 if m, ok := v.Interface().(pref.ProtoMessage); ok {
827 return m
828 }
829 return legacyWrapMessage(v).Interface()
830}