github.com/jhump/protoreflect@v1.16.0/desc/builder/field.go (about)

     1  package builder
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"unicode"
     7  
     8  	"google.golang.org/protobuf/proto"
     9  	"google.golang.org/protobuf/types/descriptorpb"
    10  
    11  	"github.com/jhump/protoreflect/desc"
    12  	"github.com/jhump/protoreflect/desc/internal"
    13  )
    14  
    15  // FieldBuilder is a builder used to construct a desc.FieldDescriptor. A field
    16  // builder is used to create fields and extensions as well as map entry
    17  // messages. It is also used to link groups (defined via a message builder) into
    18  // an enclosing message, associating it with a group field.  A non-extension
    19  // field builder *must* be added to a message before calling its Build() method.
    20  //
    21  // To create a new FieldBuilder, use NewField, NewMapField, NewGroupField,
    22  // NewExtension, or NewExtensionImported (depending on the type of field being
    23  // built).
    24  type FieldBuilder struct {
    25  	baseBuilder
    26  	number int32
    27  
    28  	// msgType is populated for fields that have a "private" message type that
    29  	// isn't expected to be referenced elsewhere. This happens for map fields,
    30  	// where the private message type represents the map entry, and for group
    31  	// fields.
    32  	msgType   *MessageBuilder
    33  	fieldType *FieldType
    34  
    35  	Options *descriptorpb.FieldOptions
    36  	Label   descriptorpb.FieldDescriptorProto_Label
    37  
    38  	// Proto3Optional indicates if the field is a proto3 optional field. This
    39  	// only applies to fields in files with "proto3" syntax whose Cardinality
    40  	// is set to protoreflect.Optional.
    41  	//
    42  	// If the file's syntax is not "proto3", this may not be set to true.
    43  	//
    44  	// This allows setting a field in a proto3 file to have explicit field
    45  	// presence. To manage field presence for fields in files that use
    46  	// "editions", set the field_presence field of the features option in
    47  	// Options.
    48  	Proto3Optional bool
    49  
    50  	Default  string
    51  	JsonName string
    52  
    53  	foreignExtendee *desc.MessageDescriptor
    54  	localExtendee   *MessageBuilder
    55  }
    56  
    57  // NewField creates a new FieldBuilder for a non-extension field with the given
    58  // name and type. To create a map or group field, see NewMapField or
    59  // NewGroupField respectively.
    60  //
    61  // The new field will be optional. See SetLabel, SetRepeated, and SetRequired
    62  // for changing this aspect of the field. The new field's tag will be zero,
    63  // which means it will be auto-assigned when the descriptor is built. Use
    64  // SetNumber or TrySetNumber to assign an explicit tag number.
    65  func NewField(name string, typ *FieldType) *FieldBuilder {
    66  	flb := &FieldBuilder{
    67  		baseBuilder: baseBuilderWithName(name),
    68  		fieldType:   typ,
    69  	}
    70  	return flb
    71  }
    72  
    73  // NewMapField creates a new FieldBuilder for a non-extension field with the
    74  // given name and whose type is a map of the given key and value types. Map keys
    75  // can be any of the scalar integer types, booleans, or strings. If any other
    76  // type is specified, this function will panic. Map values cannot be groups: if
    77  // a group type is specified, this function will panic.
    78  //
    79  // When this field is added to a message, the associated map entry message type
    80  // will also be added.
    81  //
    82  // The new field's tag will be zero, which means it will be auto-assigned when
    83  // the descriptor is built. Use SetNumber or TrySetNumber to assign an explicit
    84  // tag number.
    85  func NewMapField(name string, keyTyp, valTyp *FieldType) *FieldBuilder {
    86  	switch keyTyp.fieldType {
    87  	case descriptorpb.FieldDescriptorProto_TYPE_BOOL,
    88  		descriptorpb.FieldDescriptorProto_TYPE_STRING,
    89  		descriptorpb.FieldDescriptorProto_TYPE_INT32, descriptorpb.FieldDescriptorProto_TYPE_INT64,
    90  		descriptorpb.FieldDescriptorProto_TYPE_SINT32, descriptorpb.FieldDescriptorProto_TYPE_SINT64,
    91  		descriptorpb.FieldDescriptorProto_TYPE_UINT32, descriptorpb.FieldDescriptorProto_TYPE_UINT64,
    92  		descriptorpb.FieldDescriptorProto_TYPE_FIXED32, descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
    93  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED32, descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
    94  		// allowed
    95  	default:
    96  		panic(fmt.Sprintf("Map types cannot have keys of type %v", keyTyp.fieldType))
    97  	}
    98  	if valTyp.fieldType == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
    99  		panic(fmt.Sprintf("Map types cannot have values of type %v", valTyp.fieldType))
   100  	}
   101  	entryMsg := NewMessage(entryTypeName(name))
   102  	keyFlb := NewField("key", keyTyp)
   103  	keyFlb.number = 1
   104  	valFlb := NewField("value", valTyp)
   105  	valFlb.number = 2
   106  	entryMsg.AddField(keyFlb)
   107  	entryMsg.AddField(valFlb)
   108  	entryMsg.Options = &descriptorpb.MessageOptions{MapEntry: proto.Bool(true)}
   109  
   110  	flb := NewField(name, FieldTypeMessage(entryMsg)).
   111  		SetLabel(descriptorpb.FieldDescriptorProto_LABEL_REPEATED)
   112  	flb.msgType = entryMsg
   113  	entryMsg.setParent(flb)
   114  	return flb
   115  }
   116  
   117  // NewGroupField creates a new FieldBuilder for a non-extension field whose type
   118  // is a group with the given definition. The given message's name must start
   119  // with a capital letter, and the resulting field will have the same name but
   120  // converted to all lower-case. If a message is given with a name that starts
   121  // with a lower-case letter, this function will panic.
   122  //
   123  // When this field is added to a message, the associated group message type will
   124  // also be added.
   125  //
   126  // The new field will be optional. See SetLabel, SetRepeated, and SetRequired
   127  // for changing this aspect of the field. The new field's tag will be zero,
   128  // which means it will be auto-assigned when the descriptor is built. Use
   129  // SetNumber or TrySetNumber to assign an explicit tag number.
   130  func NewGroupField(mb *MessageBuilder) *FieldBuilder {
   131  	if !unicode.IsUpper(rune(mb.name[0])) {
   132  		panic(fmt.Sprintf("group name %s must start with a capital letter", mb.name))
   133  	}
   134  	Unlink(mb)
   135  
   136  	ft := &FieldType{
   137  		fieldType:    descriptorpb.FieldDescriptorProto_TYPE_GROUP,
   138  		localMsgType: mb,
   139  	}
   140  	fieldName := strings.ToLower(mb.GetName())
   141  	flb := NewField(fieldName, ft)
   142  	flb.msgType = mb
   143  	mb.setParent(flb)
   144  	return flb
   145  }
   146  
   147  // NewExtension creates a new FieldBuilder for an extension field with the given
   148  // name, tag, type, and extendee. The extendee given is a message builder.
   149  //
   150  // The new field will be optional. See SetLabel and SetRepeated for changing
   151  // this aspect of the field.
   152  func NewExtension(name string, tag int32, typ *FieldType, extendee *MessageBuilder) *FieldBuilder {
   153  	if extendee == nil {
   154  		panic("extendee cannot be nil")
   155  	}
   156  	flb := NewField(name, typ).SetNumber(tag)
   157  	flb.localExtendee = extendee
   158  	return flb
   159  }
   160  
   161  // NewExtensionImported creates a new FieldBuilder for an extension field with
   162  // the given name, tag, type, and extendee. The extendee given is a message
   163  // descriptor.
   164  //
   165  // The new field will be optional. See SetLabel and SetRepeated for changing
   166  // this aspect of the field.
   167  func NewExtensionImported(name string, tag int32, typ *FieldType, extendee *desc.MessageDescriptor) *FieldBuilder {
   168  	if extendee == nil {
   169  		panic("extendee cannot be nil")
   170  	}
   171  	flb := NewField(name, typ).SetNumber(tag)
   172  	flb.foreignExtendee = extendee
   173  	return flb
   174  }
   175  
   176  // FromField returns a FieldBuilder that is effectively a copy of the given
   177  // descriptor.
   178  //
   179  // Note that it is not just the given field that is copied but its entire file.
   180  // So the caller can get the parent element of the returned builder and the
   181  // result would be a builder that is effectively a copy of the field
   182  // descriptor's parent.
   183  //
   184  // This means that field builders created from descriptors do not need to be
   185  // explicitly assigned to a file in order to preserve the original field's
   186  // package name.
   187  func FromField(fld *desc.FieldDescriptor) (*FieldBuilder, error) {
   188  	if fb, err := FromFile(fld.GetFile()); err != nil {
   189  		return nil, err
   190  	} else if flb, ok := fb.findFullyQualifiedElement(fld.GetFullyQualifiedName()).(*FieldBuilder); ok {
   191  		return flb, nil
   192  	} else {
   193  		return nil, fmt.Errorf("could not find field %s after converting file %q to builder", fld.GetFullyQualifiedName(), fld.GetFile().GetName())
   194  	}
   195  }
   196  
   197  func fromField(fld *desc.FieldDescriptor) (*FieldBuilder, error) {
   198  	ft := fieldTypeFromDescriptor(fld)
   199  	flb := NewField(fld.GetName(), ft)
   200  	flb.Options = fld.GetFieldOptions()
   201  	flb.Label = fld.GetLabel()
   202  	flb.Proto3Optional = fld.IsProto3Optional()
   203  	flb.Default = fld.AsFieldDescriptorProto().GetDefaultValue()
   204  	flb.JsonName = fld.GetJSONName()
   205  	setComments(&flb.comments, fld.GetSourceInfo())
   206  
   207  	if fld.IsExtension() {
   208  		flb.foreignExtendee = fld.GetOwner()
   209  	}
   210  	if err := flb.TrySetNumber(fld.GetNumber()); err != nil {
   211  		return nil, err
   212  	}
   213  	return flb, nil
   214  }
   215  
   216  // SetName changes this field's name, returning the field builder for method
   217  // chaining. If the given new name is not valid (e.g. TrySetName would have
   218  // returned an error) then this method will panic.
   219  func (flb *FieldBuilder) SetName(newName string) *FieldBuilder {
   220  	if err := flb.TrySetName(newName); err != nil {
   221  		panic(err)
   222  	}
   223  	return flb
   224  }
   225  
   226  // TrySetName changes this field's name. It will return an error if the given
   227  // new name is not a valid protobuf identifier or if the parent builder already
   228  // has an element with the given name.
   229  //
   230  // If the field is a non-extension whose parent is a one-of, the one-of's
   231  // enclosing message is checked for elements with a conflicting name. Despite
   232  // the fact that one-of choices are modeled as children of the one-of builder,
   233  // in the protobuf IDL they are actually all defined in the message's namespace.
   234  func (flb *FieldBuilder) TrySetName(newName string) error {
   235  	var oldMsgName string
   236  	if flb.msgType != nil {
   237  		if flb.fieldType.fieldType == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
   238  			return fmt.Errorf("cannot change name of group field %s; change name of group instead", GetFullyQualifiedName(flb))
   239  		} else {
   240  			oldMsgName = flb.msgType.name
   241  			msgName := entryTypeName(newName)
   242  			if err := flb.msgType.trySetNameInternal(msgName); err != nil {
   243  				return err
   244  			}
   245  		}
   246  	}
   247  	if err := flb.baseBuilder.setName(flb, newName); err != nil {
   248  		// undo change to map entry name
   249  		if flb.msgType != nil && flb.fieldType.fieldType != descriptorpb.FieldDescriptorProto_TYPE_GROUP {
   250  			flb.msgType.setNameInternal(oldMsgName)
   251  		}
   252  		return err
   253  	}
   254  	return nil
   255  }
   256  
   257  func (flb *FieldBuilder) trySetNameInternal(newName string) error {
   258  	return flb.baseBuilder.setName(flb, newName)
   259  }
   260  
   261  func (flb *FieldBuilder) setNameInternal(newName string) {
   262  	if err := flb.trySetNameInternal(newName); err != nil {
   263  		panic(err)
   264  	}
   265  }
   266  
   267  // SetComments sets the comments associated with the field. This method returns
   268  // the field builder, for method chaining.
   269  func (flb *FieldBuilder) SetComments(c Comments) *FieldBuilder {
   270  	flb.comments = c
   271  	return flb
   272  }
   273  
   274  func (flb *FieldBuilder) setParent(newParent Builder) {
   275  	flb.baseBuilder.setParent(newParent)
   276  }
   277  
   278  // GetChildren returns any builders assigned to this field builder. The only
   279  // kind of children a field can have are message types, that correspond to the
   280  // field's map entry type or group type (for map and group fields respectively).
   281  func (flb *FieldBuilder) GetChildren() []Builder {
   282  	if flb.msgType != nil {
   283  		return []Builder{flb.msgType}
   284  	}
   285  	return nil
   286  }
   287  
   288  func (flb *FieldBuilder) findChild(name string) Builder {
   289  	if flb.msgType != nil && flb.msgType.name == name {
   290  		return flb.msgType
   291  	}
   292  	return nil
   293  }
   294  
   295  func (flb *FieldBuilder) removeChild(b Builder) {
   296  	if mb, ok := b.(*MessageBuilder); ok && mb == flb.msgType {
   297  		flb.msgType = nil
   298  		if p, ok := flb.parent.(*MessageBuilder); ok {
   299  			delete(p.symbols, mb.GetName())
   300  		}
   301  	}
   302  }
   303  
   304  func (flb *FieldBuilder) renamedChild(b Builder, oldName string) error {
   305  	if flb.msgType != nil {
   306  		var oldFieldName string
   307  		if flb.fieldType.fieldType == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
   308  			if !unicode.IsUpper(rune(b.GetName()[0])) {
   309  				return fmt.Errorf("group name %s must start with capital letter", b.GetName())
   310  			}
   311  			// change field name to be lower-case form of group name
   312  			oldFieldName = flb.name
   313  			fieldName := strings.ToLower(b.GetName())
   314  			if err := flb.trySetNameInternal(fieldName); err != nil {
   315  				return err
   316  			}
   317  		}
   318  		if p, ok := flb.parent.(*MessageBuilder); ok {
   319  			if err := p.addSymbol(b); err != nil {
   320  				if flb.fieldType.fieldType == descriptorpb.FieldDescriptorProto_TYPE_GROUP {
   321  					// revert the field rename
   322  					flb.setNameInternal(oldFieldName)
   323  				}
   324  				return err
   325  			}
   326  		}
   327  	}
   328  	return nil
   329  }
   330  
   331  // GetNumber returns this field's tag number, or zero if the tag number will be
   332  // auto-assigned when the field descriptor is built.
   333  func (flb *FieldBuilder) GetNumber() int32 {
   334  	return flb.number
   335  }
   336  
   337  // SetNumber changes the numeric tag for this field and then returns the field,
   338  // for method chaining. If the given new tag is not valid (e.g. TrySetNumber
   339  // would have returned an error) then this method will panic.
   340  func (flb *FieldBuilder) SetNumber(tag int32) *FieldBuilder {
   341  	if err := flb.TrySetNumber(tag); err != nil {
   342  		panic(err)
   343  	}
   344  	return flb
   345  }
   346  
   347  // TrySetNumber changes this field's tag number. It will return an error if the
   348  // given new tag is out of valid range or (for non-extension fields) if the
   349  // enclosing message already includes a field with the given tag.
   350  //
   351  // Non-extension fields can be set to zero, which means a proper tag number will
   352  // be auto-assigned when the descriptor is built. Extension field tags, however,
   353  // must be set to a valid non-zero value.
   354  func (flb *FieldBuilder) TrySetNumber(tag int32) error {
   355  	if tag == flb.number {
   356  		return nil // no change
   357  	}
   358  	if tag < 0 {
   359  		return fmt.Errorf("cannot set tag number for field %s to negative value %d", GetFullyQualifiedName(flb), tag)
   360  	}
   361  	if tag == 0 && flb.IsExtension() {
   362  		return fmt.Errorf("cannot set tag number for extension %s; only regular fields can be auto-assigned", GetFullyQualifiedName(flb))
   363  	}
   364  	if tag >= internal.SpecialReservedStart && tag <= internal.SpecialReservedEnd {
   365  		return fmt.Errorf("tag for field %s cannot be in special reserved range %d-%d", GetFullyQualifiedName(flb), internal.SpecialReservedStart, internal.SpecialReservedEnd)
   366  	}
   367  	if tag > internal.MaxTag {
   368  		return fmt.Errorf("tag for field %s cannot be above max %d", GetFullyQualifiedName(flb), internal.MaxTag)
   369  	}
   370  	oldTag := flb.number
   371  	flb.number = tag
   372  	if flb.IsExtension() {
   373  		// extension tags are not tracked by builders, so no more to do
   374  		return nil
   375  	}
   376  	switch p := flb.parent.(type) {
   377  	case *OneOfBuilder:
   378  		m := p.parent()
   379  		if m != nil {
   380  			if err := m.addTag(flb); err != nil {
   381  				flb.number = oldTag
   382  				return err
   383  			}
   384  			delete(m.fieldTags, oldTag)
   385  		}
   386  	case *MessageBuilder:
   387  		if err := p.addTag(flb); err != nil {
   388  			flb.number = oldTag
   389  			return err
   390  		}
   391  		delete(p.fieldTags, oldTag)
   392  	}
   393  	return nil
   394  }
   395  
   396  // SetOptions sets the field options for this field and returns the field, for
   397  // method chaining.
   398  func (flb *FieldBuilder) SetOptions(options *descriptorpb.FieldOptions) *FieldBuilder {
   399  	flb.Options = options
   400  	return flb
   401  }
   402  
   403  // SetLabel sets the label for this field, which can be optional, repeated, or
   404  // required. It returns the field builder, for method chaining.
   405  func (flb *FieldBuilder) SetLabel(lbl descriptorpb.FieldDescriptorProto_Label) *FieldBuilder {
   406  	flb.Label = lbl
   407  	return flb
   408  }
   409  
   410  // SetProto3Optional sets whether this is a proto3 optional field. It returns
   411  // the field builder, for method chaining.
   412  func (flb *FieldBuilder) SetProto3Optional(p3o bool) *FieldBuilder {
   413  	flb.Proto3Optional = p3o
   414  	return flb
   415  }
   416  
   417  // SetRepeated sets the label for this field to repeated. It returns the field
   418  // builder, for method chaining.
   419  func (flb *FieldBuilder) SetRepeated() *FieldBuilder {
   420  	return flb.SetLabel(descriptorpb.FieldDescriptorProto_LABEL_REPEATED)
   421  }
   422  
   423  // SetRequired sets the label for this field to required. It returns the field
   424  // builder, for method chaining.
   425  func (flb *FieldBuilder) SetRequired() *FieldBuilder {
   426  	return flb.SetLabel(descriptorpb.FieldDescriptorProto_LABEL_REQUIRED)
   427  }
   428  
   429  // SetOptional sets the label for this field to optional. It returns the field
   430  // builder, for method chaining.
   431  func (flb *FieldBuilder) SetOptional() *FieldBuilder {
   432  	return flb.SetLabel(descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL)
   433  }
   434  
   435  // IsRepeated returns true if this field's label is repeated. Fields created via
   436  // NewMapField will be repeated (since map's are represented "under the hood" as
   437  // a repeated field of map entry messages).
   438  func (flb *FieldBuilder) IsRepeated() bool {
   439  	return flb.Label == descriptorpb.FieldDescriptorProto_LABEL_REPEATED
   440  }
   441  
   442  // IsRequired returns true if this field's label is required.
   443  func (flb *FieldBuilder) IsRequired() bool {
   444  	return flb.Label == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED
   445  }
   446  
   447  // IsOptional returns true if this field's label is optional.
   448  func (flb *FieldBuilder) IsOptional() bool {
   449  	return flb.Label == descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL
   450  }
   451  
   452  // IsMap returns true if this field is a map field.
   453  func (flb *FieldBuilder) IsMap() bool {
   454  	return flb.IsRepeated() &&
   455  		flb.msgType != nil &&
   456  		flb.fieldType.fieldType != descriptorpb.FieldDescriptorProto_TYPE_GROUP &&
   457  		flb.msgType.Options != nil &&
   458  		flb.msgType.Options.GetMapEntry()
   459  }
   460  
   461  // GetType returns the field's type.
   462  func (flb *FieldBuilder) GetType() *FieldType {
   463  	return flb.fieldType
   464  }
   465  
   466  // SetType changes the field's type and returns the field builder, for method
   467  // chaining.
   468  func (flb *FieldBuilder) SetType(ft *FieldType) *FieldBuilder {
   469  	flb.fieldType = ft
   470  	if flb.msgType != nil && flb.msgType != ft.localMsgType {
   471  		Unlink(flb.msgType)
   472  	}
   473  	return flb
   474  }
   475  
   476  // SetDefaultValue changes the field's type and returns the field builder, for
   477  // method chaining.
   478  func (flb *FieldBuilder) SetDefaultValue(defValue string) *FieldBuilder {
   479  	flb.Default = defValue
   480  	return flb
   481  }
   482  
   483  // SetJsonName sets the name used in the field's JSON representation and then
   484  // returns the field builder, for method chaining.
   485  func (flb *FieldBuilder) SetJsonName(jsonName string) *FieldBuilder {
   486  	flb.JsonName = jsonName
   487  	return flb
   488  }
   489  
   490  // IsExtension returns true if this is an extension field.
   491  func (flb *FieldBuilder) IsExtension() bool {
   492  	return flb.localExtendee != nil || flb.foreignExtendee != nil
   493  }
   494  
   495  // GetExtendeeTypeName returns the fully qualified name of the extended message
   496  // or it returns an empty string if this is not an extension field.
   497  func (flb *FieldBuilder) GetExtendeeTypeName() string {
   498  	if flb.foreignExtendee != nil {
   499  		return flb.foreignExtendee.GetFullyQualifiedName()
   500  	} else if flb.localExtendee != nil {
   501  		return GetFullyQualifiedName(flb.localExtendee)
   502  	} else {
   503  		return ""
   504  	}
   505  }
   506  
   507  func (flb *FieldBuilder) buildProto(path []int32, sourceInfo *descriptorpb.SourceCodeInfo, isMessageSet bool) (*descriptorpb.FieldDescriptorProto, error) {
   508  	addCommentsTo(sourceInfo, path, &flb.comments)
   509  
   510  	isProto3 := flb.GetFile().IsProto3
   511  	isEditions := flb.GetFile().Edition > 0
   512  	if flb.Proto3Optional {
   513  		if !isProto3 {
   514  			return nil, fmt.Errorf("field %s is not in a proto3 syntax file but is marked as a proto3 optional field", GetFullyQualifiedName(flb))
   515  		}
   516  		if flb.IsExtension() {
   517  			return nil, fmt.Errorf("field %s: extensions cannot be proto3 optional fields", GetFullyQualifiedName(flb))
   518  		}
   519  		if _, ok := flb.GetParent().(*OneOfBuilder); ok {
   520  			return nil, fmt.Errorf("field %s: proto3 optional fields cannot belong to a oneof", GetFullyQualifiedName(flb))
   521  		}
   522  	}
   523  
   524  	var lbl *descriptorpb.FieldDescriptorProto_Label
   525  	if int32(flb.Label) != 0 {
   526  		if (isProto3 || isEditions) && flb.Label == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED {
   527  			return nil, fmt.Errorf("field %s: only proto2 allows required fields", GetFullyQualifiedName(flb))
   528  		}
   529  		lbl = flb.Label.Enum()
   530  	}
   531  	var typeName *string
   532  	tn := flb.fieldType.GetTypeName()
   533  	if tn != "" {
   534  		typeName = proto.String("." + tn)
   535  	}
   536  	var extendee *string
   537  	if flb.IsExtension() {
   538  		extendee = proto.String("." + flb.GetExtendeeTypeName())
   539  	}
   540  	jsName := flb.JsonName
   541  	if jsName == "" {
   542  		jsName = internal.JsonName(flb.name)
   543  	}
   544  	var def *string
   545  	if flb.Default != "" {
   546  		def = proto.String(flb.Default)
   547  	}
   548  	var proto3Optional *bool
   549  	if flb.Proto3Optional {
   550  		proto3Optional = proto.Bool(true)
   551  	}
   552  
   553  	maxTag := internal.GetMaxTag(isMessageSet)
   554  	if flb.number > maxTag {
   555  		return nil, fmt.Errorf("tag for field %s cannot be above max %d", GetFullyQualifiedName(flb), maxTag)
   556  	}
   557  
   558  	fd := &descriptorpb.FieldDescriptorProto{
   559  		Name:           proto.String(flb.name),
   560  		Number:         proto.Int32(flb.number),
   561  		Options:        flb.Options,
   562  		Label:          lbl,
   563  		Type:           flb.fieldType.fieldType.Enum(),
   564  		TypeName:       typeName,
   565  		JsonName:       proto.String(jsName),
   566  		DefaultValue:   def,
   567  		Extendee:       extendee,
   568  		Proto3Optional: proto3Optional,
   569  	}
   570  	return fd, nil
   571  }
   572  
   573  // Build constructs a field descriptor based on the contents of this field
   574  // builder. If there are any problems constructing the descriptor, including
   575  // resolving symbols referenced by the builder or failing to meet certain
   576  // validation rules, an error is returned.
   577  func (flb *FieldBuilder) Build() (*desc.FieldDescriptor, error) {
   578  	fld, err := flb.BuildDescriptor()
   579  	if err != nil {
   580  		return nil, err
   581  	}
   582  	return fld.(*desc.FieldDescriptor), nil
   583  }
   584  
   585  // BuildDescriptor constructs a field descriptor based on the contents of this
   586  // field builder. Most usages will prefer Build() instead, whose return type is
   587  // a concrete descriptor type. This method is present to satisfy the Builder
   588  // interface.
   589  func (flb *FieldBuilder) BuildDescriptor() (desc.Descriptor, error) {
   590  	return doBuild(flb, BuilderOptions{})
   591  }
   592  
   593  // OneOfBuilder is a builder used to construct a desc.OneOfDescriptor. A one-of
   594  // builder *must* be added to a message before calling its Build() method.
   595  //
   596  // To create a new OneOfBuilder, use NewOneOf.
   597  type OneOfBuilder struct {
   598  	baseBuilder
   599  
   600  	Options *descriptorpb.OneofOptions
   601  
   602  	choices []*FieldBuilder
   603  	symbols map[string]*FieldBuilder
   604  }
   605  
   606  // NewOneOf creates a new OneOfBuilder for a one-of with the given name.
   607  func NewOneOf(name string) *OneOfBuilder {
   608  	return &OneOfBuilder{
   609  		baseBuilder: baseBuilderWithName(name),
   610  		symbols:     map[string]*FieldBuilder{},
   611  	}
   612  }
   613  
   614  // FromOneOf returns a OneOfBuilder that is effectively a copy of the given
   615  // descriptor.
   616  //
   617  // Note that it is not just the given one-of that is copied but its entire file.
   618  // So the caller can get the parent element of the returned builder and the
   619  // result would be a builder that is effectively a copy of the one-of
   620  // descriptor's parent message.
   621  //
   622  // This means that one-of builders created from descriptors do not need to be
   623  // explicitly assigned to a file in order to preserve the original one-of's
   624  // package name.
   625  //
   626  // This function returns an error if the given descriptor is synthetic.
   627  func FromOneOf(ood *desc.OneOfDescriptor) (*OneOfBuilder, error) {
   628  	if ood.IsSynthetic() {
   629  		return nil, fmt.Errorf("one-of %s is synthetic", ood.GetFullyQualifiedName())
   630  	}
   631  	if fb, err := FromFile(ood.GetFile()); err != nil {
   632  		return nil, err
   633  	} else if oob, ok := fb.findFullyQualifiedElement(ood.GetFullyQualifiedName()).(*OneOfBuilder); ok {
   634  		return oob, nil
   635  	} else {
   636  		return nil, fmt.Errorf("could not find one-of %s after converting file %q to builder", ood.GetFullyQualifiedName(), ood.GetFile().GetName())
   637  	}
   638  }
   639  
   640  func fromOneOf(ood *desc.OneOfDescriptor) (*OneOfBuilder, error) {
   641  	oob := NewOneOf(ood.GetName())
   642  	oob.Options = ood.GetOneOfOptions()
   643  	setComments(&oob.comments, ood.GetSourceInfo())
   644  
   645  	for _, fld := range ood.GetChoices() {
   646  		if flb, err := fromField(fld); err != nil {
   647  			return nil, err
   648  		} else if err := oob.TryAddChoice(flb); err != nil {
   649  			return nil, err
   650  		}
   651  	}
   652  
   653  	return oob, nil
   654  }
   655  
   656  // SetName changes this one-of's name, returning the one-of builder for method
   657  // chaining. If the given new name is not valid (e.g. TrySetName would have
   658  // returned an error) then this method will panic.
   659  func (oob *OneOfBuilder) SetName(newName string) *OneOfBuilder {
   660  	if err := oob.TrySetName(newName); err != nil {
   661  		panic(err)
   662  	}
   663  	return oob
   664  }
   665  
   666  // TrySetName changes this one-of's name. It will return an error if the given
   667  // new name is not a valid protobuf identifier or if the parent message builder
   668  // already has an element with the given name.
   669  func (oob *OneOfBuilder) TrySetName(newName string) error {
   670  	return oob.baseBuilder.setName(oob, newName)
   671  }
   672  
   673  // SetComments sets the comments associated with the one-of. This method
   674  // returns the one-of builder, for method chaining.
   675  func (oob *OneOfBuilder) SetComments(c Comments) *OneOfBuilder {
   676  	oob.comments = c
   677  	return oob
   678  }
   679  
   680  // GetChildren returns any builders assigned to this one-of builder. These will
   681  // be choices for the one-of, each of which will be a field builder.
   682  func (oob *OneOfBuilder) GetChildren() []Builder {
   683  	var ch []Builder
   684  	for _, evb := range oob.choices {
   685  		ch = append(ch, evb)
   686  	}
   687  	return ch
   688  }
   689  
   690  func (oob *OneOfBuilder) parent() *MessageBuilder {
   691  	if oob.baseBuilder.parent == nil {
   692  		return nil
   693  	}
   694  	return oob.baseBuilder.parent.(*MessageBuilder)
   695  }
   696  
   697  func (oob *OneOfBuilder) findChild(name string) Builder {
   698  	// in terms of finding a child by qualified name, fields in the
   699  	// one-of are considered children of the message, not the one-of
   700  	return nil
   701  }
   702  
   703  func (oob *OneOfBuilder) removeChild(b Builder) {
   704  	if p, ok := b.GetParent().(*OneOfBuilder); !ok || p != oob {
   705  		return
   706  	}
   707  
   708  	if oob.parent() != nil {
   709  		// remove from message's name and tag maps
   710  		flb := b.(*FieldBuilder)
   711  		delete(oob.parent().fieldTags, flb.GetNumber())
   712  		delete(oob.parent().symbols, flb.GetName())
   713  	}
   714  
   715  	oob.choices = deleteBuilder(b.GetName(), oob.choices).([]*FieldBuilder)
   716  	delete(oob.symbols, b.GetName())
   717  	b.setParent(nil)
   718  }
   719  
   720  func (oob *OneOfBuilder) renamedChild(b Builder, oldName string) error {
   721  	if p, ok := b.GetParent().(*OneOfBuilder); !ok || p != oob {
   722  		return nil
   723  	}
   724  
   725  	if err := oob.addSymbol(b.(*FieldBuilder)); err != nil {
   726  		return err
   727  	}
   728  
   729  	// update message's name map (to make sure new field name doesn't
   730  	// collide with other kinds of elements in the message)
   731  	if oob.parent() != nil {
   732  		if err := oob.parent().addSymbol(b); err != nil {
   733  			delete(oob.symbols, b.GetName())
   734  			return err
   735  		}
   736  		delete(oob.parent().symbols, oldName)
   737  	}
   738  
   739  	delete(oob.symbols, oldName)
   740  	return nil
   741  }
   742  
   743  func (oob *OneOfBuilder) addSymbol(b *FieldBuilder) error {
   744  	if _, ok := oob.symbols[b.GetName()]; ok {
   745  		return fmt.Errorf("one-of %s already contains field named %q", GetFullyQualifiedName(oob), b.GetName())
   746  	}
   747  	oob.symbols[b.GetName()] = b
   748  	return nil
   749  }
   750  
   751  // GetChoice returns the field with the given name. If no such field exists in
   752  // the one-of, nil is returned.
   753  func (oob *OneOfBuilder) GetChoice(name string) *FieldBuilder {
   754  	return oob.symbols[name]
   755  }
   756  
   757  // RemoveChoice removes the field with the given name. If no such field exists
   758  // in the one-of, this is a no-op. This returns the one-of builder, for method
   759  // chaining.
   760  func (oob *OneOfBuilder) RemoveChoice(name string) *OneOfBuilder {
   761  	oob.TryRemoveChoice(name)
   762  	return oob
   763  }
   764  
   765  // TryRemoveChoice removes the field with the given name and returns false if
   766  // the one-of has no such field.
   767  func (oob *OneOfBuilder) TryRemoveChoice(name string) bool {
   768  	if flb, ok := oob.symbols[name]; ok {
   769  		oob.removeChild(flb)
   770  		return true
   771  	}
   772  	return false
   773  }
   774  
   775  // AddChoice adds the given field to this one-of. If an error prevents the field
   776  // from being added, this method panics. If the given field is an extension,
   777  // this method panics. If the given field is a group or map field or if it is
   778  // not optional (e.g. it is required or repeated), this method panics. This
   779  // returns the one-of builder, for method chaining.
   780  func (oob *OneOfBuilder) AddChoice(flb *FieldBuilder) *OneOfBuilder {
   781  	if err := oob.TryAddChoice(flb); err != nil {
   782  		panic(err)
   783  	}
   784  	return oob
   785  }
   786  
   787  // TryAddChoice adds the given field to this one-of, returning any error that
   788  // prevents the field from being added (such as a name collision with another
   789  // element already added to the enclosing message). An error is returned if the
   790  // given field is an extension field, a map or group field, or repeated or
   791  // required.
   792  func (oob *OneOfBuilder) TryAddChoice(flb *FieldBuilder) error {
   793  	if flb.IsExtension() {
   794  		return fmt.Errorf("field %s is an extension, not a regular field", flb.GetName())
   795  	}
   796  	if flb.msgType != nil && flb.fieldType.fieldType != descriptorpb.FieldDescriptorProto_TYPE_GROUP {
   797  		return fmt.Errorf("cannot add a map field %q to one-of %s", flb.name, GetFullyQualifiedName(oob))
   798  	}
   799  	if flb.IsRepeated() || flb.IsRequired() {
   800  		return fmt.Errorf("fields in a one-of must be optional, %s is %v", flb.name, flb.Label)
   801  	}
   802  	if err := oob.addSymbol(flb); err != nil {
   803  		return err
   804  	}
   805  	mb := oob.parent()
   806  	if mb != nil {
   807  		// If we are moving field from a message to a one-of that belongs to the
   808  		// same message, we have to use different order of operations to prevent
   809  		// failure (otherwise, it looks like it's being added twice).
   810  		// (We do similar if moving the other direction, from the one-of into
   811  		// the message to which one-of belongs.)
   812  		needToUnlinkFirst := mb.isPresentButNotChild(flb)
   813  		if needToUnlinkFirst {
   814  			Unlink(flb)
   815  			mb.registerField(flb)
   816  		} else {
   817  			if err := mb.registerField(flb); err != nil {
   818  				delete(oob.symbols, flb.GetName())
   819  				return err
   820  			}
   821  			Unlink(flb)
   822  		}
   823  	}
   824  	flb.setParent(oob)
   825  	oob.choices = append(oob.choices, flb)
   826  	return nil
   827  }
   828  
   829  // SetOptions sets the one-of options for this one-of and returns the one-of,
   830  // for method chaining.
   831  func (oob *OneOfBuilder) SetOptions(options *descriptorpb.OneofOptions) *OneOfBuilder {
   832  	oob.Options = options
   833  	return oob
   834  }
   835  
   836  func (oob *OneOfBuilder) buildProto(path []int32, sourceInfo *descriptorpb.SourceCodeInfo) (*descriptorpb.OneofDescriptorProto, error) {
   837  	addCommentsTo(sourceInfo, path, &oob.comments)
   838  
   839  	for _, flb := range oob.choices {
   840  		if flb.IsRepeated() || flb.IsRequired() {
   841  			return nil, fmt.Errorf("fields in a one-of must be optional, %s is %v", GetFullyQualifiedName(flb), flb.Label)
   842  		}
   843  	}
   844  
   845  	return &descriptorpb.OneofDescriptorProto{
   846  		Name:    proto.String(oob.name),
   847  		Options: oob.Options,
   848  	}, nil
   849  }
   850  
   851  // Build constructs a one-of descriptor based on the contents of this one-of
   852  // builder. If there are any problems constructing the descriptor, including
   853  // resolving symbols referenced by the builder or failing to meet certain
   854  // validation rules, an error is returned.
   855  func (oob *OneOfBuilder) Build() (*desc.OneOfDescriptor, error) {
   856  	ood, err := oob.BuildDescriptor()
   857  	if err != nil {
   858  		return nil, err
   859  	}
   860  	return ood.(*desc.OneOfDescriptor), nil
   861  }
   862  
   863  // BuildDescriptor constructs a one-of descriptor based on the contents of this
   864  // one-of builder. Most usages will prefer Build() instead, whose return type is
   865  // a concrete descriptor type. This method is present to satisfy the Builder
   866  // interface.
   867  func (oob *OneOfBuilder) BuildDescriptor() (desc.Descriptor, error) {
   868  	return doBuild(oob, BuilderOptions{})
   869  }
   870  
   871  func entryTypeName(fieldName string) string {
   872  	return internal.InitCap(internal.JsonName(fieldName)) + "Entry"
   873  }