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
5package filedesc
6
7import (
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
19func (fd *File) lazyRawInit() {
20	fd.unmarshalFull(fd.builder.RawDescriptor)
21	fd.resolveMessages()
22	fd.resolveExtensions()
23	fd.resolveServices()
24}
25
26func (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
58func (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
80func (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
95func (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
113func (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
131func (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
185func (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
222func 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
244func (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
279func (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
341func (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
362func 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
384func 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
413func (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.JSONName.Init(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
480func (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
507func (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
534func (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.JSONName.Init(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
580func (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
599func (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
630func (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.
672func 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.
683func (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