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