blob: 9d587d25f89badea304ed04c2263b9d026e78843 [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 Neilc37adef2019-04-01 13:49:56 -07008 "reflect"
Damien Neilc37adef2019-04-01 13:49:56 -07009
10 "google.golang.org/protobuf/internal/encoding/wire"
Damien Neilc37adef2019-04-01 13:49:56 -070011 "google.golang.org/protobuf/proto"
12 pref "google.golang.org/protobuf/reflect/protoreflect"
13)
14
15type errInvalidUTF8 struct{}
16
17func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
18func (errInvalidUTF8) InvalidUTF8() bool { return true }
19
Damien Neile91877d2019-06-27 10:54:42 -070020func makeOneofFieldCoder(si structInfo, fd pref.FieldDescriptor) pointerCoderFuncs {
21 ot := si.oneofWrappersByNumber[fd.Number()]
22 funcs := fieldCoder(fd, ot.Field(0).Type)
23 fs := si.oneofsByName[fd.ContainingOneof().Name()]
Damien Neilc37adef2019-04-01 13:49:56 -070024 ft := fs.Type
Damien Neile91877d2019-06-27 10:54:42 -070025 wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
26 tagsize := wire.SizeVarint(wiretag)
27 getInfo := func(p pointer) (pointer, bool) {
Damien Neil5322bdb2019-04-09 15:57:05 -070028 v := p.AsValueOf(ft).Elem()
29 if v.IsNil() {
Damien Neile91877d2019-06-27 10:54:42 -070030 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070031 }
32 v = v.Elem() // interface -> *struct
Damien Neile91877d2019-06-27 10:54:42 -070033 if v.Elem().Type() != ot {
34 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070035 }
Damien Neile91877d2019-06-27 10:54:42 -070036 return pointerOfValue(v).Apply(zeroOffset), true
Damien Neil5322bdb2019-04-09 15:57:05 -070037 }
Damien Neile91877d2019-06-27 10:54:42 -070038 pcf := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -070039 size: func(p pointer, _ int, opts marshalOptions) int {
Damien Neile91877d2019-06-27 10:54:42 -070040 v, ok := getInfo(p)
41 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070042 return 0
43 }
Damien Neile91877d2019-06-27 10:54:42 -070044 return funcs.size(v, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070045 },
46 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neile91877d2019-06-27 10:54:42 -070047 v, ok := getInfo(p)
48 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070049 return b, nil
50 }
Damien Neile91877d2019-06-27 10:54:42 -070051 return funcs.marshal(b, v, wiretag, opts)
Damien Neil5322bdb2019-04-09 15:57:05 -070052 },
Damien Neile91877d2019-06-27 10:54:42 -070053 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070054 var vw reflect.Value // pointer to wrapper type
55 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
56 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
57 vw = vi.Elem()
58 } else {
59 vw = reflect.New(ot)
60 }
61 n, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070062 if err != nil {
63 return 0, err
Damien Neilc37adef2019-04-01 13:49:56 -070064 }
Joe Tsai6c286742019-07-11 23:15:05 -070065 vi.Set(vw)
Damien Neile91877d2019-06-27 10:54:42 -070066 return n, nil
Damien Neilc37adef2019-04-01 13:49:56 -070067 },
68 }
Damien Neile91877d2019-06-27 10:54:42 -070069 if funcs.isInit != nil {
70 pcf.isInit = func(p pointer) error {
71 v, ok := getInfo(p)
72 if !ok {
73 return nil
74 }
75 return funcs.isInit(v)
76 }
77 }
78 return pcf
Damien Neilc37adef2019-04-01 13:49:56 -070079}
80
81func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -070082 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -070083 return pointerCoderFuncs{
84 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -070085 return sizeMessageInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070086 },
87 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -070088 return appendMessageInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070089 },
Damien Neile91877d2019-06-27 10:54:42 -070090 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -070091 return consumeMessageInfo(b, p, mi, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070092 },
Damien Neil5322bdb2019-04-09 15:57:05 -070093 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -070094 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -070095 },
Damien Neilc37adef2019-04-01 13:49:56 -070096 }
97 } else {
98 return pointerCoderFuncs{
99 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700100 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700101 return sizeMessage(m, tagsize, opts)
102 },
103 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700104 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700105 return appendMessage(b, m, wiretag, opts)
106 },
Damien Neile91877d2019-06-27 10:54:42 -0700107 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
108 mp := p.AsValueOf(ft).Elem()
109 if mp.IsNil() {
110 mp.Set(reflect.New(ft.Elem()))
111 }
112 return consumeMessage(b, asMessage(mp), wtyp, opts)
113 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700114 isInit: func(p pointer) error {
115 m := asMessage(p.AsValueOf(ft).Elem())
116 return proto.IsInitialized(m)
117 },
Damien Neilc37adef2019-04-01 13:49:56 -0700118 }
119 }
120}
121
Joe Tsai4fe96632019-05-22 05:12:36 -0400122func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700123 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
124}
125
Joe Tsai4fe96632019-05-22 05:12:36 -0400126func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700127 b = wire.AppendVarint(b, wiretag)
128 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
129 return mi.marshalAppendPointer(b, p.Elem(), opts)
130}
131
Damien Neile91877d2019-06-27 10:54:42 -0700132func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
133 if wtyp != wire.BytesType {
134 return 0, errUnknown
135 }
136 v, n := wire.ConsumeBytes(b)
137 if n < 0 {
138 return 0, wire.ParseError(n)
139 }
140 if p.Elem().IsNil() {
141 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
142 }
143 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
144 return 0, err
145 }
146 return n, nil
147}
148
Damien Neilc37adef2019-04-01 13:49:56 -0700149func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
150 return wire.SizeBytes(proto.Size(m)) + tagsize
151}
152
153func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
154 b = wire.AppendVarint(b, wiretag)
155 b = wire.AppendVarint(b, uint64(proto.Size(m)))
156 return opts.Options().MarshalAppend(b, m)
157}
158
Damien Neile91877d2019-06-27 10:54:42 -0700159func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
160 if wtyp != wire.BytesType {
161 return 0, errUnknown
162 }
163 v, n := wire.ConsumeBytes(b)
164 if n < 0 {
165 return 0, wire.ParseError(n)
166 }
167 if err := opts.Options().Unmarshal(v, m); err != nil {
168 return 0, err
169 }
170 return n, nil
171}
172
Damien Neilc37adef2019-04-01 13:49:56 -0700173func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
174 m := Export{}.MessageOf(ival).Interface()
175 return sizeMessage(m, tagsize, opts)
176}
177
178func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
179 m := Export{}.MessageOf(ival).Interface()
180 return appendMessage(b, m, wiretag, opts)
181}
182
Damien Neile91877d2019-06-27 10:54:42 -0700183func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
184 m := Export{}.MessageOf(ival).Interface()
185 n, err := consumeMessage(b, m, wtyp, opts)
186 return ival, n, err
187}
188
Damien Neil5322bdb2019-04-09 15:57:05 -0700189func isInitMessageIface(ival interface{}) error {
190 m := Export{}.MessageOf(ival).Interface()
191 return proto.IsInitialized(m)
192}
193
Damien Neilc37adef2019-04-01 13:49:56 -0700194var coderMessageIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700195 size: sizeMessageIface,
196 marshal: appendMessageIface,
197 unmarshal: consumeMessageIface,
198 isInit: isInitMessageIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700199}
200
201func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700202 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700203 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700204 return pointerCoderFuncs{
205 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700206 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700207 },
208 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700209 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700210 },
Damien Neile91877d2019-06-27 10:54:42 -0700211 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700212 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700213 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700214 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700215 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700216 },
Damien Neilc37adef2019-04-01 13:49:56 -0700217 }
218 } else {
219 return pointerCoderFuncs{
220 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700221 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700222 return sizeGroup(m, tagsize, opts)
223 },
224 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700225 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700226 return appendGroup(b, m, wiretag, opts)
227 },
Damien Neile91877d2019-06-27 10:54:42 -0700228 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
229 mp := p.AsValueOf(ft).Elem()
230 if mp.IsNil() {
231 mp.Set(reflect.New(ft.Elem()))
232 }
233 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
234 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700235 isInit: func(p pointer) error {
236 m := asMessage(p.AsValueOf(ft).Elem())
237 return proto.IsInitialized(m)
238 },
Damien Neilc37adef2019-04-01 13:49:56 -0700239 }
240 }
241}
242
Joe Tsai4fe96632019-05-22 05:12:36 -0400243func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700244 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
245}
246
Joe Tsai4fe96632019-05-22 05:12:36 -0400247func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700248 b = wire.AppendVarint(b, wiretag) // start group
249 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
250 b = wire.AppendVarint(b, wiretag+1) // end group
251 return b, err
252}
253
Damien Neile91877d2019-06-27 10:54:42 -0700254func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
255 if wtyp != wire.StartGroupType {
256 return 0, errUnknown
257 }
258 if p.Elem().IsNil() {
259 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
260 }
261 return mi.unmarshalPointer(b, p.Elem(), num, opts)
262}
263
Damien Neilc37adef2019-04-01 13:49:56 -0700264func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
265 return 2*tagsize + proto.Size(m)
266}
267
268func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
269 b = wire.AppendVarint(b, wiretag) // start group
270 b, err := opts.Options().MarshalAppend(b, m)
271 b = wire.AppendVarint(b, wiretag+1) // end group
272 return b, err
273}
274
Damien Neile91877d2019-06-27 10:54:42 -0700275func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
276 if wtyp != wire.StartGroupType {
277 return 0, errUnknown
278 }
279 b, n := wire.ConsumeGroup(num, b)
280 if n < 0 {
281 return 0, wire.ParseError(n)
282 }
283 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700284}
285
Damien Neile91877d2019-06-27 10:54:42 -0700286func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
287 return ifaceCoderFuncs{
288 size: func(ival interface{}, tagsize int, opts marshalOptions) int {
289 m := Export{}.MessageOf(ival).Interface()
290 return sizeGroup(m, tagsize, opts)
291 },
292 marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
293 m := Export{}.MessageOf(ival).Interface()
294 return appendGroup(b, m, wiretag, opts)
295 },
296 unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
297 m := Export{}.MessageOf(ival).Interface()
298 n, err := consumeGroup(b, m, num, wtyp, opts)
299 return ival, n, err
300 },
301 isInit: isInitMessageIface,
302 }
Damien Neilc37adef2019-04-01 13:49:56 -0700303}
304
305func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700306 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700307 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700308 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700309 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700310 },
Damien Neilc37adef2019-04-01 13:49:56 -0700311 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700312 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700313 },
Damien Neile91877d2019-06-27 10:54:42 -0700314 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700315 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700316 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700317 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700318 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700319 },
Damien Neilc37adef2019-04-01 13:49:56 -0700320 }
321 }
322 return pointerCoderFuncs{
323 size: func(p pointer, tagsize int, opts marshalOptions) int {
324 return sizeMessageSlice(p, ft, tagsize, opts)
325 },
326 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
327 return appendMessageSlice(b, p, wiretag, ft, opts)
328 },
Damien Neile91877d2019-06-27 10:54:42 -0700329 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
330 return consumeMessageSlice(b, p, ft, wtyp, opts)
331 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700332 isInit: func(p pointer) error {
333 return isInitMessageSlice(p, ft)
334 },
Damien Neilc37adef2019-04-01 13:49:56 -0700335 }
336}
337
Joe Tsai4fe96632019-05-22 05:12:36 -0400338func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700339 s := p.PointerSlice()
340 n := 0
341 for _, v := range s {
342 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
343 }
344 return n
345}
346
Joe Tsai4fe96632019-05-22 05:12:36 -0400347func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700348 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700349 var err error
350 for _, v := range s {
351 b = wire.AppendVarint(b, wiretag)
352 siz := mi.sizePointer(v, opts)
353 b = wire.AppendVarint(b, uint64(siz))
354 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700355 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700356 return b, err
357 }
358 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700359 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700360}
361
Damien Neile91877d2019-06-27 10:54:42 -0700362func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
363 if wtyp != wire.BytesType {
364 return 0, errUnknown
365 }
366 v, n := wire.ConsumeBytes(b)
367 if n < 0 {
368 return 0, wire.ParseError(n)
369 }
370 m := reflect.New(mi.GoType.Elem()).Interface()
371 mp := pointerOfIface(m)
372 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
373 return 0, err
374 }
375 p.AppendPointerSlice(mp)
376 return n, nil
377}
378
Damien Neil5322bdb2019-04-09 15:57:05 -0700379func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
380 s := p.PointerSlice()
381 for _, v := range s {
382 if err := mi.isInitializedPointer(v); err != nil {
383 return err
384 }
385 }
386 return nil
387}
388
Damien Neilc37adef2019-04-01 13:49:56 -0700389func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
390 s := p.PointerSlice()
391 n := 0
392 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700393 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700394 n += wire.SizeBytes(proto.Size(m)) + tagsize
395 }
396 return n
397}
398
399func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
400 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700401 var err error
402 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700403 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700404 b = wire.AppendVarint(b, wiretag)
405 siz := proto.Size(m)
406 b = wire.AppendVarint(b, uint64(siz))
407 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700408 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700409 return b, err
410 }
411 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700412 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700413}
414
Damien Neile91877d2019-06-27 10:54:42 -0700415func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
416 if wtyp != wire.BytesType {
417 return 0, errUnknown
418 }
419 v, n := wire.ConsumeBytes(b)
420 if n < 0 {
421 return 0, wire.ParseError(n)
422 }
423 mp := reflect.New(goType.Elem())
424 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
425 return 0, err
426 }
427 p.AppendPointerSlice(pointerOfValue(mp))
428 return n, nil
429}
430
Damien Neil5322bdb2019-04-09 15:57:05 -0700431func isInitMessageSlice(p pointer, goType reflect.Type) error {
432 s := p.PointerSlice()
433 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700434 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700435 if err := proto.IsInitialized(m); err != nil {
436 return err
437 }
438 }
439 return nil
440}
441
Damien Neilc37adef2019-04-01 13:49:56 -0700442// Slices of messages
443
444func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
445 p := pointerOfIface(ival)
446 return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
447}
448
449func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
450 p := pointerOfIface(ival)
451 return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
452}
453
Damien Neile91877d2019-06-27 10:54:42 -0700454func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
455 p := pointerOfIface(ival)
456 n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
457 return ival, n, err
458}
459
Damien Neil5322bdb2019-04-09 15:57:05 -0700460func isInitMessageSliceIface(ival interface{}) error {
461 p := pointerOfIface(ival)
462 return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
463}
464
Damien Neilc37adef2019-04-01 13:49:56 -0700465var coderMessageSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700466 size: sizeMessageSliceIface,
467 marshal: appendMessageSliceIface,
468 unmarshal: consumeMessageSliceIface,
469 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700470}
471
472func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700473 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700474 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700475 return pointerCoderFuncs{
476 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700477 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700478 },
479 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700480 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700481 },
Damien Neile91877d2019-06-27 10:54:42 -0700482 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700483 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700484 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700485 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700486 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700487 },
Damien Neilc37adef2019-04-01 13:49:56 -0700488 }
489 }
490 return pointerCoderFuncs{
491 size: func(p pointer, tagsize int, opts marshalOptions) int {
492 return sizeGroupSlice(p, ft, tagsize, opts)
493 },
494 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
495 return appendGroupSlice(b, p, wiretag, ft, opts)
496 },
Damien Neile91877d2019-06-27 10:54:42 -0700497 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
498 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
499 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700500 isInit: func(p pointer) error {
501 return isInitMessageSlice(p, ft)
502 },
Damien Neilc37adef2019-04-01 13:49:56 -0700503 }
504}
505
506func sizeGroupSlice(p pointer, messageType 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(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700511 n += 2*tagsize + proto.Size(m)
512 }
513 return n
514}
515
516func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType 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(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700521 b = wire.AppendVarint(b, wiretag) // start group
522 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700523 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700524 return b, err
525 }
526 b = wire.AppendVarint(b, wiretag+1) // end group
527 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700528 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700529}
530
Damien Neile91877d2019-06-27 10:54:42 -0700531func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
532 if wtyp != wire.StartGroupType {
533 return 0, errUnknown
534 }
535 b, n := wire.ConsumeGroup(num, b)
536 if n < 0 {
537 return 0, wire.ParseError(n)
538 }
539 mp := reflect.New(goType.Elem())
540 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
541 return 0, err
542 }
543 p.AppendPointerSlice(pointerOfValue(mp))
544 return n, nil
545}
546
Joe Tsai4fe96632019-05-22 05:12:36 -0400547func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700548 s := p.PointerSlice()
549 n := 0
550 for _, v := range s {
551 n += 2*tagsize + mi.sizePointer(v, opts)
552 }
553 return n
554}
555
Joe Tsai4fe96632019-05-22 05:12:36 -0400556func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700557 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700558 var err error
559 for _, v := range s {
560 b = wire.AppendVarint(b, wiretag) // start group
561 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700562 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700563 return b, err
564 }
565 b = wire.AppendVarint(b, wiretag+1) // end group
566 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700567 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700568}
569
Damien Neile91877d2019-06-27 10:54:42 -0700570func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
571 if wtyp != wire.StartGroupType {
572 return 0, errUnknown
573 }
574 m := reflect.New(mi.GoType.Elem()).Interface()
575 mp := pointerOfIface(m)
576 n, err := mi.unmarshalPointer(b, mp, num, opts)
577 if err != nil {
578 return 0, err
579 }
580 p.AppendPointerSlice(mp)
581 return n, nil
582}
583
Damien Neilc37adef2019-04-01 13:49:56 -0700584func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
585 p := pointerOfIface(ival)
586 return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
587}
588
589func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
590 p := pointerOfIface(ival)
591 return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
592}
593
Damien Neile91877d2019-06-27 10:54:42 -0700594func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
595 p := pointerOfIface(ival)
596 n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
597 return ival, n, err
598}
599
Damien Neilc37adef2019-04-01 13:49:56 -0700600var coderGroupSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700601 size: sizeGroupSliceIface,
602 marshal: appendGroupSliceIface,
603 unmarshal: consumeGroupSliceIface,
604 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700605}
606
607// Enums
608
609func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
610 v := reflect.ValueOf(ival).Int()
611 return wire.SizeVarint(uint64(v)) + tagsize
612}
613
614func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
615 v := reflect.ValueOf(ival).Int()
616 b = wire.AppendVarint(b, wiretag)
617 b = wire.AppendVarint(b, uint64(v))
618 return b, nil
619}
620
Damien Neile91877d2019-06-27 10:54:42 -0700621func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
622 if wtyp != wire.VarintType {
623 return nil, 0, errUnknown
624 }
625 v, n := wire.ConsumeVarint(b)
626 if n < 0 {
627 return nil, 0, wire.ParseError(n)
628 }
629 rv := reflect.New(reflect.TypeOf(ival)).Elem()
630 rv.SetInt(int64(v))
631 return rv.Interface(), n, nil
632}
633
Damien Neilc37adef2019-04-01 13:49:56 -0700634var coderEnumIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700635 size: sizeEnumIface,
636 marshal: appendEnumIface,
637 unmarshal: consumeEnumIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700638}
639
640func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
641 return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
642}
643
644func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
645 for i, llen := 0, s.Len(); i < llen; i++ {
646 size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
647 }
648 return size
649}
650
651func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
652 return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
653}
654
655func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
656 for i, llen := 0, s.Len(); i < llen; i++ {
657 b = wire.AppendVarint(b, wiretag)
658 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
659 }
660 return b, nil
661}
662
Damien Neile91877d2019-06-27 10:54:42 -0700663func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
664 n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
665 return ival, n, err
666}
667
668func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
669 s = s.Elem() // *[]E -> []E
670 if wtyp == wire.BytesType {
671 b, n = wire.ConsumeBytes(b)
672 if n < 0 {
673 return 0, wire.ParseError(n)
674 }
675 for len(b) > 0 {
676 v, n := wire.ConsumeVarint(b)
677 if n < 0 {
678 return 0, wire.ParseError(n)
679 }
680 rv := reflect.New(s.Type().Elem()).Elem()
681 rv.SetInt(int64(v))
682 s.Set(reflect.Append(s, rv))
683 b = b[n:]
684 }
685 return n, nil
686 }
687 if wtyp != wire.VarintType {
688 return 0, errUnknown
689 }
690 v, n := wire.ConsumeVarint(b)
691 if n < 0 {
692 return 0, wire.ParseError(n)
693 }
694 rv := reflect.New(s.Type().Elem()).Elem()
695 rv.SetInt(int64(v))
696 s.Set(reflect.Append(s, rv))
697 return n, nil
698}
699
Damien Neilc37adef2019-04-01 13:49:56 -0700700var coderEnumSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700701 size: sizeEnumSliceIface,
702 marshal: appendEnumSliceIface,
703 unmarshal: consumeEnumSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700704}
705
Damien Neil7492a092019-07-10 15:23:29 -0700706func sizeEnumPackedSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
707 return sizeEnumPackedSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
708}
709
710func sizeEnumPackedSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
711 llen := s.Len()
712 if llen == 0 {
713 return 0
714 }
715 n := 0
716 for i := 0; i < llen; i++ {
717 n += wire.SizeVarint(uint64(s.Index(i).Int()))
718 }
719 return tagsize + wire.SizeBytes(n)
720}
721
722func appendEnumPackedSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
723 return appendEnumPackedSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
724}
725
726func appendEnumPackedSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
727 llen := s.Len()
728 if llen == 0 {
729 return b, nil
730 }
731 b = wire.AppendVarint(b, wiretag)
732 n := 0
733 for i := 0; i < llen; i++ {
734 n += wire.SizeVarint(uint64(s.Index(i).Int()))
735 }
736 b = wire.AppendVarint(b, uint64(n))
737 for i := 0; i < llen; i++ {
738 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
739 }
740 return b, nil
741}
742
743var coderEnumPackedSliceIface = ifaceCoderFuncs{
744 size: sizeEnumPackedSliceIface,
745 marshal: appendEnumPackedSliceIface,
746 unmarshal: consumeEnumSliceIface,
747}
748
Damien Neil5b6d0472019-06-14 11:54:07 -0700749func asMessage(v reflect.Value) pref.ProtoMessage {
750 if m, ok := v.Interface().(pref.ProtoMessage); ok {
751 return m
752 }
753 return legacyWrapMessage(v)
754}