podman

Форк
0
523 строки · 14.6 Кб
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
				case "proto3":
117
					fd.L1.Syntax = protoreflect.Proto3
118
				case "editions":
119
					fd.L1.Syntax = protoreflect.Editions
120
				default:
121
					panic("invalid syntax")
122
				}
123
			case genid.FileDescriptorProto_Name_field_number:
124
				fd.L1.Path = sb.MakeString(v)
125
			case genid.FileDescriptorProto_Package_field_number:
126
				fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
127
			case genid.FileDescriptorProto_Options_field_number:
128
				options = v
129
			case genid.FileDescriptorProto_EnumType_field_number:
130
				if prevField != genid.FileDescriptorProto_EnumType_field_number {
131
					if numEnums > 0 {
132
						panic("non-contiguous repeated field")
133
					}
134
					posEnums = len(b0) - len(b) - n - m
135
				}
136
				numEnums++
137
			case genid.FileDescriptorProto_MessageType_field_number:
138
				if prevField != genid.FileDescriptorProto_MessageType_field_number {
139
					if numMessages > 0 {
140
						panic("non-contiguous repeated field")
141
					}
142
					posMessages = len(b0) - len(b) - n - m
143
				}
144
				numMessages++
145
			case genid.FileDescriptorProto_Extension_field_number:
146
				if prevField != genid.FileDescriptorProto_Extension_field_number {
147
					if numExtensions > 0 {
148
						panic("non-contiguous repeated field")
149
					}
150
					posExtensions = len(b0) - len(b) - n - m
151
				}
152
				numExtensions++
153
			case genid.FileDescriptorProto_Service_field_number:
154
				if prevField != genid.FileDescriptorProto_Service_field_number {
155
					if numServices > 0 {
156
						panic("non-contiguous repeated field")
157
					}
158
					posServices = len(b0) - len(b) - n - m
159
				}
160
				numServices++
161
			}
162
			prevField = num
163
		case protowire.VarintType:
164
			v, m := protowire.ConsumeVarint(b)
165
			b = b[m:]
166
			switch num {
167
			case genid.FileDescriptorProto_Edition_field_number:
168
				fd.L1.Edition = Edition(v)
169
			}
170
		default:
171
			m := protowire.ConsumeFieldValue(num, typ, b)
172
			b = b[m:]
173
			prevField = -1 // ignore known field numbers of unknown wire type
174
		}
175
	}
176

177
	// If syntax is missing, it is assumed to be proto2.
178
	if fd.L1.Syntax == 0 {
179
		fd.L1.Syntax = protoreflect.Proto2
180
	}
181

182
	if fd.L1.Syntax == protoreflect.Editions {
183
		fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition)
184
	}
185

186
	// Parse editions features from options if any
187
	if options != nil {
188
		fd.unmarshalSeedOptions(options)
189
	}
190

191
	// Must allocate all declarations before parsing each descriptor type
192
	// to ensure we handled all descriptors in "flattened ordering".
193
	if numEnums > 0 {
194
		fd.L1.Enums.List = fd.allocEnums(numEnums)
195
	}
196
	if numMessages > 0 {
197
		fd.L1.Messages.List = fd.allocMessages(numMessages)
198
	}
199
	if numExtensions > 0 {
200
		fd.L1.Extensions.List = fd.allocExtensions(numExtensions)
201
	}
202
	if numServices > 0 {
203
		fd.L1.Services.List = fd.allocServices(numServices)
204
	}
205

206
	if numEnums > 0 {
207
		b := b0[posEnums:]
208
		for i := range fd.L1.Enums.List {
209
			_, n := protowire.ConsumeVarint(b)
210
			v, m := protowire.ConsumeBytes(b[n:])
211
			fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i)
212
			b = b[n+m:]
213
		}
214
	}
215
	if numMessages > 0 {
216
		b := b0[posMessages:]
217
		for i := range fd.L1.Messages.List {
218
			_, n := protowire.ConsumeVarint(b)
219
			v, m := protowire.ConsumeBytes(b[n:])
220
			fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i)
221
			b = b[n+m:]
222
		}
223
	}
224
	if numExtensions > 0 {
225
		b := b0[posExtensions:]
226
		for i := range fd.L1.Extensions.List {
227
			_, n := protowire.ConsumeVarint(b)
228
			v, m := protowire.ConsumeBytes(b[n:])
229
			fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i)
230
			b = b[n+m:]
231
		}
232
	}
233
	if numServices > 0 {
234
		b := b0[posServices:]
235
		for i := range fd.L1.Services.List {
236
			_, n := protowire.ConsumeVarint(b)
237
			v, m := protowire.ConsumeBytes(b[n:])
238
			fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i)
239
			b = b[n+m:]
240
		}
241
	}
242
}
243

