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