Test Failed
Push — main ( 973aa1...436074 )
by Christian
02:37
created

filedesc.*Field.unmarshalFull   F

Complexity

Conditions 19

Size

Total Lines 65
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 54
nop 5
dl 0
loc 65
rs 0.5999
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like filedesc.*Field.unmarshalFull often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
	"reflect"
9
	"sync"
10
11
	"google.golang.org/protobuf/encoding/protowire"
12
	"google.golang.org/protobuf/internal/descopts"
13
	"google.golang.org/protobuf/internal/genid"
14
	"google.golang.org/protobuf/internal/strs"
15
	"google.golang.org/protobuf/proto"
16
	pref "google.golang.org/protobuf/reflect/protoreflect"
17
)
18
19
func (fd *File) lazyRawInit() {
20
	fd.unmarshalFull(fd.builder.RawDescriptor)
21
	fd.resolveMessages()
22
	fd.resolveExtensions()
23
	fd.resolveServices()
24
}
25
26
func (file *File) resolveMessages() {
27
	var depIdx int32
28
	for i := range file.allMessages {
29
		md := &file.allMessages[i]
30
31
		// Resolve message field dependencies.
32
		for j := range md.L2.Fields.List {
33
			fd := &md.L2.Fields.List[j]
34
35
			// Weak fields are resolved upon actual use.
36
			if fd.L1.IsWeak {
37
				continue
38
			}
39
40
			// Resolve message field dependency.
41
			switch fd.L1.Kind {
42
			case pref.EnumKind:
43
				fd.L1.Enum = file.resolveEnumDependency(fd.L1.Enum, listFieldDeps, depIdx)
44
				depIdx++
45
			case pref.MessageKind, pref.GroupKind:
46
				fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx)
47
				depIdx++
48
			}
49
50
			// Default is resolved here since it depends on Enum being resolved.
51
			if v := fd.L1.Default.val; v.IsValid() {
52
				fd.L1.Default = unmarshalDefault(v.Bytes(), fd.L1.Kind, file, fd.L1.Enum)
53
			}
54
		}
55
	}