244
func (fd *File) unmarshalSeedOptions(b []byte) {
245
	for b := b; len(b) > 0; {
246
		num, typ, n := protowire.ConsumeTag(b)
247
		b = b[n:]
248
		switch typ {
249
		case protowire.BytesType:
250
			v, m := protowire.ConsumeBytes(b)
251
			b = b[m:]
252
			switch num {
253
			case genid.FileOptions_Features_field_number:
254
				if fd.Syntax() != protoreflect.Editions {
255
					panic(fmt.Sprintf("invalid descriptor: using edition features in a proto with syntax %s", fd.Syntax()))
256
				}
257
				fd.L1.EditionFeatures = unmarshalFeatureSet(v, fd.L1.EditionFeatures)
258
			}
259
		default:
260
			m := protowire.ConsumeFieldValue(num, typ, b)
261
			b = b[m:]
262
		}
263
	}
264
}
265

266
func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
267
	ed.L0.ParentFile = pf
268
	ed.L0.Parent = pd
269
	ed.L0.Index = i
270

271
	var numValues int
272
	for b := b; len(b) > 0; {
273
		num, typ, n := protowire.ConsumeTag(b)
274
		b = b[n:]
275
		switch typ {
276
		case protowire.BytesType:
277
			v, m := protowire.ConsumeBytes(b)
278
			b = b[m:]
279
			switch num {
280
			case genid.EnumDescriptorProto_Name_field_number:
281
				ed.L0.FullName = appendFullName(sb, pd.FullName(), v)
282
			case genid.EnumDescriptorProto_Value_field_number:
283
				numValues++
284
			}
285
		default:
286
			m := protowire.ConsumeFieldValue(num, typ, b)
287
			b = b[m:]
288
		}
289
	}
290

291
	// Only construct enum value descriptors for top-level enums since
292
	// they are needed for registration.
293
	if pd != pf {
294
		return
295
	}
296
	ed.L1.eagerValues = true
297
	ed.L2 = new(EnumL2)
298
	ed.L2.Values.List = make([]EnumValue, numValues)
299
	for i := 0; len(b) > 0; {
300
		num, typ, n := protowire.ConsumeTag(b)
301
		b = b[n:]
302
		switch typ {
303
		case protowire.BytesType:
304
			v, m := protowire.ConsumeBytes(b)
305
			b = b[m:]
306
			switch num {
307
			case genid.EnumDescriptorProto_Value_field_number:
308
				ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i)
309
				i++
310
			}
311
		default:
312
			m := protowire.ConsumeFieldValue(num, typ, b)
313
			b = b[m:]
314
		}
315
	}
316
}
317

318
func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
319
	md.L0.ParentFile = pf
320
	md.L0.Parent = pd
321
	md.L0.Index = i
322
	md.L1.EditionFeatures = featuresFromParentDesc(md.Parent())
323

324
	var prevField protoreflect.FieldNumber
325
	var numEnums, numMessages, numExtensions int
326
	var posEnums, posMessages, posExtensions int
327
	b0 := b
328
	for len(b) > 0 {
329
		num, typ, n := protowire.ConsumeTag(b)
330
		b = b[n:]
331
		switch typ {
332
		case protowire.BytesType:
333
			v, m := protowire.ConsumeBytes(b)
334
			b = b[m:]
335
			switch num {
336
			case genid.DescriptorProto_Name_field_number:
337
				md.L0.FullName = appendFullName(sb, pd.FullName(), v)
338
			case genid.DescriptorProto_EnumType_field_number:
339
				if prevField != genid.DescriptorProto_EnumType_field_number {
340
					if numEnums > 0 {
341
						panic("non-contiguous repeated field")
342
					}
343
					posEnums = len(b0) - len(b) - n - m
344
				}
345
				numEnums++
346
			case genid.DescriptorProto_NestedType_field_number:
347
				if prevField != genid.DescriptorProto_NestedType_field_number {
348
					if numMessages > 0 {
349
						panic("non-contiguous repeated field")
350
					}
351
					posMessages = len(b0) - len(b) - n - m
352
				}
353
				numMessages++
354
			case genid.DescriptorProto_Extension_field_number:
355
				if prevField != genid.DescriptorProto_Extension_field_number {
356
					if numExtensions > 0 {
357
						panic("non-contiguous repeated field")
358
					}
359
					posExtensions = len(b0) - len(b) - n - m
360
				}
361
				numExtensions++
362
			case genid.DescriptorProto_Options_field_number:
363
				md.unmarshalSeedOptions(v)
364
			}
365
			prevField = num
366
		default:
367
			m := protowire.ConsumeFieldValue(num, typ, b)
368
			b = b[m:]
369
			prevField = -1 // ignore known field numbers of unknown wire type
370
		}
371
	}
372

373
	// Must allocate all declarations before parsing each descriptor type
374
	// to ensure we handled all descriptors in "flattened ordering".
375
	if numEnums > 0 {
376
		md.L1.Enums.List = pf.allocEnums(numEnums)
377
	}
378
	if numMessages > 0 {
379
		md.L1.Messages.List = pf.allocMessages(numMessages)
380
	}
381
	if numExtensions > 0 {
382
		md.L1.Extensions.List = pf.allocExtensions(numExtensions)
383
	}
384

