blob: 8d0e3397ba11948cdd2e75999fe2915c0524f979 [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) {
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 }
62 n, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070063 if err != nil {
64 return 0, err
Damien Neilc37adef2019-04-01 13:49:56 -070065 }
Joe Tsai6c286742019-07-11 23:15:05 -070066 vi.Set(vw)
Damien Neile91877d2019-06-27 10:54:42 -070067 return n, nil
Damien Neilc37adef2019-04-01 13:49:56 -070068 },
69 }
Damien Neile91877d2019-06-27 10:54:42 -070070 if funcs.isInit != nil {
71 pcf.isInit = func(p pointer) error {
72 v, ok := getInfo(p)
73 if !ok {
74 return nil
75 }
76 return funcs.isInit(v)
77 }
78 }
79 return pcf
Damien Neilc37adef2019-04-01 13:49:56 -070080}
81
82func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -040083 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -070084 return pointerCoderFuncs{
85 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai4fe96632019-05-22 05:12:36 -040086 return sizeMessageInfo(p, fi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070087 },
88 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai4fe96632019-05-22 05:12:36 -040089 return appendMessageInfo(b, p, wiretag, fi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070090 },
Damien Neile91877d2019-06-27 10:54:42 -070091 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
92 return consumeMessageInfo(b, p, fi, wtyp, opts)
93 },
Damien Neil5322bdb2019-04-09 15:57:05 -070094 isInit: func(p pointer) error {
95 return fi.isInitializedPointer(p.Elem())
96 },
Damien Neilc37adef2019-04-01 13:49:56 -070097 }
98 } else {
99 return pointerCoderFuncs{
100 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700101 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700102 return sizeMessage(m, tagsize, opts)
103 },
104 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700105 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700106 return appendMessage(b, m, wiretag, opts)
107 },
Damien Neile91877d2019-06-27 10:54:42 -0700108 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
109 mp := p.AsValueOf(ft).Elem()
110 if mp.IsNil() {
111 mp.Set(reflect.New(ft.Elem()))
112 }
113 return consumeMessage(b, asMessage(mp), wtyp, opts)
114 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700115 isInit: func(p pointer) error {
116 m := asMessage(p.AsValueOf(ft).Elem())
117 return proto.IsInitialized(m)
118 },
Damien Neilc37adef2019-04-01 13:49:56 -0700119 }
120 }
121}
122
Joe Tsai4fe96632019-05-22 05:12:36 -0400123func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700124 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
125}
126
Joe Tsai4fe96632019-05-22 05:12:36 -0400127func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700128 b = wire.AppendVarint(b, wiretag)
129 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
130 return mi.marshalAppendPointer(b, p.Elem(), opts)
131}
132
Damien Neile91877d2019-06-27 10:54:42 -0700133func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
134 if wtyp != wire.BytesType {
135 return 0, errUnknown
136 }
137 v, n := wire.ConsumeBytes(b)
138 if n < 0 {
139 return 0, wire.ParseError(n)
140 }
141 if p.Elem().IsNil() {
142 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
143 }
144 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
145 return 0, err
146 }
147 return n, nil
148}
149
Damien Neilc37adef2019-04-01 13:49:56 -0700150func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
151 return wire.SizeBytes(proto.Size(m)) + tagsize
152}
153
154func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
155 b = wire.AppendVarint(b, wiretag)
156 b = wire.AppendVarint(b, uint64(proto.Size(m)))
157 return opts.Options().MarshalAppend(b, m)
158}
159
Damien Neile91877d2019-06-27 10:54:42 -0700160func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
161 if wtyp != wire.BytesType {
162 return 0, errUnknown
163 }
164 v, n := wire.ConsumeBytes(b)
165 if n < 0 {
166 return 0, wire.ParseError(n)
167 }
168 if err := opts.Options().Unmarshal(v, m); err != nil {
169 return 0, err
170 }
171 return n, nil
172}
173
Damien Neilc37adef2019-04-01 13:49:56 -0700174func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
175 m := Export{}.MessageOf(ival).Interface()
176 return sizeMessage(m, tagsize, opts)
177}
178
179func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
180 m := Export{}.MessageOf(ival).Interface()
181 return appendMessage(b, m, wiretag, opts)
182}
183
Damien Neile91877d2019-06-27 10:54:42 -0700184func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
185 m := Export{}.MessageOf(ival).Interface()
186 n, err := consumeMessage(b, m, wtyp, opts)
187 return ival, n, err
188}
189
Damien Neil5322bdb2019-04-09 15:57:05 -0700190func isInitMessageIface(ival interface{}) error {
191 m := Export{}.MessageOf(ival).Interface()
192 return proto.IsInitialized(m)
193}
194
Damien Neilc37adef2019-04-01 13:49:56 -0700195var coderMessageIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700196 size: sizeMessageIface,
197 marshal: appendMessageIface,
198 unmarshal: consumeMessageIface,
199 isInit: isInitMessageIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700200}
201
202func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700203 num := fd.Number()
Joe Tsai4fe96632019-05-22 05:12:36 -0400204 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700205 return pointerCoderFuncs{
206 size: func(p pointer, tagsize int, opts marshalOptions) int {
207 return sizeGroupType(p, fi, tagsize, opts)
208 },
209 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
210 return appendGroupType(b, p, wiretag, fi, opts)
211 },
Damien Neile91877d2019-06-27 10:54:42 -0700212 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
213 return consumeGroupType(b, p, fi, num, wtyp, opts)
214 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700215 isInit: func(p pointer) error {
216 return fi.isInitializedPointer(p.Elem())
217 },
Damien Neilc37adef2019-04-01 13:49:56 -0700218 }
219 } else {
220 return pointerCoderFuncs{
221 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700222 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700223 return sizeGroup(m, tagsize, opts)
224 },
225 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700226 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700227 return appendGroup(b, m, wiretag, opts)
228 },
Damien Neile91877d2019-06-27 10:54:42 -0700229 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
230 mp := p.AsValueOf(ft).Elem()
231 if mp.IsNil() {
232 mp.Set(reflect.New(ft.Elem()))
233 }
234 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
235 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700236 isInit: func(p pointer) error {
237 m := asMessage(p.AsValueOf(ft).Elem())
238 return proto.IsInitialized(m)
239 },
Damien Neilc37adef2019-04-01 13:49:56 -0700240 }
241 }
242}
243
Joe Tsai4fe96632019-05-22 05:12:36 -0400244func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700245 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
246}
247
Joe Tsai4fe96632019-05-22 05:12:36 -0400248func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700249 b = wire.AppendVarint(b, wiretag) // start group
250 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
251 b = wire.AppendVarint(b, wiretag+1) // end group
252 return b, err
253}
254
Damien Neile91877d2019-06-27 10:54:42 -0700255func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
256 if wtyp != wire.StartGroupType {
257 return 0, errUnknown
258 }
259 if p.Elem().IsNil() {
260 p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
261 }
262 return mi.unmarshalPointer(b, p.Elem(), num, opts)
263}
264
Damien Neilc37adef2019-04-01 13:49:56 -0700265func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
266 return 2*tagsize + proto.Size(m)
267}
268
269func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
270 b = wire.AppendVarint(b, wiretag) // start group
271 b, err := opts.Options().MarshalAppend(b, m)
272 b = wire.AppendVarint(b, wiretag+1) // end group
273 return b, err
274}
275
Damien Neile91877d2019-06-27 10:54:42 -0700276func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
277 if wtyp != wire.StartGroupType {
278 return 0, errUnknown
279 }
280 b, n := wire.ConsumeGroup(num, b)
281 if n < 0 {
282 return 0, wire.ParseError(n)
283 }
284 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700285}
286
Damien Neile91877d2019-06-27 10:54:42 -0700287func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
288 return ifaceCoderFuncs{
289 size: func(ival interface{}, tagsize int, opts marshalOptions) int {
290 m := Export{}.MessageOf(ival).Interface()
291 return sizeGroup(m, tagsize, opts)
292 },
293 marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
294 m := Export{}.MessageOf(ival).Interface()
295 return appendGroup(b, m, wiretag, opts)
296 },
297 unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
298 m := Export{}.MessageOf(ival).Interface()
299 n, err := consumeGroup(b, m, num, wtyp, opts)
300 return ival, n, err
301 },
302 isInit: isInitMessageIface,
303 }
Damien Neilc37adef2019-04-01 13:49:56 -0700304}
305
306func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai4fe96632019-05-22 05:12:36 -0400307 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700308 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700309 size: func(p pointer, tagsize int, opts marshalOptions) int {
310 return sizeMessageSliceInfo(p, fi, tagsize, opts)
311 },
Damien Neilc37adef2019-04-01 13:49:56 -0700312 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
313 return appendMessageSliceInfo(b, p, wiretag, fi, opts)
314 },
Damien Neile91877d2019-06-27 10:54:42 -0700315 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
316 return consumeMessageSliceInfo(b, p, fi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700317 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700318 isInit: func(p pointer) error {
319 return isInitMessageSliceInfo(p, fi)
320 },
Damien Neilc37adef2019-04-01 13:49:56 -0700321 }
322 }
323 return pointerCoderFuncs{
324 size: func(p pointer, tagsize int, opts marshalOptions) int {
325 return sizeMessageSlice(p, ft, tagsize, opts)
326 },
327 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
328 return appendMessageSlice(b, p, wiretag, ft, opts)
329 },
Damien Neile91877d2019-06-27 10:54:42 -0700330 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
331 return consumeMessageSlice(b, p, ft, wtyp, opts)
332 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700333 isInit: func(p pointer) error {
334 return isInitMessageSlice(p, ft)
335 },
Damien Neilc37adef2019-04-01 13:49:56 -0700336 }
337}
338
Joe Tsai4fe96632019-05-22 05:12:36 -0400339func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700340 s := p.PointerSlice()
341 n := 0
342 for _, v := range s {
343 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
344 }
345 return n
346}
347
Joe Tsai4fe96632019-05-22 05:12:36 -0400348func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700349 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700350 var err error
351 for _, v := range s {
352 b = wire.AppendVarint(b, wiretag)
353 siz := mi.sizePointer(v, opts)
354 b = wire.AppendVarint(b, uint64(siz))
355 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700356 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700357 return b, err
358 }
359 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700360 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700361}
362
Damien Neile91877d2019-06-27 10:54:42 -0700363func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
364 if wtyp != wire.BytesType {
365 return 0, errUnknown
366 }
367 v, n := wire.ConsumeBytes(b)
368 if n < 0 {
369 return 0, wire.ParseError(n)
370 }
371 m := reflect.New(mi.GoType.Elem()).Interface()
372 mp := pointerOfIface(m)
373 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
374 return 0, err
375 }
376 p.AppendPointerSlice(mp)
377 return n, nil
378}
379
Damien Neil5322bdb2019-04-09 15:57:05 -0700380func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
381 s := p.PointerSlice()
382 for _, v := range s {
383 if err := mi.isInitializedPointer(v); err != nil {
384 return err
385 }
386 }
387 return nil
388}
389
Damien Neilc37adef2019-04-01 13:49:56 -0700390func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
391 s := p.PointerSlice()
392 n := 0
393 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700394 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700395 n += wire.SizeBytes(proto.Size(m)) + tagsize
396 }
397 return n
398}
399
400func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
401 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700402 var err error
403 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700404 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700405 b = wire.AppendVarint(b, wiretag)
406 siz := proto.Size(m)
407 b = wire.AppendVarint(b, uint64(siz))
408 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700409 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700410 return b, err
411 }
412 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700413 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700414}
415
Damien Neile91877d2019-06-27 10:54:42 -0700416func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
417 if wtyp != wire.BytesType {
418 return 0, errUnknown
419 }
420 v, n := wire.ConsumeBytes(b)
421 if n < 0 {
422 return 0, wire.ParseError(n)
423 }
424 mp := reflect.New(goType.Elem())
425 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
426 return 0, err
427 }
428 p.AppendPointerSlice(pointerOfValue(mp))
429 return n, nil
430}
431
Damien Neil5322bdb2019-04-09 15:57:05 -0700432func isInitMessageSlice(p pointer, goType reflect.Type) error {
433 s := p.PointerSlice()
434 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700435 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700436 if err := proto.IsInitialized(m); err != nil {
437 return err
438 }
439 }
440 return nil
441}
442
Damien Neilc37adef2019-04-01 13:49:56 -0700443// Slices of messages
444
445func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
446 p := pointerOfIface(ival)
447 return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
448}
449
450func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
451 p := pointerOfIface(ival)
452 return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
453}
454
Damien Neile91877d2019-06-27 10:54:42 -0700455func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
456 p := pointerOfIface(ival)
457 n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
458 return ival, n, err
459}
460
Damien Neil5322bdb2019-04-09 15:57:05 -0700461func isInitMessageSliceIface(ival interface{}) error {
462 p := pointerOfIface(ival)
463 return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
464}
465
Damien Neilc37adef2019-04-01 13:49:56 -0700466var coderMessageSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700467 size: sizeMessageSliceIface,
468 marshal: appendMessageSliceIface,
469 unmarshal: consumeMessageSliceIface,
470 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700471}
472
473func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700474 num := fd.Number()
Joe Tsai4fe96632019-05-22 05:12:36 -0400475 if fi, ok := getMessageInfo(ft); ok {
Damien Neilc37adef2019-04-01 13:49:56 -0700476 return pointerCoderFuncs{
477 size: func(p pointer, tagsize int, opts marshalOptions) int {
478 return sizeGroupSliceInfo(p, fi, tagsize, opts)
479 },
480 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
481 return appendGroupSliceInfo(b, p, wiretag, fi, opts)
482 },
Damien Neile91877d2019-06-27 10:54:42 -0700483 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
484 return consumeGroupSliceInfo(b, p, num, wtyp, fi, opts)
485 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700486 isInit: func(p pointer) error {
487 return isInitMessageSliceInfo(p, fi)
488 },
Damien Neilc37adef2019-04-01 13:49:56 -0700489 }
490 }
491 return pointerCoderFuncs{
492 size: func(p pointer, tagsize int, opts marshalOptions) int {
493 return sizeGroupSlice(p, ft, tagsize, opts)
494 },
495 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
496 return appendGroupSlice(b, p, wiretag, ft, opts)
497 },
Damien Neile91877d2019-06-27 10:54:42 -0700498 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
499 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
500 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700501 isInit: func(p pointer) error {
502 return isInitMessageSlice(p, ft)
503 },
Damien Neilc37adef2019-04-01 13:49:56 -0700504 }
505}
506
507func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
508 s := p.PointerSlice()
509 n := 0
510 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700511 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700512 n += 2*tagsize + proto.Size(m)
513 }
514 return n
515}
516
517func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
518 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700519 var err error
520 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700521 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700522 b = wire.AppendVarint(b, wiretag) // start group
523 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700524 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700525 return b, err
526 }
527 b = wire.AppendVarint(b, wiretag+1) // end group
528 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700529 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700530}
531
Damien Neile91877d2019-06-27 10:54:42 -0700532func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
533 if wtyp != wire.StartGroupType {
534 return 0, errUnknown
535 }
536 b, n := wire.ConsumeGroup(num, b)
537 if n < 0 {
538 return 0, wire.ParseError(n)
539 }
540 mp := reflect.New(goType.Elem())
541 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
542 return 0, err
543 }
544 p.AppendPointerSlice(pointerOfValue(mp))
545 return n, nil
546}
547
Joe Tsai4fe96632019-05-22 05:12:36 -0400548func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700549 s := p.PointerSlice()
550 n := 0
551 for _, v := range s {
552 n += 2*tagsize + mi.sizePointer(v, opts)
553 }
554 return n
555}
556
Joe Tsai4fe96632019-05-22 05:12:36 -0400557func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700558 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700559 var err error
560 for _, v := range s {
561 b = wire.AppendVarint(b, wiretag) // start group
562 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700563 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700564 return b, err
565 }
566 b = wire.AppendVarint(b, wiretag+1) // end group
567 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700568 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700569}
570
Damien Neile91877d2019-06-27 10:54:42 -0700571func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
572 if wtyp != wire.StartGroupType {
573 return 0, errUnknown
574 }
575 m := reflect.New(mi.GoType.Elem()).Interface()
576 mp := pointerOfIface(m)
577 n, err := mi.unmarshalPointer(b, mp, num, opts)
578 if err != nil {
579 return 0, err
580 }
581 p.AppendPointerSlice(mp)
582 return n, nil
583}
584
Damien Neilc37adef2019-04-01 13:49:56 -0700585func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
586 p := pointerOfIface(ival)
587 return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
588}
589
590func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
591 p := pointerOfIface(ival)
592 return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
593}
594
Damien Neile91877d2019-06-27 10:54:42 -0700595func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
596 p := pointerOfIface(ival)
597 n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
598 return ival, n, err
599}
600
Damien Neilc37adef2019-04-01 13:49:56 -0700601var coderGroupSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700602 size: sizeGroupSliceIface,
603 marshal: appendGroupSliceIface,
604 unmarshal: consumeGroupSliceIface,
605 isInit: isInitMessageSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700606}
607
608// Enums
609
610func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
611 v := reflect.ValueOf(ival).Int()
612 return wire.SizeVarint(uint64(v)) + tagsize
613}
614
615func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
616 v := reflect.ValueOf(ival).Int()
617 b = wire.AppendVarint(b, wiretag)
618 b = wire.AppendVarint(b, uint64(v))
619 return b, nil
620}
621
Damien Neile91877d2019-06-27 10:54:42 -0700622func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
623 if wtyp != wire.VarintType {
624 return nil, 0, errUnknown
625 }
626 v, n := wire.ConsumeVarint(b)
627 if n < 0 {
628 return nil, 0, wire.ParseError(n)
629 }
630 rv := reflect.New(reflect.TypeOf(ival)).Elem()
631 rv.SetInt(int64(v))
632 return rv.Interface(), n, nil
633}
634
Damien Neilc37adef2019-04-01 13:49:56 -0700635var coderEnumIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700636 size: sizeEnumIface,
637 marshal: appendEnumIface,
638 unmarshal: consumeEnumIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700639}
640
641func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
642 return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
643}
644
645func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
646 for i, llen := 0, s.Len(); i < llen; i++ {
647 size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
648 }
649 return size
650}
651
652func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
653 return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
654}
655
656func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
657 for i, llen := 0, s.Len(); i < llen; i++ {
658 b = wire.AppendVarint(b, wiretag)
659 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
660 }
661 return b, nil
662}
663
Damien Neile91877d2019-06-27 10:54:42 -0700664func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
665 n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
666 return ival, n, err
667}
668
669func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
670 s = s.Elem() // *[]E -> []E
671 if wtyp == wire.BytesType {
672 b, n = wire.ConsumeBytes(b)
673 if n < 0 {
674 return 0, wire.ParseError(n)
675 }
676 for len(b) > 0 {
677 v, n := wire.ConsumeVarint(b)
678 if n < 0 {
679 return 0, wire.ParseError(n)
680 }
681 rv := reflect.New(s.Type().Elem()).Elem()
682 rv.SetInt(int64(v))
683 s.Set(reflect.Append(s, rv))
684 b = b[n:]
685 }
686 return n, nil
687 }
688 if wtyp != wire.VarintType {
689 return 0, errUnknown
690 }
691 v, n := wire.ConsumeVarint(b)
692 if n < 0 {
693 return 0, wire.ParseError(n)
694 }
695 rv := reflect.New(s.Type().Elem()).Elem()
696 rv.SetInt(int64(v))
697 s.Set(reflect.Append(s, rv))
698 return n, nil
699}
700
Damien Neilc37adef2019-04-01 13:49:56 -0700701var coderEnumSliceIface = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700702 size: sizeEnumSliceIface,
703 marshal: appendEnumSliceIface,
704 unmarshal: consumeEnumSliceIface,
Damien Neilc37adef2019-04-01 13:49:56 -0700705}
706
Damien Neil7492a092019-07-10 15:23:29 -0700707func sizeEnumPackedSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
708 return sizeEnumPackedSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
709}
710
711func sizeEnumPackedSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
712 llen := s.Len()
713 if llen == 0 {
714 return 0
715 }
716 n := 0
717 for i := 0; i < llen; i++ {
718 n += wire.SizeVarint(uint64(s.Index(i).Int()))
719 }
720 return tagsize + wire.SizeBytes(n)
721}
722
723func appendEnumPackedSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
724 return appendEnumPackedSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
725}
726
727func appendEnumPackedSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
728 llen := s.Len()
729 if llen == 0 {
730 return b, nil
731 }
732 b = wire.AppendVarint(b, wiretag)
733 n := 0
734 for i := 0; i < llen; i++ {
735 n += wire.SizeVarint(uint64(s.Index(i).Int()))
736 }
737 b = wire.AppendVarint(b, uint64(n))
738 for i := 0; i < llen; i++ {
739 b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
740 }
741 return b, nil
742}
743
744var coderEnumPackedSliceIface = ifaceCoderFuncs{
745 size: sizeEnumPackedSliceIface,
746 marshal: appendEnumPackedSliceIface,
747 unmarshal: consumeEnumSliceIface,
748}
749
Damien Neilc37adef2019-04-01 13:49:56 -0700750// Strings with UTF8 validation.
751
752func appendStringValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
753 v := *p.String()
754 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700755 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700756 if !utf8.ValidString(v) {
757 return b, errInvalidUTF8{}
758 }
759 return b, nil
760}
761
Damien Neile91877d2019-06-27 10:54:42 -0700762func consumeStringValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
763 if wtyp != wire.BytesType {
764 return 0, errUnknown
765 }
766 v, n := wire.ConsumeString(b)
767 if n < 0 {
768 return 0, wire.ParseError(n)
769 }
770 if !utf8.ValidString(v) {
771 return 0, errInvalidUTF8{}
772 }
773 *p.String() = v
774 return n, nil
775}
776
Damien Neilc37adef2019-04-01 13:49:56 -0700777var coderStringValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700778 size: sizeString,
779 marshal: appendStringValidateUTF8,
780 unmarshal: consumeStringValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700781}
782
783func appendStringNoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
784 v := *p.String()
785 if len(v) == 0 {
786 return b, nil
787 }
788 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700789 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700790 if !utf8.ValidString(v) {
791 return b, errInvalidUTF8{}
792 }
793 return b, nil
794}
795
796var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700797 size: sizeStringNoZero,
798 marshal: appendStringNoZeroValidateUTF8,
799 unmarshal: consumeStringValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700800}
801
802func sizeStringSliceValidateUTF8(p pointer, tagsize int, _ marshalOptions) (size int) {
803 s := *p.StringSlice()
804 for _, v := range s {
Damien Neilcedb5952019-06-21 12:04:07 -0700805 size += tagsize + wire.SizeBytes(len(v))
Damien Neilc37adef2019-04-01 13:49:56 -0700806 }
807 return size
808}
809
810func appendStringSliceValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
811 s := *p.StringSlice()
812 var err error
813 for _, v := range s {
814 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700815 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700816 if !utf8.ValidString(v) {
Damien Neile91877d2019-06-27 10:54:42 -0700817 return b, errInvalidUTF8{}
Damien Neilc37adef2019-04-01 13:49:56 -0700818 }
819 }
820 return b, err
821}
822
Damien Neile91877d2019-06-27 10:54:42 -0700823func consumeStringSliceValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
824 if wtyp != wire.BytesType {
825 return 0, errUnknown
826 }
827 sp := p.StringSlice()
828 v, n := wire.ConsumeString(b)
829 if n < 0 {
830 return 0, wire.ParseError(n)
831 }
832 if !utf8.ValidString(v) {
833 return 0, errInvalidUTF8{}
834 }
835 *sp = append(*sp, v)
836 return n, nil
837}
838
Damien Neilc37adef2019-04-01 13:49:56 -0700839var coderStringSliceValidateUTF8 = pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700840 size: sizeStringSliceValidateUTF8,
841 marshal: appendStringSliceValidateUTF8,
842 unmarshal: consumeStringSliceValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700843}
844
845func sizeStringIfaceValidateUTF8(ival interface{}, tagsize int, _ marshalOptions) int {
846 v := ival.(string)
Damien Neilcedb5952019-06-21 12:04:07 -0700847 return tagsize + wire.SizeBytes(len(v))
Damien Neilc37adef2019-04-01 13:49:56 -0700848}
849
850func appendStringIfaceValidateUTF8(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
851 v := ival.(string)
852 b = wire.AppendVarint(b, wiretag)
Damien Neilcedb5952019-06-21 12:04:07 -0700853 b = wire.AppendString(b, v)
Damien Neilc37adef2019-04-01 13:49:56 -0700854 if !utf8.ValidString(v) {
855 return b, errInvalidUTF8{}
856 }
857 return b, nil
858}
859
Damien Neile91877d2019-06-27 10:54:42 -0700860func consumeStringIfaceValidateUTF8(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
861 if wtyp != wire.BytesType {
862 return nil, 0, errUnknown
863 }
864 v, n := wire.ConsumeString(b)
865 if n < 0 {
866 return nil, 0, wire.ParseError(n)
867 }
868 if !utf8.ValidString(v) {
869 return nil, 0, errInvalidUTF8{}
870 }
871 return v, n, nil
872}
873
Damien Neilc37adef2019-04-01 13:49:56 -0700874var coderStringIfaceValidateUTF8 = ifaceCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700875 size: sizeStringIfaceValidateUTF8,
876 marshal: appendStringIfaceValidateUTF8,
877 unmarshal: consumeStringIfaceValidateUTF8,
Damien Neilc37adef2019-04-01 13:49:56 -0700878}
Damien Neil5b6d0472019-06-14 11:54:07 -0700879
880func asMessage(v reflect.Value) pref.ProtoMessage {
881 if m, ok := v.Interface().(pref.ProtoMessage); ok {
882 return m
883 }
884 return legacyWrapMessage(v)
885}