56
}
57
58
func (file *File) resolveExtensions() {
59
	var depIdx int32
60
	for i := range file.allExtensions {
61
		xd := &file.allExtensions[i]
62
63
		// Resolve extension field dependency.
64
		switch xd.L1.Kind {
65
		case pref.EnumKind:
66
			xd.L2.Enum = file.resolveEnumDependency(xd.L2.Enum, listExtDeps, depIdx)
67
			depIdx++
68
		case pref.MessageKind, pref.GroupKind:
69
			xd.L2.Message = file.resolveMessageDependency(xd.L2.Message, listExtDeps, depIdx)
70
			depIdx++
71
		}
72
73
		// Default is resolved here since it depends on Enum being resolved.
74
		if v := xd.L2.Default.val; v.IsValid() {
75
			xd.L2.Default = unmarshalDefault(v.Bytes(), xd.L1.Kind, file, xd.L2.Enum)
76
		}
77
	}
78
}
79
80
func (file *File) resolveServices() {
81
	var depIdx int32
82
	for i := range file.allServices {
83
		sd := &file.allServices[i]
84
85
		// Resolve method dependencies.
86
		for j := range sd.L2.Methods.List {
87
			md := &sd.L2.Methods.List[j]
88
			md.L1.Input = file.resolveMessageDependency(md.L1.Input, listMethInDeps, depIdx)
89
			md.L1.Output = file.resolveMessageDependency(md.L1.Output, listMethOutDeps, depIdx)
90
			depIdx++
91
		}
92
	}
93
}
94
95
func (file *File) resolveEnumDependency(ed pref.EnumDescriptor, i, j int32) pref.EnumDescriptor {
96
	r := file.builder.FileRegistry
97
	if r, ok := r.(resolverByIndex); ok {
98
		if ed2 := r.FindEnumByIndex(i, j, file.allEnums, file.allMessages); ed2 != nil {
99
			return ed2
100
		}
101
	}
102
	for i := range file.allEnums {
103
		if ed2 := &file.allEnums[i]; ed2.L0.FullName == ed.FullName() {
104
			return ed2
105
		}
106
	}
107
	if d, _ := r.FindDescriptorByName(ed.FullName()); d != nil {
108
		return d.(pref.EnumDescriptor)
109
	}
110
	return ed
111
}
112
113
func (file *File) resolveMessageDependency(md pref.MessageDescriptor, i, j int32) pref.MessageDescriptor {
114
	r := file.builder.FileRegistry
115
	if r, ok := r.(resolverByIndex); ok {
116
		if md2 := r.FindMessageByIndex(i, j, file.allEnums, file.allMessages); md2 != nil {
117
			return md2
118
		}
119
	}
120
	for i := range file.allMessages {
121
		if md2 := &file.allMessages[i]; md2.L0.FullName == md.FullName() {
122
			return md2
123
		}
124
	}
125
	if d, _ := r.FindDescriptorByName(md.FullName()); d != nil {
126
		return d.(pref.MessageDescriptor)
127
	}
128
	return md
129
}
130
131
func (fd *File) unmarshalFull(b []byte) {
132
	sb := getBuilder()
133
	defer putBuilder(sb)
134
135
	var enumIdx, messageIdx, extensionIdx, serviceIdx int
136
	var rawOptions []byte
137
	fd.L2 = new(FileL2)
138
	for len(b) > 0 {
139
		num, typ, n := protowire.ConsumeTag(b)
140
		b = b[n:]
141
		switch typ {
142
		case protowire.VarintType:
143
			v, m := protowire.ConsumeVarint(b)
144
			b = b[m:]
145
			switch num {
146
			case genid.FileDescriptorProto_PublicDependency_field_number:
147
				fd.L2.Imports[v].IsPublic = true
148
			case genid.FileDescriptorProto_WeakDependency_field_number:
149
				fd.L2.Imports[v].IsWeak = true
150
			}
151
		case protowire.BytesType:
152
			v, m := protowire.ConsumeBytes(b)
153
			b = b[m:]
154
			switch num {
155
			case genid.FileDescriptorProto_Dependency_field_number:
156
				path := sb.MakeString(v)
157
				imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
158
				if imp == nil {
159
					imp = PlaceholderFile(path)
160
				}
161
				fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp})
162
			case genid.FileDescriptorProto_EnumType_field_number:
163
				fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
164
				enumIdx++
165
			case genid.FileDescriptorProto_MessageType_field_number:
166
				fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
167
				messageIdx++
168
			case genid.FileDescriptorProto_Extension_field_number:
169
				fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
170
				extensionIdx++
171
			case genid.FileDescriptorProto_Service_field_number:
172
				fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb)
173
				serviceIdx++
174
			case genid.FileDescriptorProto_Options_field_number:
175
				rawOptions = appendOptions(rawOptions, v)
176
			}
177
		default:
178
			m := protowire.ConsumeFieldValue(num, typ, b)
179
			b = b[m:]
180
		}
181
	}
182
	fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
183
}
184
185
func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
186
	var rawValues [][]byte
187
	var rawOptions []byte
188
	if !ed.L1.eagerValues {
189
		ed.L2 = new(EnumL2)
190
	}
191
	for len(b) > 0 {
192
		num, typ, n := protowire.ConsumeTag(b)
193
		b = b[n:]
194
		switch typ {
195
		case protowire.BytesType:
196
			v, m := protowire.ConsumeBytes(b)
197
			b = b[m:]
198
			switch num {
199
			case genid.EnumDescriptorProto_Value_field_number:
200
				rawValues = append(rawValues, v)
201
			case genid.EnumDescriptorProto_ReservedName_field_number:
202
				ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
203
			case genid.EnumDescriptorProto_ReservedRange_field_number:
204
				ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v))
205
			case genid.EnumDescriptorProto_Options_field_number:
206
				rawOptions = appendOptions(rawOptions, v)
207
			}
