blob: 5414635b18f852b8aebb07f4e2c10796276eb084 [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
Joe Tsai9b22b932019-08-08 19:23:32 -070033 if v.IsNil() || v.Elem().Type() != ot {
Damien Neile91877d2019-06-27 10:54:42 -070034 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() {
Damien Neil16163b42019-08-06 15:43:25 -0700141 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700142 }
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 Neil68b81c32019-08-22 11:41:32 -0700173func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
174 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700175 return sizeMessage(m, tagsize, opts)
176}
177
Damien Neil68b81c32019-08-22 11:41:32 -0700178func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
179 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700180 return appendMessage(b, m, wiretag, opts)
181}
182
Damien Neil68b81c32019-08-22 11:41:32 -0700183func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
184 m := v.Message().Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700185 n, err := consumeMessage(b, m, wtyp, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700186 return v, n, err
Damien Neile91877d2019-06-27 10:54:42 -0700187}
188
Damien Neil68b81c32019-08-22 11:41:32 -0700189func isInitMessageValue(v pref.Value) error {
190 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700191 return proto.IsInitialized(m)
192}
193
Damien Neil68b81c32019-08-22 11:41:32 -0700194var coderMessageValue = valueCoderFuncs{
195 size: sizeMessageValue,
196 marshal: appendMessageValue,
197 unmarshal: consumeMessageValue,
198 isInit: isInitMessageValue,
199}
200
201func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
202 m := v.Message().Interface()
203 return sizeGroup(m, tagsize, opts)
204}
205
206func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
207 m := v.Message().Interface()
208 return appendGroup(b, m, wiretag, opts)
209}
210
211func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
212 m := v.Message().Interface()
213 n, err := consumeGroup(b, m, num, wtyp, opts)
214 return v, n, err
215}
216
217var coderGroupValue = valueCoderFuncs{
218 size: sizeGroupValue,
219 marshal: appendGroupValue,
220 unmarshal: consumeGroupValue,
221 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700222}
223
224func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700225 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700226 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700227 return pointerCoderFuncs{
228 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700229 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700230 },
231 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700232 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700233 },
Damien Neile91877d2019-06-27 10:54:42 -0700234 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700235 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700236 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700237 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700238 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700239 },
Damien Neilc37adef2019-04-01 13:49:56 -0700240 }
241 } else {
242 return pointerCoderFuncs{
243 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700244 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700245 return sizeGroup(m, tagsize, opts)
246 },
247 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700248 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700249 return appendGroup(b, m, wiretag, opts)
250 },
Damien Neile91877d2019-06-27 10:54:42 -0700251 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
252 mp := p.AsValueOf(ft).Elem()
253 if mp.IsNil() {
254 mp.Set(reflect.New(ft.Elem()))
255 }
256 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
257 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700258 isInit: func(p pointer) error {
259 m := asMessage(p.AsValueOf(ft).Elem())
260 return proto.IsInitialized(m)
261 },
Damien Neilc37adef2019-04-01 13:49:56 -0700262 }
263 }
264}
265
Joe Tsai4fe96632019-05-22 05:12:36 -0400266func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700267 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
268}
269
Joe Tsai4fe96632019-05-22 05:12:36 -0400270func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700271 b = wire.AppendVarint(b, wiretag) // start group
272 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
273 b = wire.AppendVarint(b, wiretag+1) // end group
274 return b, err
275}
276
Damien Neile91877d2019-06-27 10:54:42 -0700277func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
278 if wtyp != wire.StartGroupType {
279 return 0, errUnknown
280 }
281 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700282 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700283 }
284 return mi.unmarshalPointer(b, p.Elem(), num, opts)
285}
286
Damien Neilc37adef2019-04-01 13:49:56 -0700287func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
288 return 2*tagsize + proto.Size(m)
289}
290
291func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
292 b = wire.AppendVarint(b, wiretag) // start group
293 b, err := opts.Options().MarshalAppend(b, m)
294 b = wire.AppendVarint(b, wiretag+1) // end group
295 return b, err
296}
297
Damien Neile91877d2019-06-27 10:54:42 -0700298func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
299 if wtyp != wire.StartGroupType {
300 return 0, errUnknown
301 }
302 b, n := wire.ConsumeGroup(num, b)
303 if n < 0 {
304 return 0, wire.ParseError(n)
305 }
306 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700307}
308
Damien Neilc37adef2019-04-01 13:49:56 -0700309func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700310 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700311 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700312 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700313 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700314 },
Damien Neilc37adef2019-04-01 13:49:56 -0700315 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700316 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700317 },
Damien Neile91877d2019-06-27 10:54:42 -0700318 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700319 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700320 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700321 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700322 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700323 },
Damien Neilc37adef2019-04-01 13:49:56 -0700324 }
325 }
326 return pointerCoderFuncs{
327 size: func(p pointer, tagsize int, opts marshalOptions) int {
328 return sizeMessageSlice(p, ft, tagsize, opts)
329 },
330 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
331 return appendMessageSlice(b, p, wiretag, ft, opts)
332 },
Damien Neile91877d2019-06-27 10:54:42 -0700333 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
334 return consumeMessageSlice(b, p, ft, wtyp, opts)
335 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700336 isInit: func(p pointer) error {
337 return isInitMessageSlice(p, ft)
338 },
Damien Neilc37adef2019-04-01 13:49:56 -0700339 }
340}
341
Joe Tsai4fe96632019-05-22 05:12:36 -0400342func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700343 s := p.PointerSlice()
344 n := 0
345 for _, v := range s {
346 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
347 }
348 return n
349}
350
Joe Tsai4fe96632019-05-22 05:12:36 -0400351func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700352 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700353 var err error
354 for _, v := range s {
355 b = wire.AppendVarint(b, wiretag)
356 siz := mi.sizePointer(v, opts)
357 b = wire.AppendVarint(b, uint64(siz))
358 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700359 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700360 return b, err
361 }
362 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700363 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700364}
365
Damien Neile91877d2019-06-27 10:54:42 -0700366func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
367 if wtyp != wire.BytesType {
368 return 0, errUnknown
369 }
370 v, n := wire.ConsumeBytes(b)
371 if n < 0 {
372 return 0, wire.ParseError(n)
373 }
Damien Neil16163b42019-08-06 15:43:25 -0700374 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700375 mp := pointerOfIface(m)
376 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
377 return 0, err
378 }
379 p.AppendPointerSlice(mp)
380 return n, nil
381}
382
Damien Neil5322bdb2019-04-09 15:57:05 -0700383func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
384 s := p.PointerSlice()
385 for _, v := range s {
386 if err := mi.isInitializedPointer(v); err != nil {
387 return err
388 }
389 }
390 return nil
391}
392
Damien Neilc37adef2019-04-01 13:49:56 -0700393func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
394 s := p.PointerSlice()
395 n := 0
396 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700397 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700398 n += wire.SizeBytes(proto.Size(m)) + tagsize
399 }
400 return n
401}
402
403func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
404 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700405 var err error
406 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700407 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700408 b = wire.AppendVarint(b, wiretag)
409 siz := proto.Size(m)
410 b = wire.AppendVarint(b, uint64(siz))
411 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700412 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700413 return b, err
414 }
415 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700416 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700417}
418
Damien Neile91877d2019-06-27 10:54:42 -0700419func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
420 if wtyp != wire.BytesType {
421 return 0, errUnknown
422 }
423 v, n := wire.ConsumeBytes(b)
424 if n < 0 {
425 return 0, wire.ParseError(n)
426 }
427 mp := reflect.New(goType.Elem())
428 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
429 return 0, err
430 }
431 p.AppendPointerSlice(pointerOfValue(mp))
432 return n, nil
433}
434
Damien Neil5322bdb2019-04-09 15:57:05 -0700435func isInitMessageSlice(p pointer, goType reflect.Type) error {
436 s := p.PointerSlice()
437 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700438 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700439 if err := proto.IsInitialized(m); err != nil {
440 return err
441 }
442 }
443 return nil
444}
445
Damien Neilc37adef2019-04-01 13:49:56 -0700446// Slices of messages
447
Damien Neil68b81c32019-08-22 11:41:32 -0700448func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
449 list := listv.List()
450 n := 0
451 for i, llen := 0, list.Len(); i < llen; i++ {
452 m := list.Get(i).Message().Interface()
453 n += wire.SizeBytes(proto.Size(m)) + tagsize
454 }
455 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700456}
457
Damien Neil68b81c32019-08-22 11:41:32 -0700458func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
459 list := listv.List()
460 mopts := opts.Options()
461 for i, llen := 0, list.Len(); i < llen; i++ {
462 m := list.Get(i).Message().Interface()
463 b = wire.AppendVarint(b, wiretag)
464 siz := proto.Size(m)
465 b = wire.AppendVarint(b, uint64(siz))
466 var err error
467 b, err = mopts.MarshalAppend(b, m)
468 if err != nil {
469 return b, err
470 }
471 }
472 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700473}
474
Damien Neil68b81c32019-08-22 11:41:32 -0700475func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
476 list := listv.List()
477 if wtyp != wire.BytesType {
478 return pref.Value{}, 0, errUnknown
479 }
480 v, n := wire.ConsumeBytes(b)
481 if n < 0 {
482 return pref.Value{}, 0, wire.ParseError(n)
483 }
484 m := list.NewElement()
485 if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
486 return pref.Value{}, 0, err
487 }
488 list.Append(m)
489 return listv, n, nil
Damien Neile91877d2019-06-27 10:54:42 -0700490}
491
Damien Neil68b81c32019-08-22 11:41:32 -0700492func isInitMessageSliceValue(listv pref.Value) error {
493 list := listv.List()
494 for i, llen := 0, list.Len(); i < llen; i++ {
495 m := list.Get(i).Message().Interface()
496 if err := proto.IsInitialized(m); err != nil {
497 return err
498 }
499 }
500 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700501}
502
Damien Neil68b81c32019-08-22 11:41:32 -0700503var coderMessageSliceValue = valueCoderFuncs{
504 size: sizeMessageSliceValue,
505 marshal: appendMessageSliceValue,
506 unmarshal: consumeMessageSliceValue,
507 isInit: isInitMessageSliceValue,
508}
509
510func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
511 list := listv.List()
512 n := 0
513 for i, llen := 0, list.Len(); i < llen; i++ {
514 m := list.Get(i).Message().Interface()
515 n += 2*tagsize + proto.Size(m)
516 }
517 return n
518}
519
520func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
521 list := listv.List()
522 mopts := opts.Options()
523 for i, llen := 0, list.Len(); i < llen; i++ {
524 m := list.Get(i).Message().Interface()
525 b = wire.AppendVarint(b, wiretag) // start group
526 var err error
527 b, err = mopts.MarshalAppend(b, m)
528 if err != nil {
529 return b, err
530 }
531 b = wire.AppendVarint(b, wiretag+1) // end group
532 }
533 return b, nil
534}
535
536func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
537 list := listv.List()
538 if wtyp != wire.StartGroupType {
539 return pref.Value{}, 0, errUnknown
540 }
541 b, n := wire.ConsumeGroup(num, b)
542 if n < 0 {
543 return pref.Value{}, 0, wire.ParseError(n)
544 }
545 m := list.NewElement()
546 if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
547 return pref.Value{}, 0, err
548 }
549 list.Append(m)
550 return listv, n, nil
551}
552
553var coderGroupSliceValue = valueCoderFuncs{
554 size: sizeGroupSliceValue,
555 marshal: appendGroupSliceValue,
556 unmarshal: consumeGroupSliceValue,
557 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700558}
559
560func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700561 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700562 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700563 return pointerCoderFuncs{
564 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700565 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700566 },
567 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700568 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700569 },
Damien Neile91877d2019-06-27 10:54:42 -0700570 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700571 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700572 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700573 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700574 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700575 },
Damien Neilc37adef2019-04-01 13:49:56 -0700576 }
577 }
578 return pointerCoderFuncs{
579 size: func(p pointer, tagsize int, opts marshalOptions) int {
580 return sizeGroupSlice(p, ft, tagsize, opts)
581 },
582 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
583 return appendGroupSlice(b, p, wiretag, ft, opts)
584 },
Damien Neile91877d2019-06-27 10:54:42 -0700585 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
586 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
587 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700588 isInit: func(p pointer) error {
589 return isInitMessageSlice(p, ft)
590 },
Damien Neilc37adef2019-04-01 13:49:56 -0700591 }
592}
593
594func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
595 s := p.PointerSlice()
596 n := 0
597 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700598 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700599 n += 2*tagsize + proto.Size(m)
600 }
601 return n
602}
603
604func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
605 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700606 var err error
607 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700608 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700609 b = wire.AppendVarint(b, wiretag) // start group
610 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700611 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700612 return b, err
613 }
614 b = wire.AppendVarint(b, wiretag+1) // end group
615 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700616 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700617}
618
Damien Neile91877d2019-06-27 10:54:42 -0700619func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
620 if wtyp != wire.StartGroupType {
621 return 0, errUnknown
622 }
623 b, n := wire.ConsumeGroup(num, b)
624 if n < 0 {
625 return 0, wire.ParseError(n)
626 }
627 mp := reflect.New(goType.Elem())
628 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
629 return 0, err
630 }
631 p.AppendPointerSlice(pointerOfValue(mp))
632 return n, nil
633}
634
Joe Tsai4fe96632019-05-22 05:12:36 -0400635func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700636 s := p.PointerSlice()
637 n := 0
638 for _, v := range s {
639 n += 2*tagsize + mi.sizePointer(v, opts)
640 }
641 return n
642}
643
Joe Tsai4fe96632019-05-22 05:12:36 -0400644func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700645 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700646 var err error
647 for _, v := range s {
648 b = wire.AppendVarint(b, wiretag) // start group
649 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700650 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700651 return b, err
652 }
653 b = wire.AppendVarint(b, wiretag+1) // end group
654 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700655 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700656}
657
Damien Neile91877d2019-06-27 10:54:42 -0700658func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
659 if wtyp != wire.StartGroupType {
660 return 0, errUnknown
661 }
Damien Neil16163b42019-08-06 15:43:25 -0700662 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700663 mp := pointerOfIface(m)
664 n, err := mi.unmarshalPointer(b, mp, num, opts)
665 if err != nil {
666 return 0, err
667 }
668 p.AppendPointerSlice(mp)
669 return n, nil
670}
671
Damien Neil5b6d0472019-06-14 11:54:07 -0700672func asMessage(v reflect.Value) pref.ProtoMessage {
673 if m, ok := v.Interface().(pref.ProtoMessage); ok {
674 return m
675 }
676 return legacyWrapMessage(v)
677}