blob: 0e26e17845d69edf812fa864017d0b654e1ee73c [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
Damien Neile89e6242019-05-13 23:55:40 -070012 defval "google.golang.org/protobuf/internal/encoding/defval"
13 wire "google.golang.org/protobuf/internal/encoding/wire"
14 fieldnum "google.golang.org/protobuf/internal/fieldnum"
15 pimpl "google.golang.org/protobuf/internal/impl"
16 ptype "google.golang.org/protobuf/internal/prototype"
17 pvalue "google.golang.org/protobuf/internal/value"
18 pref "google.golang.org/protobuf/reflect/protoreflect"
19 preg "google.golang.org/protobuf/reflect/protoregistry"
Damien Neil8012b442019-01-18 09:32:24 -080020)
21
22func (file *fileDesc) lazyInit() *fileLazy {
23 file.once.Do(func() {
Joe Tsaie089c0f2019-04-16 01:46:14 -070024 file.unmarshalFull(file.rawDesc)
Damien Neil8012b442019-01-18 09:32:24 -080025 file.resolveImports()
26 file.resolveEnums()
27 file.resolveMessages()
28 file.resolveExtensions()
29 file.resolveServices()
30 file.finishInit()
31 })
32 return file.lazy
33}
34
35func (file *fileDesc) resolveImports() {
36 // TODO: Resolve file dependencies.
37}
38
39func (file *fileDesc) resolveEnums() {
40 enumDecls := file.GoTypes[:len(file.allEnums)]
41 for i := range file.allEnums {
42 ed := &file.allEnums[i]
43
44 // Associate the EnumType with a concrete Go type.
45 enumCache := map[pref.EnumNumber]pref.Enum{}
46 ed.lazy.typ = reflect.TypeOf(enumDecls[i])
47 ed.lazy.new = func(n pref.EnumNumber) pref.Enum {
48 if v, ok := enumCache[n]; ok {
49 return v
50 }
51 v := reflect.New(ed.lazy.typ).Elem()
52 v.SetInt(int64(n))
53 return v.Interface().(pref.Enum)
54 }
55 for i := range ed.lazy.values.list {
56 n := ed.lazy.values.list[i].number
57 enumCache[n] = ed.lazy.new(n)
58 }
59 }
60}
61
62func (file *fileDesc) resolveMessages() {
63 messageDecls := file.GoTypes[len(file.allEnums):]
64 for i := range file.allMessages {
65 md := &file.allMessages[i]
66
67 // Associate the MessageType with a concrete Go type.
Joe Tsai4532dd72019-03-19 17:04:06 -070068 if !md.isMapEntry {
69 md.lazy.typ = reflect.TypeOf(messageDecls[i])
70 md.lazy.new = func() pref.Message {
71 t := md.lazy.typ.Elem()
72 return reflect.New(t).Interface().(pref.ProtoMessage).ProtoReflect()
73 }
Damien Neil8012b442019-01-18 09:32:24 -080074 }
75
76 // Resolve message field dependencies.
77 for j := range md.lazy.fields.list {
78 fd := &md.lazy.fields.list[j]
79 if fd.isWeak {
80 continue
81 }
82
83 switch fd.kind {
84 case pref.EnumKind:
85 fd.enumType = file.popEnumDependency()
86 case pref.MessageKind, pref.GroupKind:
87 fd.messageType = file.popMessageDependency()
88 }
89 fd.isMap = file.isMapEntry(fd.messageType)
90 if !fd.hasPacked && file.lazy.syntax != pref.Proto2 && fd.cardinality == pref.Repeated {
91 switch fd.kind {
92 case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
93 fd.isPacked = false
94 default:
95 fd.isPacked = true
96 }
97 }
98 fd.defVal.lazyInit(fd.kind, file.enumValuesOf(fd.enumType))
99 }
100 }
101}
102
103func (file *fileDesc) resolveExtensions() {
Joe Tsaib2f66be2019-05-22 00:42:45 -0400104 // TODO: Delete this and use reflect/prototype instead.
105
Damien Neil8012b442019-01-18 09:32:24 -0800106 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:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700121 et := pimpl.Export{}.EnumTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800122 xd.lazy.typ = typ
123 xd.lazy.new = func() pref.Value {
124 return xd.lazy.defVal.get()
125 }
126 xd.lazy.valueOf = func(v interface{}) pref.Value {
127 ev := v.(pref.Enum)
128 return pref.ValueOf(ev.Number())
129 }
130 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700131 return et.New(pv.Enum())
Damien Neil8012b442019-01-18 09:32:24 -0800132 }
133 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700134 mt := pimpl.Export{}.MessageTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800135 xd.lazy.typ = typ
136 xd.lazy.new = func() pref.Value {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700137 return pref.ValueOf(mt.New())
Damien Neil8012b442019-01-18 09:32:24 -0800138 }
139 xd.lazy.valueOf = func(v interface{}) pref.Value {
140 mv := v.(pref.ProtoMessage).ProtoReflect()
141 return pref.ValueOf(mv)
142 }
143 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
144 return pv.Message().Interface()
145 }
146 default:
147 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
148 xd.lazy.new = func() pref.Value {
149 return xd.lazy.defVal.get()
150 }
151 xd.lazy.valueOf = func(v interface{}) pref.Value {
152 return pref.ValueOf(v)
153 }
154 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
155 return pv.Interface()
156 }
157 }
158 case pref.Repeated:
159 c := pvalue.NewConverter(typ, xd.lazy.kind)
160 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
161 xd.lazy.new = func() pref.Value {
162 v := reflect.New(xd.lazy.typ.Elem()).Interface()
163 return pref.ValueOf(pvalue.ListOf(v, c))
164 }
165 xd.lazy.valueOf = func(v interface{}) pref.Value {
166 return pref.ValueOf(pvalue.ListOf(v, c))
167 }
168 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
169 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
170 }
171 default:
172 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
173 }
174
175 // Resolve extension field dependency.
176 switch xd.lazy.kind {
177 case pref.EnumKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700178 xd.lazy.enumType = file.popEnumDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800179 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700180 xd.lazy.messageType = file.popMessageDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800181 }
182 xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
183 }
184}
185
186var goTypeForPBKind = map[pref.Kind]reflect.Type{
187 pref.BoolKind: reflect.TypeOf(bool(false)),
188 pref.Int32Kind: reflect.TypeOf(int32(0)),
189 pref.Sint32Kind: reflect.TypeOf(int32(0)),
190 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
191 pref.Int64Kind: reflect.TypeOf(int64(0)),
192 pref.Sint64Kind: reflect.TypeOf(int64(0)),
193 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
194 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
195 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
196 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
197 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
198 pref.FloatKind: reflect.TypeOf(float32(0)),
199 pref.DoubleKind: reflect.TypeOf(float64(0)),
200 pref.StringKind: reflect.TypeOf(string("")),
201 pref.BytesKind: reflect.TypeOf([]byte(nil)),
202}
203
204func (file *fileDesc) resolveServices() {
205 for i := range file.services.list {
206 sd := &file.services.list[i]
207
208 // Resolve method dependencies.
209 for j := range sd.lazy.methods.list {
210 md := &sd.lazy.methods.list[j]
211 md.inputType = file.popMessageDependency()
212 md.outputType = file.popMessageDependency()
213 }
214 }
215}
216
217// isMapEntry reports whether the message is a map entry, being careful to
218// avoid calling the IsMapEntry method if the message is declared
219// within the same file (which would cause a recursive init deadlock).
220func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
221 if md == nil {
222 return false
223 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700224 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
225 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800226 }
227 return md.IsMapEntry()
228}
229
230// enumValuesOf retrieves the list of enum values for the given enum,
231// being careful to avoid calling the Values method if the enum is declared
232// within the same file (which would cause a recursive init deadlock).
233func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
234 if ed == nil {
235 return nil
236 }
237 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
238 return &ed.lazy.values
239 }
240 return ed.Values()
241}
242
Joe Tsai4532dd72019-03-19 17:04:06 -0700243func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800244 depIdx := fd.popDependencyIndex()
245 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
246 return &fd.allEnums[depIdx]
247 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700248 return pimpl.Export{}.EnumDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800249 }
250}
251
Joe Tsai4532dd72019-03-19 17:04:06 -0700252func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800253 depIdx := fd.popDependencyIndex()
254 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700255 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800256 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700257 return pimpl.Export{}.MessageDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800258 }
259}
260
261func (fi *fileInit) popDependencyIndex() int {
262 depIdx := fi.DependencyIndexes[0]
263 fi.DependencyIndexes = fi.DependencyIndexes[1:]
264 return int(depIdx)
265}
266
267func (fi *fileInit) finishInit() {
268 if len(fi.DependencyIndexes) > 0 {
269 panic("unused dependencies")
270 }
271 *fi = fileInit{} // clear fileInit for GC to reclaim resources
272}
273
274type defaultValue struct {
275 has bool
276 val pref.Value
277 enum pref.EnumValueDescriptor
278 check func() // only set for non-empty bytes
279}
280
281func (dv *defaultValue) get() pref.Value {
282 if dv.check != nil {
283 dv.check()
284 }
285 return dv.val
286}
287
288func (dv *defaultValue) lazyInit(k pref.Kind, eds pref.EnumValueDescriptors) {
289 if dv.has {
290 switch k {
291 case pref.EnumKind:
292 // File descriptors always store default enums by name.
293 dv.enum = eds.ByName(pref.Name(dv.val.String()))
294 dv.val = pref.ValueOf(dv.enum.Number())
295 case pref.BytesKind:
296 // Store a copy of the default bytes, so that we can detect
297 // accidental mutations of the original value.
298 b := append([]byte(nil), dv.val.Bytes()...)
299 dv.check = func() {
300 if !bytes.Equal(b, dv.val.Bytes()) {
301 // TODO: Avoid panic if we're running with the race detector
302 // and instead spawn a goroutine that periodically resets
303 // this value back to the original to induce a race.
304 panic("detected mutation on the default bytes")
305 }
306 }
307 }
308 } else {
309 switch k {
310 case pref.BoolKind:
311 dv.val = pref.ValueOf(false)
312 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
313 dv.val = pref.ValueOf(int32(0))
314 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
315 dv.val = pref.ValueOf(int64(0))
316 case pref.Uint32Kind, pref.Fixed32Kind:
317 dv.val = pref.ValueOf(uint32(0))
318 case pref.Uint64Kind, pref.Fixed64Kind:
319 dv.val = pref.ValueOf(uint64(0))
320 case pref.FloatKind:
321 dv.val = pref.ValueOf(float32(0))
322 case pref.DoubleKind:
323 dv.val = pref.ValueOf(float64(0))
324 case pref.StringKind:
325 dv.val = pref.ValueOf(string(""))
326 case pref.BytesKind:
327 dv.val = pref.ValueOf([]byte(nil))
328 case pref.EnumKind:
329 dv.enum = eds.Get(0)
330 dv.val = pref.ValueOf(dv.enum.Number())
331 }
332 }
333}
334
335func (fd *fileDesc) unmarshalFull(b []byte) {
336 nb := getNameBuilder()
337 defer putNameBuilder(nb)
338
339 var hasSyntax bool
340 var enumIdx, messageIdx, extensionIdx, serviceIdx int
Damien Neil2300c182019-04-15 13:05:13 -0700341 fd.lazy = &fileLazy{}
Damien Neil8012b442019-01-18 09:32:24 -0800342 for len(b) > 0 {
343 num, typ, n := wire.ConsumeTag(b)
344 b = b[n:]
345 switch typ {
346 case wire.VarintType:
347 v, m := wire.ConsumeVarint(b)
348 b = b[m:]
349 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700350 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800351 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700352 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800353 fd.lazy.imports[v].IsWeak = true
354 }
355 case wire.BytesType:
356 v, m := wire.ConsumeBytes(b)
357 b = b[m:]
358 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700359 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800360 hasSyntax = true
361 switch string(v) {
362 case "proto2":
363 fd.lazy.syntax = pref.Proto2
364 case "proto3":
365 fd.lazy.syntax = pref.Proto3
366 default:
367 panic("invalid syntax")
368 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700369 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800370 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
371 FileDescriptor: ptype.PlaceholderFile(nb.MakeString(v), ""),
372 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700373 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800374 fd.enums.list[enumIdx].unmarshalFull(v, nb)
375 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700376 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800377 fd.messages.list[messageIdx].unmarshalFull(v, nb)
378 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700379 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800380 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
381 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700382 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800383 fd.services.list[serviceIdx].unmarshalFull(v, nb)
384 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700385 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800386 fd.lazy.options = append(fd.lazy.options, v...)
387 }
388 default:
389 m := wire.ConsumeFieldValue(num, typ, b)
390 b = b[m:]
391 }
392 }
393
394 // If syntax is missing, it is assumed to be proto2.
395 if !hasSyntax {
396 fd.lazy.syntax = pref.Proto2
397 }
398}
399
400func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
401 var rawValues [][]byte
402 ed.lazy = new(enumLazy)
403 for len(b) > 0 {
404 num, typ, n := wire.ConsumeTag(b)
405 b = b[n:]
406 switch typ {
407 case wire.BytesType:
408 v, m := wire.ConsumeBytes(b)
409 b = b[m:]
410 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700411 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800412 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700413 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800414 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700415 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800416 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700417 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800418 ed.lazy.options = append(ed.lazy.options, v...)
419 }
420 default:
421 m := wire.ConsumeFieldValue(num, typ, b)
422 b = b[m:]
423 }
424 }
425
426 if len(rawValues) > 0 {
427 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
428 for i, b := range rawValues {
429 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
430 }
431 }
Damien Neil8012b442019-01-18 09:32:24 -0800432}
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 Tsaica46d8c2019-03-20 16:51:09 -0700443 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800444 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700445 case fieldnum.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 Tsaica46d8c2019-03-20 16:51:09 -0700469 case fieldnum.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 Tsaica46d8c2019-03-20 16:51:09 -0700476 case fieldnum.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800477 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700478 case fieldnum.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 }
Damien Neil8012b442019-01-18 09:32:24 -0800486}
487
488func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
489 var rawFields, rawOneofs [][]byte
490 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700491 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800492 md.lazy = new(messageLazy)
493 for len(b) > 0 {
494 num, typ, n := wire.ConsumeTag(b)
495 b = b[n:]
496 switch typ {
497 case wire.BytesType:
498 v, m := wire.ConsumeBytes(b)
499 b = b[m:]
500 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700501 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800502 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700503 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800504 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700505 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800506 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700507 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800508 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700509 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800510 r, opts := unmarshalMessageExtensionRange(v)
511 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
512 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700513 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800514 md.enums.list[enumIdx].unmarshalFull(v, nb)
515 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700516 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800517 md.messages.list[messageIdx].unmarshalFull(v, nb)
518 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700519 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800520 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
521 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700522 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700523 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800524 }
525 default:
526 m := wire.ConsumeFieldValue(num, typ, b)
527 b = b[m:]
528 }
529 }
530
531 if len(rawFields) > 0 || len(rawOneofs) > 0 {
532 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
533 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
534 for i, b := range rawFields {
535 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700536 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800537 if fd.cardinality == pref.Required {
538 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
539 }
540 }
541 for i, b := range rawOneofs {
542 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700543 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800544 }
545 }
546
Joe Tsai4532dd72019-03-19 17:04:06 -0700547 if isMapEntry != md.isMapEntry {
548 panic("mismatching map entry property")
549 }
Damien Neil8012b442019-01-18 09:32:24 -0800550}
551
Joe Tsai4532dd72019-03-19 17:04:06 -0700552func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800553 md.lazy.options = append(md.lazy.options, b...)
554 for len(b) > 0 {
555 num, typ, n := wire.ConsumeTag(b)
556 b = b[n:]
557 switch typ {
558 case wire.VarintType:
559 v, m := wire.ConsumeVarint(b)
560 b = b[m:]
561 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700562 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700563 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700564 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700565 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800566 }
567 default:
568 m := wire.ConsumeFieldValue(num, typ, b)
569 b = b[m:]
570 }
571 }
572}
573
574func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
575 for len(b) > 0 {
576 num, typ, n := wire.ConsumeTag(b)
577 b = b[n:]
578 switch typ {
579 case wire.VarintType:
580 v, m := wire.ConsumeVarint(b)
581 b = b[m:]
582 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700583 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800584 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700585 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800586 r[1] = pref.FieldNumber(v)
587 }
588 default:
589 m := wire.ConsumeFieldValue(num, typ, b)
590 b = b[m:]
591 }
592 }
593 return r
594}
595
596func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
597 for len(b) > 0 {
598 num, typ, n := wire.ConsumeTag(b)
599 b = b[n:]
600 switch typ {
601 case wire.VarintType:
602 v, m := wire.ConsumeVarint(b)
603 b = b[m:]
604 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700605 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800606 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700607 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800608 r[1] = pref.FieldNumber(v)
609 }
610 case wire.BytesType:
611 v, m := wire.ConsumeBytes(b)
612 b = b[m:]
613 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700614 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800615 opts = append(opts, v...)
616 }
617 default:
618 m := wire.ConsumeFieldValue(num, typ, b)
619 b = b[m:]
620 }
621 }
622 return r, opts
623}
624
625func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
626 fd.parentFile = pf
627 fd.parent = pd
628 fd.index = i
629
630 var rawDefVal []byte
631 var rawTypeName []byte
632 for len(b) > 0 {
633 num, typ, n := wire.ConsumeTag(b)
634 b = b[n:]
635 switch typ {
636 case wire.VarintType:
637 v, m := wire.ConsumeVarint(b)
638 b = b[m:]
639 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700640 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800641 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700642 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800643 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700644 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800645 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700646 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800647 // In messageDesc.UnmarshalFull, we allocate slices for both
648 // the field and oneof descriptors before unmarshaling either
649 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700650 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800651 od.fields.list = append(od.fields.list, fd)
652 if fd.oneofType != nil {
653 panic("oneof type already set")
654 }
655 fd.oneofType = od
656 }
657 case wire.BytesType:
658 v, m := wire.ConsumeBytes(b)
659 b = b[m:]
660 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700661 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800662 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700663 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800664 fd.hasJSONName = true
665 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700666 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800667 fd.defVal.has = true
668 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700669 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800670 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700671 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800672 fd.unmarshalOptions(v)
673 }
674 default:
675 m := wire.ConsumeFieldValue(num, typ, b)
676 b = b[m:]
677 }
678 }
679
680 if !fd.hasJSONName {
681 fd.jsonName = nb.MakeJSONName(fd.Name())
682 }
683 if rawDefVal != nil {
684 var err error
685 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
686 if err != nil {
687 panic(err)
688 }
689 }
690 if fd.isWeak {
691 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
692 panic("weak target name must be fully qualified")
693 }
Damien Neil82a03062019-05-08 07:52:49 -0700694 // Consult the global registry for weak messages.
695 name := pref.FullName(rawTypeName[1:])
696 fd.messageType, _ = preg.GlobalFiles.FindMessageByName(name)
697 if fd.messageType == nil {
698 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
699 }
Damien Neil8012b442019-01-18 09:32:24 -0800700 }
Damien Neil8012b442019-01-18 09:32:24 -0800701}
702
703func (fd *fieldDesc) unmarshalOptions(b []byte) {
704 fd.options = append(fd.options, b...)
705 for len(b) > 0 {
706 num, typ, n := wire.ConsumeTag(b)
707 b = b[n:]
708 switch typ {
709 case wire.VarintType:
710 v, m := wire.ConsumeVarint(b)
711 b = b[m:]
712 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700713 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800714 fd.hasPacked = true
715 fd.isPacked = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700716 case fieldnum.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800717 fd.isWeak = wire.DecodeBool(v)
718 }
719 default:
720 m := wire.ConsumeFieldValue(num, typ, b)
721 b = b[m:]
722 }
723 }
724}
725
726func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
727 od.parentFile = pf
728 od.parent = pd
729 od.index = i
730
731 for len(b) > 0 {
732 num, typ, n := wire.ConsumeTag(b)
733 b = b[n:]
734 switch typ {
735 case wire.BytesType:
736 v, m := wire.ConsumeBytes(b)
737 b = b[m:]
738 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700739 case fieldnum.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800740 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700741 case fieldnum.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800742 od.options = append(od.options, v...)
743 }
744 default:
745 m := wire.ConsumeFieldValue(num, typ, b)
746 b = b[m:]
747 }
748 }
Damien Neil8012b442019-01-18 09:32:24 -0800749}
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 }
Damien Neil8012b442019-01-18 09:32:24 -0800793}
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 Tsaica46d8c2019-03-20 16:51:09 -0700805 case fieldnum.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 Tsaica46d8c2019-03-20 16:51:09 -0700826 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800827 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700828 case fieldnum.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 }
Damien Neil8012b442019-01-18 09:32:24 -0800843}
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 Tsaica46d8c2019-03-20 16:51:09 -0700858 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800859 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700860 case fieldnum.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 Tsaica46d8c2019-03-20 16:51:09 -0700867 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800868 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700869 case fieldnum.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 }
Damien Neil8012b442019-01-18 09:32:24 -0800877}