208
		default:
209
			m := protowire.ConsumeFieldValue(num, typ, b)
210
			b = b[m:]
211
		}
212
	}
213
	if !ed.L1.eagerValues && len(rawValues) > 0 {
214
		ed.L2.Values.List = make([]EnumValue, len(rawValues))
215
		for i, b := range rawValues {
216
			ed.L2.Values.List[i].unmarshalFull(b, sb, ed.L0.ParentFile, ed, i)
217
		}
218
	}
219
	ed.L2.Options = ed.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Enum, rawOptions)
220
}
221
222
func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
223
	for len(b) > 0 {
224
		num, typ, n := protowire.ConsumeTag(b)
225
		b = b[n:]
226
		switch typ {
227
		case protowire.VarintType:
228
			v, m := protowire.ConsumeVarint(b)
229
			b = b[m:]
230
			switch num {
231
			case genid.EnumDescriptorProto_EnumReservedRange_Start_field_number:
232
				r[0] = pref.EnumNumber(v)
233
			case genid.EnumDescriptorProto_EnumReservedRange_End_field_number:
234
				r[1] = pref.EnumNumber(v)
235
			}
236
		default:
237
			m := protowire.ConsumeFieldValue(num, typ, b)
238
			b = b[m:]
239
		}
240
	}
241
	return r
242
}
243
244
func (vd *EnumValue) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
245
	vd.L0.ParentFile = pf
246
	vd.L0.Parent = pd
247
	vd.L0.Index = i
248
249
	var rawOptions []byte
250
	for len(b) > 0 {
251
		num, typ, n := protowire.ConsumeTag(b)
252
		b = b[n:]
253
		switch typ {
254
		case protowire.VarintType:
255
			v, m := protowire.ConsumeVarint(b)
256
			b = b[m:]
257
			switch num {
258
			case genid.EnumValueDescriptorProto_Number_field_number:
259
				vd.L1.Number = pref.EnumNumber(v)
260
			}
261
		case protowire.BytesType:
262
			v, m := protowire.ConsumeBytes(b)
263
			b = b[m:]
264
			switch num {
265
			case genid.EnumValueDescriptorProto_Name_field_number:
266
				// NOTE: Enum values are in the same scope as the enum parent.
267
				vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v)
268
			case genid.EnumValueDescriptorProto_Options_field_number:
269
				rawOptions = appendOptions(rawOptions, v)
270
			}
271
		default:
272
			m := protowire.ConsumeFieldValue(num, typ, b)
273
			b = b[m:]
274
		}
275
	}
276
	vd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.EnumValue, rawOptions)
277
}
278
279
func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) {
280
	var rawFields, rawOneofs [][]byte
281
	var enumIdx, messageIdx, extensionIdx int
282
	var rawOptions []byte
283
	md.L2 = new(MessageL2)
284
	for len(b) > 0 {
285
		num, typ, n := protowire.ConsumeTag(b)
286
		b = b[n:]
287
		switch typ {
288
		case protowire.BytesType:
289
			v, m := protowire.ConsumeBytes(b)
290
			b = b[m:]
291
			switch num {
292
			case genid.DescriptorProto_Field_field_number:
293
				rawFields = append(rawFields, v)
294
			case genid.DescriptorProto_OneofDecl_field_number:
295
				rawOneofs = append(rawOneofs, v)
296
			case genid.DescriptorProto_ReservedName_field_number:
297
				md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
298
			case genid.DescriptorProto_ReservedRange_field_number:
299
				md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v))
300
			case genid.DescriptorProto_ExtensionRange_field_number:
301
				r, rawOptions := unmarshalMessageExtensionRange(v)
302
				opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions)
303
				md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r)
304
				md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts)
305
			case genid.DescriptorProto_EnumType_field_number:
306
				md.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
307
				enumIdx++
