blob: 7382d80e41dee83e70268db2e4c0c25f2aa513ae [file] [log] [blame]
Damien Neil8012b442019-01-18 09:32:24 -08001// Copyright 2018 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 fileinit
6
7import (
8 "bytes"
9 "fmt"
10 "reflect"
11
12 defval "github.com/golang/protobuf/v2/internal/encoding/defval"
13 wire "github.com/golang/protobuf/v2/internal/encoding/wire"
Joe Tsaica46d8c2019-03-20 16:51:09 -070014 fieldnum "github.com/golang/protobuf/v2/internal/fieldnum"
Damien Neil8012b442019-01-18 09:32:24 -080015 pimpl "github.com/golang/protobuf/v2/internal/impl"
Joe Tsai990b9f52019-03-13 12:56:39 -070016 ptype "github.com/golang/protobuf/v2/internal/prototype"
Damien Neil8012b442019-01-18 09:32:24 -080017 pvalue "github.com/golang/protobuf/v2/internal/value"
18 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Damien Neil82a03062019-05-08 07:52:49 -070019 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Damien Neil8012b442019-01-18 09:32:24 -080020)
21
22func (file *fileDesc) lazyInit() *fileLazy {
23 file.once.Do(func() {
Joe Tsaie089c0f2019-04-16 01:46:14 -070024 file.unmarshalFull(file.rawDesc)
Damien Neil8012b442019-01-18 09:32:24 -080025 file.resolveImports()
26 file.resolveEnums()
27 file.resolveMessages()
28 file.resolveExtensions()
29 file.resolveServices()
30 file.finishInit()
31 })
32 return file.lazy
33}
34
35func (file *fileDesc) resolveImports() {
36 // TODO: Resolve file dependencies.
37}
38
39func (file *fileDesc) resolveEnums() {
40 enumDecls := file.GoTypes[:len(file.allEnums)]
41 for i := range file.allEnums {
42 ed := &file.allEnums[i]
43
44 // Associate the EnumType with a concrete Go type.
45 enumCache := map[pref.EnumNumber]pref.Enum{}
46 ed.lazy.typ = reflect.TypeOf(enumDecls[i])
47 ed.lazy.new = func(n pref.EnumNumber) pref.Enum {
48 if v, ok := enumCache[n]; ok {
49 return v
50 }
51 v := reflect.New(ed.lazy.typ).Elem()
52 v.SetInt(int64(n))
53 return v.Interface().(pref.Enum)
54 }
55 for i := range ed.lazy.values.list {
56 n := ed.lazy.values.list[i].number
57 enumCache[n] = ed.lazy.new(n)
58 }
59 }
60}
61
62func (file *fileDesc) resolveMessages() {
63 messageDecls := file.GoTypes[len(file.allEnums):]
64 for i := range file.allMessages {
65 md := &file.allMessages[i]
66
67 // Associate the MessageType with a concrete Go type.
Joe Tsai4532dd72019-03-19 17:04:06 -070068 if !md.isMapEntry {
69 md.lazy.typ = reflect.TypeOf(messageDecls[i])
70 md.lazy.new = func() pref.Message {
71 t := md.lazy.typ.Elem()
72 return reflect.New(t).Interface().(pref.ProtoMessage).ProtoReflect()
73 }
Damien Neil8012b442019-01-18 09:32:24 -080074 }
75
76 // Resolve message field dependencies.
77 for j := range md.lazy.fields.list {
78 fd := &md.lazy.fields.list[j]
79 if fd.isWeak {
80 continue
81 }
82
83 switch fd.kind {
84 case pref.EnumKind:
85 fd.enumType = file.popEnumDependency()
86 case pref.MessageKind, pref.GroupKind:
87 fd.messageType = file.popMessageDependency()
88 }
89 fd.isMap = file.isMapEntry(fd.messageType)
90 if !fd.hasPacked && file.lazy.syntax != pref.Proto2 && fd.cardinality == pref.Repeated {
91 switch fd.kind {
92 case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
93 fd.isPacked = false
94 default:
95 fd.isPacked = true
96 }
97 }
98 fd.defVal.lazyInit(fd.kind, file.enumValuesOf(fd.enumType))
99 }
100 }
101}
102
103func (file *fileDesc) resolveExtensions() {
104 for i := range file.allExtensions {
105 xd := &file.allExtensions[i]
106
107 // Associate the ExtensionType with a concrete Go type.
108 var typ reflect.Type
109 switch xd.lazy.kind {
110 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
111 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
112 default:
113 typ = goTypeForPBKind[xd.lazy.kind]
114 }
115 switch xd.lazy.cardinality {
116 case pref.Optional:
117 switch xd.lazy.kind {
118 case pref.EnumKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700119 et := pimpl.Export{}.EnumTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800120 xd.lazy.typ = typ
121 xd.lazy.new = func() pref.Value {
122 return xd.lazy.defVal.get()
123 }
124 xd.lazy.valueOf = func(v interface{}) pref.Value {
125 ev := v.(pref.Enum)
126 return pref.ValueOf(ev.Number())
127 }
128 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700129 return et.New(pv.Enum())
Damien Neil8012b442019-01-18 09:32:24 -0800130 }
131 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700132 mt := pimpl.Export{}.MessageTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800133 xd.lazy.typ = typ
134 xd.lazy.new = func() pref.Value {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700135 return pref.ValueOf(mt.New())
Damien Neil8012b442019-01-18 09:32:24 -0800136 }
137 xd.lazy.valueOf = func(v interface{}) pref.Value {
138 mv := v.(pref.ProtoMessage).ProtoReflect()
139 return pref.ValueOf(mv)
140 }
141 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
142 return pv.Message().Interface()
143 }
144 default:
145 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
146 xd.lazy.new = func() pref.Value {
147 return xd.lazy.defVal.get()
148 }
149 xd.lazy.valueOf = func(v interface{}) pref.Value {
150 return pref.ValueOf(v)
151 }
152 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
153 return pv.Interface()
154 }
155 }
156 case pref.Repeated:
157 c := pvalue.NewConverter(typ, xd.lazy.kind)
158 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
159 xd.lazy.new = func() pref.Value {
160 v := reflect.New(xd.lazy.typ.Elem()).Interface()
161 return pref.ValueOf(pvalue.ListOf(v, c))
162 }
163 xd.lazy.valueOf = func(v interface{}) pref.Value {
164 return pref.ValueOf(pvalue.ListOf(v, c))
165 }
166 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
167 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
168 }
169 default:
170 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
171 }
172
173 // Resolve extension field dependency.
174 switch xd.lazy.kind {
175 case pref.EnumKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700176 xd.lazy.enumType = file.popEnumDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800177 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700178 xd.lazy.messageType = file.popMessageDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800179 }
180 xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
181 }
182}
183
184var goTypeForPBKind = map[pref.Kind]reflect.Type{
185 pref.BoolKind: reflect.TypeOf(bool(false)),
186 pref.Int32Kind: reflect.TypeOf(int32(0)),
187 pref.Sint32Kind: reflect.TypeOf(int32(0)),
188 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
189 pref.Int64Kind: reflect.TypeOf(int64(0)),
190 pref.Sint64Kind: reflect.TypeOf(int64(0)),
191 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
192 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
193 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
194 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
195 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
196 pref.FloatKind: reflect.TypeOf(float32(0)),
197 pref.DoubleKind: reflect.TypeOf(float64(0)),
198 pref.StringKind: reflect.TypeOf(string("")),
199 pref.BytesKind: reflect.TypeOf([]byte(nil)),
200}
201
202func (file *fileDesc) resolveServices() {
203 for i := range file.services.list {
204 sd := &file.services.list[i]
205
206 // Resolve method dependencies.
207 for j := range sd.lazy.methods.list {
208 md := &sd.lazy.methods.list[j]
209 md.inputType = file.popMessageDependency()
210 md.outputType = file.popMessageDependency()
211 }
212 }
213}
214
215// isMapEntry reports whether the message is a map entry, being careful to
216// avoid calling the IsMapEntry method if the message is declared
217// within the same file (which would cause a recursive init deadlock).
218func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
219 if md == nil {
220 return false
221 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700222 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
223 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800224 }
225 return md.IsMapEntry()
226}
227
228// enumValuesOf retrieves the list of enum values for the given enum,
229// being careful to avoid calling the Values method if the enum is declared
230// within the same file (which would cause a recursive init deadlock).
231func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
232 if ed == nil {
233 return nil
234 }
235 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
236 return &ed.lazy.values
237 }
238 return ed.Values()
239}
240
Joe Tsai4532dd72019-03-19 17:04:06 -0700241func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800242 depIdx := fd.popDependencyIndex()
243 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
244 return &fd.allEnums[depIdx]
245 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700246 return pimpl.Export{}.EnumDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800247 }
248}
249
Joe Tsai4532dd72019-03-19 17:04:06 -0700250func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800251 depIdx := fd.popDependencyIndex()
252 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700253 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800254 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700255 return pimpl.Export{}.MessageDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800256 }
257}
258
259func (fi *fileInit) popDependencyIndex() int {
260 depIdx := fi.DependencyIndexes[0]
261 fi.DependencyIndexes = fi.DependencyIndexes[1:]
262 return int(depIdx)
263}
264
265func (fi *fileInit) finishInit() {
266 if len(fi.DependencyIndexes) > 0 {
267 panic("unused dependencies")
268 }
269 *fi = fileInit{} // clear fileInit for GC to reclaim resources
270}
271
272type defaultValue struct {
273 has bool
274 val pref.Value
275 enum pref.EnumValueDescriptor
276 check func() // only set for non-empty bytes
277}
278
279func (dv *defaultValue) get() pref.Value {
280 if dv.check != nil {
281 dv.check()
282 }
283 return dv.val
284}
285
286func (dv *defaultValue) lazyInit(k pref.Kind, eds pref.EnumValueDescriptors) {
287 if dv.has {
288 switch k {
289 case pref.EnumKind:
290 // File descriptors always store default enums by name.
291 dv.enum = eds.ByName(pref.Name(dv.val.String()))
292 dv.val = pref.ValueOf(dv.enum.Number())
293 case pref.BytesKind:
294 // Store a copy of the default bytes, so that we can detect
295 // accidental mutations of the original value.
296 b := append([]byte(nil), dv.val.Bytes()...)
297 dv.check = func() {
298 if !bytes.Equal(b, dv.val.Bytes()) {
299 // TODO: Avoid panic if we're running with the race detector
300 // and instead spawn a goroutine that periodically resets
301 // this value back to the original to induce a race.
302 panic("detected mutation on the default bytes")
303 }
304 }
305 }
306 } else {
307 switch k {
308 case pref.BoolKind:
309 dv.val = pref.ValueOf(false)
310 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
311 dv.val = pref.ValueOf(int32(0))
312 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
313 dv.val = pref.ValueOf(int64(0))
314 case pref.Uint32Kind, pref.Fixed32Kind:
315 dv.val = pref.ValueOf(uint32(0))
316 case pref.Uint64Kind, pref.Fixed64Kind:
317 dv.val = pref.ValueOf(uint64(0))
318 case pref.FloatKind:
319 dv.val = pref.ValueOf(float32(0))
320 case pref.DoubleKind:
321 dv.val = pref.ValueOf(float64(0))
322 case pref.StringKind:
323 dv.val = pref.ValueOf(string(""))
324 case pref.BytesKind:
325 dv.val = pref.ValueOf([]byte(nil))
326 case pref.EnumKind:
327 dv.enum = eds.Get(0)
328 dv.val = pref.ValueOf(dv.enum.Number())
329 }
330 }
331}
332
333func (fd *fileDesc) unmarshalFull(b []byte) {
334 nb := getNameBuilder()
335 defer putNameBuilder(nb)
336
337 var hasSyntax bool
338 var enumIdx, messageIdx, extensionIdx, serviceIdx int
Damien Neil2300c182019-04-15 13:05:13 -0700339 fd.lazy = &fileLazy{}
Damien Neil8012b442019-01-18 09:32:24 -0800340 for len(b) > 0 {
341 num, typ, n := wire.ConsumeTag(b)
342 b = b[n:]
343 switch typ {
344 case wire.VarintType:
345 v, m := wire.ConsumeVarint(b)
346 b = b[m:]
347 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700348 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800349 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700350 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800351 fd.lazy.imports[v].IsWeak = true
352 }
353 case wire.BytesType:
354 v, m := wire.ConsumeBytes(b)
355 b = b[m:]
356 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700357 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800358 hasSyntax = true
359 switch string(v) {
360 case "proto2":
361 fd.lazy.syntax = pref.Proto2
362 case "proto3":
363 fd.lazy.syntax = pref.Proto3
364 default:
365 panic("invalid syntax")
366 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700367 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800368 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
369 FileDescriptor: ptype.PlaceholderFile(nb.MakeString(v), ""),
370 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700371 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800372 fd.enums.list[enumIdx].unmarshalFull(v, nb)
373 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700374 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800375 fd.messages.list[messageIdx].unmarshalFull(v, nb)
376 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700377 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800378 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
379 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700380 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800381 fd.services.list[serviceIdx].unmarshalFull(v, nb)
382 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700383 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800384 fd.lazy.options = append(fd.lazy.options, v...)
385 }
386 default:
387 m := wire.ConsumeFieldValue(num, typ, b)
388 b = b[m:]
389 }
390 }
391
392 // If syntax is missing, it is assumed to be proto2.
393 if !hasSyntax {
394 fd.lazy.syntax = pref.Proto2
395 }
396}
397
398func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
399 var rawValues [][]byte
400 ed.lazy = new(enumLazy)
401 for len(b) > 0 {
402 num, typ, n := wire.ConsumeTag(b)
403 b = b[n:]
404 switch typ {
405 case wire.BytesType:
406 v, m := wire.ConsumeBytes(b)
407 b = b[m:]
408 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700409 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800410 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700411 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800412 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700413 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800414 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700415 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800416 ed.lazy.options = append(ed.lazy.options, v...)
417 }
418 default:
419 m := wire.ConsumeFieldValue(num, typ, b)
420 b = b[m:]
421 }
422 }
423
424 if len(rawValues) > 0 {
425 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
426 for i, b := range rawValues {
427 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
428 }
429 }
Damien Neil8012b442019-01-18 09:32:24 -0800430}
431
432func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
433 for len(b) > 0 {
434 num, typ, n := wire.ConsumeTag(b)
435 b = b[n:]
436 switch typ {
437 case wire.VarintType:
438 v, m := wire.ConsumeVarint(b)
439 b = b[m:]
440 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700441 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800442 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700443 case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800444 r[1] = pref.EnumNumber(v)
445 }
446 default:
447 m := wire.ConsumeFieldValue(num, typ, b)
448 b = b[m:]
449 }
450 }
451 return r
452}
453
454func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
455 vd.parentFile = pf
456 vd.parent = pd
457 vd.index = i
458
459 for len(b) > 0 {
460 num, typ, n := wire.ConsumeTag(b)
461 b = b[n:]
462 switch typ {
463 case wire.VarintType:
464 v, m := wire.ConsumeVarint(b)
465 b = b[m:]
466 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700467 case fieldnum.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800468 vd.number = pref.EnumNumber(v)
469 }
470 case wire.BytesType:
471 v, m := wire.ConsumeBytes(b)
472 b = b[m:]
473 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700474 case fieldnum.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800475 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700476 case fieldnum.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800477 vd.options = append(vd.options, v...)
478 }
479 default:
480 m := wire.ConsumeFieldValue(num, typ, b)
481 b = b[m:]
482 }
483 }
Damien Neil8012b442019-01-18 09:32:24 -0800484}
485
486func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
487 var rawFields, rawOneofs [][]byte
488 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700489 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800490 md.lazy = new(messageLazy)
491 for len(b) > 0 {
492 num, typ, n := wire.ConsumeTag(b)
493 b = b[n:]
494 switch typ {
495 case wire.BytesType:
496 v, m := wire.ConsumeBytes(b)
497 b = b[m:]
498 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700499 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800500 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700501 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800502 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700503 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800504 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700505 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800506 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700507 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800508 r, opts := unmarshalMessageExtensionRange(v)
509 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
510 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700511 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800512 md.enums.list[enumIdx].unmarshalFull(v, nb)
513 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700514 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800515 md.messages.list[messageIdx].unmarshalFull(v, nb)
516 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700517 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800518 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
519 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700520 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700521 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800522 }
523 default:
524 m := wire.ConsumeFieldValue(num, typ, b)
525 b = b[m:]
526 }
527 }
528
529 if len(rawFields) > 0 || len(rawOneofs) > 0 {
530 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
531 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
532 for i, b := range rawFields {
533 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700534 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800535 if fd.cardinality == pref.Required {
536 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
537 }
538 }
539 for i, b := range rawOneofs {
540 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700541 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800542 }
543 }
544
Joe Tsai4532dd72019-03-19 17:04:06 -0700545 if isMapEntry != md.isMapEntry {
546 panic("mismatching map entry property")
547 }
Damien Neil8012b442019-01-18 09:32:24 -0800548}
549
Joe Tsai4532dd72019-03-19 17:04:06 -0700550func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800551 md.lazy.options = append(md.lazy.options, b...)
552 for len(b) > 0 {
553 num, typ, n := wire.ConsumeTag(b)
554 b = b[n:]
555 switch typ {
556 case wire.VarintType:
557 v, m := wire.ConsumeVarint(b)
558 b = b[m:]
559 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700560 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700561 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700562 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700563 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800564 }
565 default:
566 m := wire.ConsumeFieldValue(num, typ, b)
567 b = b[m:]
568 }
569 }
570}
571
572func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
573 for len(b) > 0 {
574 num, typ, n := wire.ConsumeTag(b)
575 b = b[n:]
576 switch typ {
577 case wire.VarintType:
578 v, m := wire.ConsumeVarint(b)
579 b = b[m:]
580 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700581 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800582 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700583 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800584 r[1] = pref.FieldNumber(v)
585 }
586 default:
587 m := wire.ConsumeFieldValue(num, typ, b)
588 b = b[m:]
589 }
590 }
591 return r
592}
593
594func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
595 for len(b) > 0 {
596 num, typ, n := wire.ConsumeTag(b)
597 b = b[n:]
598 switch typ {
599 case wire.VarintType:
600 v, m := wire.ConsumeVarint(b)
601 b = b[m:]
602 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700603 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800604 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700605 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800606 r[1] = pref.FieldNumber(v)
607 }
608 case wire.BytesType:
609 v, m := wire.ConsumeBytes(b)
610 b = b[m:]
611 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700612 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800613 opts = append(opts, v...)
614 }
615 default:
616 m := wire.ConsumeFieldValue(num, typ, b)
617 b = b[m:]
618 }
619 }
620 return r, opts
621}
622
623func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
624 fd.parentFile = pf
625 fd.parent = pd
626 fd.index = i
627
628 var rawDefVal []byte
629 var rawTypeName []byte
630 for len(b) > 0 {
631 num, typ, n := wire.ConsumeTag(b)
632 b = b[n:]
633 switch typ {
634 case wire.VarintType:
635 v, m := wire.ConsumeVarint(b)
636 b = b[m:]
637 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700638 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800639 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700640 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800641 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700642 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800643 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700644 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800645 // In messageDesc.UnmarshalFull, we allocate slices for both
646 // the field and oneof descriptors before unmarshaling either
647 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700648 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800649 od.fields.list = append(od.fields.list, fd)
650 if fd.oneofType != nil {
651 panic("oneof type already set")
652 }
653 fd.oneofType = od
654 }
655 case wire.BytesType:
656 v, m := wire.ConsumeBytes(b)
657 b = b[m:]
658 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700659 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800660 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700661 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800662 fd.hasJSONName = true
663 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700664 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800665 fd.defVal.has = true
666 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700667 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800668 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700669 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800670 fd.unmarshalOptions(v)
671 }
672 default:
673 m := wire.ConsumeFieldValue(num, typ, b)
674 b = b[m:]
675 }
676 }
677
678 if !fd.hasJSONName {
679 fd.jsonName = nb.MakeJSONName(fd.Name())
680 }
681 if rawDefVal != nil {
682 var err error
683 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
684 if err != nil {
685 panic(err)
686 }
687 }
688 if fd.isWeak {
689 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
690 panic("weak target name must be fully qualified")
691 }
Damien Neil82a03062019-05-08 07:52:49 -0700692 // Consult the global registry for weak messages.
693 name := pref.FullName(rawTypeName[1:])
694 fd.messageType, _ = preg.GlobalFiles.FindMessageByName(name)
695 if fd.messageType == nil {
696 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
697 }
Damien Neil8012b442019-01-18 09:32:24 -0800698 }
Damien Neil8012b442019-01-18 09:32:24 -0800699}
700
701func (fd *fieldDesc) unmarshalOptions(b []byte) {
702 fd.options = append(fd.options, b...)
703 for len(b) > 0 {
704 num, typ, n := wire.ConsumeTag(b)
705 b = b[n:]
706 switch typ {
707 case wire.VarintType:
708 v, m := wire.ConsumeVarint(b)
709 b = b[m:]
710 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700711 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800712 fd.hasPacked = true
713 fd.isPacked = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700714 case fieldnum.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800715 fd.isWeak = wire.DecodeBool(v)
716 }
717 default:
718 m := wire.ConsumeFieldValue(num, typ, b)
719 b = b[m:]
720 }
721 }
722}
723
724func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
725 od.parentFile = pf
726 od.parent = pd
727 od.index = i
728
729 for len(b) > 0 {
730 num, typ, n := wire.ConsumeTag(b)
731 b = b[n:]
732 switch typ {
733 case wire.BytesType:
734 v, m := wire.ConsumeBytes(b)
735 b = b[m:]
736 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700737 case fieldnum.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800738 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700739 case fieldnum.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800740 od.options = append(od.options, v...)
741 }
742 default:
743 m := wire.ConsumeFieldValue(num, typ, b)
744 b = b[m:]
745 }
746 }
Damien Neil8012b442019-01-18 09:32:24 -0800747}
748
749func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
750 var rawDefVal []byte
751 xd.lazy = new(extensionLazy)
752 for len(b) > 0 {
753 num, typ, n := wire.ConsumeTag(b)
754 b = b[n:]
755 switch typ {
756 case wire.VarintType:
757 v, m := wire.ConsumeVarint(b)
758 b = b[m:]
759 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700760 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800761 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700762 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800763 xd.lazy.kind = pref.Kind(v)
764 }
765 case wire.BytesType:
766 v, m := wire.ConsumeBytes(b)
767 b = b[m:]
768 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700769 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800770 xd.lazy.hasJSONName = true
771 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700772 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800773 xd.lazy.defVal.has = true
774 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700775 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800776 xd.unmarshalOptions(v)
777 }
778 default:
779 m := wire.ConsumeFieldValue(num, typ, b)
780 b = b[m:]
781 }
782 }
783
784 if rawDefVal != nil {
785 var err error
786 xd.lazy.defVal.val, err = defval.Unmarshal(string(rawDefVal), xd.lazy.kind, defval.Descriptor)
787 if err != nil {
788 panic(err)
789 }
790 }
Damien Neil8012b442019-01-18 09:32:24 -0800791}
792
793func (xd *extensionDesc) unmarshalOptions(b []byte) {
794 xd.lazy.options = append(xd.lazy.options, b...)
795 for len(b) > 0 {
796 num, typ, n := wire.ConsumeTag(b)
797 b = b[n:]
798 switch typ {
799 case wire.VarintType:
800 v, m := wire.ConsumeVarint(b)
801 b = b[m:]
802 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700803 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800804 xd.lazy.isPacked = wire.DecodeBool(v)
805 }
806 default:
807 m := wire.ConsumeFieldValue(num, typ, b)
808 b = b[m:]
809 }
810 }
811}
812
813func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
814 var rawMethods [][]byte
815 sd.lazy = new(serviceLazy)
816 for len(b) > 0 {
817 num, typ, n := wire.ConsumeTag(b)
818 b = b[n:]
819 switch typ {
820 case wire.BytesType:
821 v, m := wire.ConsumeBytes(b)
822 b = b[m:]
823 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700824 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800825 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700826 case fieldnum.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800827 sd.lazy.options = append(sd.lazy.options, v...)
828 }
829 default:
830 m := wire.ConsumeFieldValue(num, typ, b)
831 b = b[m:]
832 }
833 }
834
835 if len(rawMethods) > 0 {
836 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
837 for i, b := range rawMethods {
838 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
839 }
840 }
Damien Neil8012b442019-01-18 09:32:24 -0800841}
842
843func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
844 md.parentFile = pf
845 md.parent = pd
846 md.index = i
847
848 for len(b) > 0 {
849 num, typ, n := wire.ConsumeTag(b)
850 b = b[n:]
851 switch typ {
852 case wire.VarintType:
853 v, m := wire.ConsumeVarint(b)
854 b = b[m:]
855 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700856 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800857 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700858 case fieldnum.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800859 md.isStreamingServer = wire.DecodeBool(v)
860 }
861 case wire.BytesType:
862 v, m := wire.ConsumeBytes(b)
863 b = b[m:]
864 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700865 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800866 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700867 case fieldnum.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800868 md.options = append(md.options, v...)
869 }
870 default:
871 m := wire.ConsumeFieldValue(num, typ, b)
872 b = b[m:]
873 }
874 }
Damien Neil8012b442019-01-18 09:32:24 -0800875}