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