308
			case genid.DescriptorProto_NestedType_field_number:
309
				md.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
310
				messageIdx++
311
			case genid.DescriptorProto_Extension_field_number:
312
				md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
313
				extensionIdx++
314
			case genid.DescriptorProto_Options_field_number:
315
				md.unmarshalOptions(v)
316
				rawOptions = appendOptions(rawOptions, v)
317
			}
318
		default:
319
			m := protowire.ConsumeFieldValue(num, typ, b)
320
			b = b[m:]
321
		}
322
	}
323
	if len(rawFields) > 0 || len(rawOneofs) > 0 {
324
		md.L2.Fields.List = make([]Field, len(rawFields))
325
		md.L2.Oneofs.List = make([]Oneof, len(rawOneofs))
326
		for i, b := range rawFields {
327
			fd := &md.L2.Fields.List[i]
328
			fd.unmarshalFull(b, sb, md.L0.ParentFile, md, i)
329
			if fd.L1.Cardinality == pref.Required {
330
				md.L2.RequiredNumbers.List = append(md.L2.RequiredNumbers.List, fd.L1.Number)
331
			}
332
		}
333
		for i, b := range rawOneofs {
334
			od := &md.L2.Oneofs.List[i]
335
			od.unmarshalFull(b, sb, md.L0.ParentFile, md, i)
336
		}
337
	}
338
	md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions)
339
}
340
341
func (md *Message) unmarshalOptions(b []byte) {
342
	for len(b) > 0 {
343
		num, typ, n := protowire.ConsumeTag(b)
344
		b = b[n:]
345
		switch typ {
346
		case protowire.VarintType:
347
			v, m := protowire.ConsumeVarint(b)
348
			b = b[m:]
349
			switch num {
350
			case genid.MessageOptions_MapEntry_field_number:
351
				md.L1.IsMapEntry = protowire.DecodeBool(v)
352
			case genid.MessageOptions_MessageSetWireFormat_field_number:
353
				md.L1.IsMessageSet = protowire.DecodeBool(v)
354
			}
355
		default:
356
			m := protowire.ConsumeFieldValue(num, typ, b)
357
			b = b[m:]
358
		}
359
	}
360
}
361
362
func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
363
	for len(b) > 0 {
364
		num, typ, n := protowire.ConsumeTag(b)
365
		b = b[n:]
366
		switch typ {
367
		case protowire.VarintType:
368
			v, m := protowire.ConsumeVarint(b)
369
			b = b[m:]
370
			switch num {
371
			case genid.DescriptorProto_ReservedRange_Start_field_number:
372
				r[0] = pref.FieldNumber(v)
373
			case genid.DescriptorProto_ReservedRange_End_field_number:
374
				r[1] = pref.FieldNumber(v)
375
			}
376
		default:
377
			m := protowire.ConsumeFieldValue(num, typ, b)
378
			b = b[m:]
379
		}
380
	}
381
	return r
382
}
383
384
func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, rawOptions []byte) {
385
	for len(b) > 0 {
386
		num, typ, n := protowire.ConsumeTag(b)
387
		b = b[n:]
388
		switch typ {
389
		case protowire.VarintType:
390
			v, m := protowire.ConsumeVarint(b)
391
			b = b[m:]
392
			switch num {
393
			case genid.DescriptorProto_ExtensionRange_Start_field_number:
394
				r[0] = pref.FieldNumber(v)
395
			case genid.DescriptorProto_ExtensionRange_End_field_number:
396
				r[1] = pref.FieldNumber(v)
397
			}
398
		case protowire.BytesType:
399
			v, m := protowire.ConsumeBytes(b)
400
			b = b[m:]
401
			switch num {
402
			case genid.DescriptorProto_ExtensionRange_Options_field_number:
403
				rawOptions = appendOptions(rawOptions, v)
404
			}
405
		default:
406
			m := protowire.ConsumeFieldValue(num, typ, b)
407
			b = b[m:]
408
		}
409
	}
410
	return r, rawOptions
411
}
412
413
func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
414
	fd.L0.ParentFile = pf
