...

Source file src/google.golang.org/protobuf/internal/filedesc/desc.go

Documentation: google.golang.org/protobuf/internal/filedesc

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

View as plain text