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	"bytes"
9	"fmt"
10	"sync"
11	"sync/atomic"
12
13	"google.golang.org/protobuf/internal/descfmt"
14	"google.golang.org/protobuf/internal/descopts"
15	"google.golang.org/protobuf/internal/encoding/defval"
16	"google.golang.org/protobuf/internal/genid"
17	"google.golang.org/protobuf/internal/pragma"
18	"google.golang.org/protobuf/internal/strs"
19	pref "google.golang.org/protobuf/reflect/protoreflect"
20	"google.golang.org/protobuf/reflect/protoregistry"
21)
22
23// The types in this file may have a suffix:
24//	• L0: Contains fields common to all descriptors (except File) and
25//	must be initialized up front.
26//	• L1: Contains fields specific to a descriptor and
27//	must be initialized up front.
28//	• L2: Contains fields that are lazily initialized when constructing
29//	from the raw file descriptor. When constructing as a literal, the L2
30//	fields must be initialized up front.
31//
32// The types are exported so that packages like reflect/protodesc can
33// directly construct descriptors.
34
35type (
36	File struct {
37		fileRaw
38		L1 FileL1
39
40		once uint32     // atomically set if L2 is valid
41		mu   sync.Mutex // protects L2
42		L2   *FileL2
43	}
44	FileL1 struct {
45		Syntax  pref.Syntax
46		Path    string
47		Package pref.FullName
48
49		Enums      Enums
50		Messages   Messages
51		Extensions Extensions
52		Services   Services
53	}
54	FileL2 struct {
55		Options   func() pref.ProtoMessage
56		Imports   FileImports
57		Locations SourceLocations
58	}
59)
60
61func (fd *File) ParentFile() pref.FileDescriptor { return fd }
62func (fd *File) Parent() pref.Descriptor         { return nil }
63func (fd *File) Index() int                      { return 0 }
64func (fd *File) Syntax() pref.Syntax             { return fd.L1.Syntax }
65func (fd *File) Name() pref.Name                 { return fd.L1.Package.Name() }
66func (fd *File) FullName() pref.FullName         { return fd.L1.Package }
67func (fd *File) IsPlaceholder() bool             { return false }
68func (fd *File) Options() pref.ProtoMessage {
69	if f := fd.lazyInit().Options; f != nil {
70		return f()
71	}
72	return descopts.File
73}
74func (fd *File) Path() string                          { return fd.L1.Path }
75func (fd *File) Package() pref.FullName                { return fd.L1.Package }
76func (fd *File) Imports() pref.FileImports             { return &fd.lazyInit().Imports }
77func (fd *File) Enums() pref.EnumDescriptors           { return &fd.L1.Enums }
78func (fd *File) Messages() pref.MessageDescriptors     { return &fd.L1.Messages }
79func (fd *File) Extensions() pref.ExtensionDescriptors { return &fd.L1.Extensions }
80func (fd *File) Services() pref.ServiceDescriptors     { return &fd.L1.Services }
81func (fd *File) SourceLocations() pref.SourceLocations { return &fd.lazyInit().Locations }
82func (fd *File) Format(s fmt.State, r rune)            { descfmt.FormatDesc(s, r, fd) }
83func (fd *File) ProtoType(pref.FileDescriptor)         {}
84func (fd *File) ProtoInternal(pragma.DoNotImplement)   {}
85
86func (fd *File) lazyInit() *FileL2 {
87	if atomic.LoadUint32(&fd.once) == 0 {
88		fd.lazyInitOnce()
89	}
90	return fd.L2
91}
92
93func (fd *File) lazyInitOnce() {
94	fd.mu.Lock()
95	if fd.L2 == nil {
96		fd.lazyRawInit() // recursively initializes all L2 structures
97	}
98	atomic.StoreUint32(&fd.once, 1)
99	fd.mu.Unlock()
100}
101
102// ProtoLegacyRawDesc is a pseudo-internal API for allowing the v1 code
103// to be able to retrieve the raw descriptor.
104//
105// WARNING: This method is exempt from the compatibility promise and may be
106// removed in the future without warning.
107func (fd *File) ProtoLegacyRawDesc() []byte {
108	return fd.builder.RawDescriptor
109}
110
111// GoPackagePath is a pseudo-internal API for determining the Go package path
112// that this file descriptor is declared in.
113//
114// WARNING: This method is exempt from the compatibility promise and may be
115// removed in the future without warning.
116func (fd *File) GoPackagePath() string {
117	return fd.builder.GoPackagePath
118}
119
120type (
121	Enum struct {
122		Base
123		L1 EnumL1
124		L2 *EnumL2 // protected by fileDesc.once
125	}
126	EnumL1 struct {
127		eagerValues bool // controls whether EnumL2.Values is already populated
128	}
129	EnumL2 struct {
130		Options        func() pref.ProtoMessage
131		Values         EnumValues
132		ReservedNames  Names
133		ReservedRanges EnumRanges
134	}
135
136	EnumValue struct {
137		Base
138		L1 EnumValueL1
139	}
140	EnumValueL1 struct {
141		Options func() pref.ProtoMessage
142		Number  pref.EnumNumber
143	}
144)
145
146func (ed *Enum) Options() pref.ProtoMessage {
147	if f := ed.lazyInit().Options; f != nil {
148		return f()
149	}
150	return descopts.Enum
151}
152func (ed *Enum) Values() pref.EnumValueDescriptors {
153	if ed.L1.eagerValues {
154		return &ed.L2.Values
155	}
156	return &ed.lazyInit().Values
157}
158func (ed *Enum) ReservedNames() pref.Names       { return &ed.lazyInit().ReservedNames }
159func (ed *Enum) ReservedRanges() pref.EnumRanges { return &ed.lazyInit().ReservedRanges }
160func (ed *Enum) Format(s fmt.State, r rune)      { descfmt.FormatDesc(s, r, ed) }
161func (ed *Enum) ProtoType(pref.EnumDescriptor)   {}
162func (ed *Enum) lazyInit() *EnumL2 {
163	ed.L0.ParentFile.lazyInit() // implicitly initializes L2
164	return ed.L2
165}
166
167func (ed *EnumValue) Options() pref.ProtoMessage {
168	if f := ed.L1.Options; f != nil {
169		return f()
170	}
171	return descopts.EnumValue
172}
173func (ed *EnumValue) Number() pref.EnumNumber            { return ed.L1.Number }
174func (ed *EnumValue) Format(s fmt.State, r rune)         { descfmt.FormatDesc(s, r, ed) }
175func (ed *EnumValue) ProtoType(pref.EnumValueDescriptor) {}
176
177type (
178	Message struct {
179		Base
180		L1 MessageL1
181		L2 *MessageL2 // protected by fileDesc.once
182	}
183	MessageL1 struct {
184		Enums        Enums
185		Messages     Messages
186		Extensions   Extensions
187		IsMapEntry   bool // promoted from google.protobuf.MessageOptions
188		IsMessageSet bool // promoted from google.protobuf.MessageOptions
189	}
190	MessageL2 struct {
191		Options               func() pref.ProtoMessage
192		Fields                Fields
193		Oneofs                Oneofs
194		ReservedNames         Names
195		ReservedRanges        FieldRanges
196		RequiredNumbers       FieldNumbers // must be consistent with Fields.Cardinality
197		ExtensionRanges       FieldRanges
198		ExtensionRangeOptions []func() pref.ProtoMessage // must be same length as ExtensionRanges
199	}
200
201	Field struct {
202		Base
203		L1 FieldL1
204	}
205	FieldL1 struct {
206		Options          func() pref.ProtoMessage
207		Number           pref.FieldNumber
208		Cardinality      pref.Cardinality // must be consistent with Message.RequiredNumbers
209		Kind             pref.Kind
210		JSONName         jsonName
211		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
212		IsWeak           bool // promoted from google.protobuf.FieldOptions
213		HasPacked        bool // promoted from google.protobuf.FieldOptions
214		IsPacked         bool // promoted from google.protobuf.FieldOptions
215		HasEnforceUTF8   bool // promoted from google.protobuf.FieldOptions
216		EnforceUTF8      bool // promoted from google.protobuf.FieldOptions
217		Default          defaultValue
218		ContainingOneof  pref.OneofDescriptor // must be consistent with Message.Oneofs.Fields
219		Enum             pref.EnumDescriptor
220		Message          pref.MessageDescriptor
221	}
222
223	Oneof struct {
224		Base
225		L1 OneofL1
226	}
227	OneofL1 struct {
228		Options func() pref.ProtoMessage
229		Fields  OneofFields // must be consistent with Message.Fields.ContainingOneof
230	}
231)
232
233func (md *Message) Options() pref.ProtoMessage {
234	if f := md.lazyInit().Options; f != nil {
235		return f()
236	}
237	return descopts.Message
238}
239func (md *Message) IsMapEntry() bool                   { return md.L1.IsMapEntry }
240func (md *Message) Fields() pref.FieldDescriptors      { return &md.lazyInit().Fields }
241func (md *Message) Oneofs() pref.OneofDescriptors      { return &md.lazyInit().Oneofs }
242func (md *Message) ReservedNames() pref.Names          { return &md.lazyInit().ReservedNames }
243func (md *Message) ReservedRanges() pref.FieldRanges   { return &md.lazyInit().ReservedRanges }
244func (md *Message) RequiredNumbers() pref.FieldNumbers { return &md.lazyInit().RequiredNumbers }
245func (md *Message) ExtensionRanges() pref.FieldRanges  { return &md.lazyInit().ExtensionRanges }
246func (md *Message) ExtensionRangeOptions(i int) pref.ProtoMessage {
247	if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil {
248		return f()
249	}
250	return descopts.ExtensionRange
251}
252func (md *Message) Enums() pref.EnumDescriptors           { return &md.L1.Enums }
253func (md *Message) Messages() pref.MessageDescriptors     { return &md.L1.Messages }
254func (md *Message) Extensions() pref.ExtensionDescriptors { return &md.L1.Extensions }
255func (md *Message) ProtoType(pref.MessageDescriptor)      {}
256func (md *Message) Format(s fmt.State, r rune)            { descfmt.FormatDesc(s, r, md) }
257func (md *Message) lazyInit() *MessageL2 {
258	md.L0.ParentFile.lazyInit() // implicitly initializes L2
259	return md.L2
260}
261
262// IsMessageSet is a pseudo-internal API for checking whether a message
263// should serialize in the proto1 message format.
264//
265// WARNING: This method is exempt from the compatibility promise and may be
266// removed in the future without warning.
267func (md *Message) IsMessageSet() bool {
268	return md.L1.IsMessageSet
269}
270
271func (fd *Field) Options() pref.ProtoMessage {
272	if f := fd.L1.Options; f != nil {
273		return f()
274	}
275	return descopts.Field
276}
277func (fd *Field) Number() pref.FieldNumber      { return fd.L1.Number }
278func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality }
279func (fd *Field) Kind() pref.Kind               { return fd.L1.Kind }
280func (fd *Field) HasJSONName() bool             { return fd.L1.JSONName.has }
281func (fd *Field) JSONName() string              { return fd.L1.JSONName.get(fd) }
282func (fd *Field) HasPresence() bool {
283	return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil)
284}
285func (fd *Field) HasOptionalKeyword() bool {
286	return (fd.L0.ParentFile.L1.Syntax == pref.Proto2 && fd.L1.Cardinality == pref.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional
287}
288func (fd *Field) IsPacked() bool {
289	if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != pref.Proto2 && fd.L1.Cardinality == pref.Repeated {
290		switch fd.L1.Kind {
291		case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind:
292		default:
293			return true
294		}
295	}
296	return fd.L1.IsPacked
297}
298func (fd *Field) IsExtension() bool { return false }
299func (fd *Field) IsWeak() bool      { return fd.L1.IsWeak }
300func (fd *Field) IsList() bool      { return fd.Cardinality() == pref.Repeated && !fd.IsMap() }
301func (fd *Field) IsMap() bool       { return fd.Message() != nil && fd.Message().IsMapEntry() }
302func (fd *Field) MapKey() pref.FieldDescriptor {
303	if !fd.IsMap() {
304		return nil
305	}
306	return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number)
307}
308func (fd *Field) MapValue() pref.FieldDescriptor {
309	if !fd.IsMap() {
310		return nil
311	}
312	return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number)
313}
314func (fd *Field) HasDefault() bool                           { return fd.L1.Default.has }
315func (fd *Field) Default() pref.Value                        { return fd.L1.Default.get(fd) }
316func (fd *Field) DefaultEnumValue() pref.EnumValueDescriptor { return fd.L1.Default.enum }
317func (fd *Field) ContainingOneof() pref.OneofDescriptor      { return fd.L1.ContainingOneof }
318func (fd *Field) ContainingMessage() pref.MessageDescriptor {
319	return fd.L0.Parent.(pref.MessageDescriptor)
320}
321func (fd *Field) Enum() pref.EnumDescriptor {
322	return fd.L1.Enum
323}
324func (fd *Field) Message() pref.MessageDescriptor {
325	if fd.L1.IsWeak {
326		if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil {
327			return d.(pref.MessageDescriptor)
328		}
329	}
330	return fd.L1.Message
331}
332func (fd *Field) Format(s fmt.State, r rune)     { descfmt.FormatDesc(s, r, fd) }
333func (fd *Field) ProtoType(pref.FieldDescriptor) {}
334
335// EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8
336// validation for the string field. This exists for Google-internal use only
337// since proto3 did not enforce UTF-8 validity prior to the open-source release.
338// If this method does not exist, the default is to enforce valid UTF-8.
339//
340// WARNING: This method is exempt from the compatibility promise and may be
341// removed in the future without warning.
342func (fd *Field) EnforceUTF8() bool {
343	if fd.L1.HasEnforceUTF8 {
344		return fd.L1.EnforceUTF8
345	}
346	return fd.L0.ParentFile.L1.Syntax == pref.Proto3
347}
348
349func (od *Oneof) IsSynthetic() bool {
350	return od.L0.ParentFile.L1.Syntax == pref.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword()
351}
352func (od *Oneof) Options() pref.ProtoMessage {
353	if f := od.L1.Options; f != nil {
354		return f()
355	}
356	return descopts.Oneof
357}
358func (od *Oneof) Fields() pref.FieldDescriptors  { return &od.L1.Fields }
359func (od *Oneof) Format(s fmt.State, r rune)     { descfmt.FormatDesc(s, r, od) }
360func (od *Oneof) ProtoType(pref.OneofDescriptor) {}
361
362type (
363	Extension struct {
364		Base
365		L1 ExtensionL1
366		L2 *ExtensionL2 // protected by fileDesc.once
367	}
368	ExtensionL1 struct {
369		Number      pref.FieldNumber
370		Extendee    pref.MessageDescriptor
371		Cardinality pref.Cardinality
372		Kind        pref.Kind
373	}
374	ExtensionL2 struct {
375		Options          func() pref.ProtoMessage
376		JSONName         jsonName
377		IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto
378		IsPacked         bool // promoted from google.protobuf.FieldOptions
379		Default          defaultValue
380		Enum             pref.EnumDescriptor
381		Message          pref.MessageDescriptor
382	}
383)
384
385func (xd *Extension) Options() pref.ProtoMessage {
386	if f := xd.lazyInit().Options; f != nil {
387		return f()
388	}
389	return descopts.Field
390}
391func (xd *Extension) Number() pref.FieldNumber      { return xd.L1.Number }
392func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality }
393func (xd *Extension) Kind() pref.Kind               { return xd.L1.Kind }
394func (xd *Extension) HasJSONName() bool             { return xd.lazyInit().JSONName.has }
395func (xd *Extension) JSONName() string              { return xd.lazyInit().JSONName.get(xd) }
396func (xd *Extension) HasPresence() bool             { return xd.L1.Cardinality != pref.Repeated }
397func (xd *Extension) HasOptionalKeyword() bool {
398	return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional
399}
400func (xd *Extension) IsPacked() bool                             { return xd.lazyInit().IsPacked }
401func (xd *Extension) IsExtension() bool                          { return true }
402func (xd *Extension) IsWeak() bool                               { return false }
403func (xd *Extension) IsList() bool                               { return xd.Cardinality() == pref.Repeated }
404func (xd *Extension) IsMap() bool                                { return false }
405func (xd *Extension) MapKey() pref.FieldDescriptor               { return nil }
406func (xd *Extension) MapValue() pref.FieldDescriptor             { return nil }
407func (xd *Extension) HasDefault() bool                           { return xd.lazyInit().Default.has }
408func (xd *Extension) Default() pref.Value                        { return xd.lazyInit().Default.get(xd) }
409func (xd *Extension) DefaultEnumValue() pref.EnumValueDescriptor { return xd.lazyInit().Default.enum }
410func (xd *Extension) ContainingOneof() pref.OneofDescriptor      { return nil }
411func (xd *Extension) ContainingMessage() pref.MessageDescriptor  { return xd.L1.Extendee }
412func (xd *Extension) Enum() pref.EnumDescriptor                  { return xd.lazyInit().Enum }
413func (xd *Extension) Message() pref.MessageDescriptor            { return xd.lazyInit().Message }
414func (xd *Extension) Format(s fmt.State, r rune)                 { descfmt.FormatDesc(s, r, xd) }
415func (xd *Extension) ProtoType(pref.FieldDescriptor)             {}
416func (xd *Extension) ProtoInternal(pragma.DoNotImplement)        {}
417func (xd *Extension) lazyInit() *ExtensionL2 {
418	xd.L0.ParentFile.lazyInit() // implicitly initializes L2
419	return xd.L2
420}
421
422type (
423	Service struct {
424		Base
425		L1 ServiceL1
426		L2 *ServiceL2 // protected by fileDesc.once
427	}
428	ServiceL1 struct{}
429	ServiceL2 struct {
430		Options func() pref.ProtoMessage
431		Methods Methods
432	}
433
434	Method struct {
435		Base
436		L1 MethodL1
437	}
438	MethodL1 struct {
439		Options           func() pref.ProtoMessage
440		Input             pref.MessageDescriptor
441		Output            pref.MessageDescriptor
442		IsStreamingClient bool
443		IsStreamingServer bool
444	}
445)
446
447func (sd *Service) Options() pref.ProtoMessage {
448	if f := sd.lazyInit().Options; f != nil {
449		return f()
450	}
451	return descopts.Service
452}
453func (sd *Service) Methods() pref.MethodDescriptors     { return &sd.lazyInit().Methods }
454func (sd *Service) Format(s fmt.State, r rune)          { descfmt.FormatDesc(s, r, sd) }
455func (sd *Service) ProtoType(pref.ServiceDescriptor)    {}
456func (sd *Service) ProtoInternal(pragma.DoNotImplement) {}
457func (sd *Service) lazyInit() *ServiceL2 {
458	sd.L0.ParentFile.lazyInit() // implicitly initializes L2
459	return sd.L2
460}
461
462func (md *Method) Options() pref.ProtoMessage {
463	if f := md.L1.Options; f != nil {
464		return f()
465	}
466	return descopts.Method
467}
468func (md *Method) Input() pref.MessageDescriptor       { return md.L1.Input }
469func (md *Method) Output() pref.MessageDescriptor      { return md.L1.Output }
470func (md *Method) IsStreamingClient() bool             { return md.L1.IsStreamingClient }
471func (md *Method) IsStreamingServer() bool             { return md.L1.IsStreamingServer }
472func (md *Method) Format(s fmt.State, r rune)          { descfmt.FormatDesc(s, r, md) }
473func (md *Method) ProtoType(pref.MethodDescriptor)     {}
474func (md *Method) ProtoInternal(pragma.DoNotImplement) {}
475
476// Surrogate files are can be used to create standalone descriptors
477// where the syntax is only information derived from the parent file.
478var (
479	SurrogateProto2 = &File{L1: FileL1{Syntax: pref.Proto2}, L2: &FileL2{}}
480	SurrogateProto3 = &File{L1: FileL1{Syntax: pref.Proto3}, L2: &FileL2{}}
481)
482
483type (
484	Base struct {
485		L0 BaseL0
486	}
487	BaseL0 struct {
488		FullName   pref.FullName // must be populated
489		ParentFile *File         // must be populated
490		Parent     pref.Descriptor
491		Index      int
492	}
493)
494
495func (d *Base) Name() pref.Name         { return d.L0.FullName.Name() }
496func (d *Base) FullName() pref.FullName { return d.L0.FullName }
497func (d *Base) ParentFile() pref.FileDescriptor {
498	if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 {
499		return nil // surrogate files are not real parents
500	}
501	return d.L0.ParentFile
502}
503func (d *Base) Parent() pref.Descriptor             { return d.L0.Parent }
504func (d *Base) Index() int                          { return d.L0.Index }
505func (d *Base) Syntax() pref.Syntax                 { return d.L0.ParentFile.Syntax() }
506func (d *Base) IsPlaceholder() bool                 { return false }
507func (d *Base) ProtoInternal(pragma.DoNotImplement) {}
508
509type jsonName struct {
510	has  bool
511	once sync.Once
512	name string
513}
514
515// Init initializes the name. It is exported for use by other internal packages.
516func (js *jsonName) Init(s string) {
517	js.has = true
518	js.name = s
519}
520
521func (js *jsonName) get(fd pref.FieldDescriptor) string {
522	if !js.has {
523		js.once.Do(func() {
524			js.name = strs.JSONCamelCase(string(fd.Name()))
525		})
526	}
527	return js.name
528}
529
530func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue {
531	dv := defaultValue{has: v.IsValid(), val: v, enum: ev}
532	if b, ok := v.Interface().([]byte); ok {
533		// Store a copy of the default bytes, so that we can detect
534		// accidental mutations of the original value.
535		dv.bytes = append([]byte(nil), b...)
536	}
537	return dv
538}
539
540func unmarshalDefault(b []byte, k pref.Kind, pf *File, ed pref.EnumDescriptor) defaultValue {
541	var evs pref.EnumValueDescriptors
542	if k == pref.EnumKind {
543		// If the enum is declared within the same file, be careful not to
544		// blindly call the Values method, lest we bind ourselves in a deadlock.
545		if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf {
546			evs = &e.L2.Values
547		} else {
548			evs = ed.Values()
549		}
550
551		// If we are unable to resolve the enum dependency, use a placeholder
552		// enum value since we will not be able to parse the default value.
553		if ed.IsPlaceholder() && pref.Name(b).IsValid() {
554			v := pref.ValueOfEnum(0)
555			ev := PlaceholderEnumValue(ed.FullName().Parent().Append(pref.Name(b)))
556			return DefaultValue(v, ev)
557		}
558	}
559
560	v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor)
561	if err != nil {
562		panic(err)
563	}
564	return DefaultValue(v, ev)
565}
566
567type defaultValue struct {
568	has   bool
569	val   pref.Value
570	enum  pref.EnumValueDescriptor
571	bytes []byte
572}
573
574func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value {
575	// Return the zero value as the default if unpopulated.
576	if !dv.has {
577		if fd.Cardinality() == pref.Repeated {
578			return pref.Value{}
579		}
580		switch fd.Kind() {
581		case pref.BoolKind:
582			return pref.ValueOfBool(false)
583		case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
584			return pref.ValueOfInt32(0)
585		case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
586			return pref.ValueOfInt64(0)
587		case pref.Uint32Kind, pref.Fixed32Kind:
588			return pref.ValueOfUint32(0)
589		case pref.Uint64Kind, pref.Fixed64Kind:
590			return pref.ValueOfUint64(0)
591		case pref.FloatKind:
592			return pref.ValueOfFloat32(0)
593		case pref.DoubleKind:
594			return pref.ValueOfFloat64(0)
595		case pref.StringKind:
596			return pref.ValueOfString("")
597		case pref.BytesKind:
598			return pref.ValueOfBytes(nil)
599		case pref.EnumKind:
600			if evs := fd.Enum().Values(); evs.Len() > 0 {
601				return pref.ValueOfEnum(evs.Get(0).Number())
602			}
603			return pref.ValueOfEnum(0)
604		}
605	}
606
607	if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) {
608		// TODO: Avoid panic if we're running with the race detector
609		// and instead spawn a goroutine that periodically resets
610		// this value back to the original to induce a race.
611		panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName()))
612	}
613	return dv.val
614}
615