415
	fd.L0.Parent = pd
416
	fd.L0.Index = i
417
418
	var rawTypeName []byte
419
	var rawOptions []byte
420
	for len(b) > 0 {
421
		num, typ, n := protowire.ConsumeTag(b)
422
		b = b[n:]
423
		switch typ {
424
		case protowire.VarintType:
425
			v, m := protowire.ConsumeVarint(b)
426
			b = b[m:]
427
			switch num {
428
			case genid.FieldDescriptorProto_Number_field_number:
429
				fd.L1.Number = pref.FieldNumber(v)
430
			case genid.FieldDescriptorProto_Label_field_number:
431
				fd.L1.Cardinality = pref.Cardinality(v)
432
			case genid.FieldDescriptorProto_Type_field_number:
433
				fd.L1.Kind = pref.Kind(v)
434
			case genid.FieldDescriptorProto_OneofIndex_field_number:
435
				// In Message.unmarshalFull, we allocate slices for both
436
				// the field and oneof descriptors before unmarshaling either
437
				// of them. This ensures pointers to slice elements are stable.
438
				od := &pd.(*Message).L2.Oneofs.List[v]
439
				od.L1.Fields.List = append(od.L1.Fields.List, fd)
440
				if fd.L1.ContainingOneof != nil {
441
					panic("oneof type already set")
442
				}
443
				fd.L1.ContainingOneof = od
444
			case genid.FieldDescriptorProto_Proto3Optional_field_number:
445
				fd.L1.IsProto3Optional = protowire.DecodeBool(v)
446
			}
447
		case protowire.BytesType:
448
			v, m := protowire.ConsumeBytes(b)
449
			b = b[m:]
450
			switch num {
451
			case genid.FieldDescriptorProto_Name_field_number:
452
				fd.L0.FullName = appendFullName(sb, pd.FullName(), v)
453
			case genid.FieldDescriptorProto_JsonName_field_number:
454
				fd.L1.StringName.InitJSON(sb.MakeString(v))
455
			case genid.FieldDescriptorProto_DefaultValue_field_number:
456
				fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages
457
			case genid.FieldDescriptorProto_TypeName_field_number:
458
				rawTypeName = v
459
			case genid.FieldDescriptorProto_Options_field_number:
460
				fd.unmarshalOptions(v)
461
				rawOptions = appendOptions(rawOptions, v)
462
			}
463
		default:
464
			m := protowire.ConsumeFieldValue(num, typ, b)
465
			b = b[m:]
466
		}
467
	}
468
	if rawTypeName != nil {
469
		name := makeFullName(sb, rawTypeName)
470
		switch fd.L1.Kind {
471
		case pref.EnumKind:
472
			fd.L1.Enum = PlaceholderEnum(name)
473
		case pref.MessageKind, pref.GroupKind:
474
			fd.L1.Message = PlaceholderMessage(name)
475
		}
476
	}
477
	fd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Field, rawOptions)
478
}
479
480
func (fd *Field) unmarshalOptions(b []byte) {
481
	const FieldOptions_EnforceUTF8 = 13
482
483
	for len(b) > 0 {
484
		num, typ, n := protowire.ConsumeTag(b)
485
		b = b[n:]
486
		switch typ {
487
		case protowire.VarintType:
488
			v, m := protowire.ConsumeVarint(b)
489
			b = b[m:]
490
			switch num {
491
			case genid.FieldOptions_Packed_field_number:
492
				fd.L1.HasPacked = true
493
				fd.L1.IsPacked = protowire.DecodeBool(v)
494
			case genid.FieldOptions_Weak_field_number:
495
				fd.L1.IsWeak = protowire.DecodeBool(v)
496
			case FieldOptions_EnforceUTF8:
497
				fd.L1.HasEnforceUTF8 = true
498
				fd.L1.EnforceUTF8 = protowire.DecodeBool(v)
499
			}
500
		default:
501
			m := protowire.ConsumeFieldValue(num, typ, b)
502
			b = b[m:]
503
		}
504
	}
505
}
506
507
func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
508
	od.L0.ParentFile = pf
