desc_init.go raw
1 // Copyright 2019 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
5 package filedesc
6
7 import (
8 "fmt"
9 "sync"
10
11 "google.golang.org/protobuf/encoding/protowire"
12 "google.golang.org/protobuf/internal/genid"
13 "google.golang.org/protobuf/internal/strs"
14 "google.golang.org/protobuf/reflect/protoreflect"
15 )
16
17 // fileRaw is a data struct used when initializing a file descriptor from
18 // a raw FileDescriptorProto.
19 type fileRaw struct {
20 builder Builder
21 allEnums []Enum
22 allMessages []Message
23 allExtensions []Extension
24 allServices []Service
25 }
26
27 func newRawFile(db Builder) *File {
28 fd := &File{fileRaw: fileRaw{builder: db}}
29 fd.initDecls(db.NumEnums, db.NumMessages, db.NumExtensions, db.NumServices)
30 fd.unmarshalSeed(db.RawDescriptor)
31
32 // Extended message targets are eagerly resolved since registration
33 // needs this information at program init time.
34 for i := range fd.allExtensions {
35 xd := &fd.allExtensions[i]
36 xd.L1.Extendee = fd.resolveMessageDependency(xd.L1.Extendee, listExtTargets, int32(i))
37 }
38
39 fd.checkDecls()
40 return fd
41 }
42
43 // initDecls pre-allocates slices for the exact number of enums, messages
44 // (including map entries), extensions, and services declared in the proto file.
45 // This is done to avoid regrowing the slice, which would change the address
46 // for any previously seen declaration.
47 //
48 // The alloc methods "allocates" slices by pulling from the capacity.
49 func (fd *File) initDecls(numEnums, numMessages, numExtensions, numServices int32) {
50 fd.allEnums = make([]Enum, 0, numEnums)
51 fd.allMessages = make([]Message, 0, numMessages)
52 fd.allExtensions = make([]Extension, 0, numExtensions)
53 fd.allServices = make([]Service, 0, numServices)
54 }
55
56 func (fd *File) allocEnums(n int) []Enum {
57 total := len(fd.allEnums)
58 es := fd.allEnums[total : total+n]
59 fd.allEnums = fd.allEnums[:total+n]
60 return es
61 }
62 func (fd *File) allocMessages(n int) []Message {
63 total := len(fd.allMessages)
64 ms := fd.allMessages[total : total+n]
65 fd.allMessages = fd.allMessages[:total+n]
66 return ms
67 }
68 func (fd *File) allocExtensions(n int) []Extension {
69 total := len(fd.allExtensions)
70 xs := fd.allExtensions[total : total+n]
71 fd.allExtensions = fd.allExtensions[:total+n]
72 return xs
73 }
74 func (fd *File) allocServices(n int) []Service {
75 total := len(fd.allServices)
76 xs := fd.allServices[total : total+n]
77 fd.allServices = fd.allServices[:total+n]
78 return xs
79 }
80
81 // checkDecls performs a sanity check that the expected number of expected
82 // declarations matches the number that were found in the descriptor proto.
83 func (fd *File) checkDecls() {
84 switch {
85 case len(fd.allEnums) != cap(fd.allEnums):
86 case len(fd.allMessages) != cap(fd.allMessages):
87 case len(fd.allExtensions) != cap(fd.allExtensions):
88 case len(fd.allServices) != cap(fd.allServices):
89 default:
90 return
91 }
92 panic("mismatching cardinality")
93 }
94
95 func (fd *File) unmarshalSeed(b []byte) {
96 sb := getBuilder()
97 defer putBuilder(sb)
98
99 var prevField protoreflect.FieldNumber
100 var numEnums, numMessages, numExtensions, numServices int
101 var posEnums, posMessages, posExtensions, posServices int
102 var options []byte
103 b0 := b
104 for len(b) > 0 {
105 num, typ, n := protowire.ConsumeTag(b)
106 b = b[n:]
107 switch typ {
108 case protowire.BytesType:
109 v, m := protowire.ConsumeBytes(b)
110 b = b[m:]
111 switch num {
112 case genid.FileDescriptorProto_Syntax_field_number:
113 switch string(v) {
114 case "proto2":
115 fd.L1.Syntax = protoreflect.Proto2
116 fd.L1.Edition = EditionProto2
117 case "proto3":
118 fd.L1.Syntax = protoreflect.Proto3
119 fd.L1.Edition = EditionProto3
120 case "editions":
121 fd.L1.Syntax = protoreflect.Editions
122 default:
123 panic("invalid syntax")
124 }
125 case genid.FileDescriptorProto_Name_field_number:
126 fd.L1.Path = sb.MakeString(v)
127 case genid.FileDescriptorProto_Package_field_number:
128 fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
129 case genid.FileDescriptorProto_Options_field_number:
130 options = v
131 case genid.FileDescriptorProto_EnumType_field_number:
132 if prevField != genid.FileDescriptorProto_EnumType_field_number {
133 if numEnums > 0 {
134 panic("non-contiguous repeated field")
135 }
136 posEnums = len(b0) - len(b) - n - m
137 }
138 numEnums++
139 case genid.FileDescriptorProto_MessageType_field_number:
140 if prevField != genid.FileDescriptorProto_MessageType_field_number {
141 if numMessages > 0 {
142 panic("non-contiguous repeated field")
143 }
144 posMessages = len(b0) - len(b) - n - m
145 }
146 numMessages++
147 case genid.FileDescriptorProto_Extension_field_number:
148 if prevField != genid.FileDescriptorProto_Extension_field_number {
149 if numExtensions > 0 {
150 panic("non-contiguous repeated field")
151 }
152 posExtensions = len(b0) - len(b) - n - m
153 }
154 numExtensions++
155 case genid.FileDescriptorProto_Service_field_number:
156 if prevField != genid.FileDescriptorProto_Service_field_number {
157 if numServices > 0 {
158 panic("non-contiguous repeated field")
159 }
160 posServices = len(b0) - len(b) - n - m
161 }
162 numServices++
163 }
164 prevField = num
165 case protowire.VarintType:
166 v, m := protowire.ConsumeVarint(b)
167 b = b[m:]
168 switch num {
169 case genid.FileDescriptorProto_Edition_field_number:
170 fd.L1.Edition = Edition(v)
171 }
172 default:
173 m := protowire.ConsumeFieldValue(num, typ, b)
174 b = b[m:]
175 prevField = -1 // ignore known field numbers of unknown wire type
176 }
177 }
178
179 // If syntax is missing, it is assumed to be proto2.
180 if fd.L1.Syntax == 0 {
181 fd.L1.Syntax = protoreflect.Proto2
182 fd.L1.Edition = EditionProto2
183 }
184
185 fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition)
186
187 // Parse editions features from options if any
188 if options != nil {
189 fd.unmarshalSeedOptions(options)
190 }
191
192 // Must allocate all declarations before parsing each descriptor type
193 // to ensure we handled all descriptors in "flattened ordering".
194 if numEnums > 0 {
195 fd.L1.Enums.List = fd.allocEnums(numEnums)
196 }
197 if numMessages > 0 {
198 fd.L1.Messages.List = fd.allocMessages(numMessages)
199 }
200 if numExtensions > 0 {
201 fd.L1.Extensions.List = fd.allocExtensions(numExtensions)
202 }
203 if numServices > 0 {
204 fd.L1.Services.List = fd.allocServices(numServices)
205 }
206
207 if numEnums > 0 {
208 b := b0[posEnums:]
209 for i := range fd.L1.Enums.List {
210 _, n := protowire.ConsumeVarint(b)
211 v, m := protowire.ConsumeBytes(b[n:])
212 fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i)
213 b = b[n+m:]
214 }
215 }
216 if numMessages > 0 {
217 b := b0[posMessages:]
218 for i := range fd.L1.Messages.List {
219 _, n := protowire.ConsumeVarint(b)
220 v, m := protowire.ConsumeBytes(b[n:])
221 fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i)
222 b = b[n+m:]
223 }
224 }
225 if numExtensions > 0 {
226 b := b0[posExtensions:]
227 for i := range fd.L1.Extensions.List {
228 _, n := protowire.ConsumeVarint(b)
229 v, m := protowire.ConsumeBytes(b[n:])
230 fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i)
231 b = b[n+m:]
232 }
233 }
234 if numServices > 0 {
235 b := b0[posServices:]
236 for i := range fd.L1.Services.List {
237 _, n := protowire.ConsumeVarint(b)
238 v, m := protowire.ConsumeBytes(b[n:])
239 fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i)
240 b = b[n+m:]
241 }
242 }
243 }
244
245 func (fd *File) unmarshalSeedOptions(b []byte) {
246 for b := b; len(b) > 0; {
247 num, typ, n := protowire.ConsumeTag(b)
248 b = b[n:]
249 switch typ {
250 case protowire.BytesType:
251 v, m := protowire.ConsumeBytes(b)
252 b = b[m:]
253 switch num {
254 case genid.FileOptions_Features_field_number:
255 if fd.Syntax() != protoreflect.Editions {
256 panic(fmt.Sprintf("invalid descriptor: using edition features in a proto with syntax %s", fd.Syntax()))
257 }
258 fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
259 }
260 default:
261 m := protowire.ConsumeFieldValue(num, typ, b)
262 b = b[m:]
263 }
264 }
265 }
266
267 func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
268 ed.L0.ParentFile = pf
269 ed.L0.Parent = pd
270 ed.L0.Index = i
271 ed.L1.EditionFeatures = featuresFromParentDesc(ed.Parent())
272
273 var numValues int
274 for b := b; len(b) > 0; {
275 num, typ, n := protowire.ConsumeTag(b)
276 b = b[n:]
277 switch typ {
278 case protowire.BytesType:
279 v, m := protowire.ConsumeBytes(b)
280 b = b[m:]
281 switch num {
282 case genid.EnumDescriptorProto_Name_field_number:
283 ed.L0.FullName = appendFullName(sb, pd.FullName(), v)
284 case genid.EnumDescriptorProto_Value_field_number:
285 numValues++
286 }
287 case protowire.VarintType:
288 v, m := protowire.ConsumeVarint(b)
289 b = b[m:]
290 switch num {
291 case genid.EnumDescriptorProto_Visibility_field_number:
292 ed.L1.Visibility = int32(v)
293 }
294 default:
295 m := protowire.ConsumeFieldValue(num, typ, b)
296 b = b[m:]
297 }
298 }
299
300 // Only construct enum value descriptors for top-level enums since
301 // they are needed for registration.
302 if pd != pf {
303 return
304 }
305 ed.L1.eagerValues = true
306 ed.L2 = new(EnumL2)
307 ed.L2.Values.List = make([]EnumValue, numValues)
308 for i := 0; len(b) > 0; {
309 num, typ, n := protowire.ConsumeTag(b)
310 b = b[n:]
311 switch typ {
312 case protowire.BytesType:
313 v, m := protowire.ConsumeBytes(b)
314 b = b[m:]
315 switch num {
316 case genid.EnumDescriptorProto_Value_field_number:
317 ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i)
318 i++
319 }
320 default:
321 m := protowire.ConsumeFieldValue(num, typ, b)
322 b = b[m:]
323 }
324 }
325 }
326
327 func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
328 md.L0.ParentFile = pf
329 md.L0.Parent = pd
330 md.L0.Index = i
331 md.L1.EditionFeatures = featuresFromParentDesc(md.Parent())
332
333 var prevField protoreflect.FieldNumber
334 var numEnums, numMessages, numExtensions int
335 var posEnums, posMessages, posExtensions int
336 b0 := b
337 for len(b) > 0 {
338 num, typ, n := protowire.ConsumeTag(b)
339 b = b[n:]
340 switch typ {
341 case protowire.BytesType:
342 v, m := protowire.ConsumeBytes(b)
343 b = b[m:]
344 switch num {
345 case genid.DescriptorProto_Name_field_number:
346 md.L0.FullName = appendFullName(sb, pd.FullName(), v)
347 case genid.DescriptorProto_EnumType_field_number:
348 if prevField != genid.DescriptorProto_EnumType_field_number {
349 if numEnums > 0 {
350 panic("non-contiguous repeated field")
351 }
352 posEnums = len(b0) - len(b) - n - m
353 }
354 numEnums++
355 case genid.DescriptorProto_NestedType_field_number:
356 if prevField != genid.DescriptorProto_NestedType_field_number {
357 if numMessages > 0 {
358 panic("non-contiguous repeated field")
359 }
360 posMessages = len(b0) - len(b) - n - m
361 }
362 numMessages++
363 case genid.DescriptorProto_Extension_field_number:
364 if prevField != genid.DescriptorProto_Extension_field_number {
365 if numExtensions > 0 {
366 panic("non-contiguous repeated field")
367 }
368 posExtensions = len(b0) - len(b) - n - m
369 }
370 numExtensions++
371 case genid.DescriptorProto_Options_field_number:
372 md.unmarshalSeedOptions(v)
373 }
374 prevField = num
375 case protowire.VarintType:
376 v, m := protowire.ConsumeVarint(b)
377 b = b[m:]
378 switch num {
379 case genid.DescriptorProto_Visibility_field_number:
380 md.L1.Visibility = int32(v)
381 }
382 default:
383 m := protowire.ConsumeFieldValue(num, typ, b)
384 b = b[m:]
385 prevField = -1 // ignore known field numbers of unknown wire type
386 }
387 }
388
389 // Must allocate all declarations before parsing each descriptor type
390 // to ensure we handled all descriptors in "flattened ordering".
391 if numEnums > 0 {
392 md.L1.Enums.List = pf.allocEnums(numEnums)
393 }
394 if numMessages > 0 {
395 md.L1.Messages.List = pf.allocMessages(numMessages)
396 }
397 if numExtensions > 0 {
398 md.L1.Extensions.List = pf.allocExtensions(numExtensions)
399 }
400
401 if numEnums > 0 {
402 b := b0[posEnums:]
403 for i := range md.L1.Enums.List {
404 _, n := protowire.ConsumeVarint(b)
405 v, m := protowire.ConsumeBytes(b[n:])
406 md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i)
407 b = b[n+m:]
408 }
409 }
410 if numMessages > 0 {
411 b := b0[posMessages:]
412 for i := range md.L1.Messages.List {
413 _, n := protowire.ConsumeVarint(b)
414 v, m := protowire.ConsumeBytes(b[n:])
415 md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i)
416 b = b[n+m:]
417 }
418 }
419 if numExtensions > 0 {
420 b := b0[posExtensions:]
421 for i := range md.L1.Extensions.List {
422 _, n := protowire.ConsumeVarint(b)
423 v, m := protowire.ConsumeBytes(b[n:])
424 md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i)
425 b = b[n+m:]
426 }
427 }
428 }
429
430 func (md *Message) unmarshalSeedOptions(b []byte) {
431 for len(b) > 0 {
432 num, typ, n := protowire.ConsumeTag(b)
433 b = b[n:]
434 switch typ {
435 case protowire.VarintType:
436 v, m := protowire.ConsumeVarint(b)
437 b = b[m:]
438 switch num {
439 case genid.MessageOptions_MapEntry_field_number:
440 md.L1.IsMapEntry = protowire.DecodeBool(v)
441 case genid.MessageOptions_MessageSetWireFormat_field_number:
442 md.L1.IsMessageSet = protowire.DecodeBool(v)
443 }
444 case protowire.BytesType:
445 v, m := protowire.ConsumeBytes(b)
446 b = b[m:]
447 switch num {
448 case genid.MessageOptions_Features_field_number:
449 md.L1.EditionFeatures = unmarshalFeatureSet(v, md.L1.EditionFeatures)
450 }
451 default:
452 m := protowire.ConsumeFieldValue(num, typ, b)
453 b = b[m:]
454 }
455 }
456 }
457
458 func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
459 xd.L0.ParentFile = pf
460 xd.L0.Parent = pd
461 xd.L0.Index = i
462 xd.L1.EditionFeatures = featuresFromParentDesc(pd)
463
464 for len(b) > 0 {
465 num, typ, n := protowire.ConsumeTag(b)
466 b = b[n:]
467 switch typ {
468 case protowire.VarintType:
469 v, m := protowire.ConsumeVarint(b)
470 b = b[m:]
471 switch num {
472 case genid.FieldDescriptorProto_Number_field_number:
473 xd.L1.Number = protoreflect.FieldNumber(v)
474 case genid.FieldDescriptorProto_Label_field_number:
475 xd.L1.Cardinality = protoreflect.Cardinality(v)
476 case genid.FieldDescriptorProto_Type_field_number:
477 xd.L1.Kind = protoreflect.Kind(v)
478 }
479 case protowire.BytesType:
480 v, m := protowire.ConsumeBytes(b)
481 b = b[m:]
482 switch num {
483 case genid.FieldDescriptorProto_Name_field_number:
484 xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
485 case genid.FieldDescriptorProto_Extendee_field_number:
486 xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
487 case genid.FieldDescriptorProto_Options_field_number:
488 xd.unmarshalOptions(v)
489 }
490 default:
491 m := protowire.ConsumeFieldValue(num, typ, b)
492 b = b[m:]
493 }
494 }
495
496 if xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded {
497 xd.L1.Kind = protoreflect.GroupKind
498 }
499 }
500
501 func (xd *Extension) unmarshalOptions(b []byte) {
502 for len(b) > 0 {
503 num, typ, n := protowire.ConsumeTag(b)
504 b = b[n:]
505 switch typ {
506 case protowire.VarintType:
507 v, m := protowire.ConsumeVarint(b)
508 b = b[m:]
509 switch num {
510 case genid.FieldOptions_Packed_field_number:
511 xd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v)
512 case genid.FieldOptions_Lazy_field_number:
513 xd.L1.IsLazy = protowire.DecodeBool(v)
514 }
515 case protowire.BytesType:
516 v, m := protowire.ConsumeBytes(b)
517 b = b[m:]
518 switch num {
519 case genid.FieldOptions_Features_field_number:
520 xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures)
521 }
522 default:
523 m := protowire.ConsumeFieldValue(num, typ, b)
524 b = b[m:]
525 }
526 }
527 }
528
529 func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
530 sd.L0.ParentFile = pf
531 sd.L0.Parent = pd
532 sd.L0.Index = i
533
534 for len(b) > 0 {
535 num, typ, n := protowire.ConsumeTag(b)
536 b = b[n:]
537 switch typ {
538 case protowire.BytesType:
539 v, m := protowire.ConsumeBytes(b)
540 b = b[m:]
541 switch num {
542 case genid.ServiceDescriptorProto_Name_field_number:
543 sd.L0.FullName = appendFullName(sb, pd.FullName(), v)
544 }
545 default:
546 m := protowire.ConsumeFieldValue(num, typ, b)
547 b = b[m:]
548 }
549 }
550 }
551
552 var nameBuilderPool = sync.Pool{
553 New: func() any { return new(strs.Builder) },
554 }
555
556 func getBuilder() *strs.Builder {
557 return nameBuilderPool.Get().(*strs.Builder)
558 }
559 func putBuilder(b *strs.Builder) {
560 nameBuilderPool.Put(b)
561 }
562
563 // makeFullName converts b to a protoreflect.FullName,
564 // where b must start with a leading dot.
565 func makeFullName(sb *strs.Builder, b []byte) protoreflect.FullName {
566 if len(b) == 0 || b[0] != '.' {
567 panic("name reference must be fully qualified")
568 }
569 return protoreflect.FullName(sb.MakeString(b[1:]))
570 }
571
572 func appendFullName(sb *strs.Builder, prefix protoreflect.FullName, suffix []byte) protoreflect.FullName {
573 return sb.AppendFullName(prefix, protoreflect.Name(strs.UnsafeString(suffix)))
574 }
575