blob: ffcad728d7553493b93da2be2f7988d427f56c87 [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"
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.
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)
Joe Tsai1321a0e2019-03-20 09:46:22 -0700563 case descfield.MessageOptions_MessageSetWireFormat:
564 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800565 }
566 default:
567 m := wire.ConsumeFieldValue(num, typ, b)
568 b = b[m:]
569 }
570 }
571}
572
573func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
574 for len(b) > 0 {
575 num, typ, n := wire.ConsumeTag(b)
576 b = b[n:]
577 switch typ {
578 case wire.VarintType:
579 v, m := wire.ConsumeVarint(b)
580 b = b[m:]
581 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800582 case descfield.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800583 r[0] = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800584 case descfield.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800585 r[1] = pref.FieldNumber(v)
586 }
587 default:
588 m := wire.ConsumeFieldValue(num, typ, b)
589 b = b[m:]
590 }
591 }
592 return r
593}
594
595func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
596 for len(b) > 0 {
597 num, typ, n := wire.ConsumeTag(b)
598 b = b[n:]
599 switch typ {
600 case wire.VarintType:
601 v, m := wire.ConsumeVarint(b)
602 b = b[m:]
603 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800604 case descfield.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800605 r[0] = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800606 case descfield.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800607 r[1] = pref.FieldNumber(v)
608 }
609 case wire.BytesType:
610 v, m := wire.ConsumeBytes(b)
611 b = b[m:]
612 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800613 case descfield.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800614 opts = append(opts, v...)
615 }
616 default:
617 m := wire.ConsumeFieldValue(num, typ, b)
618 b = b[m:]
619 }
620 }
621 return r, opts
622}
623
624func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
625 fd.parentFile = pf
626 fd.parent = pd
627 fd.index = i
628
629 var rawDefVal []byte
630 var rawTypeName []byte
631 for len(b) > 0 {
632 num, typ, n := wire.ConsumeTag(b)
633 b = b[n:]
634 switch typ {
635 case wire.VarintType:
636 v, m := wire.ConsumeVarint(b)
637 b = b[m:]
638 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800639 case descfield.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800640 fd.number = pref.FieldNumber(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800641 case descfield.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800642 fd.cardinality = pref.Cardinality(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800643 case descfield.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800644 fd.kind = pref.Kind(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800645 case descfield.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800646 // In messageDesc.UnmarshalFull, we allocate slices for both
647 // the field and oneof descriptors before unmarshaling either
648 // of them. This ensures pointers to slice elements are stable.
649 od := &pd.(*messageDesc).lazy.oneofs.list[v]
650 od.fields.list = append(od.fields.list, fd)
651 if fd.oneofType != nil {
652 panic("oneof type already set")
653 }
654 fd.oneofType = od
655 }
656 case wire.BytesType:
657 v, m := wire.ConsumeBytes(b)
658 b = b[m:]
659 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800660 case descfield.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800661 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800662 case descfield.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800663 fd.hasJSONName = true
664 fd.jsonName = nb.MakeString(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800665 case descfield.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800666 fd.defVal.has = true
667 rawDefVal = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800668 case descfield.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800669 rawTypeName = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800670 case descfield.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800671 fd.unmarshalOptions(v)
672 }
673 default:
674 m := wire.ConsumeFieldValue(num, typ, b)
675 b = b[m:]
676 }
677 }
678
679 if !fd.hasJSONName {
680 fd.jsonName = nb.MakeJSONName(fd.Name())
681 }
682 if rawDefVal != nil {
683 var err error
684 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
685 if err != nil {
686 panic(err)
687 }
688 }
689 if fd.isWeak {
690 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
691 panic("weak target name must be fully qualified")
692 }
693 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
694 }
695
696 fd.parentFile.lazy.byName[fd.FullName()] = fd
697}
698
699func (fd *fieldDesc) unmarshalOptions(b []byte) {
700 fd.options = append(fd.options, b...)
701 for len(b) > 0 {
702 num, typ, n := wire.ConsumeTag(b)
703 b = b[n:]
704 switch typ {
705 case wire.VarintType:
706 v, m := wire.ConsumeVarint(b)
707 b = b[m:]
708 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800709 case descfield.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800710 fd.hasPacked = true
711 fd.isPacked = wire.DecodeBool(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800712 case descfield.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800713 fd.isWeak = wire.DecodeBool(v)
714 }
715 default:
716 m := wire.ConsumeFieldValue(num, typ, b)
717 b = b[m:]
718 }
719 }
720}
721
722func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
723 od.parentFile = pf
724 od.parent = pd
725 od.index = i
726
727 for len(b) > 0 {
728 num, typ, n := wire.ConsumeTag(b)
729 b = b[n:]
730 switch typ {
731 case wire.BytesType:
732 v, m := wire.ConsumeBytes(b)
733 b = b[m:]
734 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800735 case descfield.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800736 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800737 case descfield.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800738 od.options = append(od.options, v...)
739 }
740 default:
741 m := wire.ConsumeFieldValue(num, typ, b)
742 b = b[m:]
743 }
744 }
745
746 od.parentFile.lazy.byName[od.FullName()] = od
747}
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 Tsai1af1de02019-03-01 16:12:32 -0800760 case descfield.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800761 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800762 case descfield.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 Tsai1af1de02019-03-01 16:12:32 -0800769 case descfield.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800770 xd.lazy.hasJSONName = true
771 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800772 case descfield.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800773 xd.lazy.defVal.has = true
774 rawDefVal = v
Joe Tsai1af1de02019-03-01 16:12:32 -0800775 case descfield.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 }
791
792 xd.parentFile.lazy.byName[xd.FullName()] = xd
793}
794
795func (xd *extensionDesc) unmarshalOptions(b []byte) {
796 xd.lazy.options = append(xd.lazy.options, b...)
797 for len(b) > 0 {
798 num, typ, n := wire.ConsumeTag(b)
799 b = b[n:]
800 switch typ {
801 case wire.VarintType:
802 v, m := wire.ConsumeVarint(b)
803 b = b[m:]
804 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800805 case descfield.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800806 xd.lazy.isPacked = wire.DecodeBool(v)
807 }
808 default:
809 m := wire.ConsumeFieldValue(num, typ, b)
810 b = b[m:]
811 }
812 }
813}
814
815func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
816 var rawMethods [][]byte
817 sd.lazy = new(serviceLazy)
818 for len(b) > 0 {
819 num, typ, n := wire.ConsumeTag(b)
820 b = b[n:]
821 switch typ {
822 case wire.BytesType:
823 v, m := wire.ConsumeBytes(b)
824 b = b[m:]
825 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800826 case descfield.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800827 rawMethods = append(rawMethods, v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800828 case descfield.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800829 sd.lazy.options = append(sd.lazy.options, v...)
830 }
831 default:
832 m := wire.ConsumeFieldValue(num, typ, b)
833 b = b[m:]
834 }
835 }
836
837 if len(rawMethods) > 0 {
838 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
839 for i, b := range rawMethods {
840 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
841 }
842 }
843
844 sd.parentFile.lazy.byName[sd.FullName()] = sd
845}
846
847func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
848 md.parentFile = pf
849 md.parent = pd
850 md.index = i
851
852 for len(b) > 0 {
853 num, typ, n := wire.ConsumeTag(b)
854 b = b[n:]
855 switch typ {
856 case wire.VarintType:
857 v, m := wire.ConsumeVarint(b)
858 b = b[m:]
859 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800860 case descfield.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800861 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800862 case descfield.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800863 md.isStreamingServer = wire.DecodeBool(v)
864 }
865 case wire.BytesType:
866 v, m := wire.ConsumeBytes(b)
867 b = b[m:]
868 switch num {
Joe Tsai1af1de02019-03-01 16:12:32 -0800869 case descfield.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800870 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsai1af1de02019-03-01 16:12:32 -0800871 case descfield.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800872 md.options = append(md.options, v...)
873 }
874 default:
875 m := wire.ConsumeFieldValue(num, typ, b)
876 b = b[m:]
877 }
878 }
879
880 md.parentFile.lazy.byName[md.FullName()] = md
881}