blob: be3ebebbbf0ea9ada4d74d484636c3075f17055c [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 Neil82a03062019-05-08 07:52:49 -070019 preg "github.com/golang/protobuf/v2/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() {
104 for i := range file.allExtensions {
105 xd := &file.allExtensions[i]
106
107 // Associate the ExtensionType with a concrete Go type.
108 var typ reflect.Type
109 switch xd.lazy.kind {
110 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
111 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
112 default:
113 typ = goTypeForPBKind[xd.lazy.kind]
114 }
115 switch xd.lazy.cardinality {
116 case pref.Optional:
117 switch xd.lazy.kind {
118 case pref.EnumKind:
119 xd.lazy.typ = typ
120 xd.lazy.new = func() pref.Value {
121 return xd.lazy.defVal.get()
122 }
123 xd.lazy.valueOf = func(v interface{}) pref.Value {
124 ev := v.(pref.Enum)
125 return pref.ValueOf(ev.Number())
126 }
127 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
128 return xd.lazy.enumType.New(pv.Enum())
129 }
130 case pref.MessageKind, pref.GroupKind:
131 xd.lazy.typ = typ
132 xd.lazy.new = func() pref.Value {
133 return pref.ValueOf(xd.lazy.messageType.New())
134 }
135 xd.lazy.valueOf = func(v interface{}) pref.Value {
136 mv := v.(pref.ProtoMessage).ProtoReflect()
137 return pref.ValueOf(mv)
138 }
139 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
140 return pv.Message().Interface()
141 }
142 default:
143 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
144 xd.lazy.new = func() pref.Value {
145 return xd.lazy.defVal.get()
146 }
147 xd.lazy.valueOf = func(v interface{}) pref.Value {
148 return pref.ValueOf(v)
149 }
150 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
151 return pv.Interface()
152 }
153 }
154 case pref.Repeated:
155 c := pvalue.NewConverter(typ, xd.lazy.kind)
156 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
157 xd.lazy.new = func() pref.Value {
158 v := reflect.New(xd.lazy.typ.Elem()).Interface()
159 return pref.ValueOf(pvalue.ListOf(v, c))
160 }
161 xd.lazy.valueOf = func(v interface{}) pref.Value {
162 return pref.ValueOf(pvalue.ListOf(v, c))
163 }
164 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
165 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
166 }
167 default:
168 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
169 }
170
171 // Resolve extension field dependency.
172 switch xd.lazy.kind {
173 case pref.EnumKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700174 xd.lazy.enumType = file.popEnumDependency().(pref.EnumType)
Damien Neil8012b442019-01-18 09:32:24 -0800175 case pref.MessageKind, pref.GroupKind:
Joe Tsai4532dd72019-03-19 17:04:06 -0700176 xd.lazy.messageType = file.popMessageDependency().(pref.MessageType)
Damien Neil8012b442019-01-18 09:32:24 -0800177 }
178 xd.lazy.defVal.lazyInit(xd.lazy.kind, file.enumValuesOf(xd.lazy.enumType))
179 }
180}
181
182var goTypeForPBKind = map[pref.Kind]reflect.Type{
183 pref.BoolKind: reflect.TypeOf(bool(false)),
184 pref.Int32Kind: reflect.TypeOf(int32(0)),
185 pref.Sint32Kind: reflect.TypeOf(int32(0)),
186 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
187 pref.Int64Kind: reflect.TypeOf(int64(0)),
188 pref.Sint64Kind: reflect.TypeOf(int64(0)),
189 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
190 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
191 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
192 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
193 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
194 pref.FloatKind: reflect.TypeOf(float32(0)),
195 pref.DoubleKind: reflect.TypeOf(float64(0)),
196 pref.StringKind: reflect.TypeOf(string("")),
197 pref.BytesKind: reflect.TypeOf([]byte(nil)),
198}
199
200func (file *fileDesc) resolveServices() {
201 for i := range file.services.list {
202 sd := &file.services.list[i]
203
204 // Resolve method dependencies.
205 for j := range sd.lazy.methods.list {
206 md := &sd.lazy.methods.list[j]
207 md.inputType = file.popMessageDependency()
208 md.outputType = file.popMessageDependency()
209 }
210 }
211}
212
213// isMapEntry reports whether the message is a map entry, being careful to
214// avoid calling the IsMapEntry method if the message is declared
215// within the same file (which would cause a recursive init deadlock).
216func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
217 if md == nil {
218 return false
219 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700220 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
221 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800222 }
223 return md.IsMapEntry()
224}
225
226// enumValuesOf retrieves the list of enum values for the given enum,
227// being careful to avoid calling the Values method if the enum is declared
228// within the same file (which would cause a recursive init deadlock).
229func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
230 if ed == nil {
231 return nil
232 }
233 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
234 return &ed.lazy.values
235 }
236 return ed.Values()
237}
238
Joe Tsai4532dd72019-03-19 17:04:06 -0700239func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800240 depIdx := fd.popDependencyIndex()
241 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
242 return &fd.allEnums[depIdx]
243 } else {
244 return pimpl.Export{}.EnumTypeOf(fd.GoTypes[depIdx])
245 }
246}
247
Joe Tsai4532dd72019-03-19 17:04:06 -0700248func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800249 depIdx := fd.popDependencyIndex()
250 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700251 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800252 } else {
253 return pimpl.Export{}.MessageTypeOf(fd.GoTypes[depIdx])
254 }
255}
256
257func (fi *fileInit) popDependencyIndex() int {
258 depIdx := fi.DependencyIndexes[0]
259 fi.DependencyIndexes = fi.DependencyIndexes[1:]
260 return int(depIdx)
261}
262
263func (fi *fileInit) finishInit() {
264 if len(fi.DependencyIndexes) > 0 {
265 panic("unused dependencies")
266 }
267 *fi = fileInit{} // clear fileInit for GC to reclaim resources
268}
269
270type defaultValue struct {
271 has bool
272 val pref.Value
273 enum pref.EnumValueDescriptor
274 check func() // only set for non-empty bytes
275}
276
277func (dv *defaultValue) get() pref.Value {
278 if dv.check != nil {
279 dv.check()
280 }
281 return dv.val
282}
283
284func (dv *defaultValue) lazyInit(k pref.Kind, eds pref.EnumValueDescriptors) {
285 if dv.has {
286 switch k {
287 case pref.EnumKind:
288 // File descriptors always store default enums by name.
289 dv.enum = eds.ByName(pref.Name(dv.val.String()))
290 dv.val = pref.ValueOf(dv.enum.Number())
291 case pref.BytesKind:
292 // Store a copy of the default bytes, so that we can detect
293 // accidental mutations of the original value.
294 b := append([]byte(nil), dv.val.Bytes()...)
295 dv.check = func() {
296 if !bytes.Equal(b, dv.val.Bytes()) {
297 // TODO: Avoid panic if we're running with the race detector
298 // and instead spawn a goroutine that periodically resets
299 // this value back to the original to induce a race.
300 panic("detected mutation on the default bytes")
301 }
302 }
303 }
304 } else {
305 switch k {
306 case pref.BoolKind:
307 dv.val = pref.ValueOf(false)
308 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
309 dv.val = pref.ValueOf(int32(0))
310 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
311 dv.val = pref.ValueOf(int64(0))
312 case pref.Uint32Kind, pref.Fixed32Kind:
313 dv.val = pref.ValueOf(uint32(0))
314 case pref.Uint64Kind, pref.Fixed64Kind:
315 dv.val = pref.ValueOf(uint64(0))
316 case pref.FloatKind:
317 dv.val = pref.ValueOf(float32(0))
318 case pref.DoubleKind:
319 dv.val = pref.ValueOf(float64(0))
320 case pref.StringKind:
321 dv.val = pref.ValueOf(string(""))
322 case pref.BytesKind:
323 dv.val = pref.ValueOf([]byte(nil))
324 case pref.EnumKind:
325 dv.enum = eds.Get(0)
326 dv.val = pref.ValueOf(dv.enum.Number())
327 }
328 }
329}
330
331func (fd *fileDesc) unmarshalFull(b []byte) {
332 nb := getNameBuilder()
333 defer putNameBuilder(nb)
334
335 var hasSyntax bool
336 var enumIdx, messageIdx, extensionIdx, serviceIdx int
Damien Neil2300c182019-04-15 13:05:13 -0700337 fd.lazy = &fileLazy{}
Damien Neil8012b442019-01-18 09:32:24 -0800338 for len(b) > 0 {
339 num, typ, n := wire.ConsumeTag(b)
340 b = b[n:]
341 switch typ {
342 case wire.VarintType:
343 v, m := wire.ConsumeVarint(b)
344 b = b[m:]
345 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700346 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800347 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700348 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800349 fd.lazy.imports[v].IsWeak = true
350 }
351 case wire.BytesType:
352 v, m := wire.ConsumeBytes(b)
353 b = b[m:]
354 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700355 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800356 hasSyntax = true
357 switch string(v) {
358 case "proto2":
359 fd.lazy.syntax = pref.Proto2
360 case "proto3":
361 fd.lazy.syntax = pref.Proto3
362 default:
363 panic("invalid syntax")
364 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700365 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800366 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
367 FileDescriptor: ptype.PlaceholderFile(nb.MakeString(v), ""),
368 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700369 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800370 fd.enums.list[enumIdx].unmarshalFull(v, nb)
371 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700372 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800373 fd.messages.list[messageIdx].unmarshalFull(v, nb)
374 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700375 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800376 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
377 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700378 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800379 fd.services.list[serviceIdx].unmarshalFull(v, nb)
380 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700381 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800382 fd.lazy.options = append(fd.lazy.options, v...)
383 }
384 default:
385 m := wire.ConsumeFieldValue(num, typ, b)
386 b = b[m:]
387 }
388 }
389
390 // If syntax is missing, it is assumed to be proto2.
391 if !hasSyntax {
392 fd.lazy.syntax = pref.Proto2
393 }
394}
395
396func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
397 var rawValues [][]byte
398 ed.lazy = new(enumLazy)
399 for len(b) > 0 {
400 num, typ, n := wire.ConsumeTag(b)
401 b = b[n:]
402 switch typ {
403 case wire.BytesType:
404 v, m := wire.ConsumeBytes(b)
405 b = b[m:]
406 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700407 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800408 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700409 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800410 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700411 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800412 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700413 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800414 ed.lazy.options = append(ed.lazy.options, v...)
415 }
416 default:
417 m := wire.ConsumeFieldValue(num, typ, b)
418 b = b[m:]
419 }
420 }
421
422 if len(rawValues) > 0 {
423 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
424 for i, b := range rawValues {
425 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
426 }
427 }
Damien Neil8012b442019-01-18 09:32:24 -0800428}
429
430func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
431 for len(b) > 0 {
432 num, typ, n := wire.ConsumeTag(b)
433 b = b[n:]
434 switch typ {
435 case wire.VarintType:
436 v, m := wire.ConsumeVarint(b)
437 b = b[m:]
438 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700439 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800440 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700441 case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800442 r[1] = pref.EnumNumber(v)
443 }
444 default:
445 m := wire.ConsumeFieldValue(num, typ, b)
446 b = b[m:]
447 }
448 }
449 return r
450}
451
452func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
453 vd.parentFile = pf
454 vd.parent = pd
455 vd.index = i
456
457 for len(b) > 0 {
458 num, typ, n := wire.ConsumeTag(b)
459 b = b[n:]
460 switch typ {
461 case wire.VarintType:
462 v, m := wire.ConsumeVarint(b)
463 b = b[m:]
464 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700465 case fieldnum.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800466 vd.number = pref.EnumNumber(v)
467 }
468 case wire.BytesType:
469 v, m := wire.ConsumeBytes(b)
470 b = b[m:]
471 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700472 case fieldnum.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800473 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700474 case fieldnum.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800475 vd.options = append(vd.options, v...)
476 }
477 default:
478 m := wire.ConsumeFieldValue(num, typ, b)
479 b = b[m:]
480 }
481 }
Damien Neil8012b442019-01-18 09:32:24 -0800482}
483
484func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
485 var rawFields, rawOneofs [][]byte
486 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700487 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800488 md.lazy = new(messageLazy)
489 for len(b) > 0 {
490 num, typ, n := wire.ConsumeTag(b)
491 b = b[n:]
492 switch typ {
493 case wire.BytesType:
494 v, m := wire.ConsumeBytes(b)
495 b = b[m:]
496 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700497 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800498 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700499 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800500 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700501 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800502 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700503 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800504 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700505 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800506 r, opts := unmarshalMessageExtensionRange(v)
507 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
508 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700509 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800510 md.enums.list[enumIdx].unmarshalFull(v, nb)
511 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700512 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800513 md.messages.list[messageIdx].unmarshalFull(v, nb)
514 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700515 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800516 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
517 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700518 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700519 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800520 }
521 default:
522 m := wire.ConsumeFieldValue(num, typ, b)
523 b = b[m:]
524 }
525 }
526
527 if len(rawFields) > 0 || len(rawOneofs) > 0 {
528 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
529 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
530 for i, b := range rawFields {
531 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700532 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800533 if fd.cardinality == pref.Required {
534 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
535 }
536 }
537 for i, b := range rawOneofs {
538 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700539 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800540 }
541 }
542
Joe Tsai4532dd72019-03-19 17:04:06 -0700543 if isMapEntry != md.isMapEntry {
544 panic("mismatching map entry property")
545 }
Damien Neil8012b442019-01-18 09:32:24 -0800546}
547
Joe Tsai4532dd72019-03-19 17:04:06 -0700548func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800549 md.lazy.options = append(md.lazy.options, b...)
550 for len(b) > 0 {
551 num, typ, n := wire.ConsumeTag(b)
552 b = b[n:]
553 switch typ {
554 case wire.VarintType:
555 v, m := wire.ConsumeVarint(b)
556 b = b[m:]
557 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700558 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700559 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700560 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700561 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800562 }
563 default:
564 m := wire.ConsumeFieldValue(num, typ, b)
565 b = b[m:]
566 }
567 }
568}
569
570func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
571 for len(b) > 0 {
572 num, typ, n := wire.ConsumeTag(b)
573 b = b[n:]
574 switch typ {
575 case wire.VarintType:
576 v, m := wire.ConsumeVarint(b)
577 b = b[m:]
578 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700579 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800580 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700581 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800582 r[1] = pref.FieldNumber(v)
583 }
584 default:
585 m := wire.ConsumeFieldValue(num, typ, b)
586 b = b[m:]
587 }
588 }
589 return r
590}
591
592func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
593 for len(b) > 0 {
594 num, typ, n := wire.ConsumeTag(b)
595 b = b[n:]
596 switch typ {
597 case wire.VarintType:
598 v, m := wire.ConsumeVarint(b)
599 b = b[m:]
600 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700601 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800602 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700603 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800604 r[1] = pref.FieldNumber(v)
605 }
606 case wire.BytesType:
607 v, m := wire.ConsumeBytes(b)
608 b = b[m:]
609 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700610 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800611 opts = append(opts, v...)
612 }
613 default:
614 m := wire.ConsumeFieldValue(num, typ, b)
615 b = b[m:]
616 }
617 }
618 return r, opts
619}
620
621func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
622 fd.parentFile = pf
623 fd.parent = pd
624 fd.index = i
625
626 var rawDefVal []byte
627 var rawTypeName []byte
628 for len(b) > 0 {
629 num, typ, n := wire.ConsumeTag(b)
630 b = b[n:]
631 switch typ {
632 case wire.VarintType:
633 v, m := wire.ConsumeVarint(b)
634 b = b[m:]
635 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700636 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800637 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700638 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800639 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700640 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800641 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700642 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800643 // In messageDesc.UnmarshalFull, we allocate slices for both
644 // the field and oneof descriptors before unmarshaling either
645 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700646 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800647 od.fields.list = append(od.fields.list, fd)
648 if fd.oneofType != nil {
649 panic("oneof type already set")
650 }
651 fd.oneofType = od
652 }
653 case wire.BytesType:
654 v, m := wire.ConsumeBytes(b)
655 b = b[m:]
656 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700657 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800658 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700659 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800660 fd.hasJSONName = true
661 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700662 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800663 fd.defVal.has = true
664 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700665 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800666 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700667 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800668 fd.unmarshalOptions(v)
669 }
670 default:
671 m := wire.ConsumeFieldValue(num, typ, b)
672 b = b[m:]
673 }
674 }
675
676 if !fd.hasJSONName {
677 fd.jsonName = nb.MakeJSONName(fd.Name())
678 }
679 if rawDefVal != nil {
680 var err error
681 fd.defVal.val, err = defval.Unmarshal(string(rawDefVal), fd.kind, defval.Descriptor)
682 if err != nil {
683 panic(err)
684 }
685 }
686 if fd.isWeak {
687 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
688 panic("weak target name must be fully qualified")
689 }
Damien Neil82a03062019-05-08 07:52:49 -0700690 // Consult the global registry for weak messages.
691 name := pref.FullName(rawTypeName[1:])
692 fd.messageType, _ = preg.GlobalFiles.FindMessageByName(name)
693 if fd.messageType == nil {
694 fd.messageType = ptype.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
695 }
Damien Neil8012b442019-01-18 09:32:24 -0800696 }
Damien Neil8012b442019-01-18 09:32:24 -0800697}
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 Tsaica46d8c2019-03-20 16:51:09 -0700709 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800710 fd.hasPacked = true
711 fd.isPacked = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700712 case fieldnum.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 Tsaica46d8c2019-03-20 16:51:09 -0700735 case fieldnum.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800736 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700737 case fieldnum.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 }
Damien Neil8012b442019-01-18 09:32:24 -0800745}
746
747func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
748 var rawDefVal []byte
749 xd.lazy = new(extensionLazy)
750 for len(b) > 0 {
751 num, typ, n := wire.ConsumeTag(b)
752 b = b[n:]
753 switch typ {
754 case wire.VarintType:
755 v, m := wire.ConsumeVarint(b)
756 b = b[m:]
757 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700758 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800759 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700760 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800761 xd.lazy.kind = pref.Kind(v)
762 }
763 case wire.BytesType:
764 v, m := wire.ConsumeBytes(b)
765 b = b[m:]
766 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700767 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800768 xd.lazy.hasJSONName = true
769 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700770 case fieldnum.FieldDescriptorProto_DefaultValue:
Damien Neil8012b442019-01-18 09:32:24 -0800771 xd.lazy.defVal.has = true
772 rawDefVal = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700773 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800774 xd.unmarshalOptions(v)
775 }
776 default:
777 m := wire.ConsumeFieldValue(num, typ, b)
778 b = b[m:]
779 }
780 }
781
782 if rawDefVal != nil {
783 var err error
784 xd.lazy.defVal.val, err = defval.Unmarshal(string(rawDefVal), xd.lazy.kind, defval.Descriptor)
785 if err != nil {
786 panic(err)
787 }
788 }
Damien Neil8012b442019-01-18 09:32:24 -0800789}
790
791func (xd *extensionDesc) unmarshalOptions(b []byte) {
792 xd.lazy.options = append(xd.lazy.options, b...)
793 for len(b) > 0 {
794 num, typ, n := wire.ConsumeTag(b)
795 b = b[n:]
796 switch typ {
797 case wire.VarintType:
798 v, m := wire.ConsumeVarint(b)
799 b = b[m:]
800 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700801 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800802 xd.lazy.isPacked = wire.DecodeBool(v)
803 }
804 default:
805 m := wire.ConsumeFieldValue(num, typ, b)
806 b = b[m:]
807 }
808 }
809}
810
811func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
812 var rawMethods [][]byte
813 sd.lazy = new(serviceLazy)
814 for len(b) > 0 {
815 num, typ, n := wire.ConsumeTag(b)
816 b = b[n:]
817 switch typ {
818 case wire.BytesType:
819 v, m := wire.ConsumeBytes(b)
820 b = b[m:]
821 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700822 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800823 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700824 case fieldnum.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800825 sd.lazy.options = append(sd.lazy.options, v...)
826 }
827 default:
828 m := wire.ConsumeFieldValue(num, typ, b)
829 b = b[m:]
830 }
831 }
832
833 if len(rawMethods) > 0 {
834 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
835 for i, b := range rawMethods {
836 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
837 }
838 }
Damien Neil8012b442019-01-18 09:32:24 -0800839}
840
841func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
842 md.parentFile = pf
843 md.parent = pd
844 md.index = i
845
846 for len(b) > 0 {
847 num, typ, n := wire.ConsumeTag(b)
848 b = b[n:]
849 switch typ {
850 case wire.VarintType:
851 v, m := wire.ConsumeVarint(b)
852 b = b[m:]
853 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700854 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800855 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700856 case fieldnum.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800857 md.isStreamingServer = wire.DecodeBool(v)
858 }
859 case wire.BytesType:
860 v, m := wire.ConsumeBytes(b)
861 b = b[m:]
862 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700863 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800864 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700865 case fieldnum.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800866 md.options = append(md.options, v...)
867 }
868 default:
869 m := wire.ConsumeFieldValue(num, typ, b)
870 b = b[m:]
871 }
872 }
Damien Neil8012b442019-01-18 09:32:24 -0800873}