blob: 4cfd9b06c9f522f784fec23340a0b00c3635c554 [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 Neil6e40b322019-10-01 13:05:16 -07008 "fmt"
Damien Neilc37adef2019-04-01 13:49:56 -07009 "reflect"
Joe Tsai6e095992019-08-10 13:56:36 -070010 "sync"
Damien Neilc37adef2019-04-01 13:49:56 -070011
12 "google.golang.org/protobuf/internal/encoding/wire"
Damien Neilc37adef2019-04-01 13:49:56 -070013 "google.golang.org/protobuf/proto"
14 pref "google.golang.org/protobuf/reflect/protoreflect"
Joe Tsai6e095992019-08-10 13:56:36 -070015 preg "google.golang.org/protobuf/reflect/protoregistry"
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
Damien Neil6e40b322019-10-01 13:05:16 -070094 num := fd.Number()
Joe Tsai6e095992019-08-10 13:56:36 -070095 return pointerCoderFuncs{
96 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil6e40b322019-10-01 13:05:16 -070097 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -070098 if !ok {
99 return 0
100 }
Damien Neil6e40b322019-10-01 13:05:16 -0700101 lazyInit()
102 if messageType == nil {
103 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
104 }
105 return sizeMessage(m, tagsize, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700106 },
107 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil6e40b322019-10-01 13:05:16 -0700108 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700109 if !ok {
110 return b, nil
111 }
Damien Neil6e40b322019-10-01 13:05:16 -0700112 lazyInit()
113 if messageType == nil {
114 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
115 }
116 return appendMessage(b, m, wiretag, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700117 },
118 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
119 fs := p.WeakFields()
Damien Neil6e40b322019-10-01 13:05:16 -0700120 m, ok := fs.get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700121 if !ok {
122 lazyInit()
123 if messageType == nil {
124 return 0, errUnknown
125 }
Damien Neil6e40b322019-10-01 13:05:16 -0700126 m = messageType.New().Interface()
127 fs.set(num, m)
Joe Tsai6e095992019-08-10 13:56:36 -0700128 }
Damien Neil6e40b322019-10-01 13:05:16 -0700129 return consumeMessage(b, m, wtyp, opts)
Joe Tsai6e095992019-08-10 13:56:36 -0700130 },
131 isInit: func(p pointer) error {
Damien Neil6e40b322019-10-01 13:05:16 -0700132 m, ok := p.WeakFields().get(num)
Joe Tsai6e095992019-08-10 13:56:36 -0700133 if !ok {
134 return nil
135 }
Damien Neil6e40b322019-10-01 13:05:16 -0700136 return proto.IsInitialized(m)
Joe Tsai6e095992019-08-10 13:56:36 -0700137 },
138 }
139}
140
Damien Neilc37adef2019-04-01 13:49:56 -0700141func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700142 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700143 return pointerCoderFuncs{
144 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700145 return sizeMessageInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700146 },
147 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700148 return appendMessageInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700149 },
Damien Neile91877d2019-06-27 10:54:42 -0700150 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700151 return consumeMessageInfo(b, p, mi, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700152 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700153 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700154 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700155 },
Damien Neilc37adef2019-04-01 13:49:56 -0700156 }
157 } else {
158 return pointerCoderFuncs{
159 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700160 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700161 return sizeMessage(m, tagsize, opts)
162 },
163 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700164 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700165 return appendMessage(b, m, wiretag, opts)
166 },
Damien Neile91877d2019-06-27 10:54:42 -0700167 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
168 mp := p.AsValueOf(ft).Elem()
169 if mp.IsNil() {
170 mp.Set(reflect.New(ft.Elem()))
171 }
172 return consumeMessage(b, asMessage(mp), wtyp, opts)
173 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700174 isInit: func(p pointer) error {
175 m := asMessage(p.AsValueOf(ft).Elem())
176 return proto.IsInitialized(m)
177 },
Damien Neilc37adef2019-04-01 13:49:56 -0700178 }
179 }
180}
181
Joe Tsai4fe96632019-05-22 05:12:36 -0400182func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700183 return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
184}
185
Joe Tsai4fe96632019-05-22 05:12:36 -0400186func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700187 b = wire.AppendVarint(b, wiretag)
188 b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
189 return mi.marshalAppendPointer(b, p.Elem(), opts)
190}
191
Damien Neile91877d2019-06-27 10:54:42 -0700192func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
193 if wtyp != wire.BytesType {
194 return 0, errUnknown
195 }
196 v, n := wire.ConsumeBytes(b)
197 if n < 0 {
198 return 0, wire.ParseError(n)
199 }
200 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700201 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700202 }
203 if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
204 return 0, err
205 }
206 return n, nil
207}
208
Damien Neilc37adef2019-04-01 13:49:56 -0700209func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
210 return wire.SizeBytes(proto.Size(m)) + tagsize
211}
212
213func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
214 b = wire.AppendVarint(b, wiretag)
215 b = wire.AppendVarint(b, uint64(proto.Size(m)))
216 return opts.Options().MarshalAppend(b, m)
217}
218
Damien Neile91877d2019-06-27 10:54:42 -0700219func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
220 if wtyp != wire.BytesType {
221 return 0, errUnknown
222 }
223 v, n := wire.ConsumeBytes(b)
224 if n < 0 {
225 return 0, wire.ParseError(n)
226 }
227 if err := opts.Options().Unmarshal(v, m); err != nil {
228 return 0, err
229 }
230 return n, nil
231}
232
Damien Neil68b81c32019-08-22 11:41:32 -0700233func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
234 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700235 return sizeMessage(m, tagsize, opts)
236}
237
Damien Neil68b81c32019-08-22 11:41:32 -0700238func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
239 m := v.Message().Interface()
Damien Neilc37adef2019-04-01 13:49:56 -0700240 return appendMessage(b, m, wiretag, opts)
241}
242
Damien Neil68b81c32019-08-22 11:41:32 -0700243func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
244 m := v.Message().Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700245 n, err := consumeMessage(b, m, wtyp, opts)
Damien Neil68b81c32019-08-22 11:41:32 -0700246 return v, n, err
Damien Neile91877d2019-06-27 10:54:42 -0700247}
248
Damien Neil68b81c32019-08-22 11:41:32 -0700249func isInitMessageValue(v pref.Value) error {
250 m := v.Message().Interface()
Damien Neil5322bdb2019-04-09 15:57:05 -0700251 return proto.IsInitialized(m)
252}
253
Damien Neil68b81c32019-08-22 11:41:32 -0700254var coderMessageValue = valueCoderFuncs{
255 size: sizeMessageValue,
256 marshal: appendMessageValue,
257 unmarshal: consumeMessageValue,
258 isInit: isInitMessageValue,
259}
260
261func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
262 m := v.Message().Interface()
263 return sizeGroup(m, tagsize, opts)
264}
265
266func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
267 m := v.Message().Interface()
268 return appendGroup(b, m, wiretag, opts)
269}
270
271func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
272 m := v.Message().Interface()
273 n, err := consumeGroup(b, m, num, wtyp, opts)
274 return v, n, err
275}
276
277var coderGroupValue = valueCoderFuncs{
278 size: sizeGroupValue,
279 marshal: appendGroupValue,
280 unmarshal: consumeGroupValue,
281 isInit: isInitMessageValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700282}
283
284func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700285 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700286 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700287 return pointerCoderFuncs{
288 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700289 return sizeGroupType(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700290 },
291 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700292 return appendGroupType(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700293 },
Damien Neile91877d2019-06-27 10:54:42 -0700294 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700295 return consumeGroupType(b, p, mi, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700296 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700297 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700298 return mi.isInitializedPointer(p.Elem())
Damien Neil5322bdb2019-04-09 15:57:05 -0700299 },
Damien Neilc37adef2019-04-01 13:49:56 -0700300 }
301 } else {
302 return pointerCoderFuncs{
303 size: func(p pointer, tagsize int, opts marshalOptions) int {
Damien Neil5b6d0472019-06-14 11:54:07 -0700304 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700305 return sizeGroup(m, tagsize, opts)
306 },
307 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Damien Neil5b6d0472019-06-14 11:54:07 -0700308 m := asMessage(p.AsValueOf(ft).Elem())
Damien Neilc37adef2019-04-01 13:49:56 -0700309 return appendGroup(b, m, wiretag, opts)
310 },
Damien Neile91877d2019-06-27 10:54:42 -0700311 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
312 mp := p.AsValueOf(ft).Elem()
313 if mp.IsNil() {
314 mp.Set(reflect.New(ft.Elem()))
315 }
316 return consumeGroup(b, asMessage(mp), num, wtyp, opts)
317 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700318 isInit: func(p pointer) error {
319 m := asMessage(p.AsValueOf(ft).Elem())
320 return proto.IsInitialized(m)
321 },
Damien Neilc37adef2019-04-01 13:49:56 -0700322 }
323 }
324}
325
Joe Tsai4fe96632019-05-22 05:12:36 -0400326func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700327 return 2*tagsize + mi.sizePointer(p.Elem(), opts)
328}
329
Joe Tsai4fe96632019-05-22 05:12:36 -0400330func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700331 b = wire.AppendVarint(b, wiretag) // start group
332 b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
333 b = wire.AppendVarint(b, wiretag+1) // end group
334 return b, err
335}
336
Damien Neile91877d2019-06-27 10:54:42 -0700337func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
338 if wtyp != wire.StartGroupType {
339 return 0, errUnknown
340 }
341 if p.Elem().IsNil() {
Damien Neil16163b42019-08-06 15:43:25 -0700342 p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
Damien Neile91877d2019-06-27 10:54:42 -0700343 }
344 return mi.unmarshalPointer(b, p.Elem(), num, opts)
345}
346
Damien Neilc37adef2019-04-01 13:49:56 -0700347func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
348 return 2*tagsize + proto.Size(m)
349}
350
351func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
352 b = wire.AppendVarint(b, wiretag) // start group
353 b, err := opts.Options().MarshalAppend(b, m)
354 b = wire.AppendVarint(b, wiretag+1) // end group
355 return b, err
356}
357
Damien Neile91877d2019-06-27 10:54:42 -0700358func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
359 if wtyp != wire.StartGroupType {
360 return 0, errUnknown
361 }
362 b, n := wire.ConsumeGroup(num, b)
363 if n < 0 {
364 return 0, wire.ParseError(n)
365 }
366 return n, opts.Options().Unmarshal(b, m)
Damien Neilc37adef2019-04-01 13:49:56 -0700367}
368
Damien Neilc37adef2019-04-01 13:49:56 -0700369func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Joe Tsai070c1012019-07-26 23:45:58 -0700370 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700371 return pointerCoderFuncs{
Damien Neile91877d2019-06-27 10:54:42 -0700372 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700373 return sizeMessageSliceInfo(p, mi, tagsize, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700374 },
Damien Neilc37adef2019-04-01 13:49:56 -0700375 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700376 return appendMessageSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700377 },
Damien Neile91877d2019-06-27 10:54:42 -0700378 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700379 return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700380 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700381 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700382 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700383 },
Damien Neilc37adef2019-04-01 13:49:56 -0700384 }
385 }
386 return pointerCoderFuncs{
387 size: func(p pointer, tagsize int, opts marshalOptions) int {
388 return sizeMessageSlice(p, ft, tagsize, opts)
389 },
390 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
391 return appendMessageSlice(b, p, wiretag, ft, opts)
392 },
Damien Neile91877d2019-06-27 10:54:42 -0700393 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
394 return consumeMessageSlice(b, p, ft, wtyp, opts)
395 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700396 isInit: func(p pointer) error {
397 return isInitMessageSlice(p, ft)
398 },
Damien Neilc37adef2019-04-01 13:49:56 -0700399 }
400}
401
Joe Tsai4fe96632019-05-22 05:12:36 -0400402func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700403 s := p.PointerSlice()
404 n := 0
405 for _, v := range s {
406 n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
407 }
408 return n
409}
410
Joe Tsai4fe96632019-05-22 05:12:36 -0400411func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700412 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700413 var err error
414 for _, v := range s {
415 b = wire.AppendVarint(b, wiretag)
416 siz := mi.sizePointer(v, opts)
417 b = wire.AppendVarint(b, uint64(siz))
418 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700419 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700420 return b, err
421 }
422 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700423 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700424}
425
Damien Neile91877d2019-06-27 10:54:42 -0700426func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
427 if wtyp != wire.BytesType {
428 return 0, errUnknown
429 }
430 v, n := wire.ConsumeBytes(b)
431 if n < 0 {
432 return 0, wire.ParseError(n)
433 }
Damien Neil16163b42019-08-06 15:43:25 -0700434 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700435 mp := pointerOfIface(m)
436 if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
437 return 0, err
438 }
439 p.AppendPointerSlice(mp)
440 return n, nil
441}
442
Damien Neil5322bdb2019-04-09 15:57:05 -0700443func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
444 s := p.PointerSlice()
445 for _, v := range s {
446 if err := mi.isInitializedPointer(v); err != nil {
447 return err
448 }
449 }
450 return nil
451}
452
Damien Neilc37adef2019-04-01 13:49:56 -0700453func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
454 s := p.PointerSlice()
455 n := 0
456 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700457 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700458 n += wire.SizeBytes(proto.Size(m)) + tagsize
459 }
460 return n
461}
462
463func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
464 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700465 var err error
466 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700467 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700468 b = wire.AppendVarint(b, wiretag)
469 siz := proto.Size(m)
470 b = wire.AppendVarint(b, uint64(siz))
471 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700472 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700473 return b, err
474 }
475 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700476 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700477}
478
Damien Neile91877d2019-06-27 10:54:42 -0700479func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
480 if wtyp != wire.BytesType {
481 return 0, errUnknown
482 }
483 v, n := wire.ConsumeBytes(b)
484 if n < 0 {
485 return 0, wire.ParseError(n)
486 }
487 mp := reflect.New(goType.Elem())
488 if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
489 return 0, err
490 }
491 p.AppendPointerSlice(pointerOfValue(mp))
492 return n, nil
493}
494
Damien Neil5322bdb2019-04-09 15:57:05 -0700495func isInitMessageSlice(p pointer, goType reflect.Type) error {
496 s := p.PointerSlice()
497 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700498 m := asMessage(v.AsValueOf(goType.Elem()))
Damien Neil5322bdb2019-04-09 15:57:05 -0700499 if err := proto.IsInitialized(m); err != nil {
500 return err
501 }
502 }
503 return nil
504}
505
Damien Neilc37adef2019-04-01 13:49:56 -0700506// Slices of messages
507
Damien Neil68b81c32019-08-22 11:41:32 -0700508func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
509 list := listv.List()
510 n := 0
511 for i, llen := 0, list.Len(); i < llen; i++ {
512 m := list.Get(i).Message().Interface()
513 n += wire.SizeBytes(proto.Size(m)) + tagsize
514 }
515 return n
Damien Neilc37adef2019-04-01 13:49:56 -0700516}
517
Damien Neil68b81c32019-08-22 11:41:32 -0700518func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
519 list := listv.List()
520 mopts := opts.Options()
521 for i, llen := 0, list.Len(); i < llen; i++ {
522 m := list.Get(i).Message().Interface()
523 b = wire.AppendVarint(b, wiretag)
524 siz := proto.Size(m)
525 b = wire.AppendVarint(b, uint64(siz))
526 var err error
527 b, err = mopts.MarshalAppend(b, m)
528 if err != nil {
529 return b, err
530 }
531 }
532 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700533}
534
Damien Neil68b81c32019-08-22 11:41:32 -0700535func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
536 list := listv.List()
537 if wtyp != wire.BytesType {
538 return pref.Value{}, 0, errUnknown
539 }
540 v, n := wire.ConsumeBytes(b)
541 if n < 0 {
542 return pref.Value{}, 0, wire.ParseError(n)
543 }
544 m := list.NewElement()
545 if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
546 return pref.Value{}, 0, err
547 }
548 list.Append(m)
549 return listv, n, nil
Damien Neile91877d2019-06-27 10:54:42 -0700550}
551
Damien Neil68b81c32019-08-22 11:41:32 -0700552func isInitMessageSliceValue(listv pref.Value) error {
553 list := listv.List()
554 for i, llen := 0, list.Len(); i < llen; i++ {
555 m := list.Get(i).Message().Interface()
556 if err := proto.IsInitialized(m); err != nil {
557 return err
558 }
559 }
560 return nil
Damien Neil5322bdb2019-04-09 15:57:05 -0700561}
562
Damien Neil68b81c32019-08-22 11:41:32 -0700563var coderMessageSliceValue = valueCoderFuncs{
564 size: sizeMessageSliceValue,
565 marshal: appendMessageSliceValue,
566 unmarshal: consumeMessageSliceValue,
567 isInit: isInitMessageSliceValue,
568}
569
570func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
571 list := listv.List()
572 n := 0
573 for i, llen := 0, list.Len(); i < llen; i++ {
574 m := list.Get(i).Message().Interface()
575 n += 2*tagsize + proto.Size(m)
576 }
577 return n
578}
579
580func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
581 list := listv.List()
582 mopts := opts.Options()
583 for i, llen := 0, list.Len(); i < llen; i++ {
584 m := list.Get(i).Message().Interface()
585 b = wire.AppendVarint(b, wiretag) // start group
586 var err error
587 b, err = mopts.MarshalAppend(b, m)
588 if err != nil {
589 return b, err
590 }
591 b = wire.AppendVarint(b, wiretag+1) // end group
592 }
593 return b, nil
594}
595
596func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
597 list := listv.List()
598 if wtyp != wire.StartGroupType {
599 return pref.Value{}, 0, errUnknown
600 }
601 b, n := wire.ConsumeGroup(num, b)
602 if n < 0 {
603 return pref.Value{}, 0, wire.ParseError(n)
604 }
605 m := list.NewElement()
606 if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
607 return pref.Value{}, 0, err
608 }
609 list.Append(m)
610 return listv, n, nil
611}
612
613var coderGroupSliceValue = valueCoderFuncs{
614 size: sizeGroupSliceValue,
615 marshal: appendGroupSliceValue,
616 unmarshal: consumeGroupSliceValue,
617 isInit: isInitMessageSliceValue,
Damien Neilc37adef2019-04-01 13:49:56 -0700618}
619
620func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
Damien Neile91877d2019-06-27 10:54:42 -0700621 num := fd.Number()
Joe Tsai070c1012019-07-26 23:45:58 -0700622 if mi := getMessageInfo(ft); mi != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700623 return pointerCoderFuncs{
624 size: func(p pointer, tagsize int, opts marshalOptions) int {
Joe Tsai070c1012019-07-26 23:45:58 -0700625 return sizeGroupSliceInfo(p, mi, tagsize, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700626 },
627 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700628 return appendGroupSliceInfo(b, p, wiretag, mi, opts)
Damien Neilc37adef2019-04-01 13:49:56 -0700629 },
Damien Neile91877d2019-06-27 10:54:42 -0700630 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
Joe Tsai070c1012019-07-26 23:45:58 -0700631 return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700632 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700633 isInit: func(p pointer) error {
Joe Tsai070c1012019-07-26 23:45:58 -0700634 return isInitMessageSliceInfo(p, mi)
Damien Neil5322bdb2019-04-09 15:57:05 -0700635 },
Damien Neilc37adef2019-04-01 13:49:56 -0700636 }
637 }
638 return pointerCoderFuncs{
639 size: func(p pointer, tagsize int, opts marshalOptions) int {
640 return sizeGroupSlice(p, ft, tagsize, opts)
641 },
642 marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
643 return appendGroupSlice(b, p, wiretag, ft, opts)
644 },
Damien Neile91877d2019-06-27 10:54:42 -0700645 unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
646 return consumeGroupSlice(b, p, num, wtyp, ft, opts)
647 },
Damien Neil5322bdb2019-04-09 15:57:05 -0700648 isInit: func(p pointer) error {
649 return isInitMessageSlice(p, ft)
650 },
Damien Neilc37adef2019-04-01 13:49:56 -0700651 }
652}
653
654func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
655 s := p.PointerSlice()
656 n := 0
657 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700658 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700659 n += 2*tagsize + proto.Size(m)
660 }
661 return n
662}
663
664func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
665 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700666 var err error
667 for _, v := range s {
Damien Neile91877d2019-06-27 10:54:42 -0700668 m := asMessage(v.AsValueOf(messageType.Elem()))
Damien Neilc37adef2019-04-01 13:49:56 -0700669 b = wire.AppendVarint(b, wiretag) // start group
670 b, err = opts.Options().MarshalAppend(b, m)
Damien Neil8c86fc52019-06-19 09:28:29 -0700671 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700672 return b, err
673 }
674 b = wire.AppendVarint(b, wiretag+1) // end group
675 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700676 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700677}
678
Damien Neile91877d2019-06-27 10:54:42 -0700679func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
680 if wtyp != wire.StartGroupType {
681 return 0, errUnknown
682 }
683 b, n := wire.ConsumeGroup(num, b)
684 if n < 0 {
685 return 0, wire.ParseError(n)
686 }
687 mp := reflect.New(goType.Elem())
688 if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
689 return 0, err
690 }
691 p.AppendPointerSlice(pointerOfValue(mp))
692 return n, nil
693}
694
Joe Tsai4fe96632019-05-22 05:12:36 -0400695func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
Damien Neilc37adef2019-04-01 13:49:56 -0700696 s := p.PointerSlice()
697 n := 0
698 for _, v := range s {
699 n += 2*tagsize + mi.sizePointer(v, opts)
700 }
701 return n
702}
703
Joe Tsai4fe96632019-05-22 05:12:36 -0400704func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
Damien Neilc37adef2019-04-01 13:49:56 -0700705 s := p.PointerSlice()
Damien Neilc37adef2019-04-01 13:49:56 -0700706 var err error
707 for _, v := range s {
708 b = wire.AppendVarint(b, wiretag) // start group
709 b, err = mi.marshalAppendPointer(b, v, opts)
Damien Neil8c86fc52019-06-19 09:28:29 -0700710 if err != nil {
Damien Neilc37adef2019-04-01 13:49:56 -0700711 return b, err
712 }
713 b = wire.AppendVarint(b, wiretag+1) // end group
714 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700715 return b, nil
Damien Neilc37adef2019-04-01 13:49:56 -0700716}
717
Damien Neile91877d2019-06-27 10:54:42 -0700718func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
719 if wtyp != wire.StartGroupType {
720 return 0, errUnknown
721 }
Damien Neil16163b42019-08-06 15:43:25 -0700722 m := reflect.New(mi.GoReflectType.Elem()).Interface()
Damien Neile91877d2019-06-27 10:54:42 -0700723 mp := pointerOfIface(m)
724 n, err := mi.unmarshalPointer(b, mp, num, opts)
725 if err != nil {
726 return 0, err
727 }
728 p.AppendPointerSlice(mp)
729 return n, nil
730}
731
Damien Neil5b6d0472019-06-14 11:54:07 -0700732func asMessage(v reflect.Value) pref.ProtoMessage {
733 if m, ok := v.Interface().(pref.ProtoMessage); ok {
734 return m
735 }
736 return legacyWrapMessage(v)
737}