blob: 2f7d3caac07e0ca367bd661fee3c549870a6bbf6 [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
Joe Tsai1af1de02019-03-01 16:12:32 -080012 descfield "github.com/golang/protobuf/v2/internal/descfield"
Damien Neil8012b442019-01-18 09:32:24 -080013 defval "github.com/golang/protobuf/v2/internal/encoding/defval"
14 wire "github.com/golang/protobuf/v2/internal/encoding/wire"
15 pimpl "github.com/golang/protobuf/v2/internal/impl"
16 pvalue "github.com/golang/protobuf/v2/internal/value"
17 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
18 ptype "github.com/golang/protobuf/v2/reflect/prototype"
19)
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.
67 //
68 // Note that descriptors for map entries, which have no associated
69 // Go type, also implement the protoreflect.MessageType interface,
70 // but have a GoType accessor that reports nil. Calling New results
71 // in a panic, which is sensible behavior.
72 md.lazy.typ = reflect.TypeOf(messageDecls[i])
73 md.lazy.new = func() pref.Message {
74 t := md.lazy.typ.Elem()
75 return reflect.New(t).Interface().(pref.ProtoMessage).ProtoReflect()
76 }
77
78 // Resolve message field dependencies.
79 for j := range md.lazy.fields.list {
80 fd := &md.lazy.fields.list[j]
81 if fd.isWeak {
82 continue
83 }
84
85 switch fd.kind {
86 case pref.EnumKind:
87 fd.enumType = file.popEnumDependency()
88 case pref.MessageKind, pref.GroupKind:
89 fd.messageType = file.popMessageDependency()
90 }
91 fd.isMap = file.isMapEntry(fd.messageType)
92 if !fd.hasPacked && file.lazy.syntax != pref.Proto2 && fd.cardinality == pref.Repeated {
93 switch fd.kind {
94 case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
95 fd.isPacked = false
96 default:
97 fd.isPacked = true
98 }
99 }
100 fd.defVal.lazyInit(fd.kind, file.enumValuesOf(fd.enumType))
101 }
102 }
103}
104
105func (file *fileDesc) resolveExtensions() {
106 for i := range file.allExtensions {
107 xd := &file.allExtensions[i]
108
109 // Associate the ExtensionType with a concrete Go type.
110 var typ reflect.Type
111 switch xd.lazy.kind {
112 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
113 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
114 default:
115 typ = goTypeForPBKind[xd.lazy.kind]
116 }
117 switch xd.lazy.cardinality {
118 case pref.Optional:
119 switch xd.lazy.kind {
120 case pref.EnumKind:
121 xd.lazy.typ = typ
122 xd.lazy.new = func() pref.Value {
123 return xd.lazy.defVal.get()
124 }
125 xd.lazy.valueOf = func(v interface{}) pref.Value {
126 ev := v.(pref.Enum)
127 return pref.ValueOf(ev.Number())
128 }
129 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
130 return xd.lazy.enumType.New(pv.Enum())
131 }
132 case pref.MessageKind, pref.GroupKind:
133 xd.lazy.typ = typ
134 xd.lazy.new = func() pref.Value {
135 return pref.ValueOf(xd.lazy.messageType.New())
136 }
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:
176 xd.lazy.enumType = file.popEnumDependency()
177 case pref.MessageKind, pref.GroupKind:
178 xd.lazy.messageType = file.popMessageDependency()
179 }
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 }
222 if md, ok := md.(*messageDesc); ok && md.parentFile == fd {
223 return md.lazy.isMapEntry
224 }
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
241func (fd *fileDesc) popEnumDependency() pref.EnumType {
242 depIdx := fd.popDependencyIndex()
243 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
244 return &fd.allEnums[depIdx]
245 } else {
246 return pimpl.Export{}.EnumTypeOf(fd.GoTypes[depIdx])
247 }
248}
249
250func (fd *fileDesc) popMessageDependency() pref.MessageType {
251 depIdx := fd.popDependencyIndex()
252 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
253 return &fd.allMessages[depIdx-len(fd.allEnums)]
254 } else {
255 return pimpl.Export{}.MessageTypeOf(fd.GoTypes[depIdx])
256 }
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
339 fd.lazy = &fileLazy{byName: make(map[pref.FullName]pref.Descriptor)}
340 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 Tsai1af1de02019-03-01 16:12:32 -0800348 case descfield.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800349 fd.lazy.imports[v].IsPublic = true
Joe Tsai1af1de02019-03-01 16:12:32 -0800350 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800357 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800367 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800371 case descfield.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800372 fd.enums.list[enumIdx].unmarshalFull(v, nb)
373 enumIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800374 case descfield.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800375 fd.messages.list[messageIdx].unmarshalFull(v, nb)
376 messageIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800377 case descfield.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800378 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
379 extensionIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800380 case descfield.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800381 fd.services.list[serviceIdx].unmarshalFull(v, nb)
382 serviceIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800383 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800409 case descfield.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800410 rawValues = append(rawValues, v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800411 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800413 case descfield.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800414 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsai1af1de02019-03-01 16:12:32 -0800415 case descfield.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 }
430
431 ed.parentFile.lazy.byName[ed.FullName()] = ed
432}
433
434func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
435 for len(b) > 0 {
436 num, typ, n := wire.ConsumeTag(b)
437 b = b[n:]
438 switch typ {
439 case wire.VarintType:
440 v, m := wire.ConsumeVarint(b)
441 b = b[m:]
442 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800443 case descfield.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800444 r[0] = pref.EnumNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800445 case descfield.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800446 r[1] = pref.EnumNumber(v)
447 }
448 default:
449 m := wire.ConsumeFieldValue(num, typ, b)
450 b = b[m:]
451 }
452 }
453 return r
454}
455
456func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
457 vd.parentFile = pf
458 vd.parent = pd
459 vd.index = i
460
461 for len(b) > 0 {
462 num, typ, n := wire.ConsumeTag(b)
463 b = b[n:]
464 switch typ {
465 case wire.VarintType:
466 v, m := wire.ConsumeVarint(b)
467 b = b[m:]
468 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800469 case descfield.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800470 vd.number = pref.EnumNumber(v)
471 }
472 case wire.BytesType:
473 v, m := wire.ConsumeBytes(b)
474 b = b[m:]
475 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800476 case descfield.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800477 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800478 case descfield.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800479 vd.options = append(vd.options, v...)
480 }
481 default:
482 m := wire.ConsumeFieldValue(num, typ, b)
483 b = b[m:]
484 }
485 }
486
487 vd.parentFile.lazy.byName[vd.FullName()] = vd
488}
489
490func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
491 var rawFields, rawOneofs [][]byte
492 var enumIdx, messageIdx, extensionIdx int
493 md.lazy = new(messageLazy)
494 for len(b) > 0 {
495 num, typ, n := wire.ConsumeTag(b)
496 b = b[n:]
497 switch typ {
498 case wire.BytesType:
499 v, m := wire.ConsumeBytes(b)
500 b = b[m:]
501 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800502 case descfield.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800503 rawFields = append(rawFields, v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800504 case descfield.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800505 rawOneofs = append(rawOneofs, v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800506 case descfield.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800507 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsai1af1de02019-03-01 16:12:32 -0800508 case descfield.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800509 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsai1af1de02019-03-01 16:12:32 -0800510 case descfield.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800511 r, opts := unmarshalMessageExtensionRange(v)
512 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
513 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsai1af1de02019-03-01 16:12:32 -0800514 case descfield.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800515 md.enums.list[enumIdx].unmarshalFull(v, nb)
516 enumIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800517 case descfield.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800518 md.messages.list[messageIdx].unmarshalFull(v, nb)
519 messageIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800520 case descfield.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800521 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
522 extensionIdx++
Joe Tsai1af1de02019-03-01 16:12:32 -0800523 case descfield.DescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800524 md.unmarshalOptions(v)
525 }
526 default:
527 m := wire.ConsumeFieldValue(num, typ, b)
528 b = b[m:]
529 }
530 }
531
532 if len(rawFields) > 0 || len(rawOneofs) > 0 {
533 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
534 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
535 for i, b := range rawFields {
536 fd := &md.lazy.fields.list[i]
537 fd.unmarshalFull(b, nb, md.parentFile, md, i)
538 if fd.cardinality == pref.Required {
539 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
540 }
541 }
542 for i, b := range rawOneofs {
543 od := &md.lazy.oneofs.list[i]
544 od.unmarshalFull(b, nb, md.parentFile, md, i)
545 }
546 }
547
548 md.parentFile.lazy.byName[md.FullName()] = md
549}
550
551func (md *messageDesc) unmarshalOptions(b []byte) {
552 md.lazy.options = append(md.lazy.options, b...)
553 for len(b) > 0 {
554 num, typ, n := wire.ConsumeTag(b)
555 b = b[n:]
556 switch typ {
557 case wire.VarintType:
558 v, m := wire.ConsumeVarint(b)
559 b = b[m:]
560 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800561 case descfield.MessageOptions_MapEntry:
Damien Neil8012b442019-01-18 09:32:24 -0800562 md.lazy.isMapEntry = wire.DecodeBool(v)
563 }
564 default:
565 m := wire.ConsumeFieldValue(num, typ, b)
566 b = b[m:]
567 }
568 }
569}
570
571func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
572 for len(b) > 0 {
573 num, typ, n := wire.ConsumeTag(b)
574 b = b[n:]
575 switch typ {
576 case wire.VarintType:
577 v, m := wire.ConsumeVarint(b)
578 b = b[m:]
579 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800580 case descfield.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800581 r[0] = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800582 case descfield.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800583 r[1] = pref.FieldNumber(v)
584 }
585 default:
586 m := wire.ConsumeFieldValue(num, typ, b)
587 b = b[m:]
588 }
589 }
590 return r
591}
592
593func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
594 for len(b) > 0 {
595 num, typ, n := wire.ConsumeTag(b)
596 b = b[n:]
597 switch typ {
598 case wire.VarintType:
599 v, m := wire.ConsumeVarint(b)
600 b = b[m:]
601 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800602 case descfield.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800603 r[0] = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800604 case descfield.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800605 r[1] = pref.FieldNumber(v)
606 }
607 case wire.BytesType:
608 v, m := wire.ConsumeBytes(b)
609 b = b[m:]
610 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800611 case descfield.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800612 opts = append(opts, v...)
613 }
614 default:
615 m := wire.ConsumeFieldValue(num, typ, b)
616 b = b[m:]
617 }
618 }
619 return r, opts
620}
621
622func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
623 fd.parentFile = pf
624 fd.parent = pd
625 fd.index = i
626
627 var rawDefVal []byte
628 var rawTypeName []byte
629 for len(b) > 0 {
630 num, typ, n := wire.ConsumeTag(b)
631 b = b[n:]
632 switch typ {
633 case wire.VarintType:
634 v, m := wire.ConsumeVarint(b)
635 b = b[m:]
636 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800637 case descfield.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800638 fd.number = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800639 case descfield.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800640 fd.cardinality = pref.Cardinality(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800641 case descfield.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800642 fd.kind = pref.Kind(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800643 case descfield.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800644 // In messageDesc.UnmarshalFull, we allocate slices for both
645 // the field and oneof descriptors before unmarshaling either
646 // of them. This ensures pointers to slice elements are stable.
647 od := &pd.(*messageDesc).lazy.oneofs.list[v]
648 od.fields.list = append(od.fields.list, fd)
649 if fd.oneofType != nil {
650 panic("oneof type already set")
651 }
652 fd.oneofType = od
653 }
654 case wire.BytesType:
655 v, m := wire.ConsumeBytes(b)
656 b = b[m:]
657 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800658 case descfield.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800659 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800660 case descfield.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800661 fd.hasJSONName = true
662 fd.jsonName = nb.MakeString(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800663 case descfield.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800664 fd.defVal.has = true
665 rawDefVal = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800666 case descfield.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800667 rawTypeName = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800668 case descfield.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800669 fd.unmarshalOptions(v)
670 }
671 default:
672 m := wire.ConsumeFieldValue(num, typ, b)
673 b = b[m:]
674 }
675 }
676
677 if !fd.hasJSONName {
678 fd.jsonName = nb.MakeJSONName(fd.Name())
679 }
680 if rawDefVal != nil {
681 var err error
682 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
683 if err != nil {
684 panic(err)
685 }
686 }
687 if fd.isWeak {
688 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
689 panic("weak target name must be fully qualified")
690 }
691 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
692 }
693
694 fd.parentFile.lazy.byName[fd.FullName()] = fd
695}
696
697func (fd *fieldDesc) unmarshalOptions(b []byte) {
698 fd.options = append(fd.options, b...)
699 for len(b) > 0 {
700 num, typ, n := wire.ConsumeTag(b)
701 b = b[n:]
702 switch typ {
703 case wire.VarintType:
704 v, m := wire.ConsumeVarint(b)
705 b = b[m:]
706 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800707 case descfield.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800708 fd.hasPacked = true
709 fd.isPacked = wire.DecodeBool(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800710 case descfield.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800711 fd.isWeak = wire.DecodeBool(v)
712 }
713 default:
714 m := wire.ConsumeFieldValue(num, typ, b)
715 b = b[m:]
716 }
717 }
718}
719
720func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
721 od.parentFile = pf
722 od.parent = pd
723 od.index = i
724
725 for len(b) > 0 {
726 num, typ, n := wire.ConsumeTag(b)
727 b = b[n:]
728 switch typ {
729 case wire.BytesType:
730 v, m := wire.ConsumeBytes(b)
731 b = b[m:]
732 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800733 case descfield.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800734 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800735 case descfield.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800736 od.options = append(od.options, v...)
737 }
738 default:
739 m := wire.ConsumeFieldValue(num, typ, b)
740 b = b[m:]
741 }
742 }
743
744 od.parentFile.lazy.byName[od.FullName()] = od
745}
746
747func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
748 var rawDefVal []byte
749 xd.lazy = new(extensionLazy)
750 for len(b) > 0 {
751 num, typ, n := wire.ConsumeTag(b)
752 b = b[n:]
753 switch typ {
754 case wire.VarintType:
755 v, m := wire.ConsumeVarint(b)
756 b = b[m:]
757 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800758 case descfield.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800759 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800760 case descfield.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800761 xd.lazy.kind = pref.Kind(v)
762 }
763 case wire.BytesType:
764 v, m := wire.ConsumeBytes(b)
765 b = b[m:]
766 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800767 case descfield.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800768 xd.lazy.hasJSONName = true
769 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800770 case descfield.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800771 xd.lazy.defVal.has = true
772 rawDefVal = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800773 case descfield.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800774 xd.unmarshalOptions(v)
775 }
776 default:
777 m := wire.ConsumeFieldValue(num, typ, b)
778 b = b[m:]
779 }
780 }
781
782 if rawDefVal != nil {
783 var err error
784 xd.lazy.defVal.val, err = defval.Unmarshal(string(rawDefVal), xd.lazy.kind, defval.Descriptor)
785 if err != nil {
786 panic(err)
787 }
788 }
789
790 xd.parentFile.lazy.byName[xd.FullName()] = xd
791}
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 Tsai1af1de02019-03-01 16:12:32 -0800803 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800824 case descfield.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800825 rawMethods = append(rawMethods, v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800826 case descfield.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 }
841
842 sd.parentFile.lazy.byName[sd.FullName()] = sd
843}
844
845func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
846 md.parentFile = pf
847 md.parent = pd
848 md.index = i
849
850 for len(b) > 0 {
851 num, typ, n := wire.ConsumeTag(b)
852 b = b[n:]
853 switch typ {
854 case wire.VarintType:
855 v, m := wire.ConsumeVarint(b)
856 b = b[m:]
857 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800858 case descfield.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800859 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800860 case descfield.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800861 md.isStreamingServer = wire.DecodeBool(v)
862 }
863 case wire.BytesType:
864 v, m := wire.ConsumeBytes(b)
865 b = b[m:]
866 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800867 case descfield.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800868 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800869 case descfield.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800870 md.options = append(md.options, v...)
871 }
872 default:
873 m := wire.ConsumeFieldValue(num, typ, b)
874 b = b[m:]
875 }
876 }
877
878 md.parentFile.lazy.byName[md.FullName()] = md
879}