509
	od.L0.Parent = pd
510
	od.L0.Index = i
511
512
	var rawOptions []byte
513
	for len(b) > 0 {
514
		num, typ, n := protowire.ConsumeTag(b)
515
		b = b[n:]
516
		switch typ {
517
		case protowire.BytesType:
518
			v, m := protowire.ConsumeBytes(b)
519
			b = b[m:]
520
			switch num {
521
			case genid.OneofDescriptorProto_Name_field_number:
522
				od.L0.FullName = appendFullName(sb, pd.FullName(), v)
523
			case genid.OneofDescriptorProto_Options_field_number:
524
				rawOptions = appendOptions(rawOptions, v)
525
			}
526
		default:
527
			m := protowire.ConsumeFieldValue(num, typ, b)
528
			b = b[m:]
529
		}
530
	}
531
	od.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Oneof, rawOptions)
532
}
533
534
func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
535
	var rawTypeName []byte
536
	var rawOptions []byte
537
	xd.L2 = new(ExtensionL2)
538
	for len(b) > 0 {
539
		num, typ, n := protowire.ConsumeTag(b)
540
		b = b[n:]
541
		switch typ {
542
		case protowire.VarintType:
543
			v, m := protowire.ConsumeVarint(b)
544
			b = b[m:]
545
			switch num {
546
			case genid.FieldDescriptorProto_Proto3Optional_field_number:
547
				xd.L2.IsProto3Optional = protowire.DecodeBool(v)
548
			}
549
		case protowire.BytesType:
550
			v, m := protowire.ConsumeBytes(b)
551
			b = b[m:]
552
			switch num {
553
			case genid.FieldDescriptorProto_JsonName_field_number:
554
				xd.L2.StringName.InitJSON(sb.MakeString(v))
555
			case genid.FieldDescriptorProto_DefaultValue_field_number:
556
				xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions
557
			case genid.FieldDescriptorProto_TypeName_field_number:
558
				rawTypeName = v
559
			case genid.FieldDescriptorProto_Options_field_number:
560
				xd.unmarshalOptions(v)
561
				rawOptions = appendOptions(rawOptions, v)
562
			}
563
		default:
564
			m := protowire.ConsumeFieldValue(num, typ, b)
565
			b = b[m:]
566
		}
567
	}
568
	if rawTypeName != nil {
569
		name := makeFullName(sb, rawTypeName)
570
		switch xd.L1.Kind {
571
		case pref.EnumKind:
572
			xd.L2.Enum = PlaceholderEnum(name)
573
		case pref.MessageKind, pref.GroupKind:
574
			xd.L2.Message = PlaceholderMessage(name)
575
		}
576
	}
577
	xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions)
578
}
579
580
func (xd *Extension) unmarshalOptions(b []byte) {
581
	for len(b) > 0 {
582
		num, typ, n := protowire.ConsumeTag(b)
583
		b = b[n:]
584
		switch typ {
585
		case protowire.VarintType:
586
			v, m := protowire.ConsumeVarint(b)
587
			b = b[m:]
588
			switch num {
589
			case genid.FieldOptions_Packed_field_number:
590
				xd.L2.IsPacked = protowire.DecodeBool(v)
591
			}
592
		default:
593
			m := protowire.ConsumeFieldValue(num, typ, b)
594
			b = b[m:]
595
		}
596
	}
597
}
598
599
func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) {
600
	var rawMethods [][]byte
601
	var rawOptions []byte
602
	sd.L2 = new(ServiceL2)
603
	for len(b) > 0 {
604
		num, typ, n := protowire.ConsumeTag(b)
605
		b = b[n:]
606
		switch typ {
607
		case protowire.BytesType:
608
			v, m := protowire.ConsumeBytes(b)
609
			b = b[m:]
610
			switch num {
611
			case genid.ServiceDescriptorProto_Method_field_number:
612
				rawMethods = append(rawMethods, v)
613
			case genid.ServiceDescriptorProto_Options_field_number:
614
				rawOptions = appendOptions(rawOptions, v)
615
			}
616
		default:
617
			m := protowire.ConsumeFieldValue(num, typ, b)
618
			b = b[m:]
619
		}
620
	}
621
	if len(rawMethods) > 0 {
622
		sd.L2.Methods.List = make([]Method, len(rawMethods))
623
		for i, b := range rawMethods {
624
			sd.L2.Methods.List[i].unmarshalFull(b, sb, sd.L0.ParentFile, sd, i)
625
		}
626
	}
627
	sd.L2.Options = sd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Service, rawOptions)
