blob: bbcc9d9b015e5763b58d26c8b8c0d3ca29f41364 [file] [log] [blame]
Damien Neil8012b442019-01-18 09:32:24 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package fileinit
6
7import (
8 "bytes"
9 "fmt"
10 "reflect"
11
12 defval "github.com/golang/protobuf/v2/internal/encoding/defval"
13 wire "github.com/golang/protobuf/v2/internal/encoding/wire"
Joe Tsaica46d8c2019-03-20 16:51:09 -070014 fieldnum "github.com/golang/protobuf/v2/internal/fieldnum"
Damien Neil8012b442019-01-18 09:32:24 -080015 pimpl "github.com/golang/protobuf/v2/internal/impl"
Joe Tsai990b9f52019-03-13 12:56:39 -070016 ptype "github.com/golang/protobuf/v2/internal/prototype"
Damien Neil8012b442019-01-18 09:32:24 -080017 pvalue "github.com/golang/protobuf/v2/internal/value"
18 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Damien Neil8012b442019-01-18 09:32:24 -080019)
20
21func (file *fileDesc) lazyInit() *fileLazy {
22 file.once.Do(func() {
23 file.unmarshalFull(file.RawDescriptor)
24 file.resolveImports()
25 file.resolveEnums()
26 file.resolveMessages()
27 file.resolveExtensions()
28 file.resolveServices()
29 file.finishInit()
30 })
31 return file.lazy
32}
33
34func (file *fileDesc) resolveImports() {
35 // TODO: Resolve file dependencies.
36}
37
38func (file *fileDesc) resolveEnums() {
39 enumDecls := file.GoTypes[:len(file.allEnums)]
40 for i := range file.allEnums {
41 ed := &file.allEnums[i]
42
43 // Associate the EnumType with a concrete Go type.
44 enumCache := map[pref.EnumNumber]pref.Enum{}
45 ed.lazy.typ = reflect.TypeOf(enumDecls[i])
46 ed.lazy.new = func(n pref.EnumNumber) pref.Enum {
47 if v, ok := enumCache[n]; ok {
48 return v
49 }
50 v := reflect.New(ed.lazy.typ).Elem()
51 v.SetInt(int64(n))
52 return v.Interface().(pref.Enum)
53 }
54 for i := range ed.lazy.values.list {
55 n := ed.lazy.values.list[i].number
56 enumCache[n] = ed.lazy.new(n)
57 }
58 }
59}
60
61func (file *fileDesc) resolveMessages() {
62 messageDecls := file.GoTypes[len(file.allEnums):]
63 for i := range file.allMessages {
64 md := &file.allMessages[i]
65
66 // Associate the MessageType with a concrete Go type.
Joe Tsai4532dd72019-03-19 17:04:06 -070067 if !md.isMapEntry {
68 md.lazy.typ = reflect.TypeOf(messageDecls[i])
69 md.lazy.new = func() pref.Message {
70 t := md.lazy.typ.Elem()
71 return reflect.New(t).Interface().(pref.ProtoMessage).ProtoReflect()
72 }
Damien Neil8012b442019-01-18 09:32:24 -080073 }
74
75 // Resolve message field dependencies.
76 for j := range md.lazy.fields.list {
77 fd := &md.lazy.fields.list[j]
78 if fd.isWeak {
79 continue
80 }
81
82 switch fd.kind {
83 case pref.EnumKind:
84 fd.enumType = file.popEnumDependency()
85 case pref.MessageKind, pref.GroupKind:
86 fd.messageType = file.popMessageDependency()
87 }
88 fd.isMap = file.isMapEntry(fd.messageType)
89 if !fd.hasPacked && file.lazy.syntax != pref.Proto2 && fd.cardinality == pref.Repeated {
90 switch fd.kind {
91 case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
92 fd.isPacked = false
93 default:
94 fd.isPacked = true
95 }
96 }
97 fd.defVal.lazyInit(fd.kind, file.enumValuesOf(fd.enumType))
98 }
99 }
100}
101
102func (file *fileDesc) resolveExtensions() {
103 for i := range file.allExtensions {
104 xd := &file.allExtensions[i]
105
106 // Associate the ExtensionType with a concrete Go type.
107 var typ reflect.Type
108 switch xd.lazy.kind {
109 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
110 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
111 default:
112 typ = goTypeForPBKind[xd.lazy.kind]
113 }
114 switch xd.lazy.cardinality {
115 case pref.Optional:
116 switch xd.lazy.kind {
117 case pref.EnumKind:
118 xd.lazy.typ = typ
119 xd.lazy.new = func() pref.Value {
120 return xd.lazy.defVal.get()
121 }
122 xd.lazy.valueOf = func(v interface{}) pref.Value {
123 ev := v.(pref.Enum)
124 return pref.ValueOf(ev.Number())
125 }
126 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
127 return xd.lazy.enumType.New(pv.Enum())
128 }
129 case pref.MessageKind, pref.GroupKind:
130 xd.lazy.typ = typ
131 xd.lazy.new = func() pref.Value {
132 return pref.ValueOf(xd.lazy.messageType.New())
133 }
134 xd.lazy.valueOf = func(v interface{}) pref.Value {
135 mv := v.(pref.ProtoMessage).ProtoReflect()
136 return pref.ValueOf(mv)
137 }
138 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
139 return pv.Message().Interface()
140 }
141 default:
142 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
143 xd.lazy.new = func() pref.Value {
144 return xd.lazy.defVal.get()
145 }
146 xd.lazy.valueOf = func(v interface{}) pref.Value {
147 return pref.ValueOf(v)
148 }
149 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
150 return pv.Interface()
151 }
152 }
153 case pref.Repeated:
154 c := pvalue.NewConverter(typ, xd.lazy.kind)
155 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
156 xd.lazy.new = func() pref.Value {
157 v := reflect.New(xd.lazy.typ.Elem()).Interface()
158 return pref.ValueOf(pvalue.ListOf(v, c))
159 }
160 xd.lazy.valueOf = func(v interface{}) pref.Value {
161 return pref.ValueOf(pvalue.ListOf(v, c))
162 }
163 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
164 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
165 }
166 default:
167 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
168 }
169
170 // Resolve extension field dependency.
171 switch xd.lazy.kind {
172 case pref.EnumKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700173 xd.lazy.enumType = file.popEnumDependency().(pref.EnumType)
Damien Neil8012b442019-01-18 09:32:24 -0800174 case pref.MessageKind, pref.GroupKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700175 xd.lazy.messageType = file.popMessageDependency().(pref.MessageType)
Damien Neil8012b442019-01-18 09:32:24 -0800176 }
177 xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
178 }
179}
180
181var goTypeForPBKind = map[pref.Kind]reflect.Type{
182 pref.BoolKind: reflect.TypeOf(bool(false)),
183 pref.Int32Kind: reflect.TypeOf(int32(0)),
184 pref.Sint32Kind: reflect.TypeOf(int32(0)),
185 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
186 pref.Int64Kind: reflect.TypeOf(int64(0)),
187 pref.Sint64Kind: reflect.TypeOf(int64(0)),
188 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
189 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
190 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
191 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
192 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
193 pref.FloatKind: reflect.TypeOf(float32(0)),
194 pref.DoubleKind: reflect.TypeOf(float64(0)),
195 pref.StringKind: reflect.TypeOf(string("")),
196 pref.BytesKind: reflect.TypeOf([]byte(nil)),
197}
198
199func (file *fileDesc) resolveServices() {
200 for i := range file.services.list {
201 sd := &file.services.list[i]
202
203 // Resolve method dependencies.
204 for j := range sd.lazy.methods.list {
205 md := &sd.lazy.methods.list[j]
206 md.inputType = file.popMessageDependency()
207 md.outputType = file.popMessageDependency()
208 }
209 }
210}
211
212// isMapEntry reports whether the message is a map entry, being careful to
213// avoid calling the IsMapEntry method if the message is declared
214// within the same file (which would cause a recursive init deadlock).
215func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
216 if md == nil {
217 return false
218 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700219 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
220 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800221 }
222 return md.IsMapEntry()
223}
224
225// enumValuesOf retrieves the list of enum values for the given enum,
226// being careful to avoid calling the Values method if the enum is declared
227// within the same file (which would cause a recursive init deadlock).
228func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
229 if ed == nil {
230 return nil
231 }
232 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
233 return &ed.lazy.values
234 }
235 return ed.Values()
236}
237
Joe Tsai4532dd72019-03-19 17:04:06 -0700238func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800239 depIdx := fd.popDependencyIndex()
240 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
241 return &fd.allEnums[depIdx]
242 } else {
243 return pimpl.Export{}.EnumTypeOf(fd.GoTypes[depIdx])
244 }
245}
246
Joe Tsai4532dd72019-03-19 17:04:06 -0700247func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800248 depIdx := fd.popDependencyIndex()
249 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700250 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800251 } else {
252 return pimpl.Export{}.MessageTypeOf(fd.GoTypes[depIdx])
253 }
254}
255
256func (fi *fileInit) popDependencyIndex() int {
257 depIdx := fi.DependencyIndexes[0]
258 fi.DependencyIndexes = fi.DependencyIndexes[1:]
259 return int(depIdx)
260}
261
262func (fi *fileInit) finishInit() {
263 if len(fi.DependencyIndexes) > 0 {
264 panic("unused dependencies")
265 }
266 *fi = fileInit{} // clear fileInit for GC to reclaim resources
267}
268
269type defaultValue struct {
270 has bool
271 val pref.Value
272 enum pref.EnumValueDescriptor
273 check func() // only set for non-empty bytes
274}
275
276func (dv *defaultValue) get() pref.Value {
277 if dv.check != nil {
278 dv.check()
279 }
280 return dv.val
281}
282
283func (dv *defaultValue) lazyInit(k pref.Kind, eds pref.EnumValueDescriptors) {
284 if dv.has {
285 switch k {
286 case pref.EnumKind:
287 // File descriptors always store default enums by name.
288 dv.enum = eds.ByName(pref.Name(dv.val.String()))
289 dv.val = pref.ValueOf(dv.enum.Number())
290 case pref.BytesKind:
291 // Store a copy of the default bytes, so that we can detect
292 // accidental mutations of the original value.
293 b := append([]byte(nil), dv.val.Bytes()...)
294 dv.check = func() {
295 if !bytes.Equal(b, dv.val.Bytes()) {
296 // TODO: Avoid panic if we're running with the race detector
297 // and instead spawn a goroutine that periodically resets
298 // this value back to the original to induce a race.
299 panic("detected mutation on the default bytes")
300 }
301 }
302 }
303 } else {
304 switch k {
305 case pref.BoolKind:
306 dv.val = pref.ValueOf(false)
307 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
308 dv.val = pref.ValueOf(int32(0))
309 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
310 dv.val = pref.ValueOf(int64(0))
311 case pref.Uint32Kind, pref.Fixed32Kind:
312 dv.val = pref.ValueOf(uint32(0))
313 case pref.Uint64Kind, pref.Fixed64Kind:
314 dv.val = pref.ValueOf(uint64(0))
315 case pref.FloatKind:
316 dv.val = pref.ValueOf(float32(0))
317 case pref.DoubleKind:
318 dv.val = pref.ValueOf(float64(0))
319 case pref.StringKind:
320 dv.val = pref.ValueOf(string(""))
321 case pref.BytesKind:
322 dv.val = pref.ValueOf([]byte(nil))
323 case pref.EnumKind:
324 dv.enum = eds.Get(0)
325 dv.val = pref.ValueOf(dv.enum.Number())
326 }
327 }
328}
329
330func (fd *fileDesc) unmarshalFull(b []byte) {
331 nb := getNameBuilder()
332 defer putNameBuilder(nb)
333
334 var hasSyntax bool
335 var enumIdx, messageIdx, extensionIdx, serviceIdx int
Damien Neil2300c182019-04-15 13:05:13 -0700336 fd.lazy = &fileLazy{}
Damien Neil8012b442019-01-18 09:32:24 -0800337 for len(b) > 0 {
338 num, typ, n := wire.ConsumeTag(b)
339 b = b[n:]
340 switch typ {
341 case wire.VarintType:
342 v, m := wire.ConsumeVarint(b)
343 b = b[m:]
344 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700345 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800346 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700347 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800348 fd.lazy.imports[v].IsWeak = true
349 }
350 case wire.BytesType:
351 v, m := wire.ConsumeBytes(b)
352 b = b[m:]
353 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700354 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800355 hasSyntax = true
356 switch string(v) {
357 case "proto2":
358 fd.lazy.syntax = pref.Proto2
359 case "proto3":
360 fd.lazy.syntax = pref.Proto3
361 default:
362 panic("invalid syntax")
363 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700364 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800365 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
366 FileDescriptor: ptype.PlaceholderFile(nb.MakeString(v), ""),
367 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700368 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800369 fd.enums.list[enumIdx].unmarshalFull(v, nb)
370 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700371 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800372 fd.messages.list[messageIdx].unmarshalFull(v, nb)
373 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700374 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800375 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
376 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700377 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800378 fd.services.list[serviceIdx].unmarshalFull(v, nb)
379 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700380 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800381 fd.lazy.options = append(fd.lazy.options, v...)
382 }
383 default:
384 m := wire.ConsumeFieldValue(num, typ, b)
385 b = b[m:]
386 }
387 }
388
389 // If syntax is missing, it is assumed to be proto2.
390 if !hasSyntax {
391 fd.lazy.syntax = pref.Proto2
392 }
393}
394
395func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
396 var rawValues [][]byte
397 ed.lazy = new(enumLazy)
398 for len(b) > 0 {
399 num, typ, n := wire.ConsumeTag(b)
400 b = b[n:]
401 switch typ {
402 case wire.BytesType:
403 v, m := wire.ConsumeBytes(b)
404 b = b[m:]
405 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700406 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800407 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700408 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800409 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700410 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800411 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700412 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800413 ed.lazy.options = append(ed.lazy.options, v...)
414 }
415 default:
416 m := wire.ConsumeFieldValue(num, typ, b)
417 b = b[m:]
418 }
419 }
420
421 if len(rawValues) > 0 {
422 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
423 for i, b := range rawValues {
424 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
425 }
426 }
Damien Neil8012b442019-01-18 09:32:24 -0800427}
428
429func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
430 for len(b) > 0 {
431 num, typ, n := wire.ConsumeTag(b)
432 b = b[n:]
433 switch typ {
434 case wire.VarintType:
435 v, m := wire.ConsumeVarint(b)
436 b = b[m:]
437 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700438 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800439 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700440 case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800441 r[1] = pref.EnumNumber(v)
442 }
443 default:
444 m := wire.ConsumeFieldValue(num, typ, b)
445 b = b[m:]
446 }
447 }
448 return r
449}
450
451func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
452 vd.parentFile = pf
453 vd.parent = pd
454 vd.index = i
455
456 for len(b) > 0 {
457 num, typ, n := wire.ConsumeTag(b)
458 b = b[n:]
459 switch typ {
460 case wire.VarintType:
461 v, m := wire.ConsumeVarint(b)
462 b = b[m:]
463 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700464 case fieldnum.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800465 vd.number = pref.EnumNumber(v)
466 }
467 case wire.BytesType:
468 v, m := wire.ConsumeBytes(b)
469 b = b[m:]
470 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700471 case fieldnum.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800472 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700473 case fieldnum.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800474 vd.options = append(vd.options, v...)
475 }
476 default:
477 m := wire.ConsumeFieldValue(num, typ, b)
478 b = b[m:]
479 }
480 }
Damien Neil8012b442019-01-18 09:32:24 -0800481}
482
483func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
484 var rawFields, rawOneofs [][]byte
485 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700486 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800487 md.lazy = new(messageLazy)
488 for len(b) > 0 {
489 num, typ, n := wire.ConsumeTag(b)
490 b = b[n:]
491 switch typ {
492 case wire.BytesType:
493 v, m := wire.ConsumeBytes(b)
494 b = b[m:]
495 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700496 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800497 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700498 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800499 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700500 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800501 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700502 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800503 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700504 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800505 r, opts := unmarshalMessageExtensionRange(v)
506 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
507 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700508 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800509 md.enums.list[enumIdx].unmarshalFull(v, nb)
510 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700511 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800512 md.messages.list[messageIdx].unmarshalFull(v, nb)
513 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700514 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800515 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
516 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700517 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700518 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800519 }
520 default:
521 m := wire.ConsumeFieldValue(num, typ, b)
522 b = b[m:]
523 }
524 }
525
526 if len(rawFields) > 0 || len(rawOneofs) > 0 {
527 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
528 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
529 for i, b := range rawFields {
530 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700531 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800532 if fd.cardinality == pref.Required {
533 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
534 }
535 }
536 for i, b := range rawOneofs {
537 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700538 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800539 }
540 }
541
Joe Tsai4532dd72019-03-19 17:04:06 -0700542 if isMapEntry != md.isMapEntry {
543 panic("mismatching map entry property")
544 }
Damien Neil8012b442019-01-18 09:32:24 -0800545}
546
Joe Tsai4532dd72019-03-19 17:04:06 -0700547func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800548 md.lazy.options = append(md.lazy.options, b...)
549 for len(b) > 0 {
550 num, typ, n := wire.ConsumeTag(b)
551 b = b[n:]
552 switch typ {
553 case wire.VarintType:
554 v, m := wire.ConsumeVarint(b)
555 b = b[m:]
556 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700557 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700558 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700559 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700560 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800561 }
562 default:
563 m := wire.ConsumeFieldValue(num, typ, b)
564 b = b[m:]
565 }
566 }
567}
568
569func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
570 for len(b) > 0 {
571 num, typ, n := wire.ConsumeTag(b)
572 b = b[n:]
573 switch typ {
574 case wire.VarintType:
575 v, m := wire.ConsumeVarint(b)
576 b = b[m:]
577 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700578 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800579 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700580 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800581 r[1] = pref.FieldNumber(v)
582 }
583 default:
584 m := wire.ConsumeFieldValue(num, typ, b)
585 b = b[m:]
586 }
587 }
588 return r
589}
590
591func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
592 for len(b) > 0 {
593 num, typ, n := wire.ConsumeTag(b)
594 b = b[n:]
595 switch typ {
596 case wire.VarintType:
597 v, m := wire.ConsumeVarint(b)
598 b = b[m:]
599 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700600 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800601 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700602 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800603 r[1] = pref.FieldNumber(v)
604 }
605 case wire.BytesType:
606 v, m := wire.ConsumeBytes(b)
607 b = b[m:]
608 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700609 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800610 opts = append(opts, v...)
611 }
612 default:
613 m := wire.ConsumeFieldValue(num, typ, b)
614 b = b[m:]
615 }
616 }
617 return r, opts
618}
619
620func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
621 fd.parentFile = pf
622 fd.parent = pd
623 fd.index = i
624
625 var rawDefVal []byte
626 var rawTypeName []byte
627 for len(b) > 0 {
628 num, typ, n := wire.ConsumeTag(b)
629 b = b[n:]
630 switch typ {
631 case wire.VarintType:
632 v, m := wire.ConsumeVarint(b)
633 b = b[m:]
634 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700635 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800636 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700637 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800638 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700639 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800640 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700641 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800642 // In messageDesc.UnmarshalFull, we allocate slices for both
643 // the field and oneof descriptors before unmarshaling either
644 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700645 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800646 od.fields.list = append(od.fields.list, fd)
647 if fd.oneofType != nil {
648 panic("oneof type already set")
649 }
650 fd.oneofType = od
651 }
652 case wire.BytesType:
653 v, m := wire.ConsumeBytes(b)
654 b = b[m:]
655 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700656 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800657 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700658 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800659 fd.hasJSONName = true
660 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700661 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800662 fd.defVal.has = true
663 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700664 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800665 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700666 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800667 fd.unmarshalOptions(v)
668 }
669 default:
670 m := wire.ConsumeFieldValue(num, typ, b)
671 b = b[m:]
672 }
673 }
674
675 if !fd.hasJSONName {
676 fd.jsonName = nb.MakeJSONName(fd.Name())
677 }
678 if rawDefVal != nil {
679 var err error
680 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
681 if err != nil {
682 panic(err)
683 }
684 }
685 if fd.isWeak {
686 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
687 panic("weak target name must be fully qualified")
688 }
689 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
690 }
Damien Neil8012b442019-01-18 09:32:24 -0800691}
692
693func (fd *fieldDesc) unmarshalOptions(b []byte) {
694 fd.options = append(fd.options, b...)
695 for len(b) > 0 {
696 num, typ, n := wire.ConsumeTag(b)
697 b = b[n:]
698 switch typ {
699 case wire.VarintType:
700 v, m := wire.ConsumeVarint(b)
701 b = b[m:]
702 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700703 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800704 fd.hasPacked = true
705 fd.isPacked = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700706 case fieldnum.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800707 fd.isWeak = wire.DecodeBool(v)
708 }
709 default:
710 m := wire.ConsumeFieldValue(num, typ, b)
711 b = b[m:]
712 }
713 }
714}
715
716func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
717 od.parentFile = pf
718 od.parent = pd
719 od.index = i
720
721 for len(b) > 0 {
722 num, typ, n := wire.ConsumeTag(b)
723 b = b[n:]
724 switch typ {
725 case wire.BytesType:
726 v, m := wire.ConsumeBytes(b)
727 b = b[m:]
728 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700729 case fieldnum.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800730 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700731 case fieldnum.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800732 od.options = append(od.options, v...)
733 }
734 default:
735 m := wire.ConsumeFieldValue(num, typ, b)
736 b = b[m:]
737 }
738 }
Damien Neil8012b442019-01-18 09:32:24 -0800739}
740
741func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
742 var rawDefVal []byte
743 xd.lazy = new(extensionLazy)
744 for len(b) > 0 {
745 num, typ, n := wire.ConsumeTag(b)
746 b = b[n:]
747 switch typ {
748 case wire.VarintType:
749 v, m := wire.ConsumeVarint(b)
750 b = b[m:]
751 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700752 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800753 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700754 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800755 xd.lazy.kind = pref.Kind(v)
756 }
757 case wire.BytesType:
758 v, m := wire.ConsumeBytes(b)
759 b = b[m:]
760 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700761 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800762 xd.lazy.hasJSONName = true
763 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700764 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800765 xd.lazy.defVal.has = true
766 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700767 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800768 xd.unmarshalOptions(v)
769 }
770 default:
771 m := wire.ConsumeFieldValue(num, typ, b)
772 b = b[m:]
773 }
774 }
775
776 if rawDefVal != nil {
777 var err error
778 xd.lazy.defVal.val, err = defval.Unmarshal(string(rawDefVal), xd.lazy.kind, defval.Descriptor)
779 if err != nil {
780 panic(err)
781 }
782 }
Damien Neil8012b442019-01-18 09:32:24 -0800783}
784
785func (xd *extensionDesc) unmarshalOptions(b []byte) {
786 xd.lazy.options = append(xd.lazy.options, b...)
787 for len(b) > 0 {
788 num, typ, n := wire.ConsumeTag(b)
789 b = b[n:]
790 switch typ {
791 case wire.VarintType:
792 v, m := wire.ConsumeVarint(b)
793 b = b[m:]
794 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700795 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800796 xd.lazy.isPacked = wire.DecodeBool(v)
797 }
798 default:
799 m := wire.ConsumeFieldValue(num, typ, b)
800 b = b[m:]
801 }
802 }
803}
804
805func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
806 var rawMethods [][]byte
807 sd.lazy = new(serviceLazy)
808 for len(b) > 0 {
809 num, typ, n := wire.ConsumeTag(b)
810 b = b[n:]
811 switch typ {
812 case wire.BytesType:
813 v, m := wire.ConsumeBytes(b)
814 b = b[m:]
815 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700816 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800817 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700818 case fieldnum.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800819 sd.lazy.options = append(sd.lazy.options, v...)
820 }
821 default:
822 m := wire.ConsumeFieldValue(num, typ, b)
823 b = b[m:]
824 }
825 }
826
827 if len(rawMethods) > 0 {
828 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
829 for i, b := range rawMethods {
830 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
831 }
832 }
Damien Neil8012b442019-01-18 09:32:24 -0800833}
834
835func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
836 md.parentFile = pf
837 md.parent = pd
838 md.index = i
839
840 for len(b) > 0 {
841 num, typ, n := wire.ConsumeTag(b)
842 b = b[n:]
843 switch typ {
844 case wire.VarintType:
845 v, m := wire.ConsumeVarint(b)
846 b = b[m:]
847 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700848 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800849 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700850 case fieldnum.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800851 md.isStreamingServer = wire.DecodeBool(v)
852 }
853 case wire.BytesType:
854 v, m := wire.ConsumeBytes(b)
855 b = b[m:]
856 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700857 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800858 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700859 case fieldnum.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800860 md.options = append(md.options, v...)
861 }
862 default:
863 m := wire.ConsumeFieldValue(num, typ, b)
864 b = b[m:]
865 }
866 }
Damien Neil8012b442019-01-18 09:32:24 -0800867}