blob: 433dacb48f557af9cbd9d369508c1a0b4ea3fb1c [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 Neilc600d6c2020-01-21 15:00:33 -080016 piface "google.golang.org/protobuf/runtime/protoiface"
Damien Neilc37adef2019-04-01 13:49:56 -070017)
18
19type errInvalidUTF8 struct{}
20
21func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
22func (errInvalidUTF8) InvalidUTF8() bool { return true }
23
Damien Neilce413af2019-12-05 16:36:28 -080024// 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 type oneofFieldInfo struct {
33 wiretag uint64 // field tag (number + wire type)
34 tagsize int // size of the varint-encoded tag
35 funcs pointerCoderFuncs
Damien Neil5322bdb2019-04-09 15:57:05 -070036 }
Damien Neilce413af2019-12-05 16:36:28 -080037 fs := si.oneofsByName[od.Name()]
38 ft := fs.Type
39 oneofFields := make(map[reflect.Type]*oneofFieldInfo)
40 needIsInit := false
41 fields := od.Fields()
42 for i, lim := 0, fields.Len(); i < lim; i++ {
43 fd := od.Fields().Get(i)
44 num := fd.Number()
45 cf := mi.coderFields[num]
46 ot := si.oneofWrappersByNumber[num]
47 funcs := fieldCoder(fd, ot.Field(0).Type)
48 oneofFields[ot] = &oneofFieldInfo{
49 wiretag: cf.wiretag,
50 tagsize: cf.tagsize,
51 funcs: funcs,
52 }
53 if funcs.isInit != nil {
54 needIsInit = true
55 }
Damien Neilf0831e82020-01-21 14:25:12 -080056 cf.funcs.unmarshal = func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070057 var vw reflect.Value // pointer to wrapper type
58 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
59 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
60 vw = vi.Elem()
61 } else {
62 vw = reflect.New(ot)
63 }
Damien Neilf0831e82020-01-21 14:25:12 -080064 out, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070065 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -080066 return out, err
Damien Neilc37adef2019-04-01 13:49:56 -070067 }
Joe Tsai6c286742019-07-11 23:15:05 -070068 vi.Set(vw)
Damien Neilf0831e82020-01-21 14:25:12 -080069 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -070070 }
71 }
Damien Neilce413af2019-12-05 16:36:28 -080072 getInfo := func(p pointer) (pointer, *oneofFieldInfo) {
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, tagsize int, 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.tagsize, opts)
90 }
91 first.funcs.marshal = func(b []byte, p pointer, wiretag uint64, 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.wiretag, opts)
97 }
98 if needIsInit {
99 first.funcs.isInit = func(p pointer) error {
100 p, info := getInfo(p)
101 if info == nil || info.funcs.isInit == nil {
102 return nil
103 }
104 return info.funcs.isInit(p)
105 }
106 }
Damien Neilc37adef2019-04-01 13:49:56 -0700107}
108
Joe Tsai6e095992019-08-10 13:56:36 -0700109func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
110 var once sync.Once
111 var messageType pref.MessageType
112 lazyInit := func() {
113 once.Do(func() {
114 messageName := fd.Message().FullName()
115 messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
116 })
117 }
118
Damien Neil6e40b322019-10-01 13:05:16 -0700119 num := fd.Number()
Joe Tsai6e095992019-08-10 13:56:36 -0700120 return pointerCoderFuncs{
121 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil6e40b322019-10-01 13:05:16 -0700122 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700123 if !ok {
124 return 0
125 }
Damien Neil6e40b322019-10-01 13:05:16 -0700126 lazyInit()
127 if messageType == nil {
128 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
129 }
130 return sizeMessage(m, tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700131 },
132 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil6e40b322019-10-01 13:05:16 -0700133 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700134 if !ok {
135 return b, nil
136 }
Damien Neil6e40b322019-10-01 13:05:16 -0700137 lazyInit()
138 if messageType == nil {
139 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
140 }
141 return appendMessage(b, m, wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700142 },
Damien Neilf0831e82020-01-21 14:25:12 -0800143 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6e095992019-08-10 13:56:36 -0700144 fs := p.WeakFields()
Damien Neil6e40b322019-10-01 13:05:16 -0700145 m, ok := fs.get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700146 if !ok {
147 lazyInit()
148 if messageType == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800149 return unmarshalOutput{}, errUnknown
Joe Tsai6e095992019-08-10 13:56:36 -0700150 }
Damien Neil6e40b322019-10-01 13:05:16 -0700151 m = messageType.New().Interface()
152 fs.set(num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700153 }
Damien Neil6e40b322019-10-01 13:05:16 -0700154 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700155 },
156 isInit: func(p pointer) error {
Damien Neil6e40b322019-10-01 13:05:16 -0700157 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700158 if !ok {
159 return nil
160 }
Damien Neil6e40b322019-10-01 13:05:16 -0700161 return proto.IsInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700162 },
163 }
164}
165
Damien Neilc37adef2019-04-01 13:49:56 -0700166func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700167 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800168 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700169 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700170 return sizeMessageInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700171 },
172 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700173 return appendMessageInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700174 },
Damien Neilf0831e82020-01-21 14:25:12 -0800175 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700176 return consumeMessageInfo(b, p, mi, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700177 },
Damien Neilc37adef2019-04-01 13:49:56 -0700178 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800179 if needsInitCheck(mi.Desc) {
180 funcs.isInit = func(p pointer) error {
181 return mi.isInitializedPointer(p.Elem())
182 }
183 }
184 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700185 } else {
186 return pointerCoderFuncs{
187 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700188 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700189 return sizeMessage(m, tagsize, opts)
190 },
191 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700192 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700193 return appendMessage(b, m, wiretag, opts)
194 },
Damien Neilf0831e82020-01-21 14:25:12 -0800195 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700196 mp := p.AsValueOf(ft).Elem()
197 if mp.IsNil() {
198 mp.Set(reflect.New(ft.Elem()))
199 }
200 return consumeMessage(b, asMessage(mp), wtyp, opts)
201 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700202 isInit: func(p pointer) error {
203 m := asMessage(p.AsValueOf(ft).Elem())
204 return proto.IsInitialized(m)
205 },
Damien Neilc37adef2019-04-01 13:49:56 -0700206 }
207 }
208}
209
Joe Tsai4fe96632019-05-22 05:12:36 -0400210func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700211 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
212}
213
Joe Tsai4fe96632019-05-22 05:12:36 -0400214func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700215 b = wire.AppendVarint(b, wiretag)
216 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
217 return mi.marshalAppendPointer(b, p.Elem(), opts)
218}
219
Damien Neilf0831e82020-01-21 14:25:12 -0800220func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700221 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800222 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700223 }
224 v, n := wire.ConsumeBytes(b)
225 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800226 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700227 }
228 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700229 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700230 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800231 o, err := mi.unmarshalPointer(v, p.Elem(), 0, opts)
232 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800233 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700234 }
Damien Neilf0831e82020-01-21 14:25:12 -0800235 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800236 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800237 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700238}
239
Damien Neilc37adef2019-04-01 13:49:56 -0700240func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
241 return wire.SizeBytes(proto.Size(m)) + tagsize
242}
243
244func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
245 b = wire.AppendVarint(b, wiretag)
246 b = wire.AppendVarint(b, uint64(proto.Size(m)))
247 return opts.Options().MarshalAppend(b, m)
248}
249
Damien Neilf0831e82020-01-21 14:25:12 -0800250func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700251 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800252 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700253 }
254 v, n := wire.ConsumeBytes(b)
255 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800256 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700257 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800258 o, err := opts.Options().UnmarshalState(m, piface.UnmarshalInput{
259 Buf: v,
260 })
261 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800262 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700263 }
Damien Neilf0831e82020-01-21 14:25:12 -0800264 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800265 out.initialized = o.Initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800266 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700267}
268
Damien Neil68b81c32019-08-22 11:41:32 -0700269func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
270 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700271 return sizeMessage(m, tagsize, opts)
272}
273
Damien Neil68b81c32019-08-22 11:41:32 -0700274func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
275 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700276 return appendMessage(b, m, wiretag, opts)
277}
278
Damien Neilf0831e82020-01-21 14:25:12 -0800279func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700280 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800281 out, err := consumeMessage(b, m, wtyp, opts)
282 return v, out, err
Damien Neile91877d2019-06-27 10:54:42 -0700283}
284
Damien Neil68b81c32019-08-22 11:41:32 -0700285func isInitMessageValue(v pref.Value) error {
286 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700287 return proto.IsInitialized(m)
288}
289
Damien Neil68b81c32019-08-22 11:41:32 -0700290var coderMessageValue = valueCoderFuncs{
291 size: sizeMessageValue,
292 marshal: appendMessageValue,
293 unmarshal: consumeMessageValue,
294 isInit: isInitMessageValue,
295}
296
297func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
298 m := v.Message().Interface()
299 return sizeGroup(m, tagsize, opts)
300}
301
302func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
303 m := v.Message().Interface()
304 return appendGroup(b, m, wiretag, opts)
305}
306
Damien Neilf0831e82020-01-21 14:25:12 -0800307func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700308 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800309 out, err := consumeGroup(b, m, num, wtyp, opts)
310 return v, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700311}
312
313var coderGroupValue = valueCoderFuncs{
314 size: sizeGroupValue,
315 marshal: appendGroupValue,
316 unmarshal: consumeGroupValue,
317 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700318}
319
320func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700321 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700322 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800323 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700324 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700325 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700326 },
327 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700328 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700329 },
Damien Neilf0831e82020-01-21 14:25:12 -0800330 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700331 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700332 },
Damien Neilc37adef2019-04-01 13:49:56 -0700333 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800334 if needsInitCheck(mi.Desc) {
335 funcs.isInit = func(p pointer) error {
336 return mi.isInitializedPointer(p.Elem())
337 }
338 }
339 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700340 } else {
341 return pointerCoderFuncs{
342 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700343 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700344 return sizeGroup(m, tagsize, opts)
345 },
346 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700347 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700348 return appendGroup(b, m, wiretag, opts)
349 },
Damien Neilf0831e82020-01-21 14:25:12 -0800350 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700351 mp := p.AsValueOf(ft).Elem()
352 if mp.IsNil() {
353 mp.Set(reflect.New(ft.Elem()))
354 }
355 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
356 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700357 isInit: func(p pointer) error {
358 m := asMessage(p.AsValueOf(ft).Elem())
359 return proto.IsInitialized(m)
360 },
Damien Neilc37adef2019-04-01 13:49:56 -0700361 }
362 }
363}
364
Joe Tsai4fe96632019-05-22 05:12:36 -0400365func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700366 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
367}
368
Joe Tsai4fe96632019-05-22 05:12:36 -0400369func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700370 b = wire.AppendVarint(b, wiretag) // start group
371 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
372 b = wire.AppendVarint(b, wiretag+1) // end group
373 return b, err
374}
375
Damien Neilf0831e82020-01-21 14:25:12 -0800376func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700377 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800378 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700379 }
380 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700381 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700382 }
383 return mi.unmarshalPointer(b, p.Elem(), num, opts)
384}
385
Damien Neilc37adef2019-04-01 13:49:56 -0700386func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
387 return 2*tagsize + proto.Size(m)
388}
389
390func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
391 b = wire.AppendVarint(b, wiretag) // start group
392 b, err := opts.Options().MarshalAppend(b, m)
393 b = wire.AppendVarint(b, wiretag+1) // end group
394 return b, err
395}
396
Damien Neilf0831e82020-01-21 14:25:12 -0800397func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700398 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800399 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700400 }
401 b, n := wire.ConsumeGroup(num, b)
402 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800403 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700404 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800405 o, err := opts.Options().UnmarshalState(m, piface.UnmarshalInput{
406 Buf: b,
407 })
408 if err != nil {
409 return out, err
410 }
Damien Neilf0831e82020-01-21 14:25:12 -0800411 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800412 out.initialized = o.Initialized
413 return out, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700414}
415
Damien Neilc37adef2019-04-01 13:49:56 -0700416func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700417 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800418 funcs := pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700419 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700420 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700421 },
Damien Neilc37adef2019-04-01 13:49:56 -0700422 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700423 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700424 },
Damien Neilf0831e82020-01-21 14:25:12 -0800425 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700426 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700427 },
428 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800429 if needsInitCheck(mi.Desc) {
430 funcs.isInit = func(p pointer) error {
431 return isInitMessageSliceInfo(p, mi)
432 }
433 }
434 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700435 }
436 return pointerCoderFuncs{
437 size: func(p pointer, tagsize int, opts marshalOptions) int {
438 return sizeMessageSlice(p, ft, tagsize, opts)
439 },
440 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
441 return appendMessageSlice(b, p, wiretag, ft, opts)
442 },
Damien Neilf0831e82020-01-21 14:25:12 -0800443 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700444 return consumeMessageSlice(b, p, ft, wtyp, opts)
445 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700446 isInit: func(p pointer) error {
447 return isInitMessageSlice(p, ft)
448 },
Damien Neilc37adef2019-04-01 13:49:56 -0700449 }
450}
451
Joe Tsai4fe96632019-05-22 05:12:36 -0400452func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700453 s := p.PointerSlice()
454 n := 0
455 for _, v := range s {
456 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
457 }
458 return n
459}
460
Joe Tsai4fe96632019-05-22 05:12:36 -0400461func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700462 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700463 var err error
464 for _, v := range s {
465 b = wire.AppendVarint(b, wiretag)
466 siz := mi.sizePointer(v, opts)
467 b = wire.AppendVarint(b, uint64(siz))
468 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700469 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700470 return b, err
471 }
472 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700473 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700474}
475
Damien Neilf0831e82020-01-21 14:25:12 -0800476func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700477 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800478 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700479 }
480 v, n := wire.ConsumeBytes(b)
481 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800482 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700483 }
Damien Neil16163b42019-08-06 15:43:25 -0700484 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700485 mp := pointerOfIface(m)
Damien Neilc600d6c2020-01-21 15:00:33 -0800486 o, err := mi.unmarshalPointer(v, mp, 0, opts)
487 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800488 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700489 }
490 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800491 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800492 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800493 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700494}
495
Damien Neil5322bdb2019-04-09 15:57:05 -0700496func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
497 s := p.PointerSlice()
498 for _, v := range s {
499 if err := mi.isInitializedPointer(v); err != nil {
500 return err
501 }
502 }
503 return nil
504}
505
Damien Neilc37adef2019-04-01 13:49:56 -0700506func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
507 s := p.PointerSlice()
508 n := 0
509 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700510 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700511 n += wire.SizeBytes(proto.Size(m)) + tagsize
512 }
513 return n
514}
515
516func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
517 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700518 var err error
519 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700520 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700521 b = wire.AppendVarint(b, wiretag)
522 siz := proto.Size(m)
523 b = wire.AppendVarint(b, uint64(siz))
524 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700525 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700526 return b, err
527 }
528 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700529 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700530}
531
Damien Neilf0831e82020-01-21 14:25:12 -0800532func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700533 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800534 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700535 }
536 v, n := wire.ConsumeBytes(b)
537 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800538 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700539 }
540 mp := reflect.New(goType.Elem())
Damien Neilc600d6c2020-01-21 15:00:33 -0800541 o, err := opts.Options().UnmarshalState(asMessage(mp), piface.UnmarshalInput{
542 Buf: v,
543 })
544 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800545 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700546 }
547 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800548 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800549 out.initialized = o.Initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800550 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700551}
552
Damien Neil5322bdb2019-04-09 15:57:05 -0700553func isInitMessageSlice(p pointer, goType reflect.Type) error {
554 s := p.PointerSlice()
555 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700556 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700557 if err := proto.IsInitialized(m); err != nil {
558 return err
559 }
560 }
561 return nil
562}
563
Damien Neilc37adef2019-04-01 13:49:56 -0700564// Slices of messages
565
Damien Neil68b81c32019-08-22 11:41:32 -0700566func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
567 list := listv.List()
568 n := 0
569 for i, llen := 0, list.Len(); i < llen; i++ {
570 m := list.Get(i).Message().Interface()
571 n += wire.SizeBytes(proto.Size(m)) + tagsize
572 }
573 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700574}
575
Damien Neil68b81c32019-08-22 11:41:32 -0700576func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
577 list := listv.List()
578 mopts := opts.Options()
579 for i, llen := 0, list.Len(); i < llen; i++ {
580 m := list.Get(i).Message().Interface()
581 b = wire.AppendVarint(b, wiretag)
582 siz := proto.Size(m)
583 b = wire.AppendVarint(b, uint64(siz))
584 var err error
585 b, err = mopts.MarshalAppend(b, m)
586 if err != nil {
587 return b, err
588 }
589 }
590 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700591}
592
Damien Neilf0831e82020-01-21 14:25:12 -0800593func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700594 list := listv.List()
595 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800596 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700597 }
598 v, n := wire.ConsumeBytes(b)
599 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800600 return pref.Value{}, out, wire.ParseError(n)
Damien Neil68b81c32019-08-22 11:41:32 -0700601 }
602 m := list.NewElement()
Damien Neilc600d6c2020-01-21 15:00:33 -0800603 o, err := opts.Options().UnmarshalState(m.Message().Interface(), piface.UnmarshalInput{
604 Buf: v,
605 })
606 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800607 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700608 }
609 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800610 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800611 out.initialized = o.Initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800612 return listv, out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700613}
614
Damien Neil68b81c32019-08-22 11:41:32 -0700615func isInitMessageSliceValue(listv pref.Value) error {
616 list := listv.List()
617 for i, llen := 0, list.Len(); i < llen; i++ {
618 m := list.Get(i).Message().Interface()
619 if err := proto.IsInitialized(m); err != nil {
620 return err
621 }
622 }
623 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700624}
625
Damien Neil68b81c32019-08-22 11:41:32 -0700626var coderMessageSliceValue = valueCoderFuncs{
627 size: sizeMessageSliceValue,
628 marshal: appendMessageSliceValue,
629 unmarshal: consumeMessageSliceValue,
630 isInit: isInitMessageSliceValue,
631}
632
633func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
634 list := listv.List()
635 n := 0
636 for i, llen := 0, list.Len(); i < llen; i++ {
637 m := list.Get(i).Message().Interface()
638 n += 2*tagsize + proto.Size(m)
639 }
640 return n
641}
642
643func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
644 list := listv.List()
645 mopts := opts.Options()
646 for i, llen := 0, list.Len(); i < llen; i++ {
647 m := list.Get(i).Message().Interface()
648 b = wire.AppendVarint(b, wiretag) // start group
649 var err error
650 b, err = mopts.MarshalAppend(b, m)
651 if err != nil {
652 return b, err
653 }
654 b = wire.AppendVarint(b, wiretag+1) // end group
655 }
656 return b, nil
657}
658
Damien Neilf0831e82020-01-21 14:25:12 -0800659func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700660 list := listv.List()
661 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800662 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700663 }
664 b, n := wire.ConsumeGroup(num, b)
665 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800666 return pref.Value{}, out, wire.ParseError(n)
Damien Neil68b81c32019-08-22 11:41:32 -0700667 }
668 m := list.NewElement()
Damien Neilc600d6c2020-01-21 15:00:33 -0800669 o, err := opts.Options().UnmarshalState(m.Message().Interface(), piface.UnmarshalInput{
670 Buf: b,
671 })
672 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800673 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700674 }
675 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800676 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800677 out.initialized = o.Initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800678 return listv, out, nil
Damien Neil68b81c32019-08-22 11:41:32 -0700679}
680
681var coderGroupSliceValue = valueCoderFuncs{
682 size: sizeGroupSliceValue,
683 marshal: appendGroupSliceValue,
684 unmarshal: consumeGroupSliceValue,
685 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700686}
687
688func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700689 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700690 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800691 funcs := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -0700692 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700693 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700694 },
695 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700696 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700697 },
Damien Neilf0831e82020-01-21 14:25:12 -0800698 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700699 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700700 },
Damien Neilc37adef2019-04-01 13:49:56 -0700701 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800702 if needsInitCheck(mi.Desc) {
703 funcs.isInit = func(p pointer) error {
704 return isInitMessageSliceInfo(p, mi)
705 }
706 }
707 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700708 }
709 return pointerCoderFuncs{
710 size: func(p pointer, tagsize int, opts marshalOptions) int {
711 return sizeGroupSlice(p, ft, tagsize, opts)
712 },
713 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
714 return appendGroupSlice(b, p, wiretag, ft, opts)
715 },
Damien Neilf0831e82020-01-21 14:25:12 -0800716 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700717 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
718 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700719 isInit: func(p pointer) error {
720 return isInitMessageSlice(p, ft)
721 },
Damien Neilc37adef2019-04-01 13:49:56 -0700722 }
723}
724
725func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
726 s := p.PointerSlice()
727 n := 0
728 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700729 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700730 n += 2*tagsize + proto.Size(m)
731 }
732 return n
733}
734
735func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
736 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700737 var err error
738 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700739 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700740 b = wire.AppendVarint(b, wiretag) // start group
741 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700742 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700743 return b, err
744 }
745 b = wire.AppendVarint(b, wiretag+1) // end group
746 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700747 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700748}
749
Damien Neilf0831e82020-01-21 14:25:12 -0800750func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700751 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800752 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700753 }
754 b, n := wire.ConsumeGroup(num, b)
755 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800756 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700757 }
758 mp := reflect.New(goType.Elem())
Damien Neilc600d6c2020-01-21 15:00:33 -0800759 o, err := opts.Options().UnmarshalState(asMessage(mp), piface.UnmarshalInput{
760 Buf: b,
761 })
762 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800763 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700764 }
765 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800766 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800767 out.initialized = o.Initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800768 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700769}
770
Joe Tsai4fe96632019-05-22 05:12:36 -0400771func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700772 s := p.PointerSlice()
773 n := 0
774 for _, v := range s {
775 n += 2*tagsize + mi.sizePointer(v, opts)
776 }
777 return n
778}
779
Joe Tsai4fe96632019-05-22 05:12:36 -0400780func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700781 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700782 var err error
783 for _, v := range s {
784 b = wire.AppendVarint(b, wiretag) // start group
785 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700786 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700787 return b, err
788 }
789 b = wire.AppendVarint(b, wiretag+1) // end group
790 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700791 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700792}
793
Damien Neilf0831e82020-01-21 14:25:12 -0800794func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700795 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800796 return unmarshalOutput{}, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700797 }
Damien Neil16163b42019-08-06 15:43:25 -0700798 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700799 mp := pointerOfIface(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800800 out, err := mi.unmarshalPointer(b, mp, num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700801 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800802 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700803 }
804 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800805 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700806}
807
Damien Neil5b6d0472019-06-14 11:54:07 -0700808func asMessage(v reflect.Value) pref.ProtoMessage {
809 if m, ok := v.Interface().(pref.ProtoMessage); ok {
810 return m
811 }
812 return legacyWrapMessage(v)
813}