628
}
629
630
func (md *Method) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
631
	md.L0.ParentFile = pf
632
	md.L0.Parent = pd
633
	md.L0.Index = i
634
635
	var rawOptions []byte
636
	for len(b) > 0 {
637
		num, typ, n := protowire.ConsumeTag(b)
638
		b = b[n:]
639
		switch typ {
640
		case protowire.VarintType:
641
			v, m := protowire.ConsumeVarint(b)
642
			b = b[m:]
643
			switch num {
644
			case genid.MethodDescriptorProto_ClientStreaming_field_number:
645
				md.L1.IsStreamingClient = protowire.DecodeBool(v)
646
			case genid.MethodDescriptorProto_ServerStreaming_field_number:
647
				md.L1.IsStreamingServer = protowire.DecodeBool(v)
648
			}
649
		case protowire.BytesType:
650
			v, m := protowire.ConsumeBytes(b)
651
			b = b[m:]
652
			switch num {
653
			case genid.MethodDescriptorProto_Name_field_number:
654
				md.L0.FullName = appendFullName(sb, pd.FullName(), v)
655
			case genid.MethodDescriptorProto_InputType_field_number:
656
				md.L1.Input = PlaceholderMessage(makeFullName(sb, v))
657
			case genid.MethodDescriptorProto_OutputType_field_number:
658
				md.L1.Output = PlaceholderMessage(makeFullName(sb, v))
659
			case genid.MethodDescriptorProto_Options_field_number:
660
				rawOptions = appendOptions(rawOptions, v)
661
			}
662
		default:
663
			m := protowire.ConsumeFieldValue(num, typ, b)
664
			b = b[m:]
665
		}
666
	}
667
	md.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Method, rawOptions)
668
}
669
670
// appendOptions appends src to dst, where the returned slice is never nil.
671
// This is necessary to distinguish between empty and unpopulated options.
672
func appendOptions(dst, src []byte) []byte {
673
	if dst == nil {
674
		dst = []byte{}
675
	}
676
	return append(dst, src...)
677
}
678
679
// optionsUnmarshaler constructs a lazy unmarshal function for an options message.
680
//
681
// The type of message to unmarshal to is passed as a pointer since the
682
// vars in descopts may not yet be populated at the time this function is called.
683
func (db *Builder) optionsUnmarshaler(p *pref.ProtoMessage, b []byte) func() pref.ProtoMessage {
684
	if b == nil {
685
		return nil
686
	}
687
	var opts pref.ProtoMessage
688
	var once sync.Once
689
	return func() pref.ProtoMessage {
690
		once.Do(func() {
691
			if *p == nil {
692
				panic("Descriptor.Options called without importing the descriptor package")
693
			}
694
			opts = reflect.New(reflect.TypeOf(*p).Elem()).Interface().(pref.ProtoMessage)
695
			if err := (proto.UnmarshalOptions{
696
				AllowPartial: true,
697
				Resolver:     db.TypeResolver,
698
			}).Unmarshal(b, opts); err != nil {
699
				panic(err)
700
			}
701
		})
702
		return opts
703
	}
704
}
705