blob: 7356b323fdc3b2220f1687d4fb7c7dc5e6edcc70 [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 Neil8012b442019-01-18 09:32:24 -080019)
20
21func (file *fileDesc) lazyInit() *fileLazy {
22 file.once.Do(func() {
23 file.unmarshalFull(file.RawDescriptor)
24 file.resolveImports()
25 file.resolveEnums()
26 file.resolveMessages()
27 file.resolveExtensions()
28 file.resolveServices()
29 file.finishInit()
30 })
31 return file.lazy
32}
33
34func (file *fileDesc) resolveImports() {
35 // TODO: Resolve file dependencies.
36}
37
38func (file *fileDesc) resolveEnums() {
39 enumDecls := file.GoTypes[:len(file.allEnums)]
40 for i := range file.allEnums {
41 ed := &file.allEnums[i]
42
43 // Associate the EnumType with a concrete Go type.
44 enumCache := map[pref.EnumNumber]pref.Enum{}
45 ed.lazy.typ = reflect.TypeOf(enumDecls[i])
46 ed.lazy.new = func(n pref.EnumNumber) pref.Enum {
47 if v, ok := enumCache[n]; ok {
48 return v
49 }
50 v := reflect.New(ed.lazy.typ).Elem()
51 v.SetInt(int64(n))
52 return v.Interface().(pref.Enum)
53 }
54 for i := range ed.lazy.values.list {
55 n := ed.lazy.values.list[i].number
56 enumCache[n] = ed.lazy.new(n)
57 }
58 }
59}
60
61func (file *fileDesc) resolveMessages() {
62 messageDecls := file.GoTypes[len(file.allEnums):]
63 for i := range file.allMessages {
64 md := &file.allMessages[i]
65
66 // Associate the MessageType with a concrete Go type.
Joe Tsai4532dd72019-03-19 17:04:06 -070067 if !md.isMapEntry {
68 md.lazy.typ = reflect.TypeOf(messageDecls[i])
69 md.lazy.new = func() pref.Message {
70 t := md.lazy.typ.Elem()
71 return reflect.New(t).Interface().(pref.ProtoMessage).ProtoReflect()
72 }
Damien Neil8012b442019-01-18 09:32:24 -080073 }
74
75 // Resolve message field dependencies.
76 for j := range md.lazy.fields.list {
77 fd := &md.lazy.fields.list[j]
78 if fd.isWeak {
79 continue
80 }
81
82 switch fd.kind {
83 case pref.EnumKind:
84 fd.enumType = file.popEnumDependency()
85 case pref.MessageKind, pref.GroupKind:
86 fd.messageType = file.popMessageDependency()
87 }
88 fd.isMap = file.isMapEntry(fd.messageType)
89 if !fd.hasPacked && file.lazy.syntax != pref.Proto2 && fd.cardinality == pref.Repeated {
90 switch fd.kind {
91 case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
92 fd.isPacked = false
93 default:
94 fd.isPacked = true
95 }
96 }
97 fd.defVal.lazyInit(fd.kind, file.enumValuesOf(fd.enumType))
98 }
99 }
100}
101
102func (file *fileDesc) resolveExtensions() {
103 for i := range file.allExtensions {
104 xd := &file.allExtensions[i]
105
106 // Associate the ExtensionType with a concrete Go type.
107 var typ reflect.Type
108 switch xd.lazy.kind {
109 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
110 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
111 default:
112 typ = goTypeForPBKind[xd.lazy.kind]
113 }
114 switch xd.lazy.cardinality {
115 case pref.Optional:
116 switch xd.lazy.kind {
117 case pref.EnumKind:
118 xd.lazy.typ = typ
119 xd.lazy.new = func() pref.Value {
120 return xd.lazy.defVal.get()
121 }
122 xd.lazy.valueOf = func(v interface{}) pref.Value {
123 ev := v.(pref.Enum)
124 return pref.ValueOf(ev.Number())
125 }
126 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
127 return xd.lazy.enumType.New(pv.Enum())
128 }
129 case pref.MessageKind, pref.GroupKind:
130 xd.lazy.typ = typ
131 xd.lazy.new = func() pref.Value {
132 return pref.ValueOf(xd.lazy.messageType.New())
133 }
134 xd.lazy.valueOf = func(v interface{}) pref.Value {
135 mv := v.(pref.ProtoMessage).ProtoReflect()
136 return pref.ValueOf(mv)
137 }
138 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
139 return pv.Message().Interface()
140 }
141 default:
142 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
143 xd.lazy.new = func() pref.Value {
144 return xd.lazy.defVal.get()
145 }
146 xd.lazy.valueOf = func(v interface{}) pref.Value {
147 return pref.ValueOf(v)
148 }
149 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
150 return pv.Interface()
151 }
152 }
153 case pref.Repeated:
154 c := pvalue.NewConverter(typ, xd.lazy.kind)
155 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
156 xd.lazy.new = func() pref.Value {
157 v := reflect.New(xd.lazy.typ.Elem()).Interface()
158 return pref.ValueOf(pvalue.ListOf(v, c))
159 }
160 xd.lazy.valueOf = func(v interface{}) pref.Value {
161 return pref.ValueOf(pvalue.ListOf(v, c))
162 }
163 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
164 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
165 }
166 default:
167 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
168 }
169
170 // Resolve extension field dependency.
171 switch xd.lazy.kind {
172 case pref.EnumKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700173 xd.lazy.enumType = file.popEnumDependency().(pref.EnumType)
Damien Neil8012b442019-01-18 09:32:24 -0800174 case pref.MessageKind, pref.GroupKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700175 xd.lazy.messageType = file.popMessageDependency().(pref.MessageType)
Damien Neil8012b442019-01-18 09:32:24 -0800176 }
177 xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
178 }
179}
180
181var goTypeForPBKind = map[pref.Kind]reflect.Type{
182 pref.BoolKind: reflect.TypeOf(bool(false)),
183 pref.Int32Kind: reflect.TypeOf(int32(0)),
184 pref.Sint32Kind: reflect.TypeOf(int32(0)),
185 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
186 pref.Int64Kind: reflect.TypeOf(int64(0)),
187 pref.Sint64Kind: reflect.TypeOf(int64(0)),
188 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
189 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
190 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
191 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
192 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
193 pref.FloatKind: reflect.TypeOf(float32(0)),
194 pref.DoubleKind: reflect.TypeOf(float64(0)),
195 pref.StringKind: reflect.TypeOf(string("")),
196 pref.BytesKind: reflect.TypeOf([]byte(nil)),
197}
198
199func (file *fileDesc) resolveServices() {
200 for i := range file.services.list {
201 sd := &file.services.list[i]
202
203 // Resolve method dependencies.
204 for j := range sd.lazy.methods.list {
205 md := &sd.lazy.methods.list[j]
206 md.inputType = file.popMessageDependency()
207 md.outputType = file.popMessageDependency()
208 }
209 }
210}
211
212// isMapEntry reports whether the message is a map entry, being careful to
213// avoid calling the IsMapEntry method if the message is declared
214// within the same file (which would cause a recursive init deadlock).
215func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
216 if md == nil {
217 return false
218 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700219 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
220 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800221 }
222 return md.IsMapEntry()
223}
224
225// enumValuesOf retrieves the list of enum values for the given enum,
226// being careful to avoid calling the Values method if the enum is declared
227// within the same file (which would cause a recursive init deadlock).
228func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
229 if ed == nil {
230 return nil
231 }
232 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
233 return &ed.lazy.values
234 }
235 return ed.Values()
236}
237
Joe Tsai4532dd72019-03-19 17:04:06 -0700238func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800239 depIdx := fd.popDependencyIndex()
240 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
241 return &fd.allEnums[depIdx]
242 } else {
243 return pimpl.Export{}.EnumTypeOf(fd.GoTypes[depIdx])
244 }
245}
246
Joe Tsai4532dd72019-03-19 17:04:06 -0700247func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800248 depIdx := fd.popDependencyIndex()
249 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700250 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800251 } else {
252 return pimpl.Export{}.MessageTypeOf(fd.GoTypes[depIdx])
253 }
254}
255
256func (fi *fileInit) popDependencyIndex() int {
257 depIdx := fi.DependencyIndexes[0]
258 fi.DependencyIndexes = fi.DependencyIndexes[1:]
259 return int(depIdx)
260}
261
262func (fi *fileInit) finishInit() {
263 if len(fi.DependencyIndexes) > 0 {
264 panic("unused dependencies")
265 }
266 *fi = fileInit{} // clear fileInit for GC to reclaim resources
267}
268
269type defaultValue struct {
270 has bool
271 val pref.Value
272 enum pref.EnumValueDescriptor
273 check func() // only set for non-empty bytes
274}
275
276func (dv *defaultValue) get() pref.Value {
277 if dv.check != nil {
278 dv.check()
279 }
280 return dv.val
281}
282
283func (dv *defaultValue) lazyInit(k pref.Kind, eds pref.EnumValueDescriptors) {
284 if dv.has {
285 switch k {
286 case pref.EnumKind:
287 // File descriptors always store default enums by name.
288 dv.enum = eds.ByName(pref.Name(dv.val.String()))
289 dv.val = pref.ValueOf(dv.enum.Number())
290 case pref.BytesKind:
291 // Store a copy of the default bytes, so that we can detect
292 // accidental mutations of the original value.
293 b := append([]byte(nil), dv.val.Bytes()...)
294 dv.check = func() {
295 if !bytes.Equal(b, dv.val.Bytes()) {
296 // TODO: Avoid panic if we're running with the race detector
297 // and instead spawn a goroutine that periodically resets
298 // this value back to the original to induce a race.
299 panic("detected mutation on the default bytes")
300 }
301 }
302 }
303 } else {
304 switch k {
305 case pref.BoolKind:
306 dv.val = pref.ValueOf(false)
307 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
308 dv.val = pref.ValueOf(int32(0))
309 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
310 dv.val = pref.ValueOf(int64(0))
311 case pref.Uint32Kind, pref.Fixed32Kind:
312 dv.val = pref.ValueOf(uint32(0))
313 case pref.Uint64Kind, pref.Fixed64Kind:
314 dv.val = pref.ValueOf(uint64(0))
315 case pref.FloatKind:
316 dv.val = pref.ValueOf(float32(0))
317 case pref.DoubleKind:
318 dv.val = pref.ValueOf(float64(0))
319 case pref.StringKind:
320 dv.val = pref.ValueOf(string(""))
321 case pref.BytesKind:
322 dv.val = pref.ValueOf([]byte(nil))
323 case pref.EnumKind:
324 dv.enum = eds.Get(0)
325 dv.val = pref.ValueOf(dv.enum.Number())
326 }
327 }
328}
329
330func (fd *fileDesc) unmarshalFull(b []byte) {
331 nb := getNameBuilder()
332 defer putNameBuilder(nb)
333
334 var hasSyntax bool
335 var enumIdx, messageIdx, extensionIdx, serviceIdx int
336 fd.lazy = &fileLazy{byName: make(map[pref.FullName]pref.Descriptor)}
337 for len(b) > 0 {
338 num, typ, n := wire.ConsumeTag(b)
339 b = b[n:]
340 switch typ {
341 case wire.VarintType:
342 v, m := wire.ConsumeVarint(b)
343 b = b[m:]
344 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700345 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800346 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700347 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800348 fd.lazy.imports[v].IsWeak = true
349 }
350 case wire.BytesType:
351 v, m := wire.ConsumeBytes(b)
352 b = b[m:]
353 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700354 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800355 hasSyntax = true
356 switch string(v) {
357 case "proto2":
358 fd.lazy.syntax = pref.Proto2
359 case "proto3":
360 fd.lazy.syntax = pref.Proto3
361 default:
362 panic("invalid syntax")
363 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700364 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800365 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
366 FileDescriptor: ptype.PlaceholderFile(nb.MakeString(v), ""),
367 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700368 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800369 fd.enums.list[enumIdx].unmarshalFull(v, nb)
370 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700371 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800372 fd.messages.list[messageIdx].unmarshalFull(v, nb)
373 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700374 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800375 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
376 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700377 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800378 fd.services.list[serviceIdx].unmarshalFull(v, nb)
379 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700380 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800381 fd.lazy.options = append(fd.lazy.options, v...)
382 }
383 default:
384 m := wire.ConsumeFieldValue(num, typ, b)
385 b = b[m:]
386 }
387 }
388
389 // If syntax is missing, it is assumed to be proto2.
390 if !hasSyntax {
391 fd.lazy.syntax = pref.Proto2
392 }
393}
394
395func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
396 var rawValues [][]byte
397 ed.lazy = new(enumLazy)
398 for len(b) > 0 {
399 num, typ, n := wire.ConsumeTag(b)
400 b = b[n:]
401 switch typ {
402 case wire.BytesType:
403 v, m := wire.ConsumeBytes(b)
404 b = b[m:]
405 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700406 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800407 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700408 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800409 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700410 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800411 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700412 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800413 ed.lazy.options = append(ed.lazy.options, v...)
414 }
415 default:
416 m := wire.ConsumeFieldValue(num, typ, b)
417 b = b[m:]
418 }
419 }
420
421 if len(rawValues) > 0 {
422 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
423 for i, b := range rawValues {
424 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
425 }
426 }
427
428 ed.parentFile.lazy.byName[ed.FullName()] = ed
429}
430
431func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
432 for len(b) > 0 {
433 num, typ, n := wire.ConsumeTag(b)
434 b = b[n:]
435 switch typ {
436 case wire.VarintType:
437 v, m := wire.ConsumeVarint(b)
438 b = b[m:]
439 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700440 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800441 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700442 case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800443 r[1] = pref.EnumNumber(v)
444 }
445 default:
446 m := wire.ConsumeFieldValue(num, typ, b)
447 b = b[m:]
448 }
449 }
450 return r
451}
452
453func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
454 vd.parentFile = pf
455 vd.parent = pd
456 vd.index = i
457
458 for len(b) > 0 {
459 num, typ, n := wire.ConsumeTag(b)
460 b = b[n:]
461 switch typ {
462 case wire.VarintType:
463 v, m := wire.ConsumeVarint(b)
464 b = b[m:]
465 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700466 case fieldnum.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800467 vd.number = pref.EnumNumber(v)
468 }
469 case wire.BytesType:
470 v, m := wire.ConsumeBytes(b)
471 b = b[m:]
472 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700473 case fieldnum.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800474 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700475 case fieldnum.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800476 vd.options = append(vd.options, v...)
477 }
478 default:
479 m := wire.ConsumeFieldValue(num, typ, b)
480 b = b[m:]
481 }
482 }
483
484 vd.parentFile.lazy.byName[vd.FullName()] = vd
485}
486
487func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
488 var rawFields, rawOneofs [][]byte
489 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700490 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800491 md.lazy = new(messageLazy)
492 for len(b) > 0 {
493 num, typ, n := wire.ConsumeTag(b)
494 b = b[n:]
495 switch typ {
496 case wire.BytesType:
497 v, m := wire.ConsumeBytes(b)
498 b = b[m:]
499 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700500 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800501 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700502 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800503 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700504 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800505 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700506 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800507 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700508 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800509 r, opts := unmarshalMessageExtensionRange(v)
510 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
511 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700512 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800513 md.enums.list[enumIdx].unmarshalFull(v, nb)
514 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700515 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800516 md.messages.list[messageIdx].unmarshalFull(v, nb)
517 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700518 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800519 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
520 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700521 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700522 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800523 }
524 default:
525 m := wire.ConsumeFieldValue(num, typ, b)
526 b = b[m:]
527 }
528 }
529
530 if len(rawFields) > 0 || len(rawOneofs) > 0 {
531 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
532 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
533 for i, b := range rawFields {
534 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700535 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800536 if fd.cardinality == pref.Required {
537 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
538 }
539 }
540 for i, b := range rawOneofs {
541 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700542 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800543 }
544 }
545
Joe Tsai4532dd72019-03-19 17:04:06 -0700546 if isMapEntry != md.isMapEntry {
547 panic("mismatching map entry property")
548 }
549
550 md.parentFile.lazy.byName[md.FullName()] = md.asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800551}
552
Joe Tsai4532dd72019-03-19 17:04:06 -0700553func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800554 md.lazy.options = append(md.lazy.options, b...)
555 for len(b) > 0 {
556 num, typ, n := wire.ConsumeTag(b)
557 b = b[n:]
558 switch typ {
559 case wire.VarintType:
560 v, m := wire.ConsumeVarint(b)
561 b = b[m:]
562 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700563 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700564 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700565 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700566 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800567 }
568 default:
569 m := wire.ConsumeFieldValue(num, typ, b)
570 b = b[m:]
571 }
572 }
573}
574
575func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
576 for len(b) > 0 {
577 num, typ, n := wire.ConsumeTag(b)
578 b = b[n:]
579 switch typ {
580 case wire.VarintType:
581 v, m := wire.ConsumeVarint(b)
582 b = b[m:]
583 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700584 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800585 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700586 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800587 r[1] = pref.FieldNumber(v)
588 }
589 default:
590 m := wire.ConsumeFieldValue(num, typ, b)
591 b = b[m:]
592 }
593 }
594 return r
595}
596
597func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
598 for len(b) > 0 {
599 num, typ, n := wire.ConsumeTag(b)
600 b = b[n:]
601 switch typ {
602 case wire.VarintType:
603 v, m := wire.ConsumeVarint(b)
604 b = b[m:]
605 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700606 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800607 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700608 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800609 r[1] = pref.FieldNumber(v)
610 }
611 case wire.BytesType:
612 v, m := wire.ConsumeBytes(b)
613 b = b[m:]
614 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700615 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800616 opts = append(opts, v...)
617 }
618 default:
619 m := wire.ConsumeFieldValue(num, typ, b)
620 b = b[m:]
621 }
622 }
623 return r, opts
624}
625
626func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
627 fd.parentFile = pf
628 fd.parent = pd
629 fd.index = i
630
631 var rawDefVal []byte
632 var rawTypeName []byte
633 for len(b) > 0 {
634 num, typ, n := wire.ConsumeTag(b)
635 b = b[n:]
636 switch typ {
637 case wire.VarintType:
638 v, m := wire.ConsumeVarint(b)
639 b = b[m:]
640 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700641 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800642 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700643 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800644 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700645 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800646 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700647 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800648 // In messageDesc.UnmarshalFull, we allocate slices for both
649 // the field and oneof descriptors before unmarshaling either
650 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700651 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800652 od.fields.list = append(od.fields.list, fd)
653 if fd.oneofType != nil {
654 panic("oneof type already set")
655 }
656 fd.oneofType = od
657 }
658 case wire.BytesType:
659 v, m := wire.ConsumeBytes(b)
660 b = b[m:]
661 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700662 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800663 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700664 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800665 fd.hasJSONName = true
666 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700667 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800668 fd.defVal.has = true
669 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700670 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800671 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700672 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800673 fd.unmarshalOptions(v)
674 }
675 default:
676 m := wire.ConsumeFieldValue(num, typ, b)
677 b = b[m:]
678 }
679 }
680
681 if !fd.hasJSONName {
682 fd.jsonName = nb.MakeJSONName(fd.Name())
683 }
684 if rawDefVal != nil {
685 var err error
686 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
687 if err != nil {
688 panic(err)
689 }
690 }
691 if fd.isWeak {
692 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
693 panic("weak target name must be fully qualified")
694 }
695 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
696 }
697
698 fd.parentFile.lazy.byName[fd.FullName()] = fd
699}
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 }
747
748 od.parentFile.lazy.byName[od.FullName()] = od
749}
750
751func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
752 var rawDefVal []byte
753 xd.lazy = new(extensionLazy)
754 for len(b) > 0 {
755 num, typ, n := wire.ConsumeTag(b)
756 b = b[n:]
757 switch typ {
758 case wire.VarintType:
759 v, m := wire.ConsumeVarint(b)
760 b = b[m:]
761 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700762 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800763 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700764 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800765 xd.lazy.kind = pref.Kind(v)
766 }
767 case wire.BytesType:
768 v, m := wire.ConsumeBytes(b)
769 b = b[m:]
770 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700771 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800772 xd.lazy.hasJSONName = true
773 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700774 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800775 xd.lazy.defVal.has = true
776 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700777 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800778 xd.unmarshalOptions(v)
779 }
780 default:
781 m := wire.ConsumeFieldValue(num, typ, b)
782 b = b[m:]
783 }
784 }
785
786 if rawDefVal != nil {
787 var err error
788 xd.lazy.defVal.val, err = defval.Unmarshal(string(rawDefVal), xd.lazy.kind, defval.Descriptor)
789 if err != nil {
790 panic(err)
791 }
792 }
793
794 xd.parentFile.lazy.byName[xd.FullName()] = xd
795}
796
797func (xd *extensionDesc) unmarshalOptions(b []byte) {
798 xd.lazy.options = append(xd.lazy.options, b...)
799 for len(b) > 0 {
800 num, typ, n := wire.ConsumeTag(b)
801 b = b[n:]
802 switch typ {
803 case wire.VarintType:
804 v, m := wire.ConsumeVarint(b)
805 b = b[m:]
806 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700807 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800808 xd.lazy.isPacked = wire.DecodeBool(v)
809 }
810 default:
811 m := wire.ConsumeFieldValue(num, typ, b)
812 b = b[m:]
813 }
814 }
815}
816
817func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
818 var rawMethods [][]byte
819 sd.lazy = new(serviceLazy)
820 for len(b) > 0 {
821 num, typ, n := wire.ConsumeTag(b)
822 b = b[n:]
823 switch typ {
824 case wire.BytesType:
825 v, m := wire.ConsumeBytes(b)
826 b = b[m:]
827 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700828 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800829 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700830 case fieldnum.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800831 sd.lazy.options = append(sd.lazy.options, v...)
832 }
833 default:
834 m := wire.ConsumeFieldValue(num, typ, b)
835 b = b[m:]
836 }
837 }
838
839 if len(rawMethods) > 0 {
840 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
841 for i, b := range rawMethods {
842 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
843 }
844 }
845
846 sd.parentFile.lazy.byName[sd.FullName()] = sd
847}
848
849func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
850 md.parentFile = pf
851 md.parent = pd
852 md.index = i
853
854 for len(b) > 0 {
855 num, typ, n := wire.ConsumeTag(b)
856 b = b[n:]
857 switch typ {
858 case wire.VarintType:
859 v, m := wire.ConsumeVarint(b)
860 b = b[m:]
861 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700862 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800863 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700864 case fieldnum.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800865 md.isStreamingServer = wire.DecodeBool(v)
866 }
867 case wire.BytesType:
868 v, m := wire.ConsumeBytes(b)
869 b = b[m:]
870 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700871 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800872 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700873 case fieldnum.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800874 md.options = append(md.options, v...)
875 }
876 default:
877 m := wire.ConsumeFieldValue(num, typ, b)
878 b = b[m:]
879 }
880 }
881
882 md.parentFile.lazy.byName[md.FullName()] = md
883}