blob: 45b4664e6e40225adfcb60e024e1be2855bdf7d1 [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"
Joe Tsai6e095992019-08-10 13:56:36 -07009 "sync"
Damien Neilc37adef2019-04-01 13:49:56 -070010
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"
Joe Tsai6e095992019-08-10 13:56:36 -070014 preg "google.golang.org/protobuf/reflect/protoregistry"
15 piface "google.golang.org/protobuf/runtime/protoiface"
Damien Neilc37adef2019-04-01 13:49:56 -070016)
17
18type errInvalidUTF8 struct{}
19
20func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
21func (errInvalidUTF8) InvalidUTF8() bool { return true }
22
Joe Tsai6e095992019-08-10 13:56:36 -070023func makeOneofFieldCoder(fd pref.FieldDescriptor, si structInfo) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -070024 ot := si.oneofWrappersByNumber[fd.Number()]
25 funcs := fieldCoder(fd, ot.Field(0).Type)
26 fs := si.oneofsByName[fd.ContainingOneof().Name()]
Damien Neilc37adef2019-04-01 13:49:56 -070027 ft := fs.Type
Damien Neile91877d2019-06-27 10:54:42 -070028 wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
29 tagsize := wire.SizeVarint(wiretag)
30 getInfo := func(p pointer) (pointer, bool) {
Damien Neil5322bdb2019-04-09 15:57:05 -070031 v := p.AsValueOf(ft).Elem()
32 if v.IsNil() {
Damien Neile91877d2019-06-27 10:54:42 -070033 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070034 }
35 v = v.Elem() // interface -> *struct
Joe Tsai9b22b932019-08-08 19:23:32 -070036 if v.IsNil() || v.Elem().Type() != ot {
Damien Neile91877d2019-06-27 10:54:42 -070037 return pointer{}, false
Damien Neil5322bdb2019-04-09 15:57:05 -070038 }
Damien Neile91877d2019-06-27 10:54:42 -070039 return pointerOfValue(v).Apply(zeroOffset), true
Damien Neil5322bdb2019-04-09 15:57:05 -070040 }
Damien Neile91877d2019-06-27 10:54:42 -070041 pcf := pointerCoderFuncs{
Damien Neilc37adef2019-04-01 13:49:56 -070042 size: func(p pointer, _ int, opts marshalOptions) int {
Damien Neile91877d2019-06-27 10:54:42 -070043 v, ok := getInfo(p)
44 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070045 return 0
46 }
Damien Neile91877d2019-06-27 10:54:42 -070047 return funcs.size(v, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -070048 },
49 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neile91877d2019-06-27 10:54:42 -070050 v, ok := getInfo(p)
51 if !ok {
Damien Neilc37adef2019-04-01 13:49:56 -070052 return b, nil
53 }
Damien Neile91877d2019-06-27 10:54:42 -070054 return funcs.marshal(b, v, wiretag, opts)
Damien Neil5322bdb2019-04-09 15:57:05 -070055 },
Damien Neile91877d2019-06-27 10:54:42 -070056 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai6c286742019-07-11 23:15:05 -070057 var vw reflect.Value // pointer to wrapper type
58 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
59 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
60 vw = vi.Elem()
61 } else {
62 vw = reflect.New(ot)
63 }
64 n, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -070065 if err != nil {
66 return 0, err
Damien Neilc37adef2019-04-01 13:49:56 -070067 }
Joe Tsai6c286742019-07-11 23:15:05 -070068 vi.Set(vw)
Damien Neile91877d2019-06-27 10:54:42 -070069 return n, nil
Damien Neilc37adef2019-04-01 13:49:56 -070070 },
71 }
Damien Neile91877d2019-06-27 10:54:42 -070072 if funcs.isInit != nil {
73 pcf.isInit = func(p pointer) error {
74 v, ok := getInfo(p)
75 if !ok {
76 return nil
77 }
78 return funcs.isInit(v)
79 }
80 }
81 return pcf
Damien Neilc37adef2019-04-01 13:49:56 -070082}
83
Joe Tsai6e095992019-08-10 13:56:36 -070084func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
85 var once sync.Once
86 var messageType pref.MessageType
87 lazyInit := func() {
88 once.Do(func() {
89 messageName := fd.Message().FullName()
90 messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
91 })
92 }
93
94 num := int32(fd.Number())
95 return pointerCoderFuncs{
96 size: func(p pointer, tagsize int, opts marshalOptions) int {
97 fs := p.WeakFields()
98 m, ok := (*fs)[num]
99 if !ok {
100 return 0
101 }
102 return sizeMessage(m.(proto.Message), tagsize, opts)
103 },
104 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
105 fs := p.WeakFields()
106 m, ok := (*fs)[num]
107 if !ok {
108 return b, nil
109 }
110 return appendMessage(b, m.(proto.Message), wiretag, opts)
111 },
112 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
113 fs := p.WeakFields()
114 m, ok := (*fs)[num]
115 if !ok {
116 lazyInit()
117 if messageType == nil {
118 return 0, errUnknown
119 }
120 m = messageType.New().Interface().(piface.MessageV1)
121 if *fs == nil {
122 *fs = make(WeakFields)
123 }
124 (*fs)[num] = m
125 }
126 return consumeMessage(b, m.(proto.Message), wtyp, opts)
127 },
128 isInit: func(p pointer) error {
129 fs := p.WeakFields()
130 m, ok := (*fs)[num]
131 if !ok {
132 return nil
133 }
134 return proto.IsInitialized(m.(proto.Message))
135 },
136 }
137}
138
Damien Neilc37adef2019-04-01 13:49:56 -0700139func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700140 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700141 return pointerCoderFuncs{
142 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700143 return sizeMessageInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700144 },
145 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700146 return appendMessageInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700147 },
Damien Neile91877d2019-06-27 10:54:42 -0700148 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700149 return consumeMessageInfo(b, p, mi, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700150 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700151 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700152 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700153 },
Damien Neilc37adef2019-04-01 13:49:56 -0700154 }
155 } else {
156 return pointerCoderFuncs{
157 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700158 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700159 return sizeMessage(m, tagsize, opts)
160 },
161 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700162 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700163 return appendMessage(b, m, wiretag, opts)
164 },
Damien Neile91877d2019-06-27 10:54:42 -0700165 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
166 mp := p.AsValueOf(ft).Elem()
167 if mp.IsNil() {
168 mp.Set(reflect.New(ft.Elem()))
169 }
170 return consumeMessage(b, asMessage(mp), wtyp, opts)
171 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700172 isInit: func(p pointer) error {
173 m := asMessage(p.AsValueOf(ft).Elem())
174 return proto.IsInitialized(m)
175 },
Damien Neilc37adef2019-04-01 13:49:56 -0700176 }
177 }
178}
179
Joe Tsai4fe96632019-05-22 05:12:36 -0400180func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700181 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
182}
183
Joe Tsai4fe96632019-05-22 05:12:36 -0400184func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700185 b = wire.AppendVarint(b, wiretag)
186 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
187 return mi.marshalAppendPointer(b, p.Elem(), opts)
188}
189
Damien Neile91877d2019-06-27 10:54:42 -0700190func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
191 if wtyp != wire.BytesType {
192 return 0, errUnknown
193 }
194 v, n := wire.ConsumeBytes(b)
195 if n < 0 {
196 return 0, wire.ParseError(n)
197 }
198 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700199 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700200 }
201 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
202 return 0, err
203 }
204 return n, nil
205}
206
Damien Neilc37adef2019-04-01 13:49:56 -0700207func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
208 return wire.SizeBytes(proto.Size(m)) + tagsize
209}
210
211func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
212 b = wire.AppendVarint(b, wiretag)
213 b = wire.AppendVarint(b, uint64(proto.Size(m)))
214 return opts.Options().MarshalAppend(b, m)
215}
216
Damien Neile91877d2019-06-27 10:54:42 -0700217func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
218 if wtyp != wire.BytesType {
219 return 0, errUnknown
220 }
221 v, n := wire.ConsumeBytes(b)
222 if n < 0 {
223 return 0, wire.ParseError(n)
224 }
225 if err := opts.Options().Unmarshal(v, m); err != nil {
226 return 0, err
227 }
228 return n, nil
229}
230
Damien Neil68b81c32019-08-22 11:41:32 -0700231func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
232 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700233 return sizeMessage(m, tagsize, opts)
234}
235
Damien Neil68b81c32019-08-22 11:41:32 -0700236func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
237 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700238 return appendMessage(b, m, wiretag, opts)
239}
240
Damien Neil68b81c32019-08-22 11:41:32 -0700241func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
242 m := v.Message().Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700243 n, err := consumeMessage(b, m, wtyp, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700244 return v, n, err
Damien Neile91877d2019-06-27 10:54:42 -0700245}
246
Damien Neil68b81c32019-08-22 11:41:32 -0700247func isInitMessageValue(v pref.Value) error {
248 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700249 return proto.IsInitialized(m)
250}
251
Damien Neil68b81c32019-08-22 11:41:32 -0700252var coderMessageValue = valueCoderFuncs{
253 size: sizeMessageValue,
254 marshal: appendMessageValue,
255 unmarshal: consumeMessageValue,
256 isInit: isInitMessageValue,
257}
258
259func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
260 m := v.Message().Interface()
261 return sizeGroup(m, tagsize, opts)
262}
263
264func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
265 m := v.Message().Interface()
266 return appendGroup(b, m, wiretag, opts)
267}
268
269func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
270 m := v.Message().Interface()
271 n, err := consumeGroup(b, m, num, wtyp, opts)
272 return v, n, err
273}
274
275var coderGroupValue = valueCoderFuncs{
276 size: sizeGroupValue,
277 marshal: appendGroupValue,
278 unmarshal: consumeGroupValue,
279 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700280}
281
282func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700283 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700284 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700285 return pointerCoderFuncs{
286 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700287 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700288 },
289 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700290 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700291 },
Damien Neile91877d2019-06-27 10:54:42 -0700292 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700293 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700294 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700295 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700296 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700297 },
Damien Neilc37adef2019-04-01 13:49:56 -0700298 }
299 } else {
300 return pointerCoderFuncs{
301 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700302 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700303 return sizeGroup(m, tagsize, opts)
304 },
305 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700306 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700307 return appendGroup(b, m, wiretag, opts)
308 },
Damien Neile91877d2019-06-27 10:54:42 -0700309 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
310 mp := p.AsValueOf(ft).Elem()
311 if mp.IsNil() {
312 mp.Set(reflect.New(ft.Elem()))
313 }
314 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
315 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700316 isInit: func(p pointer) error {
317 m := asMessage(p.AsValueOf(ft).Elem())
318 return proto.IsInitialized(m)
319 },
Damien Neilc37adef2019-04-01 13:49:56 -0700320 }
321 }
322}
323
Joe Tsai4fe96632019-05-22 05:12:36 -0400324func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700325 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
326}
327
Joe Tsai4fe96632019-05-22 05:12:36 -0400328func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700329 b = wire.AppendVarint(b, wiretag) // start group
330 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
331 b = wire.AppendVarint(b, wiretag+1) // end group
332 return b, err
333}
334
Damien Neile91877d2019-06-27 10:54:42 -0700335func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
336 if wtyp != wire.StartGroupType {
337 return 0, errUnknown
338 }
339 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700340 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700341 }
342 return mi.unmarshalPointer(b, p.Elem(), num, opts)
343}
344
Damien Neilc37adef2019-04-01 13:49:56 -0700345func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
346 return 2*tagsize + proto.Size(m)
347}
348
349func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
350 b = wire.AppendVarint(b, wiretag) // start group
351 b, err := opts.Options().MarshalAppend(b, m)
352 b = wire.AppendVarint(b, wiretag+1) // end group
353 return b, err
354}
355
Damien Neile91877d2019-06-27 10:54:42 -0700356func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
357 if wtyp != wire.StartGroupType {
358 return 0, errUnknown
359 }
360 b, n := wire.ConsumeGroup(num, b)
361 if n < 0 {
362 return 0, wire.ParseError(n)
363 }
364 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700365}
366
Damien Neilc37adef2019-04-01 13:49:56 -0700367func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700368 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700369 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700370 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700371 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700372 },
Damien Neilc37adef2019-04-01 13:49:56 -0700373 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700374 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700375 },
Damien Neile91877d2019-06-27 10:54:42 -0700376 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700377 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700378 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700379 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700380 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700381 },
Damien Neilc37adef2019-04-01 13:49:56 -0700382 }
383 }
384 return pointerCoderFuncs{
385 size: func(p pointer, tagsize int, opts marshalOptions) int {
386 return sizeMessageSlice(p, ft, tagsize, opts)
387 },
388 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
389 return appendMessageSlice(b, p, wiretag, ft, opts)
390 },
Damien Neile91877d2019-06-27 10:54:42 -0700391 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
392 return consumeMessageSlice(b, p, ft, wtyp, opts)
393 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700394 isInit: func(p pointer) error {
395 return isInitMessageSlice(p, ft)
396 },
Damien Neilc37adef2019-04-01 13:49:56 -0700397 }
398}
399
Joe Tsai4fe96632019-05-22 05:12:36 -0400400func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700401 s := p.PointerSlice()
402 n := 0
403 for _, v := range s {
404 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
405 }
406 return n
407}
408
Joe Tsai4fe96632019-05-22 05:12:36 -0400409func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700410 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700411 var err error
412 for _, v := range s {
413 b = wire.AppendVarint(b, wiretag)
414 siz := mi.sizePointer(v, opts)
415 b = wire.AppendVarint(b, uint64(siz))
416 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700417 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700418 return b, err
419 }
420 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700421 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700422}
423
Damien Neile91877d2019-06-27 10:54:42 -0700424func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
425 if wtyp != wire.BytesType {
426 return 0, errUnknown
427 }
428 v, n := wire.ConsumeBytes(b)
429 if n < 0 {
430 return 0, wire.ParseError(n)
431 }
Damien Neil16163b42019-08-06 15:43:25 -0700432 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700433 mp := pointerOfIface(m)
434 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
435 return 0, err
436 }
437 p.AppendPointerSlice(mp)
438 return n, nil
439}
440
Damien Neil5322bdb2019-04-09 15:57:05 -0700441func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
442 s := p.PointerSlice()
443 for _, v := range s {
444 if err := mi.isInitializedPointer(v); err != nil {
445 return err
446 }
447 }
448 return nil
449}
450
Damien Neilc37adef2019-04-01 13:49:56 -0700451func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
452 s := p.PointerSlice()
453 n := 0
454 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700455 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700456 n += wire.SizeBytes(proto.Size(m)) + tagsize
457 }
458 return n
459}
460
461func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
462 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700463 var err error
464 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700465 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700466 b = wire.AppendVarint(b, wiretag)
467 siz := proto.Size(m)
468 b = wire.AppendVarint(b, uint64(siz))
469 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700470 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700471 return b, err
472 }
473 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700474 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700475}
476
Damien Neile91877d2019-06-27 10:54:42 -0700477func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
478 if wtyp != wire.BytesType {
479 return 0, errUnknown
480 }
481 v, n := wire.ConsumeBytes(b)
482 if n < 0 {
483 return 0, wire.ParseError(n)
484 }
485 mp := reflect.New(goType.Elem())
486 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
487 return 0, err
488 }
489 p.AppendPointerSlice(pointerOfValue(mp))
490 return n, nil
491}
492
Damien Neil5322bdb2019-04-09 15:57:05 -0700493func isInitMessageSlice(p pointer, goType reflect.Type) error {
494 s := p.PointerSlice()
495 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700496 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700497 if err := proto.IsInitialized(m); err != nil {
498 return err
499 }
500 }
501 return nil
502}
503
Damien Neilc37adef2019-04-01 13:49:56 -0700504// Slices of messages
505
Damien Neil68b81c32019-08-22 11:41:32 -0700506func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
507 list := listv.List()
508 n := 0
509 for i, llen := 0, list.Len(); i < llen; i++ {
510 m := list.Get(i).Message().Interface()
511 n += wire.SizeBytes(proto.Size(m)) + tagsize
512 }
513 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700514}
515
Damien Neil68b81c32019-08-22 11:41:32 -0700516func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
517 list := listv.List()
518 mopts := opts.Options()
519 for i, llen := 0, list.Len(); i < llen; i++ {
520 m := list.Get(i).Message().Interface()
521 b = wire.AppendVarint(b, wiretag)
522 siz := proto.Size(m)
523 b = wire.AppendVarint(b, uint64(siz))
524 var err error
525 b, err = mopts.MarshalAppend(b, m)
526 if err != nil {
527 return b, err
528 }
529 }
530 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700531}
532
Damien Neil68b81c32019-08-22 11:41:32 -0700533func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
534 list := listv.List()
535 if wtyp != wire.BytesType {
536 return pref.Value{}, 0, errUnknown
537 }
538 v, n := wire.ConsumeBytes(b)
539 if n < 0 {
540 return pref.Value{}, 0, wire.ParseError(n)
541 }
542 m := list.NewElement()
543 if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
544 return pref.Value{}, 0, err
545 }
546 list.Append(m)
547 return listv, n, nil
Damien Neile91877d2019-06-27 10:54:42 -0700548}
549
Damien Neil68b81c32019-08-22 11:41:32 -0700550func isInitMessageSliceValue(listv pref.Value) error {
551 list := listv.List()
552 for i, llen := 0, list.Len(); i < llen; i++ {
553 m := list.Get(i).Message().Interface()
554 if err := proto.IsInitialized(m); err != nil {
555 return err
556 }
557 }
558 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700559}
560
Damien Neil68b81c32019-08-22 11:41:32 -0700561var coderMessageSliceValue = valueCoderFuncs{
562 size: sizeMessageSliceValue,
563 marshal: appendMessageSliceValue,
564 unmarshal: consumeMessageSliceValue,
565 isInit: isInitMessageSliceValue,
566}
567
568func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
569 list := listv.List()
570 n := 0
571 for i, llen := 0, list.Len(); i < llen; i++ {
572 m := list.Get(i).Message().Interface()
573 n += 2*tagsize + proto.Size(m)
574 }
575 return n
576}
577
578func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
579 list := listv.List()
580 mopts := opts.Options()
581 for i, llen := 0, list.Len(); i < llen; i++ {
582 m := list.Get(i).Message().Interface()
583 b = wire.AppendVarint(b, wiretag) // start group
584 var err error
585 b, err = mopts.MarshalAppend(b, m)
586 if err != nil {
587 return b, err
588 }
589 b = wire.AppendVarint(b, wiretag+1) // end group
590 }
591 return b, nil
592}
593
594func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
595 list := listv.List()
596 if wtyp != wire.StartGroupType {
597 return pref.Value{}, 0, errUnknown
598 }
599 b, n := wire.ConsumeGroup(num, b)
600 if n < 0 {
601 return pref.Value{}, 0, wire.ParseError(n)
602 }
603 m := list.NewElement()
604 if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
605 return pref.Value{}, 0, err
606 }
607 list.Append(m)
608 return listv, n, nil
609}
610
611var coderGroupSliceValue = valueCoderFuncs{
612 size: sizeGroupSliceValue,
613 marshal: appendGroupSliceValue,
614 unmarshal: consumeGroupSliceValue,
615 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700616}
617
618func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700619 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700620 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700621 return pointerCoderFuncs{
622 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700623 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700624 },
625 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700626 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700627 },
Damien Neile91877d2019-06-27 10:54:42 -0700628 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700629 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700630 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700631 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700632 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700633 },
Damien Neilc37adef2019-04-01 13:49:56 -0700634 }
635 }
636 return pointerCoderFuncs{
637 size: func(p pointer, tagsize int, opts marshalOptions) int {
638 return sizeGroupSlice(p, ft, tagsize, opts)
639 },
640 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
641 return appendGroupSlice(b, p, wiretag, ft, opts)
642 },
Damien Neile91877d2019-06-27 10:54:42 -0700643 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
644 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
645 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700646 isInit: func(p pointer) error {
647 return isInitMessageSlice(p, ft)
648 },
Damien Neilc37adef2019-04-01 13:49:56 -0700649 }
650}
651
652func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
653 s := p.PointerSlice()
654 n := 0
655 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700656 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700657 n += 2*tagsize + proto.Size(m)
658 }
659 return n
660}
661
662func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
663 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700664 var err error
665 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700666 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700667 b = wire.AppendVarint(b, wiretag) // start group
668 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700669 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700670 return b, err
671 }
672 b = wire.AppendVarint(b, wiretag+1) // end group
673 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700674 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700675}
676
Damien Neile91877d2019-06-27 10:54:42 -0700677func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
678 if wtyp != wire.StartGroupType {
679 return 0, errUnknown
680 }
681 b, n := wire.ConsumeGroup(num, b)
682 if n < 0 {
683 return 0, wire.ParseError(n)
684 }
685 mp := reflect.New(goType.Elem())
686 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
687 return 0, err
688 }
689 p.AppendPointerSlice(pointerOfValue(mp))
690 return n, nil
691}
692
Joe Tsai4fe96632019-05-22 05:12:36 -0400693func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700694 s := p.PointerSlice()
695 n := 0
696 for _, v := range s {
697 n += 2*tagsize + mi.sizePointer(v, opts)
698 }
699 return n
700}
701
Joe Tsai4fe96632019-05-22 05:12:36 -0400702func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700703 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700704 var err error
705 for _, v := range s {
706 b = wire.AppendVarint(b, wiretag) // start group
707 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700708 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700709 return b, err
710 }
711 b = wire.AppendVarint(b, wiretag+1) // end group
712 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700713 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700714}
715
Damien Neile91877d2019-06-27 10:54:42 -0700716func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
717 if wtyp != wire.StartGroupType {
718 return 0, errUnknown
719 }
Damien Neil16163b42019-08-06 15:43:25 -0700720 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700721 mp := pointerOfIface(m)
722 n, err := mi.unmarshalPointer(b, mp, num, opts)
723 if err != nil {
724 return 0, err
725 }
726 p.AppendPointerSlice(mp)
727 return n, nil
728}
729
Damien Neil5b6d0472019-06-14 11:54:07 -0700730func asMessage(v reflect.Value) pref.ProtoMessage {
731 if m, ok := v.Interface().(pref.ProtoMessage); ok {
732 return m
733 }
734 return legacyWrapMessage(v)
735}