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