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