github.com/bakjos/protoreflect@v1.9.2/desc/builder/field.go (about)

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