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