...

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

View as plain text