blob: f5e9755a710ffa99d8f1f5269e41532e62c774f9 [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"
9 "unicode/utf8"
10
11 "google.golang.org/protobuf/internal/encoding/wire"
Damien Neilc37adef2019-04-01 13:49:56 -070012 "google.golang.org/protobuf/proto"
13 pref "google.golang.org/protobuf/reflect/protoreflect"
14)
15
16type errInvalidUTF8 struct{}
17
18func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
19func (errInvalidUTF8) InvalidUTF8() bool { return true }
20
Damien Neile91877d2019-06-27 10:54:42 -070021func makeOneofFieldCoder(si structInfo, fd pref.FieldDescriptor) pointerCoderFuncs {
22 ot := si.oneofWrappersByNumber[fd.Number()]
23 funcs := fieldCoder(fd, ot.Field(0).Type)
24 fs := si.oneofsByName[fd.ContainingOneof().Name()]
Damien Neilc37adef2019-04-01 13:49:56 -070025 ft := fs.Type
Damien Neile91877d2019-06-27 10:54:42 -070026 wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
27 tagsize := wire.SizeVarint(wiretag)
28 getInfo := func(p pointer) (pointer, bool) {
Damien Neil5322bdb2019-04-09 15:57:05 -070029 v := p.AsValueOf(ft).Elem()
30 if v.IsNil() {
Damien Neile91877d2019-06-27 10:54:42 -070031 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070032 }
33 v = v.Elem() // interface -> *struct
Damien Neile91877d2019-06-27 10:54:42 -070034 if v.Elem().Type() != ot {
35 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070036 }
Damien Neile91877d2019-06-27 10:54:42 -070037 return pointerOfValue(v).Apply(zeroOffset), true
Damien Neil5322bdb2019-04-09 15:57:05 -070038 }
Damien Neile91877d2019-06-27 10:54:42 -070039 pcf := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -070040 size: func(p pointer, _ int, opts marshalOptions) int {
Damien Neile91877d2019-06-27 10:54:42 -070041 v, ok := getInfo(p)
42 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070043 return 0
44 }
Damien Neile91877d2019-06-27 10:54:42 -070045 return funcs.size(v, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070046 },
47 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neile91877d2019-06-27 10:54:42 -070048 v, ok := getInfo(p)
49 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070050 return b, nil
51 }
Damien Neile91877d2019-06-27 10:54:42 -070052 return funcs.marshal(b, v, wiretag, opts)
Damien Neil5322bdb2019-04-09 15:57:05 -070053 },
Damien Neile91877d2019-06-27 10:54:42 -070054 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
55 v := reflect.New(ot)
56 n, err := funcs.unmarshal(b, pointerOfValue(v).Apply(zeroOffset), wtyp, opts)
57 if err != nil {
58 return 0, err
Damien Neilc37adef2019-04-01 13:49:56 -070059 }
Damien Neile91877d2019-06-27 10:54:42 -070060 p.AsValueOf(ft).Elem().Set(v)
61 return n, nil
Damien Neilc37adef2019-04-01 13:49:56 -070062 },
63 }
Damien Neile91877d2019-06-27 10:54:42 -070064 if funcs.isInit != nil {
65 pcf.isInit = func(p pointer) error {
66 v, ok := getInfo(p)
67 if !ok {
68 return nil
69 }
70 return funcs.isInit(v)
71 }
72 }
73 return pcf
Damien Neilc37adef2019-04-01 13:49:56 -070074}
75
76func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -040077 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -070078 return pointerCoderFuncs{
79 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai4fe96632019-05-22 05:12:36 -040080 return sizeMessageInfo(p, fi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070081 },
82 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai4fe96632019-05-22 05:12:36 -040083 return appendMessageInfo(b, p, wiretag, fi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070084 },
Damien Neile91877d2019-06-27 10:54:42 -070085 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
86 return consumeMessageInfo(b, p, fi, wtyp, opts)
87 },
Damien Neil5322bdb2019-04-09 15:57:05 -070088 isInit: func(p pointer) error {
89 return fi.isInitializedPointer(p.Elem())
90 },
Damien Neilc37adef2019-04-01 13:49:56 -070091 }
92 } else {
93 return pointerCoderFuncs{
94 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -070095 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -070096 return sizeMessage(m, tagsize, opts)
97 },
98 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -070099 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700100 return appendMessage(b, m, wiretag, opts)
101 },
Damien Neile91877d2019-06-27 10:54:42 -0700102 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
103 mp := p.AsValueOf(ft).Elem()
104 if mp.IsNil() {
105 mp.Set(reflect.New(ft.Elem()))
106 }
107 return consumeMessage(b, asMessage(mp), wtyp, opts)
108 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700109 isInit: func(p pointer) error {
110 m := asMessage(p.AsValueOf(ft).Elem())
111 return proto.IsInitialized(m)
112 },
Damien Neilc37adef2019-04-01 13:49:56 -0700113 }
114 }
115}
116
Joe Tsai4fe96632019-05-22 05:12:36 -0400117func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700118 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
119}
120
Joe Tsai4fe96632019-05-22 05:12:36 -0400121func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700122 b = wire.AppendVarint(b, wiretag)
123 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
124 return mi.marshalAppendPointer(b, p.Elem(), opts)
125}
126
Damien Neile91877d2019-06-27 10:54:42 -0700127func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
128 if wtyp != wire.BytesType {
129 return 0, errUnknown
130 }
131 v, n := wire.ConsumeBytes(b)
132 if n < 0 {
133 return 0, wire.ParseError(n)
134 }
135 if p.Elem().IsNil() {
136 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
137 }
138 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
139 return 0, err
140 }
141 return n, nil
142}
143
Damien Neilc37adef2019-04-01 13:49:56 -0700144func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
145 return wire.SizeBytes(proto.Size(m)) + tagsize
146}
147
148func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
149 b = wire.AppendVarint(b, wiretag)
150 b = wire.AppendVarint(b, uint64(proto.Size(m)))
151 return opts.Options().MarshalAppend(b, m)
152}
153
Damien Neile91877d2019-06-27 10:54:42 -0700154func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
155 if wtyp != wire.BytesType {
156 return 0, errUnknown
157 }
158 v, n := wire.ConsumeBytes(b)
159 if n < 0 {
160 return 0, wire.ParseError(n)
161 }
162 if err := opts.Options().Unmarshal(v, m); err != nil {
163 return 0, err
164 }
165 return n, nil
166}
167
Damien Neilc37adef2019-04-01 13:49:56 -0700168func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
169 m := Export{}.MessageOf(ival).Interface()
170 return sizeMessage(m, tagsize, opts)
171}
172
173func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
174 m := Export{}.MessageOf(ival).Interface()
175 return appendMessage(b, m, wiretag, opts)
176}
177
Damien Neile91877d2019-06-27 10:54:42 -0700178func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
179 m := Export{}.MessageOf(ival).Interface()
180 n, err := consumeMessage(b, m, wtyp, opts)
181 return ival, n, err
182}
183
Damien Neil5322bdb2019-04-09 15:57:05 -0700184func isInitMessageIface(ival interface{}) error {
185 m := Export{}.MessageOf(ival).Interface()
186 return proto.IsInitialized(m)
187}
188
Damien Neilc37adef2019-04-01 13:49:56 -0700189var coderMessageIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700190 size: sizeMessageIface,
191 marshal: appendMessageIface,
192 unmarshal: consumeMessageIface,
193 isInit: isInitMessageIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700194}
195
196func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700197 num := fd.Number()
Joe Tsai4fe96632019-05-22 05:12:36 -0400198 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700199 return pointerCoderFuncs{
200 size: func(p pointer, tagsize int, opts marshalOptions) int {
201 return sizeGroupType(p, fi, tagsize, opts)
202 },
203 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
204 return appendGroupType(b, p, wiretag, fi, opts)
205 },
Damien Neile91877d2019-06-27 10:54:42 -0700206 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
207 return consumeGroupType(b, p, fi, num, wtyp, opts)
208 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700209 isInit: func(p pointer) error {
210 return fi.isInitializedPointer(p.Elem())
211 },
Damien Neilc37adef2019-04-01 13:49:56 -0700212 }
213 } else {
214 return pointerCoderFuncs{
215 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700216 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700217 return sizeGroup(m, tagsize, opts)
218 },
219 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700220 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700221 return appendGroup(b, m, wiretag, opts)
222 },
Damien Neile91877d2019-06-27 10:54:42 -0700223 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
224 mp := p.AsValueOf(ft).Elem()
225 if mp.IsNil() {
226 mp.Set(reflect.New(ft.Elem()))
227 }
228 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
229 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700230 isInit: func(p pointer) error {
231 m := asMessage(p.AsValueOf(ft).Elem())
232 return proto.IsInitialized(m)
233 },
Damien Neilc37adef2019-04-01 13:49:56 -0700234 }
235 }
236}
237
Joe Tsai4fe96632019-05-22 05:12:36 -0400238func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700239 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
240}
241
Joe Tsai4fe96632019-05-22 05:12:36 -0400242func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700243 b = wire.AppendVarint(b, wiretag) // start group
244 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
245 b = wire.AppendVarint(b, wiretag+1) // end group
246 return b, err
247}
248
Damien Neile91877d2019-06-27 10:54:42 -0700249func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
250 if wtyp != wire.StartGroupType {
251 return 0, errUnknown
252 }
253 if p.Elem().IsNil() {
254 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
255 }
256 return mi.unmarshalPointer(b, p.Elem(), num, opts)
257}
258
Damien Neilc37adef2019-04-01 13:49:56 -0700259func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
260 return 2*tagsize + proto.Size(m)
261}
262
263func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
264 b = wire.AppendVarint(b, wiretag) // start group
265 b, err := opts.Options().MarshalAppend(b, m)
266 b = wire.AppendVarint(b, wiretag+1) // end group
267 return b, err
268}
269
Damien Neile91877d2019-06-27 10:54:42 -0700270func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
271 if wtyp != wire.StartGroupType {
272 return 0, errUnknown
273 }
274 b, n := wire.ConsumeGroup(num, b)
275 if n < 0 {
276 return 0, wire.ParseError(n)
277 }
278 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700279}
280
Damien Neile91877d2019-06-27 10:54:42 -0700281func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
282 return ifaceCoderFuncs{
283 size: func(ival interface{}, tagsize int, opts marshalOptions) int {
284 m := Export{}.MessageOf(ival).Interface()
285 return sizeGroup(m, tagsize, opts)
286 },
287 marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
288 m := Export{}.MessageOf(ival).Interface()
289 return appendGroup(b, m, wiretag, opts)
290 },
291 unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
292 m := Export{}.MessageOf(ival).Interface()
293 n, err := consumeGroup(b, m, num, wtyp, opts)
294 return ival, n, err
295 },
296 isInit: isInitMessageIface,
297 }
Damien Neilc37adef2019-04-01 13:49:56 -0700298}
299
300func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -0400301 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700302 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700303 size: func(p pointer, tagsize int, opts marshalOptions) int {
304 return sizeMessageSliceInfo(p, fi, tagsize, opts)
305 },
Damien Neilc37adef2019-04-01 13:49:56 -0700306 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
307 return appendMessageSliceInfo(b, p, wiretag, fi, opts)
308 },
Damien Neile91877d2019-06-27 10:54:42 -0700309 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
310 return consumeMessageSliceInfo(b, p, fi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700311 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700312 isInit: func(p pointer) error {
313 return isInitMessageSliceInfo(p, fi)
314 },
Damien Neilc37adef2019-04-01 13:49:56 -0700315 }
316 }
317 return pointerCoderFuncs{
318 size: func(p pointer, tagsize int, opts marshalOptions) int {
319 return sizeMessageSlice(p, ft, tagsize, opts)
320 },
321 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
322 return appendMessageSlice(b, p, wiretag, ft, opts)
323 },
Damien Neile91877d2019-06-27 10:54:42 -0700324 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
325 return consumeMessageSlice(b, p, ft, wtyp, opts)
326 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700327 isInit: func(p pointer) error {
328 return isInitMessageSlice(p, ft)
329 },
Damien Neilc37adef2019-04-01 13:49:56 -0700330 }
331}
332
Joe Tsai4fe96632019-05-22 05:12:36 -0400333func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700334 s := p.PointerSlice()
335 n := 0
336 for _, v := range s {
337 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
338 }
339 return n
340}
341
Joe Tsai4fe96632019-05-22 05:12:36 -0400342func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700343 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700344 var err error
345 for _, v := range s {
346 b = wire.AppendVarint(b, wiretag)
347 siz := mi.sizePointer(v, opts)
348 b = wire.AppendVarint(b, uint64(siz))
349 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700350 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700351 return b, err
352 }
353 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700354 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700355}
356
Damien Neile91877d2019-06-27 10:54:42 -0700357func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
358 if wtyp != wire.BytesType {
359 return 0, errUnknown
360 }
361 v, n := wire.ConsumeBytes(b)
362 if n < 0 {
363 return 0, wire.ParseError(n)
364 }
365 m := reflect.New(mi.GoType.Elem()).Interface()
366 mp := pointerOfIface(m)
367 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
368 return 0, err
369 }
370 p.AppendPointerSlice(mp)
371 return n, nil
372}
373
Damien Neil5322bdb2019-04-09 15:57:05 -0700374func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
375 s := p.PointerSlice()
376 for _, v := range s {
377 if err := mi.isInitializedPointer(v); err != nil {
378 return err
379 }
380 }
381 return nil
382}
383
Damien Neilc37adef2019-04-01 13:49:56 -0700384func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
385 s := p.PointerSlice()
386 n := 0
387 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700388 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700389 n += wire.SizeBytes(proto.Size(m)) + tagsize
390 }
391 return n
392}
393
394func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
395 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700396 var err error
397 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700398 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700399 b = wire.AppendVarint(b, wiretag)
400 siz := proto.Size(m)
401 b = wire.AppendVarint(b, uint64(siz))
402 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700403 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700404 return b, err
405 }
406 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700407 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700408}
409
Damien Neile91877d2019-06-27 10:54:42 -0700410func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
411 if wtyp != wire.BytesType {
412 return 0, errUnknown
413 }
414 v, n := wire.ConsumeBytes(b)
415 if n < 0 {
416 return 0, wire.ParseError(n)
417 }
418 mp := reflect.New(goType.Elem())
419 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
420 return 0, err
421 }
422 p.AppendPointerSlice(pointerOfValue(mp))
423 return n, nil
424}
425
Damien Neil5322bdb2019-04-09 15:57:05 -0700426func isInitMessageSlice(p pointer, goType reflect.Type) error {
427 s := p.PointerSlice()
428 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700429 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700430 if err := proto.IsInitialized(m); err != nil {
431 return err
432 }
433 }
434 return nil
435}
436
Damien Neilc37adef2019-04-01 13:49:56 -0700437// Slices of messages
438
439func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
440 p := pointerOfIface(ival)
441 return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
442}
443
444func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
445 p := pointerOfIface(ival)
446 return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
447}
448
Damien Neile91877d2019-06-27 10:54:42 -0700449func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
450 p := pointerOfIface(ival)
451 n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
452 return ival, n, err
453}
454
Damien Neil5322bdb2019-04-09 15:57:05 -0700455func isInitMessageSliceIface(ival interface{}) error {
456 p := pointerOfIface(ival)
457 return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
458}
459
Damien Neilc37adef2019-04-01 13:49:56 -0700460var coderMessageSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700461 size: sizeMessageSliceIface,
462 marshal: appendMessageSliceIface,
463 unmarshal: consumeMessageSliceIface,
464 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700465}
466
467func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700468 num := fd.Number()
Joe Tsai4fe96632019-05-22 05:12:36 -0400469 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700470 return pointerCoderFuncs{
471 size: func(p pointer, tagsize int, opts marshalOptions) int {
472 return sizeGroupSliceInfo(p, fi, tagsize, opts)
473 },
474 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
475 return appendGroupSliceInfo(b, p, wiretag, fi, opts)
476 },
Damien Neile91877d2019-06-27 10:54:42 -0700477 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
478 return consumeGroupSliceInfo(b, p, num, wtyp, fi, opts)
479 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700480 isInit: func(p pointer) error {
481 return isInitMessageSliceInfo(p, fi)
482 },
Damien Neilc37adef2019-04-01 13:49:56 -0700483 }
484 }
485 return pointerCoderFuncs{
486 size: func(p pointer, tagsize int, opts marshalOptions) int {
487 return sizeGroupSlice(p, ft, tagsize, opts)
488 },
489 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
490 return appendGroupSlice(b, p, wiretag, ft, opts)
491 },
Damien Neile91877d2019-06-27 10:54:42 -0700492 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
493 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
494 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700495 isInit: func(p pointer) error {
496 return isInitMessageSlice(p, ft)
497 },
Damien Neilc37adef2019-04-01 13:49:56 -0700498 }
499}
500
501func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
502 s := p.PointerSlice()
503 n := 0
504 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700505 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700506 n += 2*tagsize + proto.Size(m)
507 }
508 return n
509}
510
511func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
512 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700513 var err error
514 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700515 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700516 b = wire.AppendVarint(b, wiretag) // start group
517 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700518 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700519 return b, err
520 }
521 b = wire.AppendVarint(b, wiretag+1) // end group
522 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700523 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700524}
525
Damien Neile91877d2019-06-27 10:54:42 -0700526func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
527 if wtyp != wire.StartGroupType {
528 return 0, errUnknown
529 }
530 b, n := wire.ConsumeGroup(num, b)
531 if n < 0 {
532 return 0, wire.ParseError(n)
533 }
534 mp := reflect.New(goType.Elem())
535 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
536 return 0, err
537 }
538 p.AppendPointerSlice(pointerOfValue(mp))
539 return n, nil
540}
541
Joe Tsai4fe96632019-05-22 05:12:36 -0400542func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700543 s := p.PointerSlice()
544 n := 0
545 for _, v := range s {
546 n += 2*tagsize + mi.sizePointer(v, opts)
547 }
548 return n
549}
550
Joe Tsai4fe96632019-05-22 05:12:36 -0400551func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700552 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700553 var err error
554 for _, v := range s {
555 b = wire.AppendVarint(b, wiretag) // start group
556 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700557 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700558 return b, err
559 }
560 b = wire.AppendVarint(b, wiretag+1) // end group
561 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700562 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700563}
564
Damien Neile91877d2019-06-27 10:54:42 -0700565func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
566 if wtyp != wire.StartGroupType {
567 return 0, errUnknown
568 }
569 m := reflect.New(mi.GoType.Elem()).Interface()
570 mp := pointerOfIface(m)
571 n, err := mi.unmarshalPointer(b, mp, num, opts)
572 if err != nil {
573 return 0, err
574 }
575 p.AppendPointerSlice(mp)
576 return n, nil
577}
578
Damien Neilc37adef2019-04-01 13:49:56 -0700579func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
580 p := pointerOfIface(ival)
581 return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
582}
583
584func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
585 p := pointerOfIface(ival)
586 return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
587}
588
Damien Neile91877d2019-06-27 10:54:42 -0700589func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
590 p := pointerOfIface(ival)
591 n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
592 return ival, n, err
593}
594
Damien Neilc37adef2019-04-01 13:49:56 -0700595var coderGroupSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700596 size: sizeGroupSliceIface,
597 marshal: appendGroupSliceIface,
598 unmarshal: consumeGroupSliceIface,
599 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700600}
601
602// Enums
603
604func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
605 v := reflect.ValueOf(ival).Int()
606 return wire.SizeVarint(uint64(v)) + tagsize
607}
608
609func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
610 v := reflect.ValueOf(ival).Int()
611 b = wire.AppendVarint(b, wiretag)
612 b = wire.AppendVarint(b, uint64(v))
613 return b, nil
614}
615
Damien Neile91877d2019-06-27 10:54:42 -0700616func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
617 if wtyp != wire.VarintType {
618 return nil, 0, errUnknown
619 }
620 v, n := wire.ConsumeVarint(b)
621 if n < 0 {
622 return nil, 0, wire.ParseError(n)
623 }
624 rv := reflect.New(reflect.TypeOf(ival)).Elem()
625 rv.SetInt(int64(v))
626 return rv.Interface(), n, nil
627}
628
Damien Neilc37adef2019-04-01 13:49:56 -0700629var coderEnumIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700630 size: sizeEnumIface,
631 marshal: appendEnumIface,
632 unmarshal: consumeEnumIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700633}
634
635func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
636 return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
637}
638
639func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
640 for i, llen := 0, s.Len(); i < llen; i++ {
641 size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
642 }
643 return size
644}
645
646func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
647 return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
648}
649
650func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
651 for i, llen := 0, s.Len(); i < llen; i++ {
652 b = wire.AppendVarint(b, wiretag)
653 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
654 }
655 return b, nil
656}
657
Damien Neile91877d2019-06-27 10:54:42 -0700658func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
659 n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
660 return ival, n, err
661}
662
663func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
664 s = s.Elem() // *[]E -> []E
665 if wtyp == wire.BytesType {
666 b, n = wire.ConsumeBytes(b)
667 if n < 0 {
668 return 0, wire.ParseError(n)
669 }
670 for len(b) > 0 {
671 v, n := wire.ConsumeVarint(b)
672 if n < 0 {
673 return 0, wire.ParseError(n)
674 }
675 rv := reflect.New(s.Type().Elem()).Elem()
676 rv.SetInt(int64(v))
677 s.Set(reflect.Append(s, rv))
678 b = b[n:]
679 }
680 return n, nil
681 }
682 if wtyp != wire.VarintType {
683 return 0, errUnknown
684 }
685 v, n := wire.ConsumeVarint(b)
686 if n < 0 {
687 return 0, wire.ParseError(n)
688 }
689 rv := reflect.New(s.Type().Elem()).Elem()
690 rv.SetInt(int64(v))
691 s.Set(reflect.Append(s, rv))
692 return n, nil
693}
694
Damien Neilc37adef2019-04-01 13:49:56 -0700695var coderEnumSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700696 size: sizeEnumSliceIface,
697 marshal: appendEnumSliceIface,
698 unmarshal: consumeEnumSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700699}
700
Damien Neil7492a092019-07-10 15:23:29 -0700701func sizeEnumPackedSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
702 return sizeEnumPackedSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
703}
704
705func sizeEnumPackedSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
706 llen := s.Len()
707 if llen == 0 {
708 return 0
709 }
710 n := 0
711 for i := 0; i < llen; i++ {
712 n += wire.SizeVarint(uint64(s.Index(i).Int()))
713 }
714 return tagsize + wire.SizeBytes(n)
715}
716
717func appendEnumPackedSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
718 return appendEnumPackedSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
719}
720
721func appendEnumPackedSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
722 llen := s.Len()
723 if llen == 0 {
724 return b, nil
725 }
726 b = wire.AppendVarint(b, wiretag)
727 n := 0
728 for i := 0; i < llen; i++ {
729 n += wire.SizeVarint(uint64(s.Index(i).Int()))
730 }
731 b = wire.AppendVarint(b, uint64(n))
732 for i := 0; i < llen; i++ {
733 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
734 }
735 return b, nil
736}
737
738var coderEnumPackedSliceIface = ifaceCoderFuncs{
739 size: sizeEnumPackedSliceIface,
740 marshal: appendEnumPackedSliceIface,
741 unmarshal: consumeEnumSliceIface,
742}
743
Damien Neilc37adef2019-04-01 13:49:56 -0700744// Strings with UTF8 validation.
745
746func appendStringValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
747 v := *p.String()
748 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700749 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700750 if !utf8.ValidString(v) {
751 return b, errInvalidUTF8{}
752 }
753 return b, nil
754}
755
Damien Neile91877d2019-06-27 10:54:42 -0700756func consumeStringValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
757 if wtyp != wire.BytesType {
758 return 0, errUnknown
759 }
760 v, n := wire.ConsumeString(b)
761 if n < 0 {
762 return 0, wire.ParseError(n)
763 }
764 if !utf8.ValidString(v) {
765 return 0, errInvalidUTF8{}
766 }
767 *p.String() = v
768 return n, nil
769}
770
Damien Neilc37adef2019-04-01 13:49:56 -0700771var coderStringValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700772 size: sizeString,
773 marshal: appendStringValidateUTF8,
774 unmarshal: consumeStringValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700775}
776
777func appendStringNoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
778 v := *p.String()
779 if len(v) == 0 {
780 return b, nil
781 }
782 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700783 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700784 if !utf8.ValidString(v) {
785 return b, errInvalidUTF8{}
786 }
787 return b, nil
788}
789
790var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700791 size: sizeStringNoZero,
792 marshal: appendStringNoZeroValidateUTF8,
793 unmarshal: consumeStringValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700794}
795
796func sizeStringSliceValidateUTF8(p pointer, tagsize int, _ marshalOptions) (size int) {
797 s := *p.StringSlice()
798 for _, v := range s {
Damien Neilcedb5952019-06-21 12:04:07 -0700799 size += tagsize + wire.SizeBytes(len(v))
Damien Neilc37adef2019-04-01 13:49:56 -0700800 }
801 return size
802}
803
804func appendStringSliceValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
805 s := *p.StringSlice()
806 var err error
807 for _, v := range s {
808 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700809 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700810 if !utf8.ValidString(v) {
Damien Neile91877d2019-06-27 10:54:42 -0700811 return b, errInvalidUTF8{}
Damien Neilc37adef2019-04-01 13:49:56 -0700812 }
813 }
814 return b, err
815}
816
Damien Neile91877d2019-06-27 10:54:42 -0700817func consumeStringSliceValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
818 if wtyp != wire.BytesType {
819 return 0, errUnknown
820 }
821 sp := p.StringSlice()
822 v, n := wire.ConsumeString(b)
823 if n < 0 {
824 return 0, wire.ParseError(n)
825 }
826 if !utf8.ValidString(v) {
827 return 0, errInvalidUTF8{}
828 }
829 *sp = append(*sp, v)
830 return n, nil
831}
832
Damien Neilc37adef2019-04-01 13:49:56 -0700833var coderStringSliceValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700834 size: sizeStringSliceValidateUTF8,
835 marshal: appendStringSliceValidateUTF8,
836 unmarshal: consumeStringSliceValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700837}
838
839func sizeStringIfaceValidateUTF8(ival interface{}, tagsize int, _ marshalOptions) int {
840 v := ival.(string)
Damien Neilcedb5952019-06-21 12:04:07 -0700841 return tagsize + wire.SizeBytes(len(v))
Damien Neilc37adef2019-04-01 13:49:56 -0700842}
843
844func appendStringIfaceValidateUTF8(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
845 v := ival.(string)
846 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700847 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700848 if !utf8.ValidString(v) {
849 return b, errInvalidUTF8{}
850 }
851 return b, nil
852}
853
Damien Neile91877d2019-06-27 10:54:42 -0700854func consumeStringIfaceValidateUTF8(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
855 if wtyp != wire.BytesType {
856 return nil, 0, errUnknown
857 }
858 v, n := wire.ConsumeString(b)
859 if n < 0 {
860 return nil, 0, wire.ParseError(n)
861 }
862 if !utf8.ValidString(v) {
863 return nil, 0, errInvalidUTF8{}
864 }
865 return v, n, nil
866}
867
Damien Neilc37adef2019-04-01 13:49:56 -0700868var coderStringIfaceValidateUTF8 = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700869 size: sizeStringIfaceValidateUTF8,
870 marshal: appendStringIfaceValidateUTF8,
871 unmarshal: consumeStringIfaceValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700872}
Damien Neil5b6d0472019-06-14 11:54:07 -0700873
874func asMessage(v reflect.Value) pref.ProtoMessage {
875 if m, ok := v.Interface().(pref.ProtoMessage); ok {
876 return m
877 }
878 return legacyWrapMessage(v)
879}