385
	if numEnums > 0 {
386
		b := b0[posEnums:]
387
		for i := range md.L1.Enums.List {
388
			_, n := protowire.ConsumeVarint(b)
389
			v, m := protowire.ConsumeBytes(b[n:])
390
			md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i)
391
			b = b[n+m:]
392
		}
393
	}
394
	if numMessages > 0 {
395
		b := b0[posMessages:]
396
		for i := range md.L1.Messages.List {
397
			_, n := protowire.ConsumeVarint(b)
398
			v, m := protowire.ConsumeBytes(b[n:])
399
			md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i)
400
			b = b[n+m:]
401
		}
402
	}
403
	if numExtensions > 0 {
404
		b := b0[posExtensions:]
405
		for i := range md.L1.Extensions.List {
406
			_, n := protowire.ConsumeVarint(b)
407
			v, m := protowire.ConsumeBytes(b[n:])
408
			md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i)
409
			b = b[n+m:]
410
		}
411
	}
412
}
413

414
func (md *Message) unmarshalSeedOptions(b []byte) {
415
	for len(b) > 0 {
416
		num, typ, n := protowire.ConsumeTag(b)
417
		b = b[n:]
418
		switch typ {
419
		case protowire.VarintType:
420
			v, m := protowire.ConsumeVarint(b)
421
			b = b[m:]
422
			switch num {
423
			case genid.MessageOptions_MapEntry_field_number:
424
				md.L1.IsMapEntry = protowire.DecodeBool(v)
425
			case genid.MessageOptions_MessageSetWireFormat_field_number:
426
				md.L1.IsMessageSet = protowire.DecodeBool(v)
427
			}
428
		case protowire.BytesType:
429
			v, m := protowire.ConsumeBytes(b)
430
			b = b[m:]
431
			switch num {
432
			case genid.MessageOptions_Features_field_number:
433
				md.L1.EditionFeatures = unmarshalFeatureSet(v, md.L1.EditionFeatures)
434
			}
435
		default:
436
			m := protowire.ConsumeFieldValue(num, typ, b)
437
			b = b[m:]
438
		}
439
	}
440
}
441

442
func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
443
	xd.L0.ParentFile = pf
444
	xd.L0.Parent = pd
445
	xd.L0.Index = i
446

447
	for len(b) > 0 {
448
		num, typ, n := protowire.ConsumeTag(b)
449
		b = b[n:]
450
		switch typ {
451
		case protowire.VarintType:
452
			v, m := protowire.ConsumeVarint(b)
453
			b = b[m:]
454
			switch num {
455
			case genid.FieldDescriptorProto_Number_field_number:
456
				xd.L1.Number = protoreflect.FieldNumber(v)
457
			case genid.FieldDescriptorProto_Label_field_number:
458
				xd.L1.Cardinality = protoreflect.Cardinality(v)
459
			case genid.FieldDescriptorProto_Type_field_number:
460
				xd.L1.Kind = protoreflect.Kind(v)
461
			}
462
		case protowire.BytesType:
463
			v, m := protowire.ConsumeBytes(b)
464
			b = b[m:]
465
			switch num {
466
			case genid.FieldDescriptorProto_Name_field_number:
467
				xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
468
			case genid.FieldDescriptorProto_Extendee_field_number:
469
				xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
470
			}
471
		default:
472
			m := protowire.ConsumeFieldValue(num, typ, b)
473
			b = b[m:]
474
		}
475
	}
476
}
477

478
func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
479
	sd.L0.ParentFile = pf
480
	sd.L0.Parent = pd
481
	sd.L0.Index = i
482

483
	for len(b) > 0 {
484
		num, typ, n := protowire.ConsumeTag(b)
485
		b = b[n:]
486
		switch typ {
487
		case protowire.BytesType:
488
			v, m := protowire.ConsumeBytes(b)
489
			b = b[m:]
490
			switch num {
491
			case genid.ServiceDescriptorProto_Name_field_number:
492
				sd.L0.FullName = appendFullName(sb, pd.FullName(), v)
493
			}
494
		default:
495
			m := protowire.ConsumeFieldValue(num, typ, b)
496
			b = b[m:]
497
		}
498
	}
499
}
500

501
var nameBuilderPool = sync.Pool{
502
	New: func() interface{} { return new(strs.Builder) },
503
}
504

505
func getBuilder() *strs.Builder {
506
	return nameBuilderPool.Get().(*strs.Builder)
507
}
508
func putBuilder(b *strs.Builder) {
509
	nameBuilderPool.Put(b)
510
}
511

512
// makeFullName converts b to a protoreflect.FullName,
513
// where b must start with a leading dot.
514
func makeFullName(sb *strs.Builder, b []byte) protoreflect.FullName {
515
	if len(b) == 0 || b[0] != '.' {
516
		panic("name reference must be fully qualified")
517
	}
518
	return protoreflect.FullName(sb.MakeString(b[1:]))
519
}
520

521
func appendFullName(sb *strs.Builder, prefix protoreflect.FullName, suffix []byte) protoreflect.FullName {
522
	return sb.AppendFullName(prefix, protoreflect.Name(strs.UnsafeString(suffix)))
523
}
524

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.