github.com/jhump/protoreflect@v1.16.0/desc/builder/message.go (about) 1 package builder 2 3 import ( 4 "fmt" 5 "sort" 6 7 "google.golang.org/protobuf/proto" 8 "google.golang.org/protobuf/types/descriptorpb" 9 10 "github.com/jhump/protoreflect/desc" 11 "github.com/jhump/protoreflect/desc/internal" 12 ) 13 14 // MessageBuilder is a builder used to construct a desc.MessageDescriptor. A 15 // message builder can define nested messages, enums, and extensions in addition 16 // to defining the message's fields. 17 // 18 // Note that when building a descriptor from a MessageBuilder, not all protobuf 19 // validation rules are enforced. See the package documentation for more info. 20 // 21 // To create a new MessageBuilder, use NewMessage. 22 type MessageBuilder struct { 23 baseBuilder 24 25 Options *descriptorpb.MessageOptions 26 ExtensionRanges []*descriptorpb.DescriptorProto_ExtensionRange 27 ReservedRanges []*descriptorpb.DescriptorProto_ReservedRange 28 ReservedNames []string 29 30 fieldsAndOneOfs []Builder 31 fieldTags map[int32]*FieldBuilder 32 nestedMessages []*MessageBuilder 33 nestedExtensions []*FieldBuilder 34 nestedEnums []*EnumBuilder 35 symbols map[string]Builder 36 } 37 38 // NewMessage creates a new MessageBuilder for a message with the given name. 39 // Since the new message has no parent element, it also has no package name 40 // (e.g. it is in the unnamed package, until it is assigned to a file builder 41 // that defines a package name). 42 func NewMessage(name string) *MessageBuilder { 43 return &MessageBuilder{ 44 baseBuilder: baseBuilderWithName(name), 45 fieldTags: map[int32]*FieldBuilder{}, 46 symbols: map[string]Builder{}, 47 } 48 } 49 50 // FromMessage returns a MessageBuilder that is effectively a copy of the given 51 // descriptor. 52 // 53 // Note that it is not just the given message that is copied but its entire 54 // file. So the caller can get the parent element of the returned builder and 55 // the result would be a builder that is effectively a copy of the message 56 // descriptor's parent. 57 // 58 // This means that message builders created from descriptors do not need to be 59 // explicitly assigned to a file in order to preserve the original message's 60 // package name. 61 func FromMessage(md *desc.MessageDescriptor) (*MessageBuilder, error) { 62 if fb, err := FromFile(md.GetFile()); err != nil { 63 return nil, err 64 } else if mb, ok := fb.findFullyQualifiedElement(md.GetFullyQualifiedName()).(*MessageBuilder); ok { 65 return mb, nil 66 } else { 67 return nil, fmt.Errorf("could not find message %s after converting file %q to builder", md.GetFullyQualifiedName(), md.GetFile().GetName()) 68 } 69 } 70 71 func fromMessage(md *desc.MessageDescriptor, 72 localMessages map[*desc.MessageDescriptor]*MessageBuilder, 73 localEnums map[*desc.EnumDescriptor]*EnumBuilder) (*MessageBuilder, error) { 74 75 mb := NewMessage(md.GetName()) 76 mb.Options = md.GetMessageOptions() 77 mb.ExtensionRanges = md.AsDescriptorProto().GetExtensionRange() 78 mb.ReservedRanges = md.AsDescriptorProto().GetReservedRange() 79 mb.ReservedNames = md.AsDescriptorProto().GetReservedName() 80 setComments(&mb.comments, md.GetSourceInfo()) 81 82 localMessages[md] = mb 83 84 oneOfs := make([]*OneOfBuilder, len(md.GetOneOfs())) 85 for i, ood := range md.GetOneOfs() { 86 if ood.IsSynthetic() { 87 continue 88 } 89 if oob, err := fromOneOf(ood); err != nil { 90 return nil, err 91 } else { 92 oneOfs[i] = oob 93 } 94 } 95 96 for _, fld := range md.GetFields() { 97 if fld.GetOneOf() != nil && !fld.GetOneOf().IsSynthetic() { 98 // add one-ofs in the order of their first constituent field 99 oob := oneOfs[fld.AsFieldDescriptorProto().GetOneofIndex()] 100 if oob != nil { 101 oneOfs[fld.AsFieldDescriptorProto().GetOneofIndex()] = nil 102 if err := mb.TryAddOneOf(oob); err != nil { 103 return nil, err 104 } 105 } 106 continue 107 } 108 if flb, err := fromField(fld); err != nil { 109 return nil, err 110 } else if err := mb.TryAddField(flb); err != nil { 111 return nil, err 112 } 113 } 114 115 for _, nmd := range md.GetNestedMessageTypes() { 116 if nmb, err := fromMessage(nmd, localMessages, localEnums); err != nil { 117 return nil, err 118 } else if err := mb.TryAddNestedMessage(nmb); err != nil { 119 return nil, err 120 } 121 } 122 for _, ed := range md.GetNestedEnumTypes() { 123 if eb, err := fromEnum(ed, localEnums); err != nil { 124 return nil, err 125 } else if err := mb.TryAddNestedEnum(eb); err != nil { 126 return nil, err 127 } 128 } 129 for _, exd := range md.GetNestedExtensions() { 130 if exb, err := fromField(exd); err != nil { 131 return nil, err 132 } else if err := mb.TryAddNestedExtension(exb); err != nil { 133 return nil, err 134 } 135 } 136 137 return mb, nil 138 } 139 140 // SetName changes this message's name, returning the message builder for method 141 // chaining. If the given new name is not valid (e.g. TrySetName would have 142 // returned an error) then this method will panic. 143 func (mb *MessageBuilder) SetName(newName string) *MessageBuilder { 144 if err := mb.TrySetName(newName); err != nil { 145 panic(err) 146 } 147 return mb 148 } 149 150 // TrySetName changes this message's name. It will return an error if the given 151 // new name is not a valid protobuf identifier or if the parent builder already 152 // has an element with the given name. 153 // 154 // If the message is a map or group type whose parent is the corresponding map 155 // or group field, the parent field's enclosing message is checked for elements 156 // with a conflicting name. Despite the fact that these message types are 157 // modeled as children of their associated field builder, in the protobuf IDL 158 // they are actually all defined in the enclosing message's namespace. 159 func (mb *MessageBuilder) TrySetName(newName string) error { 160 if p, ok := mb.parent.(*FieldBuilder); ok && p.fieldType.fieldType != descriptorpb.FieldDescriptorProto_TYPE_GROUP { 161 return fmt.Errorf("cannot change name of map entry %s; change name of field instead", GetFullyQualifiedName(mb)) 162 } 163 return mb.trySetNameInternal(newName) 164 } 165 166 func (mb *MessageBuilder) trySetNameInternal(newName string) error { 167 return mb.baseBuilder.setName(mb, newName) 168 } 169 170 func (mb *MessageBuilder) setNameInternal(newName string) { 171 if err := mb.trySetNameInternal(newName); err != nil { 172 panic(err) 173 } 174 } 175 176 // SetComments sets the comments associated with the message. This method 177 // returns the message builder, for method chaining. 178 func (mb *MessageBuilder) SetComments(c Comments) *MessageBuilder { 179 mb.comments = c 180 return mb 181 } 182 183 // GetChildren returns any builders assigned to this message builder. These will 184 // include the message's fields and one-ofs as well as any nested messages, 185 // extensions, and enums. 186 func (mb *MessageBuilder) GetChildren() []Builder { 187 ch := append([]Builder(nil), mb.fieldsAndOneOfs...) 188 for _, nmb := range mb.nestedMessages { 189 ch = append(ch, nmb) 190 } 191 for _, exb := range mb.nestedExtensions { 192 ch = append(ch, exb) 193 } 194 for _, eb := range mb.nestedEnums { 195 ch = append(ch, eb) 196 } 197 return ch 198 } 199 200 func (mb *MessageBuilder) findChild(name string) Builder { 201 return mb.symbols[name] 202 } 203 204 func (mb *MessageBuilder) removeChild(b Builder) { 205 if p, ok := b.GetParent().(*MessageBuilder); !ok || p != mb { 206 return 207 } 208 209 switch b := b.(type) { 210 case *FieldBuilder: 211 if b.IsExtension() { 212 mb.nestedExtensions = deleteBuilder(b.GetName(), mb.nestedExtensions).([]*FieldBuilder) 213 } else { 214 mb.fieldsAndOneOfs = deleteBuilder(b.GetName(), mb.fieldsAndOneOfs).([]Builder) 215 delete(mb.fieldTags, b.GetNumber()) 216 if b.msgType != nil { 217 delete(mb.symbols, b.msgType.GetName()) 218 } 219 } 220 case *OneOfBuilder: 221 mb.fieldsAndOneOfs = deleteBuilder(b.GetName(), mb.fieldsAndOneOfs).([]Builder) 222 for _, flb := range b.choices { 223 delete(mb.symbols, flb.GetName()) 224 delete(mb.fieldTags, flb.GetNumber()) 225 } 226 case *MessageBuilder: 227 mb.nestedMessages = deleteBuilder(b.GetName(), mb.nestedMessages).([]*MessageBuilder) 228 case *EnumBuilder: 229 mb.nestedEnums = deleteBuilder(b.GetName(), mb.nestedEnums).([]*EnumBuilder) 230 } 231 delete(mb.symbols, b.GetName()) 232 b.setParent(nil) 233 } 234 235 func (mb *MessageBuilder) renamedChild(b Builder, oldName string) error { 236 if p, ok := b.GetParent().(*MessageBuilder); !ok || p != mb { 237 return nil 238 } 239 240 if err := mb.addSymbol(b); err != nil { 241 return err 242 } 243 delete(mb.symbols, oldName) 244 return nil 245 } 246 247 func (mb *MessageBuilder) addSymbol(b Builder) error { 248 if ex, ok := mb.symbols[b.GetName()]; ok { 249 return fmt.Errorf("message %s already contains element (%T) named %q", GetFullyQualifiedName(mb), ex, b.GetName()) 250 } 251 mb.symbols[b.GetName()] = b 252 return nil 253 } 254 255 func (mb *MessageBuilder) addTag(flb *FieldBuilder) error { 256 if flb.number == 0 { 257 return nil 258 } 259 if ex, ok := mb.fieldTags[flb.GetNumber()]; ok { 260 return fmt.Errorf("message %s already contains field with tag %d: %s", GetFullyQualifiedName(mb), flb.GetNumber(), ex.GetName()) 261 } 262 mb.fieldTags[flb.GetNumber()] = flb 263 return nil 264 } 265 266 func (mb *MessageBuilder) registerField(flb *FieldBuilder) error { 267 if err := mb.addSymbol(flb); err != nil { 268 return err 269 } 270 if err := mb.addTag(flb); err != nil { 271 delete(mb.symbols, flb.GetName()) 272 return err 273 } 274 if flb.msgType != nil { 275 if err := mb.addSymbol(flb.msgType); err != nil { 276 delete(mb.symbols, flb.GetName()) 277 delete(mb.fieldTags, flb.GetNumber()) 278 return err 279 } 280 } 281 return nil 282 } 283 284 // GetField returns the field with the given name. If no such field exists in 285 // the message, nil is returned. The field does not have to be an immediate 286 // child of this message but could instead be an indirect child via a one-of. 287 func (mb *MessageBuilder) GetField(name string) *FieldBuilder { 288 b := mb.symbols[name] 289 if flb, ok := b.(*FieldBuilder); ok && !flb.IsExtension() { 290 return flb 291 } else { 292 return nil 293 } 294 } 295 296 // RemoveField removes the field with the given name. If no such field exists in 297 // the message, this is a no-op. If the field is part of a one-of, the one-of 298 // remains assigned to this message and the field is removed from it. This 299 // returns the message builder, for method chaining. 300 func (mb *MessageBuilder) RemoveField(name string) *MessageBuilder { 301 mb.TryRemoveField(name) 302 return mb 303 } 304 305 // TryRemoveField removes the field with the given name and returns false if the 306 // message has no such field. If the field is part of a one-of, the one-of 307 // remains assigned to this message and the field is removed from it. 308 func (mb *MessageBuilder) TryRemoveField(name string) bool { 309 b := mb.symbols[name] 310 if flb, ok := b.(*FieldBuilder); ok && !flb.IsExtension() { 311 // parent could be mb, but could also be a one-of 312 flb.GetParent().removeChild(flb) 313 return true 314 } 315 return false 316 } 317 318 // AddField adds the given field to this message. If an error prevents the field 319 // from being added, this method panics. If the given field is an extension, 320 // this method panics. This returns the message builder, for method chaining. 321 func (mb *MessageBuilder) AddField(flb *FieldBuilder) *MessageBuilder { 322 if err := mb.TryAddField(flb); err != nil { 323 panic(err) 324 } 325 return mb 326 } 327 328 // TryAddField adds the given field to this message, returning any error that 329 // prevents the field from being added (such as a name collision with another 330 // element already added to the message). An error is returned if the given 331 // field is an extension field. 332 func (mb *MessageBuilder) TryAddField(flb *FieldBuilder) error { 333 if flb.IsExtension() { 334 return fmt.Errorf("field %s is an extension, not a regular field", flb.GetName()) 335 } 336 // If we are moving field from a one-of that belongs to this message 337 // directly to this message, we have to use different order of operations 338 // to prevent failure (otherwise, it looks like it's being added twice). 339 // (We do similar if moving the other direction, from message to a one-of 340 // that is already assigned to same message.) 341 needToUnlinkFirst := mb.isPresentButNotChild(flb) 342 if needToUnlinkFirst { 343 Unlink(flb) 344 mb.registerField(flb) 345 } else { 346 if err := mb.registerField(flb); err != nil { 347 return err 348 } 349 Unlink(flb) 350 } 351 flb.setParent(mb) 352 mb.fieldsAndOneOfs = append(mb.fieldsAndOneOfs, flb) 353 return nil 354 } 355 356 // GetOneOf returns the one-of with the given name. If no such one-of exists in 357 // the message, nil is returned. 358 func (mb *MessageBuilder) GetOneOf(name string) *OneOfBuilder { 359 b := mb.symbols[name] 360 if oob, ok := b.(*OneOfBuilder); ok { 361 return oob 362 } else { 363 return nil 364 } 365 } 366 367 // RemoveOneOf removes the one-of with the given name. If no such one-of exists 368 // in the message, this is a no-op. This returns the message builder, for method 369 // chaining. 370 func (mb *MessageBuilder) RemoveOneOf(name string) *MessageBuilder { 371 mb.TryRemoveOneOf(name) 372 return mb 373 } 374 375 // TryRemoveOneOf removes the one-of with the given name and returns false if 376 // the message has no such one-of. 377 func (mb *MessageBuilder) TryRemoveOneOf(name string) bool { 378 b := mb.symbols[name] 379 if oob, ok := b.(*OneOfBuilder); ok { 380 mb.removeChild(oob) 381 return true 382 } 383 return false 384 } 385 386 // AddOneOf adds the given one-of to this message. If an error prevents the 387 // one-of from being added, this method panics. This returns the message 388 // builder, for method chaining. 389 func (mb *MessageBuilder) AddOneOf(oob *OneOfBuilder) *MessageBuilder { 390 if err := mb.TryAddOneOf(oob); err != nil { 391 panic(err) 392 } 393 return mb 394 } 395 396 // TryAddOneOf adds the given one-of to this message, returning any error that 397 // prevents the one-of from being added (such as a name collision with another 398 // element already added to the message). 399 func (mb *MessageBuilder) TryAddOneOf(oob *OneOfBuilder) error { 400 if err := mb.addSymbol(oob); err != nil { 401 return err 402 } 403 // add nested fields to symbol and tag map 404 for i, flb := range oob.choices { 405 if err := mb.registerField(flb); err != nil { 406 // must undo all additions we've made so far 407 delete(mb.symbols, oob.GetName()) 408 for i > 1 { 409 i-- 410 flb := oob.choices[i] 411 delete(mb.symbols, flb.GetName()) 412 delete(mb.fieldTags, flb.GetNumber()) 413 } 414 return err 415 } 416 } 417 Unlink(oob) 418 oob.setParent(mb) 419 mb.fieldsAndOneOfs = append(mb.fieldsAndOneOfs, oob) 420 return nil 421 } 422 423 // GetNestedMessage returns the nested message with the given name. If no such 424 // message exists, nil is returned. The named message must be in this message's 425 // scope. If the message is nested more deeply, this will return nil. This means 426 // the message must be a direct child of this message or a child of one of this 427 // message's fields (e.g. the group type for a group field or a map entry for a 428 // map field). 429 func (mb *MessageBuilder) GetNestedMessage(name string) *MessageBuilder { 430 b := mb.symbols[name] 431 if nmb, ok := b.(*MessageBuilder); ok { 432 return nmb 433 } else { 434 return nil 435 } 436 } 437 438 // RemoveNestedMessage removes the nested message with the given name. If no 439 // such message exists, this is a no-op. This returns the message builder, for 440 // method chaining. 441 func (mb *MessageBuilder) RemoveNestedMessage(name string) *MessageBuilder { 442 mb.TryRemoveNestedMessage(name) 443 return mb 444 } 445 446 // TryRemoveNestedMessage removes the nested message with the given name and 447 // returns false if this message has no nested message with that name. If the 448 // named message is a child of a field (e.g. the group type for a group field or 449 // the map entry for a map field), it is removed from that field and thus 450 // removed from this message's scope. 451 func (mb *MessageBuilder) TryRemoveNestedMessage(name string) bool { 452 b := mb.symbols[name] 453 if nmb, ok := b.(*MessageBuilder); ok { 454 // parent could be mb, but could also be a field (if the message 455 // is the field's group or map entry type) 456 nmb.GetParent().removeChild(nmb) 457 return true 458 } 459 return false 460 } 461 462 // AddNestedMessage adds the given message as a nested child of this message. If 463 // an error prevents the message from being added, this method panics. This 464 // returns the message builder, for method chaining. 465 func (mb *MessageBuilder) AddNestedMessage(nmb *MessageBuilder) *MessageBuilder { 466 if err := mb.TryAddNestedMessage(nmb); err != nil { 467 panic(err) 468 } 469 return mb 470 } 471 472 // TryAddNestedMessage adds the given message as a nested child of this message, 473 // returning any error that prevents the message from being added (such as a 474 // name collision with another element already added to the message). 475 func (mb *MessageBuilder) TryAddNestedMessage(nmb *MessageBuilder) error { 476 // If we are moving nested message from field (map entry or group type) 477 // directly to this message, we have to use different order of operations 478 // to prevent failure (otherwise, it looks like it's being added twice). 479 // (We don't need to do similar for the other direction, because that isn't 480 // possible: you can't add messages to a field, they can only be constructed 481 // that way using NewGroupField or NewMapField.) 482 needToUnlinkFirst := mb.isPresentButNotChild(nmb) 483 if needToUnlinkFirst { 484 Unlink(nmb) 485 _ = mb.addSymbol(nmb) 486 } else { 487 if err := mb.addSymbol(nmb); err != nil { 488 return err 489 } 490 Unlink(nmb) 491 } 492 nmb.setParent(mb) 493 mb.nestedMessages = append(mb.nestedMessages, nmb) 494 return nil 495 } 496 497 func (mb *MessageBuilder) isPresentButNotChild(b Builder) bool { 498 if p, ok := b.GetParent().(*MessageBuilder); ok && p == mb { 499 // it's a child 500 return false 501 } 502 return mb.symbols[b.GetName()] == b 503 } 504 505 // GetNestedExtension returns the nested extension with the given name. If no 506 // such extension exists, nil is returned. The named extension must be in this 507 // message's scope. If the extension is nested more deeply, this will return 508 // nil. This means the extension must be a direct child of this message. 509 func (mb *MessageBuilder) GetNestedExtension(name string) *FieldBuilder { 510 b := mb.symbols[name] 511 if exb, ok := b.(*FieldBuilder); ok && exb.IsExtension() { 512 return exb 513 } else { 514 return nil 515 } 516 } 517 518 // RemoveNestedExtension removes the nested extension with the given name. If no 519 // such extension exists, this is a no-op. This returns the message builder, for 520 // method chaining. 521 func (mb *MessageBuilder) RemoveNestedExtension(name string) *MessageBuilder { 522 mb.TryRemoveNestedExtension(name) 523 return mb 524 } 525 526 // TryRemoveNestedExtension removes the nested extension with the given name and 527 // returns false if this message has no nested extension with that name. 528 func (mb *MessageBuilder) TryRemoveNestedExtension(name string) bool { 529 b := mb.symbols[name] 530 if exb, ok := b.(*FieldBuilder); ok && exb.IsExtension() { 531 mb.removeChild(exb) 532 return true 533 } 534 return false 535 } 536 537 // AddNestedExtension adds the given extension as a nested child of this 538 // message. If an error prevents the extension from being added, this method 539 // panics. This returns the message builder, for method chaining. 540 func (mb *MessageBuilder) AddNestedExtension(exb *FieldBuilder) *MessageBuilder { 541 if err := mb.TryAddNestedExtension(exb); err != nil { 542 panic(err) 543 } 544 return mb 545 } 546 547 // TryAddNestedExtension adds the given extension as a nested child of this 548 // message, returning any error that prevents the extension from being added 549 // (such as a name collision with another element already added to the message). 550 func (mb *MessageBuilder) TryAddNestedExtension(exb *FieldBuilder) error { 551 if !exb.IsExtension() { 552 return fmt.Errorf("field %s is not an extension", exb.GetName()) 553 } 554 if err := mb.addSymbol(exb); err != nil { 555 return err 556 } 557 Unlink(exb) 558 exb.setParent(mb) 559 mb.nestedExtensions = append(mb.nestedExtensions, exb) 560 return nil 561 } 562 563 // GetNestedEnum returns the nested enum with the given name. If no such enum 564 // exists, nil is returned. The named enum must be in this message's scope. If 565 // the enum is nested more deeply, this will return nil. This means the enum 566 // must be a direct child of this message. 567 func (mb *MessageBuilder) GetNestedEnum(name string) *EnumBuilder { 568 b := mb.symbols[name] 569 if eb, ok := b.(*EnumBuilder); ok { 570 return eb 571 } else { 572 return nil 573 } 574 } 575 576 // RemoveNestedEnum removes the nested enum with the given name. If no such enum 577 // exists, this is a no-op. This returns the message builder, for method 578 // chaining. 579 func (mb *MessageBuilder) RemoveNestedEnum(name string) *MessageBuilder { 580 mb.TryRemoveNestedEnum(name) 581 return mb 582 } 583 584 // TryRemoveNestedEnum removes the nested enum with the given name and returns 585 // false if this message has no nested enum with that name. 586 func (mb *MessageBuilder) TryRemoveNestedEnum(name string) bool { 587 b := mb.symbols[name] 588 if eb, ok := b.(*EnumBuilder); ok { 589 mb.removeChild(eb) 590 return true 591 } 592 return false 593 } 594 595 // AddNestedEnum adds the given enum as a nested child of this message. If an 596 // error prevents the enum from being added, this method panics. This returns 597 // the message builder, for method chaining. 598 func (mb *MessageBuilder) AddNestedEnum(eb *EnumBuilder) *MessageBuilder { 599 if err := mb.TryAddNestedEnum(eb); err != nil { 600 panic(err) 601 } 602 return mb 603 } 604 605 // TryAddNestedEnum adds the given enum as a nested child of this message, 606 // returning any error that prevents the enum from being added (such as a name 607 // collision with another element already added to the message). 608 func (mb *MessageBuilder) TryAddNestedEnum(eb *EnumBuilder) error { 609 if err := mb.addSymbol(eb); err != nil { 610 return err 611 } 612 Unlink(eb) 613 eb.setParent(mb) 614 mb.nestedEnums = append(mb.nestedEnums, eb) 615 return nil 616 } 617 618 // SetOptions sets the message options for this message and returns the message, 619 // for method chaining. 620 func (mb *MessageBuilder) SetOptions(options *descriptorpb.MessageOptions) *MessageBuilder { 621 mb.Options = options 622 return mb 623 } 624 625 // AddExtensionRange adds the given extension range to this message. The range 626 // is inclusive of both the start and end, just like defining a range in proto 627 // IDL source. This returns the message, for method chaining. 628 func (mb *MessageBuilder) AddExtensionRange(start, end int32) *MessageBuilder { 629 return mb.AddExtensionRangeWithOptions(start, end, nil) 630 } 631 632 // AddExtensionRangeWithOptions adds the given extension range to this message. 633 // The range is inclusive of both the start and end, just like defining a range 634 // in proto IDL source. This returns the message, for method chaining. 635 func (mb *MessageBuilder) AddExtensionRangeWithOptions(start, end int32, options *descriptorpb.ExtensionRangeOptions) *MessageBuilder { 636 er := &descriptorpb.DescriptorProto_ExtensionRange{ 637 Start: proto.Int32(start), 638 End: proto.Int32(end + 1), 639 Options: options, 640 } 641 mb.ExtensionRanges = append(mb.ExtensionRanges, er) 642 return mb 643 } 644 645 // SetExtensionRanges replaces all of this message's extension ranges with the 646 // given slice of ranges. Unlike AddExtensionRange and unlike the way ranges are 647 // defined in proto IDL source, a DescriptorProto_ExtensionRange struct treats 648 // the end of the range as *exclusive*. So the range is inclusive of the start 649 // but exclusive of the end. This returns the message, for method chaining. 650 func (mb *MessageBuilder) SetExtensionRanges(ranges []*descriptorpb.DescriptorProto_ExtensionRange) *MessageBuilder { 651 mb.ExtensionRanges = ranges 652 return mb 653 } 654 655 // AddReservedRange adds the given reserved range to this message. The range is 656 // inclusive of both the start and end, just like defining a range in proto IDL 657 // source. This returns the message, for method chaining. 658 func (mb *MessageBuilder) AddReservedRange(start, end int32) *MessageBuilder { 659 rr := &descriptorpb.DescriptorProto_ReservedRange{ 660 Start: proto.Int32(start), 661 End: proto.Int32(end + 1), 662 } 663 mb.ReservedRanges = append(mb.ReservedRanges, rr) 664 return mb 665 } 666 667 // SetReservedRanges replaces all of this message's reserved ranges with the 668 // given slice of ranges. Unlike AddReservedRange and unlike the way ranges are 669 // defined in proto IDL source, a DescriptorProto_ReservedRange struct treats 670 // the end of the range as *exclusive* (so it would be the value defined in the 671 // IDL plus one). So the range is inclusive of the start but exclusive of the 672 // end. This returns the message, for method chaining. 673 func (mb *MessageBuilder) SetReservedRanges(ranges []*descriptorpb.DescriptorProto_ReservedRange) *MessageBuilder { 674 mb.ReservedRanges = ranges 675 return mb 676 } 677 678 // AddReservedName adds the given name to the list of reserved field names for 679 // this message. This returns the message, for method chaining. 680 func (mb *MessageBuilder) AddReservedName(name string) *MessageBuilder { 681 mb.ReservedNames = append(mb.ReservedNames, name) 682 return mb 683 } 684 685 // SetReservedNames replaces all of this message's reserved field names with the 686 // given slice of names. This returns the message, for method chaining. 687 func (mb *MessageBuilder) SetReservedNames(names []string) *MessageBuilder { 688 mb.ReservedNames = names 689 return mb 690 } 691 692 func (mb *MessageBuilder) buildProto(path []int32, sourceInfo *descriptorpb.SourceCodeInfo) (*descriptorpb.DescriptorProto, error) { 693 addCommentsTo(sourceInfo, path, &mb.comments) 694 695 var needTagsAssigned []*descriptorpb.FieldDescriptorProto 696 nestedMessages := make([]*descriptorpb.DescriptorProto, 0, len(mb.nestedMessages)) 697 oneOfCount := 0 698 for _, b := range mb.fieldsAndOneOfs { 699 if _, ok := b.(*OneOfBuilder); ok { 700 oneOfCount++ 701 } 702 } 703 704 fields := make([]*descriptorpb.FieldDescriptorProto, 0, len(mb.fieldsAndOneOfs)-oneOfCount) 705 oneOfs := make([]*descriptorpb.OneofDescriptorProto, 0, oneOfCount) 706 707 addField := func(flb *FieldBuilder, fld *descriptorpb.FieldDescriptorProto) error { 708 fields = append(fields, fld) 709 if flb.number == 0 { 710 needTagsAssigned = append(needTagsAssigned, fld) 711 } 712 if flb.msgType != nil { 713 nmpath := append(path, internal.Message_nestedMessagesTag, int32(len(nestedMessages))) 714 if entry, err := flb.msgType.buildProto(nmpath, sourceInfo); err != nil { 715 return err 716 } else { 717 nestedMessages = append(nestedMessages, entry) 718 } 719 } 720 return nil 721 } 722 723 for _, b := range mb.fieldsAndOneOfs { 724 if flb, ok := b.(*FieldBuilder); ok { 725 fldpath := append(path, internal.Message_fieldsTag, int32(len(fields))) 726 fld, err := flb.buildProto(fldpath, sourceInfo, mb.Options.GetMessageSetWireFormat()) 727 if err != nil { 728 return nil, err 729 } 730 if err := addField(flb, fld); err != nil { 731 return nil, err 732 } 733 } else { 734 oopath := append(path, internal.Message_oneOfsTag, int32(len(oneOfs))) 735 oob := b.(*OneOfBuilder) 736 oobIndex := len(oneOfs) 737 ood, err := oob.buildProto(oopath, sourceInfo) 738 if err != nil { 739 return nil, err 740 } 741 oneOfs = append(oneOfs, ood) 742 for _, flb := range oob.choices { 743 path := append(path, internal.Message_fieldsTag, int32(len(fields))) 744 fld, err := flb.buildProto(path, sourceInfo, mb.Options.GetMessageSetWireFormat()) 745 if err != nil { 746 return nil, err 747 } 748 fld.OneofIndex = proto.Int32(int32(oobIndex)) 749 if err := addField(flb, fld); err != nil { 750 return nil, err 751 } 752 } 753 } 754 } 755 756 if len(needTagsAssigned) > 0 { 757 tags := make([]int, len(fields)-len(needTagsAssigned)) 758 tagsIndex := 0 759 for _, fld := range fields { 760 tag := fld.GetNumber() 761 if tag != 0 { 762 tags[tagsIndex] = int(tag) 763 tagsIndex++ 764 } 765 } 766 sort.Ints(tags) 767 t := 1 768 for len(needTagsAssigned) > 0 { 769 for len(tags) > 0 && t == tags[0] { 770 t++ 771 tags = tags[1:] 772 } 773 needTagsAssigned[0].Number = proto.Int32(int32(t)) 774 needTagsAssigned = needTagsAssigned[1:] 775 t++ 776 } 777 } 778 779 for _, nmb := range mb.nestedMessages { 780 path := append(path, internal.Message_nestedMessagesTag, int32(len(nestedMessages))) 781 if nmd, err := nmb.buildProto(path, sourceInfo); err != nil { 782 return nil, err 783 } else { 784 nestedMessages = append(nestedMessages, nmd) 785 } 786 } 787 788 nestedExtensions := make([]*descriptorpb.FieldDescriptorProto, 0, len(mb.nestedExtensions)) 789 for _, exb := range mb.nestedExtensions { 790 path := append(path, internal.Message_extensionsTag, int32(len(nestedExtensions))) 791 if exd, err := exb.buildProto(path, sourceInfo, isExtendeeMessageSet(exb)); err != nil { 792 return nil, err 793 } else { 794 nestedExtensions = append(nestedExtensions, exd) 795 } 796 } 797 798 nestedEnums := make([]*descriptorpb.EnumDescriptorProto, 0, len(mb.nestedEnums)) 799 for _, eb := range mb.nestedEnums { 800 path := append(path, internal.Message_enumsTag, int32(len(nestedEnums))) 801 if ed, err := eb.buildProto(path, sourceInfo); err != nil { 802 return nil, err 803 } else { 804 nestedEnums = append(nestedEnums, ed) 805 } 806 } 807 808 md := &descriptorpb.DescriptorProto{ 809 Name: proto.String(mb.name), 810 Options: mb.Options, 811 Field: fields, 812 OneofDecl: oneOfs, 813 NestedType: nestedMessages, 814 EnumType: nestedEnums, 815 Extension: nestedExtensions, 816 ExtensionRange: mb.ExtensionRanges, 817 ReservedName: mb.ReservedNames, 818 ReservedRange: mb.ReservedRanges, 819 } 820 821 if mb.GetFile().IsProto3 { 822 internal.ProcessProto3OptionalFields(md, nil) 823 } 824 825 return md, nil 826 } 827 828 // Build constructs a message descriptor based on the contents of this message 829 // builder. If there are any problems constructing the descriptor, including 830 // resolving symbols referenced by the builder or failing to meet certain 831 // validation rules, an error is returned. 832 func (mb *MessageBuilder) Build() (*desc.MessageDescriptor, error) { 833 md, err := mb.BuildDescriptor() 834 if err != nil { 835 return nil, err 836 } 837 return md.(*desc.MessageDescriptor), nil 838 } 839 840 // BuildDescriptor constructs a message descriptor based on the contents of this 841 // message builder. Most usages will prefer Build() instead, whose return type 842 // is a concrete descriptor type. This method is present to satisfy the Builder 843 // interface. 844 func (mb *MessageBuilder) BuildDescriptor() (desc.Descriptor, error) { 845 return doBuild(mb, BuilderOptions{}) 846 }