blob: 673b100575ef544b59d75dfd4b10ff9f4165a78f [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"
Joe Tsaid8881392019-06-06 13:01:53 -070015 fdesc "google.golang.org/protobuf/internal/filedesc"
Damien Neile89e6242019-05-13 23:55:40 -070016 pimpl "google.golang.org/protobuf/internal/impl"
Damien Neile89e6242019-05-13 23:55:40 -070017 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 }
Joe Tsaid8881392019-06-06 13:01:53 -070098
99 // Default is resolved here since it depends on Enum being resolved.
100 if v := fd.defVal.val; v.IsValid() {
101 fd.defVal = unmarshalDefault(v.Bytes(), fd.kind, file, fd.enumType)
102 }
Damien Neil8012b442019-01-18 09:32:24 -0800103 }
104 }
105}
106
107func (file *fileDesc) resolveExtensions() {
Joe Tsaib2f66be2019-05-22 00:42:45 -0400108 // TODO: Delete this and use reflect/prototype instead.
109
Damien Neil8012b442019-01-18 09:32:24 -0800110 for i := range file.allExtensions {
111 xd := &file.allExtensions[i]
112
113 // Associate the ExtensionType with a concrete Go type.
114 var typ reflect.Type
115 switch xd.lazy.kind {
116 case pref.EnumKind, pref.MessageKind, pref.GroupKind:
117 typ = reflect.TypeOf(file.GoTypes[file.DependencyIndexes[0]])
118 default:
119 typ = goTypeForPBKind[xd.lazy.kind]
120 }
121 switch xd.lazy.cardinality {
122 case pref.Optional:
123 switch xd.lazy.kind {
124 case pref.EnumKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700125 et := pimpl.Export{}.EnumTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800126 xd.lazy.typ = typ
127 xd.lazy.new = func() pref.Value {
Joe Tsaid8881392019-06-06 13:01:53 -0700128 return xd.lazy.defVal.get(xd)
Damien Neil8012b442019-01-18 09:32:24 -0800129 }
130 xd.lazy.valueOf = func(v interface{}) pref.Value {
131 ev := v.(pref.Enum)
132 return pref.ValueOf(ev.Number())
133 }
134 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700135 return et.New(pv.Enum())
Damien Neil8012b442019-01-18 09:32:24 -0800136 }
137 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700138 mt := pimpl.Export{}.MessageTypeOf(reflect.Zero(typ).Interface())
Damien Neil8012b442019-01-18 09:32:24 -0800139 xd.lazy.typ = typ
140 xd.lazy.new = func() pref.Value {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700141 return pref.ValueOf(mt.New())
Damien Neil8012b442019-01-18 09:32:24 -0800142 }
143 xd.lazy.valueOf = func(v interface{}) pref.Value {
144 mv := v.(pref.ProtoMessage).ProtoReflect()
145 return pref.ValueOf(mv)
146 }
147 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
148 return pv.Message().Interface()
149 }
150 default:
151 xd.lazy.typ = goTypeForPBKind[xd.lazy.kind]
152 xd.lazy.new = func() pref.Value {
Joe Tsaid8881392019-06-06 13:01:53 -0700153 return xd.lazy.defVal.get(xd)
Damien Neil8012b442019-01-18 09:32:24 -0800154 }
155 xd.lazy.valueOf = func(v interface{}) pref.Value {
156 return pref.ValueOf(v)
157 }
158 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
159 return pv.Interface()
160 }
161 }
162 case pref.Repeated:
163 c := pvalue.NewConverter(typ, xd.lazy.kind)
164 xd.lazy.typ = reflect.PtrTo(reflect.SliceOf(typ))
165 xd.lazy.new = func() pref.Value {
166 v := reflect.New(xd.lazy.typ.Elem()).Interface()
167 return pref.ValueOf(pvalue.ListOf(v, c))
168 }
169 xd.lazy.valueOf = func(v interface{}) pref.Value {
170 return pref.ValueOf(pvalue.ListOf(v, c))
171 }
172 xd.lazy.interfaceOf = func(pv pref.Value) interface{} {
173 return pv.List().(pvalue.Unwrapper).ProtoUnwrap()
174 }
175 default:
176 panic(fmt.Sprintf("invalid cardinality: %v", xd.lazy.cardinality))
177 }
178
179 // Resolve extension field dependency.
180 switch xd.lazy.kind {
181 case pref.EnumKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700182 xd.lazy.enumType = file.popEnumDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800183 case pref.MessageKind, pref.GroupKind:
Joe Tsai0fc49f82019-05-01 12:29:25 -0700184 xd.lazy.messageType = file.popMessageDependency()
Damien Neil8012b442019-01-18 09:32:24 -0800185 }
Joe Tsaid8881392019-06-06 13:01:53 -0700186
187 // Default is resolved here since it depends on Enum being resolved.
188 if v := xd.lazy.defVal.val; v.IsValid() {
189 xd.lazy.defVal = unmarshalDefault(v.Bytes(), xd.lazy.kind, file, xd.lazy.enumType)
190 }
Damien Neil8012b442019-01-18 09:32:24 -0800191 }
192}
193
194var goTypeForPBKind = map[pref.Kind]reflect.Type{
195 pref.BoolKind: reflect.TypeOf(bool(false)),
196 pref.Int32Kind: reflect.TypeOf(int32(0)),
197 pref.Sint32Kind: reflect.TypeOf(int32(0)),
198 pref.Sfixed32Kind: reflect.TypeOf(int32(0)),
199 pref.Int64Kind: reflect.TypeOf(int64(0)),
200 pref.Sint64Kind: reflect.TypeOf(int64(0)),
201 pref.Sfixed64Kind: reflect.TypeOf(int64(0)),
202 pref.Uint32Kind: reflect.TypeOf(uint32(0)),
203 pref.Fixed32Kind: reflect.TypeOf(uint32(0)),
204 pref.Uint64Kind: reflect.TypeOf(uint64(0)),
205 pref.Fixed64Kind: reflect.TypeOf(uint64(0)),
206 pref.FloatKind: reflect.TypeOf(float32(0)),
207 pref.DoubleKind: reflect.TypeOf(float64(0)),
208 pref.StringKind: reflect.TypeOf(string("")),
209 pref.BytesKind: reflect.TypeOf([]byte(nil)),
210}
211
212func (file *fileDesc) resolveServices() {
213 for i := range file.services.list {
214 sd := &file.services.list[i]
215
216 // Resolve method dependencies.
217 for j := range sd.lazy.methods.list {
218 md := &sd.lazy.methods.list[j]
219 md.inputType = file.popMessageDependency()
220 md.outputType = file.popMessageDependency()
221 }
222 }
223}
224
225// isMapEntry reports whether the message is a map entry, being careful to
226// avoid calling the IsMapEntry method if the message is declared
227// within the same file (which would cause a recursive init deadlock).
228func (fd *fileDesc) isMapEntry(md pref.MessageDescriptor) bool {
229 if md == nil {
230 return false
231 }
Joe Tsai4532dd72019-03-19 17:04:06 -0700232 if md, ok := md.(*messageDescriptor); ok && md.parentFile == fd {
233 return md.isMapEntry
Damien Neil8012b442019-01-18 09:32:24 -0800234 }
235 return md.IsMapEntry()
236}
237
238// enumValuesOf retrieves the list of enum values for the given enum,
239// being careful to avoid calling the Values method if the enum is declared
240// within the same file (which would cause a recursive init deadlock).
241func (fd *fileDesc) enumValuesOf(ed pref.EnumDescriptor) pref.EnumValueDescriptors {
242 if ed == nil {
243 return nil
244 }
245 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == fd {
246 return &ed.lazy.values
247 }
248 return ed.Values()
249}
250
Joe Tsai4532dd72019-03-19 17:04:06 -0700251func (fd *fileDesc) popEnumDependency() pref.EnumDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800252 depIdx := fd.popDependencyIndex()
253 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
254 return &fd.allEnums[depIdx]
255 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700256 return pimpl.Export{}.EnumDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800257 }
258}
259
Joe Tsai4532dd72019-03-19 17:04:06 -0700260func (fd *fileDesc) popMessageDependency() pref.MessageDescriptor {
Damien Neil8012b442019-01-18 09:32:24 -0800261 depIdx := fd.popDependencyIndex()
262 if depIdx < len(fd.allEnums)+len(fd.allMessages) {
Joe Tsai4532dd72019-03-19 17:04:06 -0700263 return fd.allMessages[depIdx-len(fd.allEnums)].asDesc()
Damien Neil8012b442019-01-18 09:32:24 -0800264 } else {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700265 return pimpl.Export{}.MessageDescriptorOf(fd.GoTypes[depIdx])
Damien Neil8012b442019-01-18 09:32:24 -0800266 }
267}
268
269func (fi *fileInit) popDependencyIndex() int {
270 depIdx := fi.DependencyIndexes[0]
271 fi.DependencyIndexes = fi.DependencyIndexes[1:]
272 return int(depIdx)
273}
274
275func (fi *fileInit) finishInit() {
276 if len(fi.DependencyIndexes) > 0 {
277 panic("unused dependencies")
278 }
279 *fi = fileInit{} // clear fileInit for GC to reclaim resources
280}
281
Joe Tsaid8881392019-06-06 13:01:53 -0700282func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue {
283 dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
284 if b, ok := v.Interface().([]byte); ok {
285 // Store a copy of the default bytes, so that we can detect
286 // accidental mutations of the original value.
287 dv.bytes = append([]byte(nil), b...)
288 }
289 return dv
290}
291
292func unmarshalDefault(b []byte, k pref.Kind, pf *fileDesc, ed pref.EnumDescriptor) defaultValue {
293 var evs pref.EnumValueDescriptors
294 if k == pref.EnumKind {
295 // If the enum is declared within the same file, be careful not to
296 // blindly call the Values method, lest we bind ourselves in a deadlock.
297 if ed, ok := ed.(*enumDesc); ok && ed.parentFile == pf {
298 evs = &ed.lazy.values
299 } else {
300 evs = ed.Values()
301 }
302 }
303
304 v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor)
305 if err != nil {
306 panic(err)
307 }
308 dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
309 if b, ok := v.Interface().([]byte); ok {
310 // Store a copy of the default bytes, so that we can detect
311 // accidental mutations of the original value.
312 dv.bytes = append([]byte(nil), b...)
313 }
314 return dv
315}
316
Damien Neil8012b442019-01-18 09:32:24 -0800317type defaultValue struct {
318 has bool
319 val pref.Value
320 enum pref.EnumValueDescriptor
Joe Tsaid8881392019-06-06 13:01:53 -0700321 bytes []byte
Damien Neil8012b442019-01-18 09:32:24 -0800322}
323
Joe Tsaid8881392019-06-06 13:01:53 -0700324func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value {
325 // Return the zero value as the default if unpopulated.
326 if !dv.has {
327 switch fd.Kind() {
328 case pref.BoolKind:
329 return pref.ValueOf(false)
330 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
331 return pref.ValueOf(int32(0))
332 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
333 return pref.ValueOf(int64(0))
334 case pref.Uint32Kind, pref.Fixed32Kind:
335 return pref.ValueOf(uint32(0))
336 case pref.Uint64Kind, pref.Fixed64Kind:
337 return pref.ValueOf(uint64(0))
338 case pref.FloatKind:
339 return pref.ValueOf(float32(0))
340 case pref.DoubleKind:
341 return pref.ValueOf(float64(0))
342 case pref.StringKind:
343 return pref.ValueOf(string(""))
344 case pref.BytesKind:
345 return pref.ValueOf([]byte(nil))
346 case pref.EnumKind:
347 return pref.ValueOf(fd.Enum().Values().Get(0).Number())
348 }
349 }
350
351 if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) {
352 // TODO: Avoid panic if we're running with the race detector
353 // and instead spawn a goroutine that periodically resets
354 // this value back to the original to induce a race.
355 panic("detected mutation on the default bytes")
Damien Neil8012b442019-01-18 09:32:24 -0800356 }
357 return dv.val
358}
359
Damien Neil8012b442019-01-18 09:32:24 -0800360func (fd *fileDesc) unmarshalFull(b []byte) {
361 nb := getNameBuilder()
362 defer putNameBuilder(nb)
363
364 var hasSyntax bool
365 var enumIdx, messageIdx, extensionIdx, serviceIdx int
Damien Neil2300c182019-04-15 13:05:13 -0700366 fd.lazy = &fileLazy{}
Damien Neil8012b442019-01-18 09:32:24 -0800367 for len(b) > 0 {
368 num, typ, n := wire.ConsumeTag(b)
369 b = b[n:]
370 switch typ {
371 case wire.VarintType:
372 v, m := wire.ConsumeVarint(b)
373 b = b[m:]
374 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700375 case fieldnum.FileDescriptorProto_PublicDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800376 fd.lazy.imports[v].IsPublic = true
Joe Tsaica46d8c2019-03-20 16:51:09 -0700377 case fieldnum.FileDescriptorProto_WeakDependency:
Damien Neil8012b442019-01-18 09:32:24 -0800378 fd.lazy.imports[v].IsWeak = true
379 }
380 case wire.BytesType:
381 v, m := wire.ConsumeBytes(b)
382 b = b[m:]
383 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700384 case fieldnum.FileDescriptorProto_Syntax:
Damien Neil8012b442019-01-18 09:32:24 -0800385 hasSyntax = true
386 switch string(v) {
387 case "proto2":
388 fd.lazy.syntax = pref.Proto2
389 case "proto3":
390 fd.lazy.syntax = pref.Proto3
391 default:
392 panic("invalid syntax")
393 }
Joe Tsaica46d8c2019-03-20 16:51:09 -0700394 case fieldnum.FileDescriptorProto_Dependency:
Damien Neil8012b442019-01-18 09:32:24 -0800395 fd.lazy.imports = append(fd.lazy.imports, pref.FileImport{
Joe Tsaid8881392019-06-06 13:01:53 -0700396 FileDescriptor: fdesc.PlaceholderFile(nb.MakeString(v)),
Damien Neil8012b442019-01-18 09:32:24 -0800397 })
Joe Tsaica46d8c2019-03-20 16:51:09 -0700398 case fieldnum.FileDescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800399 fd.enums.list[enumIdx].unmarshalFull(v, nb)
400 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700401 case fieldnum.FileDescriptorProto_MessageType:
Damien Neil8012b442019-01-18 09:32:24 -0800402 fd.messages.list[messageIdx].unmarshalFull(v, nb)
403 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700404 case fieldnum.FileDescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800405 fd.extensions.list[extensionIdx].unmarshalFull(v, nb)
406 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700407 case fieldnum.FileDescriptorProto_Service:
Damien Neil8012b442019-01-18 09:32:24 -0800408 fd.services.list[serviceIdx].unmarshalFull(v, nb)
409 serviceIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700410 case fieldnum.FileDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800411 fd.lazy.options = append(fd.lazy.options, v...)
412 }
413 default:
414 m := wire.ConsumeFieldValue(num, typ, b)
415 b = b[m:]
416 }
417 }
418
419 // If syntax is missing, it is assumed to be proto2.
420 if !hasSyntax {
421 fd.lazy.syntax = pref.Proto2
422 }
423}
424
425func (ed *enumDesc) unmarshalFull(b []byte, nb *nameBuilder) {
426 var rawValues [][]byte
427 ed.lazy = new(enumLazy)
428 for len(b) > 0 {
429 num, typ, n := wire.ConsumeTag(b)
430 b = b[n:]
431 switch typ {
432 case wire.BytesType:
433 v, m := wire.ConsumeBytes(b)
434 b = b[m:]
435 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700436 case fieldnum.EnumDescriptorProto_Value:
Damien Neil8012b442019-01-18 09:32:24 -0800437 rawValues = append(rawValues, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700438 case fieldnum.EnumDescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800439 ed.lazy.resvNames.list = append(ed.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700440 case fieldnum.EnumDescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800441 ed.lazy.resvRanges.list = append(ed.lazy.resvRanges.list, unmarshalEnumReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700442 case fieldnum.EnumDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800443 ed.lazy.options = append(ed.lazy.options, v...)
444 }
445 default:
446 m := wire.ConsumeFieldValue(num, typ, b)
447 b = b[m:]
448 }
449 }
450
451 if len(rawValues) > 0 {
452 ed.lazy.values.list = make([]enumValueDesc, len(rawValues))
453 for i, b := range rawValues {
454 ed.lazy.values.list[i].unmarshalFull(b, nb, ed.parentFile, ed, i)
455 }
456 }
Damien Neil8012b442019-01-18 09:32:24 -0800457}
458
459func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
460 for len(b) > 0 {
461 num, typ, n := wire.ConsumeTag(b)
462 b = b[n:]
463 switch typ {
464 case wire.VarintType:
465 v, m := wire.ConsumeVarint(b)
466 b = b[m:]
467 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700468 case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800469 r[0] = pref.EnumNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700470 case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800471 r[1] = pref.EnumNumber(v)
472 }
473 default:
474 m := wire.ConsumeFieldValue(num, typ, b)
475 b = b[m:]
476 }
477 }
478 return r
479}
480
481func (vd *enumValueDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
482 vd.parentFile = pf
483 vd.parent = pd
484 vd.index = i
485
486 for len(b) > 0 {
487 num, typ, n := wire.ConsumeTag(b)
488 b = b[n:]
489 switch typ {
490 case wire.VarintType:
491 v, m := wire.ConsumeVarint(b)
492 b = b[m:]
493 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700494 case fieldnum.EnumValueDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800495 vd.number = pref.EnumNumber(v)
496 }
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.EnumValueDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800502 vd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700503 case fieldnum.EnumValueDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800504 vd.options = append(vd.options, v...)
505 }
506 default:
507 m := wire.ConsumeFieldValue(num, typ, b)
508 b = b[m:]
509 }
510 }
Damien Neil8012b442019-01-18 09:32:24 -0800511}
512
513func (md *messageDesc) unmarshalFull(b []byte, nb *nameBuilder) {
514 var rawFields, rawOneofs [][]byte
515 var enumIdx, messageIdx, extensionIdx int
Joe Tsai4532dd72019-03-19 17:04:06 -0700516 var isMapEntry bool
Damien Neil8012b442019-01-18 09:32:24 -0800517 md.lazy = new(messageLazy)
518 for len(b) > 0 {
519 num, typ, n := wire.ConsumeTag(b)
520 b = b[n:]
521 switch typ {
522 case wire.BytesType:
523 v, m := wire.ConsumeBytes(b)
524 b = b[m:]
525 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700526 case fieldnum.DescriptorProto_Field:
Damien Neil8012b442019-01-18 09:32:24 -0800527 rawFields = append(rawFields, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700528 case fieldnum.DescriptorProto_OneofDecl:
Damien Neil8012b442019-01-18 09:32:24 -0800529 rawOneofs = append(rawOneofs, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700530 case fieldnum.DescriptorProto_ReservedName:
Damien Neil8012b442019-01-18 09:32:24 -0800531 md.lazy.resvNames.list = append(md.lazy.resvNames.list, pref.Name(nb.MakeString(v)))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700532 case fieldnum.DescriptorProto_ReservedRange:
Damien Neil8012b442019-01-18 09:32:24 -0800533 md.lazy.resvRanges.list = append(md.lazy.resvRanges.list, unmarshalMessageReservedRange(v))
Joe Tsaica46d8c2019-03-20 16:51:09 -0700534 case fieldnum.DescriptorProto_ExtensionRange:
Damien Neil8012b442019-01-18 09:32:24 -0800535 r, opts := unmarshalMessageExtensionRange(v)
536 md.lazy.extRanges.list = append(md.lazy.extRanges.list, r)
537 md.lazy.extRangeOptions = append(md.lazy.extRangeOptions, opts)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700538 case fieldnum.DescriptorProto_EnumType:
Damien Neil8012b442019-01-18 09:32:24 -0800539 md.enums.list[enumIdx].unmarshalFull(v, nb)
540 enumIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700541 case fieldnum.DescriptorProto_NestedType:
Damien Neil8012b442019-01-18 09:32:24 -0800542 md.messages.list[messageIdx].unmarshalFull(v, nb)
543 messageIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700544 case fieldnum.DescriptorProto_Extension:
Damien Neil8012b442019-01-18 09:32:24 -0800545 md.extensions.list[extensionIdx].unmarshalFull(v, nb)
546 extensionIdx++
Joe Tsaica46d8c2019-03-20 16:51:09 -0700547 case fieldnum.DescriptorProto_Options:
Joe Tsai4532dd72019-03-19 17:04:06 -0700548 md.unmarshalOptions(v, &isMapEntry)
Damien Neil8012b442019-01-18 09:32:24 -0800549 }
550 default:
551 m := wire.ConsumeFieldValue(num, typ, b)
552 b = b[m:]
553 }
554 }
555
556 if len(rawFields) > 0 || len(rawOneofs) > 0 {
557 md.lazy.fields.list = make([]fieldDesc, len(rawFields))
558 md.lazy.oneofs.list = make([]oneofDesc, len(rawOneofs))
559 for i, b := range rawFields {
560 fd := &md.lazy.fields.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700561 fd.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800562 if fd.cardinality == pref.Required {
563 md.lazy.reqNumbers.list = append(md.lazy.reqNumbers.list, fd.number)
564 }
565 }
566 for i, b := range rawOneofs {
567 od := &md.lazy.oneofs.list[i]
Joe Tsai4532dd72019-03-19 17:04:06 -0700568 od.unmarshalFull(b, nb, md.parentFile, md.asDesc(), i)
Damien Neil8012b442019-01-18 09:32:24 -0800569 }
570 }
571
Joe Tsai4532dd72019-03-19 17:04:06 -0700572 if isMapEntry != md.isMapEntry {
573 panic("mismatching map entry property")
574 }
Damien Neil8012b442019-01-18 09:32:24 -0800575}
576
Joe Tsai4532dd72019-03-19 17:04:06 -0700577func (md *messageDesc) unmarshalOptions(b []byte, isMapEntry *bool) {
Damien Neil8012b442019-01-18 09:32:24 -0800578 md.lazy.options = append(md.lazy.options, b...)
579 for len(b) > 0 {
580 num, typ, n := wire.ConsumeTag(b)
581 b = b[n:]
582 switch typ {
583 case wire.VarintType:
584 v, m := wire.ConsumeVarint(b)
585 b = b[m:]
586 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700587 case fieldnum.MessageOptions_MapEntry:
Joe Tsai4532dd72019-03-19 17:04:06 -0700588 *isMapEntry = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700589 case fieldnum.MessageOptions_MessageSetWireFormat:
Joe Tsai1321a0e2019-03-20 09:46:22 -0700590 md.lazy.isMessageSet = wire.DecodeBool(v)
Damien Neil8012b442019-01-18 09:32:24 -0800591 }
592 default:
593 m := wire.ConsumeFieldValue(num, typ, b)
594 b = b[m:]
595 }
596 }
597}
598
599func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
600 for len(b) > 0 {
601 num, typ, n := wire.ConsumeTag(b)
602 b = b[n:]
603 switch typ {
604 case wire.VarintType:
605 v, m := wire.ConsumeVarint(b)
606 b = b[m:]
607 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700608 case fieldnum.DescriptorProto_ReservedRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800609 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700610 case fieldnum.DescriptorProto_ReservedRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800611 r[1] = pref.FieldNumber(v)
612 }
613 default:
614 m := wire.ConsumeFieldValue(num, typ, b)
615 b = b[m:]
616 }
617 }
618 return r
619}
620
621func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, opts []byte) {
622 for len(b) > 0 {
623 num, typ, n := wire.ConsumeTag(b)
624 b = b[n:]
625 switch typ {
626 case wire.VarintType:
627 v, m := wire.ConsumeVarint(b)
628 b = b[m:]
629 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700630 case fieldnum.DescriptorProto_ExtensionRange_Start:
Damien Neil8012b442019-01-18 09:32:24 -0800631 r[0] = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700632 case fieldnum.DescriptorProto_ExtensionRange_End:
Damien Neil8012b442019-01-18 09:32:24 -0800633 r[1] = pref.FieldNumber(v)
634 }
635 case wire.BytesType:
636 v, m := wire.ConsumeBytes(b)
637 b = b[m:]
638 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700639 case fieldnum.DescriptorProto_ExtensionRange_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800640 opts = append(opts, v...)
641 }
642 default:
643 m := wire.ConsumeFieldValue(num, typ, b)
644 b = b[m:]
645 }
646 }
647 return r, opts
648}
649
650func (fd *fieldDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
651 fd.parentFile = pf
652 fd.parent = pd
653 fd.index = i
654
Damien Neil8012b442019-01-18 09:32:24 -0800655 var rawTypeName []byte
656 for len(b) > 0 {
657 num, typ, n := wire.ConsumeTag(b)
658 b = b[n:]
659 switch typ {
660 case wire.VarintType:
661 v, m := wire.ConsumeVarint(b)
662 b = b[m:]
663 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700664 case fieldnum.FieldDescriptorProto_Number:
Damien Neil8012b442019-01-18 09:32:24 -0800665 fd.number = pref.FieldNumber(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700666 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800667 fd.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700668 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800669 fd.kind = pref.Kind(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700670 case fieldnum.FieldDescriptorProto_OneofIndex:
Damien Neil8012b442019-01-18 09:32:24 -0800671 // In messageDesc.UnmarshalFull, we allocate slices for both
672 // the field and oneof descriptors before unmarshaling either
673 // of them. This ensures pointers to slice elements are stable.
Joe Tsai4532dd72019-03-19 17:04:06 -0700674 od := &pd.(messageType).lazy.oneofs.list[v]
Damien Neil8012b442019-01-18 09:32:24 -0800675 od.fields.list = append(od.fields.list, fd)
676 if fd.oneofType != nil {
677 panic("oneof type already set")
678 }
679 fd.oneofType = od
680 }
681 case wire.BytesType:
682 v, m := wire.ConsumeBytes(b)
683 b = b[m:]
684 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700685 case fieldnum.FieldDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800686 fd.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700687 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800688 fd.hasJSONName = true
689 fd.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700690 case fieldnum.FieldDescriptorProto_DefaultValue:
Joe Tsaid8881392019-06-06 13:01:53 -0700691 fd.defVal.val = pref.ValueOf(v) // temporarily store as bytes; later resolved in resolveMessages
Joe Tsaica46d8c2019-03-20 16:51:09 -0700692 case fieldnum.FieldDescriptorProto_TypeName:
Damien Neil8012b442019-01-18 09:32:24 -0800693 rawTypeName = v
Joe Tsaica46d8c2019-03-20 16:51:09 -0700694 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800695 fd.unmarshalOptions(v)
696 }
697 default:
698 m := wire.ConsumeFieldValue(num, typ, b)
699 b = b[m:]
700 }
701 }
702
703 if !fd.hasJSONName {
704 fd.jsonName = nb.MakeJSONName(fd.Name())
705 }
Damien Neil8012b442019-01-18 09:32:24 -0800706 if fd.isWeak {
707 if len(rawTypeName) == 0 || rawTypeName[0] != '.' {
708 panic("weak target name must be fully qualified")
709 }
Damien Neil82a03062019-05-08 07:52:49 -0700710 // Consult the global registry for weak messages.
711 name := pref.FullName(rawTypeName[1:])
712 fd.messageType, _ = preg.GlobalFiles.FindMessageByName(name)
713 if fd.messageType == nil {
Joe Tsaid8881392019-06-06 13:01:53 -0700714 fd.messageType = fdesc.PlaceholderMessage(pref.FullName(rawTypeName[1:]))
Damien Neil82a03062019-05-08 07:52:49 -0700715 }
Damien Neil8012b442019-01-18 09:32:24 -0800716 }
Damien Neil8012b442019-01-18 09:32:24 -0800717}
718
719func (fd *fieldDesc) unmarshalOptions(b []byte) {
720 fd.options = append(fd.options, b...)
721 for len(b) > 0 {
722 num, typ, n := wire.ConsumeTag(b)
723 b = b[n:]
724 switch typ {
725 case wire.VarintType:
726 v, m := wire.ConsumeVarint(b)
727 b = b[m:]
728 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700729 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800730 fd.hasPacked = true
731 fd.isPacked = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700732 case fieldnum.FieldOptions_Weak:
Damien Neil8012b442019-01-18 09:32:24 -0800733 fd.isWeak = wire.DecodeBool(v)
734 }
735 default:
736 m := wire.ConsumeFieldValue(num, typ, b)
737 b = b[m:]
738 }
739 }
740}
741
742func (od *oneofDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
743 od.parentFile = pf
744 od.parent = pd
745 od.index = i
746
747 for len(b) > 0 {
748 num, typ, n := wire.ConsumeTag(b)
749 b = b[n:]
750 switch typ {
751 case wire.BytesType:
752 v, m := wire.ConsumeBytes(b)
753 b = b[m:]
754 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700755 case fieldnum.OneofDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800756 od.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700757 case fieldnum.OneofDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800758 od.options = append(od.options, v...)
759 }
760 default:
761 m := wire.ConsumeFieldValue(num, typ, b)
762 b = b[m:]
763 }
764 }
Damien Neil8012b442019-01-18 09:32:24 -0800765}
766
767func (xd *extensionDesc) unmarshalFull(b []byte, nb *nameBuilder) {
Damien Neil8012b442019-01-18 09:32:24 -0800768 xd.lazy = new(extensionLazy)
769 for len(b) > 0 {
770 num, typ, n := wire.ConsumeTag(b)
771 b = b[n:]
772 switch typ {
773 case wire.VarintType:
774 v, m := wire.ConsumeVarint(b)
775 b = b[m:]
776 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700777 case fieldnum.FieldDescriptorProto_Label:
Damien Neil8012b442019-01-18 09:32:24 -0800778 xd.lazy.cardinality = pref.Cardinality(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700779 case fieldnum.FieldDescriptorProto_Type:
Damien Neil8012b442019-01-18 09:32:24 -0800780 xd.lazy.kind = pref.Kind(v)
781 }
782 case wire.BytesType:
783 v, m := wire.ConsumeBytes(b)
784 b = b[m:]
785 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700786 case fieldnum.FieldDescriptorProto_JsonName:
Damien Neil8012b442019-01-18 09:32:24 -0800787 xd.lazy.hasJSONName = true
788 xd.lazy.jsonName = nb.MakeString(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700789 case fieldnum.FieldDescriptorProto_DefaultValue:
Joe Tsaid8881392019-06-06 13:01:53 -0700790 xd.lazy.defVal.val = pref.ValueOf(v) // temporarily store as bytes; later resolved in resolveExtensions
Joe Tsaica46d8c2019-03-20 16:51:09 -0700791 case fieldnum.FieldDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800792 xd.unmarshalOptions(v)
793 }
794 default:
795 m := wire.ConsumeFieldValue(num, typ, b)
796 b = b[m:]
797 }
798 }
Damien Neil8012b442019-01-18 09:32:24 -0800799}
800
801func (xd *extensionDesc) unmarshalOptions(b []byte) {
802 xd.lazy.options = append(xd.lazy.options, b...)
803 for len(b) > 0 {
804 num, typ, n := wire.ConsumeTag(b)
805 b = b[n:]
806 switch typ {
807 case wire.VarintType:
808 v, m := wire.ConsumeVarint(b)
809 b = b[m:]
810 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700811 case fieldnum.FieldOptions_Packed:
Damien Neil8012b442019-01-18 09:32:24 -0800812 xd.lazy.isPacked = wire.DecodeBool(v)
813 }
814 default:
815 m := wire.ConsumeFieldValue(num, typ, b)
816 b = b[m:]
817 }
818 }
819}
820
821func (sd *serviceDesc) unmarshalFull(b []byte, nb *nameBuilder) {
822 var rawMethods [][]byte
823 sd.lazy = new(serviceLazy)
824 for len(b) > 0 {
825 num, typ, n := wire.ConsumeTag(b)
826 b = b[n:]
827 switch typ {
828 case wire.BytesType:
829 v, m := wire.ConsumeBytes(b)
830 b = b[m:]
831 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700832 case fieldnum.ServiceDescriptorProto_Method:
Damien Neil8012b442019-01-18 09:32:24 -0800833 rawMethods = append(rawMethods, v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700834 case fieldnum.ServiceDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800835 sd.lazy.options = append(sd.lazy.options, v...)
836 }
837 default:
838 m := wire.ConsumeFieldValue(num, typ, b)
839 b = b[m:]
840 }
841 }
842
843 if len(rawMethods) > 0 {
844 sd.lazy.methods.list = make([]methodDesc, len(rawMethods))
845 for i, b := range rawMethods {
846 sd.lazy.methods.list[i].unmarshalFull(b, nb, sd.parentFile, sd, i)
847 }
848 }
Damien Neil8012b442019-01-18 09:32:24 -0800849}
850
851func (md *methodDesc) unmarshalFull(b []byte, nb *nameBuilder, pf *fileDesc, pd pref.Descriptor, i int) {
852 md.parentFile = pf
853 md.parent = pd
854 md.index = i
855
856 for len(b) > 0 {
857 num, typ, n := wire.ConsumeTag(b)
858 b = b[n:]
859 switch typ {
860 case wire.VarintType:
861 v, m := wire.ConsumeVarint(b)
862 b = b[m:]
863 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700864 case fieldnum.MethodDescriptorProto_ClientStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800865 md.isStreamingClient = wire.DecodeBool(v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700866 case fieldnum.MethodDescriptorProto_ServerStreaming:
Damien Neil8012b442019-01-18 09:32:24 -0800867 md.isStreamingServer = wire.DecodeBool(v)
868 }
869 case wire.BytesType:
870 v, m := wire.ConsumeBytes(b)
871 b = b[m:]
872 switch num {
Joe Tsaica46d8c2019-03-20 16:51:09 -0700873 case fieldnum.MethodDescriptorProto_Name:
Damien Neil8012b442019-01-18 09:32:24 -0800874 md.fullName = nb.AppendFullName(pd.FullName(), v)
Joe Tsaica46d8c2019-03-20 16:51:09 -0700875 case fieldnum.MethodDescriptorProto_Options:
Damien Neil8012b442019-01-18 09:32:24 -0800876 md.options = append(md.options, v...)
877 }
878 default:
879 m := wire.ConsumeFieldValue(num, typ, b)
880 b = b[m:]
881 }
882 }
Damien Neil8012b442019-01-18 09:32:24 -0800883}