blob: 6204e6531db7a9e00c1625ed43cdddcc4a4db8e2 [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) {
Damien Neilce413af2019-12-05 16:36:28 -080032 fs := si.oneofsByName[od.Name()]
33 ft := fs.Type
Damien Neil316febd2020-02-09 12:26:50 -080034 oneofFields := make(map[reflect.Type]*coderFieldInfo)
Damien Neilce413af2019-12-05 16:36:28 -080035 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()
Damien Neil316febd2020-02-09 12:26:50 -080040 // 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]
Damien Neilce413af2019-12-05 16:36:28 -080047 ot := si.oneofWrappersByNumber[num]
Damien Neile8e88752020-02-11 11:25:16 -080048 cf.ft = ot.Field(0).Type
49 cf.mi, cf.funcs = fieldCoder(fd, cf.ft)
Damien Neil316febd2020-02-09 12:26:50 -080050 oneofFields[ot] = &cf
51 if cf.funcs.isInit != nil {
Damien Neilce413af2019-12-05 16:36:28 -080052 needIsInit = true
53 }
Damien Neil316febd2020-02-09 12:26:50 -080054 mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070055 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 }
Damien Neil316febd2020-02-09 12:26:50 -080062 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
Damien Neile91877d2019-06-27 10:54:42 -070063 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -080064 return out, err
Damien Neilc37adef2019-04-01 13:49:56 -070065 }
Joe Tsai6c286742019-07-11 23:15:05 -070066 vi.Set(vw)
Damien Neilf0831e82020-01-21 14:25:12 -080067 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -070068 }
69 }
Damien Neil316febd2020-02-09 12:26:50 -080070 getInfo := func(p pointer) (pointer, *coderFieldInfo) {
Damien Neilce413af2019-12-05 16:36:28 -080071 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()]
Damien Neil316febd2020-02-09 12:26:50 -080082 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
Damien Neilce413af2019-12-05 16:36:28 -080083 p, info := getInfo(p)
84 if info == nil || info.funcs.size == nil {
85 return 0
86 }
Damien Neil316febd2020-02-09 12:26:50 -080087 return info.funcs.size(p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080088 }
Damien Neil316febd2020-02-09 12:26:50 -080089 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilce413af2019-12-05 16:36:28 -080090 p, info := getInfo(p)
91 if info == nil || info.funcs.marshal == nil {
92 return b, nil
93 }
Damien Neil316febd2020-02-09 12:26:50 -080094 return info.funcs.marshal(b, p, info, opts)
Damien Neilce413af2019-12-05 16:36:28 -080095 }
Damien Neile8e88752020-02-11 11:25:16 -080096 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 }
Damien Neilce413af2019-12-05 16:36:28 -0800108 if needIsInit {
Damien Neil316febd2020-02-09 12:26:50 -0800109 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
Damien Neilce413af2019-12-05 16:36:28 -0800110 p, info := getInfo(p)
111 if info == nil || info.funcs.isInit == nil {
112 return nil
113 }
Damien Neil316febd2020-02-09 12:26:50 -0800114 return info.funcs.isInit(p, info)
Damien Neilce413af2019-12-05 16:36:28 -0800115 }
116 }
Damien Neilc37adef2019-04-01 13:49:56 -0700117}
118
Joe Tsai6e095992019-08-10 13:56:36 -0700119func 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
Joe Tsai6e095992019-08-10 13:56:36 -0700129 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800130 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neile8e88752020-02-11 11:25:16 -0800131 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700132 if !ok {
133 return 0
134 }
Damien Neil6e40b322019-10-01 13:05:16 -0700135 lazyInit()
136 if messageType == nil {
137 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
138 }
Damien Neil316febd2020-02-09 12:26:50 -0800139 return sizeMessage(m, f.tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700140 },
Damien Neil316febd2020-02-09 12:26:50 -0800141 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neile8e88752020-02-11 11:25:16 -0800142 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700143 if !ok {
144 return b, nil
145 }
Damien Neil6e40b322019-10-01 13:05:16 -0700146 lazyInit()
147 if messageType == nil {
148 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
149 }
Damien Neil316febd2020-02-09 12:26:50 -0800150 return appendMessage(b, m, f.wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700151 },
Damien Neil316febd2020-02-09 12:26:50 -0800152 unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Joe Tsai6e095992019-08-10 13:56:36 -0700153 fs := p.WeakFields()
Damien Neile8e88752020-02-11 11:25:16 -0800154 m, ok := fs.get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700155 if !ok {
156 lazyInit()
157 if messageType == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800158 return unmarshalOutput{}, errUnknown
Joe Tsai6e095992019-08-10 13:56:36 -0700159 }
Damien Neil6e40b322019-10-01 13:05:16 -0700160 m = messageType.New().Interface()
Damien Neile8e88752020-02-11 11:25:16 -0800161 fs.set(f.num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700162 }
Damien Neil6e40b322019-10-01 13:05:16 -0700163 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700164 },
Damien Neil316febd2020-02-09 12:26:50 -0800165 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neile8e88752020-02-11 11:25:16 -0800166 m, ok := p.WeakFields().get(f.num)
Joe Tsai6e095992019-08-10 13:56:36 -0700167 if !ok {
168 return nil
169 }
Joe Tsaif26a9e72020-02-20 10:05:37 -0800170 return proto.CheckInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700171 },
Damien Neile8e88752020-02-11 11:25:16 -0800172 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 },
Joe Tsai6e095992019-08-10 13:56:36 -0700188 }
189}
190
Damien Neilc37adef2019-04-01 13:49:56 -0700191func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700192 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800193 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800194 size: sizeMessageInfo,
195 marshal: appendMessageInfo,
196 unmarshal: consumeMessageInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800197 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700198 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800199 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800200 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800201 }
202 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700203 } else {
204 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800205 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700206 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800207 return sizeMessage(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700208 },
Damien Neil316febd2020-02-09 12:26:50 -0800209 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700210 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800211 return appendMessage(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700212 },
Damien Neil316febd2020-02-09 12:26:50 -0800213 unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700214 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 },
Damien Neil316febd2020-02-09 12:26:50 -0800220 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700221 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800222 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700223 },
Damien Neile8e88752020-02-11 11:25:16 -0800224 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700225 }
226 }
227}
228
Damien Neil316febd2020-02-09 12:26:50 -0800229func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
230 return wire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700231}
232
Damien Neil316febd2020-02-09 12:26:50 -0800233func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
234 b = wire.AppendVarint(b, f.wiretag)
235 b = wire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
236 return f.mi.marshalAppendPointer(b, p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700237}
238
Damien Neil316febd2020-02-09 12:26:50 -0800239func consumeMessageInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700240 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800241 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700242 }
243 v, n := wire.ConsumeBytes(b)
244 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800245 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700246 }
247 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800248 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700249 }
Damien Neil316febd2020-02-09 12:26:50 -0800250 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800251 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800252 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700253 }
Damien Neilf0831e82020-01-21 14:25:12 -0800254 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800255 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800256 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700257}
258
Damien Neil316febd2020-02-09 12:26:50 -0800259func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800260 return f.mi.checkInitializedPointer(p.Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800261}
262
Damien Neilc37adef2019-04-01 13:49:56 -0700263func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
264 return wire.SizeBytes(proto.Size(m)) + tagsize
265}
266
267func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
268 b = wire.AppendVarint(b, wiretag)
269 b = wire.AppendVarint(b, uint64(proto.Size(m)))
270 return opts.Options().MarshalAppend(b, m)
271}
272
Damien Neilf0831e82020-01-21 14:25:12 -0800273func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700274 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800275 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700276 }
277 v, n := wire.ConsumeBytes(b)
278 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800279 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700280 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800281 o, err := opts.Options().UnmarshalState(m, piface.UnmarshalInput{
282 Buf: v,
283 })
284 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800285 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700286 }
Damien Neilf0831e82020-01-21 14:25:12 -0800287 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800288 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800289 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700290}
291
Damien Neil68b81c32019-08-22 11:41:32 -0700292func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
293 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700294 return sizeMessage(m, tagsize, opts)
295}
296
Damien Neil68b81c32019-08-22 11:41:32 -0700297func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
298 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700299 return appendMessage(b, m, wiretag, opts)
300}
301
Damien Neilf0831e82020-01-21 14:25:12 -0800302func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) {
Damien Neil68b81c32019-08-22 11:41:32 -0700303 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800304 out, err := consumeMessage(b, m, wtyp, opts)
305 return v, out, err
Damien Neile91877d2019-06-27 10:54:42 -0700306}
307
Damien Neil68b81c32019-08-22 11:41:32 -0700308func isInitMessageValue(v pref.Value) error {
309 m := v.Message().Interface()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800310 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700311}
312
Damien Neil68b81c32019-08-22 11:41:32 -0700313var coderMessageValue = valueCoderFuncs{
314 size: sizeMessageValue,
315 marshal: appendMessageValue,
316 unmarshal: consumeMessageValue,
317 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800318 merge: mergeMessageValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700319}
320
321func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
322 m := v.Message().Interface()
323 return sizeGroup(m, tagsize, opts)
324}
325
326func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
327 m := v.Message().Interface()
328 return appendGroup(b, m, wiretag, opts)
329}
330
Damien Neilf0831e82020-01-21 14:25:12 -0800331func 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 -0700332 m := v.Message().Interface()
Damien Neilf0831e82020-01-21 14:25:12 -0800333 out, err := consumeGroup(b, m, num, wtyp, opts)
334 return v, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700335}
336
337var coderGroupValue = valueCoderFuncs{
338 size: sizeGroupValue,
339 marshal: appendGroupValue,
340 unmarshal: consumeGroupValue,
341 isInit: isInitMessageValue,
Damien Neile8e88752020-02-11 11:25:16 -0800342 merge: mergeMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700343}
344
345func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700346 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700347 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800348 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800349 size: sizeGroupType,
350 marshal: appendGroupType,
351 unmarshal: consumeGroupType,
Damien Neile8e88752020-02-11 11:25:16 -0800352 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700353 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800354 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800355 funcs.isInit = isInitMessageInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800356 }
357 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700358 } else {
359 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800360 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700361 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800362 return sizeGroup(m, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700363 },
Damien Neil316febd2020-02-09 12:26:50 -0800364 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700365 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neil316febd2020-02-09 12:26:50 -0800366 return appendGroup(b, m, f.wiretag, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700367 },
Damien Neil316febd2020-02-09 12:26:50 -0800368 unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700369 mp := p.AsValueOf(ft).Elem()
370 if mp.IsNil() {
371 mp.Set(reflect.New(ft.Elem()))
372 }
373 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
374 },
Damien Neil316febd2020-02-09 12:26:50 -0800375 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700376 m := asMessage(p.AsValueOf(ft).Elem())
Joe Tsaif26a9e72020-02-20 10:05:37 -0800377 return proto.CheckInitialized(m)
Damien Neil5322bdb2019-04-09 15:57:05 -0700378 },
Damien Neile8e88752020-02-11 11:25:16 -0800379 merge: mergeMessage,
Damien Neilc37adef2019-04-01 13:49:56 -0700380 }
381 }
382}
383
Damien Neil316febd2020-02-09 12:26:50 -0800384func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
385 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700386}
387
Damien Neil316febd2020-02-09 12:26:50 -0800388func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
389 b = wire.AppendVarint(b, f.wiretag) // start group
390 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
391 b = wire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700392 return b, err
393}
394
Damien Neil316febd2020-02-09 12:26:50 -0800395func consumeGroupType(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700396 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800397 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700398 }
399 if p.Elem().IsNil() {
Damien Neil316febd2020-02-09 12:26:50 -0800400 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700401 }
Damien Neil316febd2020-02-09 12:26:50 -0800402 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700403}
404
Damien Neilc37adef2019-04-01 13:49:56 -0700405func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
406 return 2*tagsize + proto.Size(m)
407}
408
409func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
410 b = wire.AppendVarint(b, wiretag) // start group
411 b, err := opts.Options().MarshalAppend(b, m)
412 b = wire.AppendVarint(b, wiretag+1) // end group
413 return b, err
414}
415
Damien Neilf0831e82020-01-21 14:25:12 -0800416func 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 -0700417 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800418 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700419 }
420 b, n := wire.ConsumeGroup(num, b)
421 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800422 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700423 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800424 o, err := opts.Options().UnmarshalState(m, piface.UnmarshalInput{
425 Buf: b,
426 })
427 if err != nil {
428 return out, err
429 }
Damien Neilf0831e82020-01-21 14:25:12 -0800430 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800431 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilc600d6c2020-01-21 15:00:33 -0800432 return out, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700433}
434
Damien Neilc37adef2019-04-01 13:49:56 -0700435func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700436 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800437 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800438 size: sizeMessageSliceInfo,
439 marshal: appendMessageSliceInfo,
440 unmarshal: consumeMessageSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800441 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700442 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800443 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800444 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800445 }
446 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700447 }
448 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800449 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
450 return sizeMessageSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700451 },
Damien Neil316febd2020-02-09 12:26:50 -0800452 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
453 return appendMessageSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700454 },
Damien Neil316febd2020-02-09 12:26:50 -0800455 unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700456 return consumeMessageSlice(b, p, ft, wtyp, opts)
457 },
Damien Neil316febd2020-02-09 12:26:50 -0800458 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700459 return isInitMessageSlice(p, ft)
460 },
Damien Neile8e88752020-02-11 11:25:16 -0800461 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700462 }
463}
464
Damien Neil316febd2020-02-09 12:26:50 -0800465func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700466 s := p.PointerSlice()
467 n := 0
468 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800469 n += wire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
Damien Neilc37adef2019-04-01 13:49:56 -0700470 }
471 return n
472}
473
Damien Neil316febd2020-02-09 12:26:50 -0800474func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700475 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700476 var err error
477 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800478 b = wire.AppendVarint(b, f.wiretag)
479 siz := f.mi.sizePointer(v, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700480 b = wire.AppendVarint(b, uint64(siz))
Damien Neil316febd2020-02-09 12:26:50 -0800481 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700482 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700483 return b, err
484 }
485 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700486 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700487}
488
Damien Neil316febd2020-02-09 12:26:50 -0800489func consumeMessageSliceInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700490 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800491 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700492 }
493 v, n := wire.ConsumeBytes(b)
494 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800495 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700496 }
Damien Neil316febd2020-02-09 12:26:50 -0800497 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700498 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800499 o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
Damien Neilc600d6c2020-01-21 15:00:33 -0800500 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800501 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700502 }
503 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800504 out.n = n
Damien Neilc600d6c2020-01-21 15:00:33 -0800505 out.initialized = o.initialized
Damien Neilf0831e82020-01-21 14:25:12 -0800506 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700507}
508
Damien Neil316febd2020-02-09 12:26:50 -0800509func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700510 s := p.PointerSlice()
511 for _, v := range s {
Joe Tsaif26a9e72020-02-20 10:05:37 -0800512 if err := f.mi.checkInitializedPointer(v); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700513 return err
514 }
515 }
516 return nil
517}
518
Damien Neilc37adef2019-04-01 13:49:56 -0700519func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
520 s := p.PointerSlice()
521 n := 0
522 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700523 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700524 n += wire.SizeBytes(proto.Size(m)) + tagsize
525 }
526 return n
527}
528
529func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
530 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700531 var err error
532 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700533 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700534 b = wire.AppendVarint(b, wiretag)
535 siz := proto.Size(m)
536 b = wire.AppendVarint(b, uint64(siz))
537 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700538 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700539 return b, err
540 }
541 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700542 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700543}
544
Damien Neilf0831e82020-01-21 14:25:12 -0800545func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700546 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800547 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700548 }
549 v, n := wire.ConsumeBytes(b)
550 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800551 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700552 }
553 mp := reflect.New(goType.Elem())
Damien Neilc600d6c2020-01-21 15:00:33 -0800554 o, err := opts.Options().UnmarshalState(asMessage(mp), piface.UnmarshalInput{
555 Buf: v,
556 })
557 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800558 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700559 }
560 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800561 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800562 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800563 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700564}
565
Damien Neil5322bdb2019-04-09 15:57:05 -0700566func isInitMessageSlice(p pointer, goType reflect.Type) error {
567 s := p.PointerSlice()
568 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700569 m := asMessage(v.AsValueOf(goType.Elem()))
Joe Tsaif26a9e72020-02-20 10:05:37 -0800570 if err := proto.CheckInitialized(m); err != nil {
Damien Neil5322bdb2019-04-09 15:57:05 -0700571 return err
572 }
573 }
574 return nil
575}
576
Damien Neilc37adef2019-04-01 13:49:56 -0700577// Slices of messages
578
Damien Neil68b81c32019-08-22 11:41:32 -0700579func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
580 list := listv.List()
581 n := 0
582 for i, llen := 0, list.Len(); i < llen; i++ {
583 m := list.Get(i).Message().Interface()
584 n += wire.SizeBytes(proto.Size(m)) + tagsize
585 }
586 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700587}
588
Damien Neil68b81c32019-08-22 11:41:32 -0700589func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
590 list := listv.List()
591 mopts := opts.Options()
592 for i, llen := 0, list.Len(); i < llen; i++ {
593 m := list.Get(i).Message().Interface()
594 b = wire.AppendVarint(b, wiretag)
595 siz := proto.Size(m)
596 b = wire.AppendVarint(b, uint64(siz))
597 var err error
598 b, err = mopts.MarshalAppend(b, m)
599 if err != nil {
600 return b, err
601 }
602 }
603 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700604}
605
Damien Neilf0831e82020-01-21 14:25:12 -0800606func 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 -0700607 list := listv.List()
608 if wtyp != wire.BytesType {
Damien Neilf0831e82020-01-21 14:25:12 -0800609 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700610 }
611 v, n := wire.ConsumeBytes(b)
612 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800613 return pref.Value{}, out, wire.ParseError(n)
Damien Neil68b81c32019-08-22 11:41:32 -0700614 }
615 m := list.NewElement()
Damien Neilc600d6c2020-01-21 15:00:33 -0800616 o, err := opts.Options().UnmarshalState(m.Message().Interface(), piface.UnmarshalInput{
617 Buf: v,
618 })
619 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800620 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700621 }
622 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800623 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800624 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800625 return listv, out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700626}
627
Damien Neil68b81c32019-08-22 11:41:32 -0700628func isInitMessageSliceValue(listv pref.Value) error {
629 list := listv.List()
630 for i, llen := 0, list.Len(); i < llen; i++ {
631 m := list.Get(i).Message().Interface()
Joe Tsaif26a9e72020-02-20 10:05:37 -0800632 if err := proto.CheckInitialized(m); err != nil {
Damien Neil68b81c32019-08-22 11:41:32 -0700633 return err
634 }
635 }
636 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700637}
638
Damien Neil68b81c32019-08-22 11:41:32 -0700639var coderMessageSliceValue = valueCoderFuncs{
640 size: sizeMessageSliceValue,
641 marshal: appendMessageSliceValue,
642 unmarshal: consumeMessageSliceValue,
643 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800644 merge: mergeMessageListValue,
Damien Neil68b81c32019-08-22 11:41:32 -0700645}
646
647func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
648 list := listv.List()
649 n := 0
650 for i, llen := 0, list.Len(); i < llen; i++ {
651 m := list.Get(i).Message().Interface()
652 n += 2*tagsize + proto.Size(m)
653 }
654 return n
655}
656
657func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
658 list := listv.List()
659 mopts := opts.Options()
660 for i, llen := 0, list.Len(); i < llen; i++ {
661 m := list.Get(i).Message().Interface()
662 b = wire.AppendVarint(b, wiretag) // start group
663 var err error
664 b, err = mopts.MarshalAppend(b, m)
665 if err != nil {
666 return b, err
667 }
668 b = wire.AppendVarint(b, wiretag+1) // end group
669 }
670 return b, nil
671}
672
Damien Neilf0831e82020-01-21 14:25:12 -0800673func 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 -0700674 list := listv.List()
675 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800676 return pref.Value{}, out, errUnknown
Damien Neil68b81c32019-08-22 11:41:32 -0700677 }
678 b, n := wire.ConsumeGroup(num, b)
679 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800680 return pref.Value{}, out, wire.ParseError(n)
Damien Neil68b81c32019-08-22 11:41:32 -0700681 }
682 m := list.NewElement()
Damien Neilc600d6c2020-01-21 15:00:33 -0800683 o, err := opts.Options().UnmarshalState(m.Message().Interface(), piface.UnmarshalInput{
684 Buf: b,
685 })
686 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800687 return pref.Value{}, out, err
Damien Neil68b81c32019-08-22 11:41:32 -0700688 }
689 list.Append(m)
Damien Neilf0831e82020-01-21 14:25:12 -0800690 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800691 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800692 return listv, out, nil
Damien Neil68b81c32019-08-22 11:41:32 -0700693}
694
695var coderGroupSliceValue = valueCoderFuncs{
696 size: sizeGroupSliceValue,
697 marshal: appendGroupSliceValue,
698 unmarshal: consumeGroupSliceValue,
699 isInit: isInitMessageSliceValue,
Damien Neile8e88752020-02-11 11:25:16 -0800700 merge: mergeMessageListValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700701}
702
703func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700704 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700705 if mi := getMessageInfo(ft); mi != nil {
Damien Neil7abc2de2020-01-09 14:13:57 -0800706 funcs := pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800707 size: sizeGroupSliceInfo,
708 marshal: appendGroupSliceInfo,
709 unmarshal: consumeGroupSliceInfo,
Damien Neile8e88752020-02-11 11:25:16 -0800710 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700711 }
Damien Neil7abc2de2020-01-09 14:13:57 -0800712 if needsInitCheck(mi.Desc) {
Damien Neil316febd2020-02-09 12:26:50 -0800713 funcs.isInit = isInitMessageSliceInfo
Damien Neil7abc2de2020-01-09 14:13:57 -0800714 }
715 return funcs
Damien Neilc37adef2019-04-01 13:49:56 -0700716 }
717 return pointerCoderFuncs{
Damien Neil316febd2020-02-09 12:26:50 -0800718 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
719 return sizeGroupSlice(p, ft, f.tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700720 },
Damien Neil316febd2020-02-09 12:26:50 -0800721 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
722 return appendGroupSlice(b, p, f.wiretag, ft, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700723 },
Damien Neil316febd2020-02-09 12:26:50 -0800724 unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700725 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
726 },
Damien Neil316febd2020-02-09 12:26:50 -0800727 isInit: func(p pointer, f *coderFieldInfo) error {
Damien Neil5322bdb2019-04-09 15:57:05 -0700728 return isInitMessageSlice(p, ft)
729 },
Damien Neile8e88752020-02-11 11:25:16 -0800730 merge: mergeMessageSlice,
Damien Neilc37adef2019-04-01 13:49:56 -0700731 }
732}
733
734func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
735 s := p.PointerSlice()
736 n := 0
737 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700738 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700739 n += 2*tagsize + proto.Size(m)
740 }
741 return n
742}
743
744func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
745 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700746 var err error
747 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700748 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700749 b = wire.AppendVarint(b, wiretag) // start group
750 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700751 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700752 return b, err
753 }
754 b = wire.AppendVarint(b, wiretag+1) // end group
755 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700756 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700757}
758
Damien Neilf0831e82020-01-21 14:25:12 -0800759func 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 -0700760 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800761 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700762 }
763 b, n := wire.ConsumeGroup(num, b)
764 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800765 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700766 }
767 mp := reflect.New(goType.Elem())
Damien Neilc600d6c2020-01-21 15:00:33 -0800768 o, err := opts.Options().UnmarshalState(asMessage(mp), piface.UnmarshalInput{
769 Buf: b,
770 })
771 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800772 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700773 }
774 p.AppendPointerSlice(pointerOfValue(mp))
Damien Neilf0831e82020-01-21 14:25:12 -0800775 out.n = n
Damien Neil466dd772020-02-14 14:49:35 -0800776 out.initialized = o.Flags&piface.UnmarshalInitialized != 0
Damien Neilf0831e82020-01-21 14:25:12 -0800777 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700778}
779
Damien Neil316febd2020-02-09 12:26:50 -0800780func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700781 s := p.PointerSlice()
782 n := 0
783 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800784 n += 2*f.tagsize + f.mi.sizePointer(v, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700785 }
786 return n
787}
788
Damien Neil316febd2020-02-09 12:26:50 -0800789func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700790 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700791 var err error
792 for _, v := range s {
Damien Neil316febd2020-02-09 12:26:50 -0800793 b = wire.AppendVarint(b, f.wiretag) // start group
794 b, err = f.mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700795 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700796 return b, err
797 }
Damien Neil316febd2020-02-09 12:26:50 -0800798 b = wire.AppendVarint(b, f.wiretag+1) // end group
Damien Neilc37adef2019-04-01 13:49:56 -0700799 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700800 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700801}
802
Damien Neil316febd2020-02-09 12:26:50 -0800803func consumeGroupSliceInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
Damien Neile91877d2019-06-27 10:54:42 -0700804 if wtyp != wire.StartGroupType {
Damien Neilf0831e82020-01-21 14:25:12 -0800805 return unmarshalOutput{}, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700806 }
Damien Neil316febd2020-02-09 12:26:50 -0800807 m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700808 mp := pointerOfIface(m)
Damien Neil316febd2020-02-09 12:26:50 -0800809 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700810 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800811 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700812 }
813 p.AppendPointerSlice(mp)
Damien Neilf0831e82020-01-21 14:25:12 -0800814 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700815}
816
Damien Neil5b6d0472019-06-14 11:54:07 -0700817func asMessage(v reflect.Value) pref.ProtoMessage {
818 if m, ok := v.Interface().(pref.ProtoMessage); ok {
819 return m
820 }
821 return legacyWrapMessage(v)
822}