github.com/syumai/protoreflect@v1.7.1-0.20200810020253-2ac7e3b3a321/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/syumai/protoreflect/desc" 11 "github.com/syumai/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 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 != dpb.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) setParent(newParent Builder) { 236 mb.baseBuilder.setParent(newParent) 237 } 238 239 func (mb *MessageBuilder) renamedChild(b Builder, oldName string) error { 240 if p, ok := b.GetParent().(*MessageBuilder); !ok || p != mb { 241 return nil 242 } 243 244 if err := mb.addSymbol(b); err != nil { 245 return err 246 } 247 delete(mb.symbols, oldName) 248 return nil 249 } 250 251 func (mb *MessageBuilder) addSymbol(b Builder) error { 252 if ex, ok := mb.symbols[b.GetName()]; ok { 253 return fmt.Errorf("message %s already contains element (%T) named %q", GetFullyQualifiedName(mb), ex, b.GetName()) 254 } 255 mb.symbols[b.GetName()] = b 256 return nil 257 } 258 259 func (mb *MessageBuilder) addTag(flb *FieldBuilder) error { 260 if flb.number == 0 { 261 return nil 262 } 263 if ex, ok := mb.fieldTags[flb.GetNumber()]; ok { 264 return fmt.Errorf("message %s already contains field with tag %d: %s", GetFullyQualifiedName(mb), flb.GetNumber(), ex.GetName()) 265 } 266 mb.fieldTags[flb.GetNumber()] = flb 267 return nil 268 } 269 270 func (mb *MessageBuilder) registerField(flb *FieldBuilder) error { 271 if err := mb.addSymbol(flb); err != nil { 272 return err 273 } 274 if err := mb.addTag(flb); err != nil { 275 delete(mb.symbols, flb.GetName()) 276 return err 277 } 278 if flb.msgType != nil { 279 if err := mb.addSymbol(flb.msgType); err != nil { 280 delete(mb.symbols, flb.GetName()) 281 delete(mb.fieldTags, flb.GetNumber()) 282 return err 283 } 284 } 285 return nil 286 } 287 288 // GetField returns the field with the given name. If no such field exists in 289 // the message, nil is returned. The field does not have to be an immediate 290 // child of this message but could instead be an indirect child via a one-of. 291 func (mb *MessageBuilder) GetField(name string) *FieldBuilder { 292 b := mb.symbols[name] 293 if flb, ok := b.(*FieldBuilder); ok && !flb.IsExtension() { 294 return flb 295 } else { 296 return nil 297 } 298 } 299 300 // RemoveField removes the field with the given name. If no such field exists in 301 // the message, this is a no-op. If the field is part of a one-of, the one-of 302 // remains assigned to this message and the field is removed from it. This 303 // returns the message builder, for method chaining. 304 func (mb *MessageBuilder) RemoveField(name string) *MessageBuilder { 305 mb.TryRemoveField(name) 306 return mb 307 } 308 309 // TryRemoveField removes the field with the given name and returns false if the 310 // message has no such field. If the field is part of a one-of, the one-of 311 // remains assigned to this message and the field is removed from it. 312 func (mb *MessageBuilder) TryRemoveField(name string) bool { 313 b := mb.symbols[name] 314 if flb, ok := b.(*FieldBuilder); ok && !flb.IsExtension() { 315 // parent could be mb, but could also be a one-of 316 flb.GetParent().removeChild(flb) 317 return true 318 } 319 return false 320 } 321 322 // AddField adds the given field to this message. If an error prevents the field 323 // from being added, this method panics. If the given field is an extension, 324 // this method panics. This returns the message builder, for method chaining. 325 func (mb *MessageBuilder) AddField(flb *FieldBuilder) *MessageBuilder { 326 if err := mb.TryAddField(flb); err != nil { 327 panic(err) 328 } 329 return mb 330 } 331 332 // TryAddField adds the given field to this message, returning any error that 333 // prevents the field from being added (such as a name collision with another 334 // element already added to the message). An error is returned if the given 335 // field is an extension field. 336 func (mb *MessageBuilder) TryAddField(flb *FieldBuilder) error { 337 if flb.IsExtension() { 338 return fmt.Errorf("field %s is an extension, not a regular field", flb.GetName()) 339 } 340 // If we are moving field from a one-of that belongs to this message 341 // directly to this message, we have to use different order of operations 342 // to prevent failure (otherwise, it looks like it's being added twice). 343 // (We do similar if moving the other direction, from message to a one-of 344 // that is already assigned to same message.) 345 needToUnlinkFirst := mb.isPresentButNotChild(flb) 346 if needToUnlinkFirst { 347 Unlink(flb) 348 mb.registerField(flb) 349 } else { 350 if err := mb.registerField(flb); err != nil { 351 return err 352 } 353 Unlink(flb) 354 } 355 flb.setParent(mb) 356 mb.fieldsAndOneOfs = append(mb.fieldsAndOneOfs, flb) 357 return nil 358 } 359 360 // GetOneOf returns the one-of with the given name. If no such one-of exists in 361 // the message, nil is returned. 362 func (mb *MessageBuilder) GetOneOf(name string) *OneOfBuilder { 363 b := mb.symbols[name] 364 if oob, ok := b.(*OneOfBuilder); ok { 365 return oob 366 } else { 367 return nil 368 } 369 } 370 371 // RemoveOneOf removes the one-of with the given name. If no such one-of exists 372 // in the message, this is a no-op. This returns the message builder, for method 373 // chaining. 374 func (mb *MessageBuilder) RemoveOneOf(name string) *MessageBuilder { 375 mb.TryRemoveOneOf(name) 376 return mb 377 } 378 379 // TryRemoveOneOf removes the one-of with the given name and returns false if 380 // the message has no such one-of. 381 func (mb *MessageBuilder) TryRemoveOneOf(name string) bool { 382 b := mb.symbols[name] 383 if oob, ok := b.(*OneOfBuilder); ok { 384 mb.removeChild(oob) 385 return true 386 } 387 return false 388 } 389 390 // AddOneOf adds the given one-of to this message. If an error prevents the 391 // one-of from being added, this method panics. This returns the message 392 // builder, for method chaining. 393 func (mb *MessageBuilder) AddOneOf(oob *OneOfBuilder) *MessageBuilder { 394 if err := mb.TryAddOneOf(oob); err != nil { 395 panic(err) 396 } 397 return mb 398 } 399 400 // TryAddOneOf adds the given one-of to this message, returning any error that 401 // prevents the one-of from being added (such as a name collision with another 402 // element already added to the message). 403 func (mb *MessageBuilder) TryAddOneOf(oob *OneOfBuilder) error { 404 if err := mb.addSymbol(oob); err != nil { 405 return err 406 } 407 // add nested fields to symbol and tag map 408 for i, flb := range oob.choices { 409 if err := mb.registerField(flb); err != nil { 410 // must undo all additions we've made so far 411 delete(mb.symbols, oob.GetName()) 412 for i > 1 { 413 i-- 414 flb := oob.choices[i] 415 delete(mb.symbols, flb.GetName()) 416 delete(mb.fieldTags, flb.GetNumber()) 417 } 418 return err 419 } 420 } 421 Unlink(oob) 422 oob.setParent(mb) 423 mb.fieldsAndOneOfs = append(mb.fieldsAndOneOfs, oob) 424 return nil 425 } 426 427 // GetNestedMessage returns the nested message with the given name. If no such 428 // message exists, nil is returned. The named message must be in this message's 429 // scope. If the message is nested more deeply, this will return nil. This means 430 // the message must be a direct child of this message or a child of one of this 431 // message's fields (e.g. the group type for a group field or a map entry for a 432 // map field). 433 func (mb *MessageBuilder) GetNestedMessage(name string) *MessageBuilder { 434 b := mb.symbols[name] 435 if nmb, ok := b.(*MessageBuilder); ok { 436 return nmb 437 } else { 438 return nil 439 } 440 } 441 442 // RemoveNestedMessage removes the nested message with the given name. If no 443 // such message exists, this is a no-op. This returns the message builder, for 444 // method chaining. 445 func (mb *MessageBuilder) RemoveNestedMessage(name string) *MessageBuilder { 446 mb.TryRemoveNestedMessage(name) 447 return mb 448 } 449 450 // TryRemoveNestedMessage removes the nested message with the given name and 451 // returns false if this message has no nested message with that name. If the 452 // named message is a child of a field (e.g. the group type for a group field or 453 // the map entry for a map field), it is removed from that field and thus 454 // removed from this message's scope. 455 func (mb *MessageBuilder) TryRemoveNestedMessage(name string) bool { 456 b := mb.symbols[name] 457 if nmb, ok := b.(*MessageBuilder); ok { 458 // parent could be mb, but could also be a field (if the message 459 // is the field's group or map entry type) 460 nmb.GetParent().removeChild(nmb) 461 return true 462 } 463 return false 464 } 465 466 // AddNestedMessage adds the given message as a nested child of this message. If 467 // an error prevents the message from being added, this method panics. This 468 // returns the message builder, for method chaining. 469 func (mb *MessageBuilder) AddNestedMessage(nmb *MessageBuilder) *MessageBuilder { 470 if err := mb.TryAddNestedMessage(nmb); err != nil { 471 panic(err) 472 } 473 return mb 474 } 475 476 // TryAddNestedMessage adds the given message as a nested child of this message, 477 // returning any error that prevents the message from being added (such as a 478 // name collision with another element already added to the message). 479 func (mb *MessageBuilder) TryAddNestedMessage(nmb *MessageBuilder) error { 480 // If we are moving nested message from field (map entry or group type) 481 // directly to this message, we have to use different order of operations 482 // to prevent failure (otherwise, it looks like it's being added twice). 483 // (We don't need to do similar for the other direction, because that isn't 484 // possible: you can't add messages to a field, they can only be constructed 485 // that way using NewGroupField or NewMapField.) 486 needToUnlinkFirst := mb.isPresentButNotChild(nmb) 487 if needToUnlinkFirst { 488 Unlink(nmb) 489 mb.addSymbol(nmb) 490 } else { 491 if err := mb.addSymbol(nmb); err != nil { 492 return err 493 } 494 Unlink(mb) 495 } 496 nmb.setParent(mb) 497 mb.nestedMessages = append(mb.nestedMessages, nmb) 498 return nil 499 } 500 501 func (mb *MessageBuilder) isPresentButNotChild(b Builder) bool { 502 if p, ok := b.GetParent().(*MessageBuilder); ok && p == mb { 503 // it's a child 504 return false 505 } 506 return mb.symbols[b.GetName()] == b 507 } 508 509 // GetNestedExtension returns the nested extension with the given name. If no 510 // such extension exists, nil is returned. The named extension must be in this 511 // message's scope. If the extension is nested more deeply, this will return 512 // nil. This means the extension must be a direct child of this message. 513 func (mb *MessageBuilder) GetNestedExtension(name string) *FieldBuilder { 514 b := mb.symbols[name] 515 if exb, ok := b.(*FieldBuilder); ok && exb.IsExtension() { 516 return exb 517 } else { 518 return nil 519 } 520 } 521 522 // RemoveNestedExtension removes the nested extension with the given name. If no 523 // such extension exists, this is a no-op. This returns the message builder, for 524 // method chaining. 525 func (mb *MessageBuilder) RemoveNestedExtension(name string) *MessageBuilder { 526 mb.TryRemoveNestedExtension(name) 527 return mb 528 } 529 530 // TryRemoveNestedExtension removes the nested extension with the given name and 531 // returns false if this message has no nested extension with that name. 532 func (mb *MessageBuilder) TryRemoveNestedExtension(name string) bool { 533 b := mb.symbols[name] 534 if exb, ok := b.(*FieldBuilder); ok && exb.IsExtension() { 535 mb.removeChild(exb) 536 return true 537 } 538 return false 539 } 540 541 // AddNestedExtension adds the given extension as a nested child of this 542 // message. If an error prevents the extension from being added, this method 543 // panics. This returns the message builder, for method chaining. 544 func (mb *MessageBuilder) AddNestedExtension(exb *FieldBuilder) *MessageBuilder { 545 if err := mb.TryAddNestedExtension(exb); err != nil { 546 panic(err) 547 } 548 return mb 549 } 550 551 // TryAddNestedExtension adds the given extension as a nested child of this 552 // message, returning any error that prevents the extension from being added 553 // (such as a name collision with another element already added to the message). 554 func (mb *MessageBuilder) TryAddNestedExtension(exb *FieldBuilder) error { 555 if !exb.IsExtension() { 556 return fmt.Errorf("field %s is not an extension", exb.GetName()) 557 } 558 if err := mb.addSymbol(exb); err != nil { 559 return err 560 } 561 Unlink(exb) 562 exb.setParent(mb) 563 mb.nestedExtensions = append(mb.nestedExtensions, exb) 564 return nil 565 } 566 567 // GetNestedEnum returns the nested enum with the given name. If no such enum 568 // exists, nil is returned. The named enum must be in this message's scope. If 569 // the enum is nested more deeply, this will return nil. This means the enum 570 // must be a direct child of this message. 571 func (mb *MessageBuilder) GetNestedEnum(name string) *EnumBuilder { 572 b := mb.symbols[name] 573 if eb, ok := b.(*EnumBuilder); ok { 574 return eb 575 } else { 576 return nil 577 } 578 } 579 580 // RemoveNestedEnum removes the nested enum with the given name. If no such enum 581 // exists, this is a no-op. This returns the message builder, for method 582 // chaining. 583 func (mb *MessageBuilder) RemoveNestedEnum(name string) *MessageBuilder { 584 mb.TryRemoveNestedEnum(name) 585 return mb 586 } 587 588 // TryRemoveNestedEnum removes the nested enum with the given name and returns 589 // false if this message has no nested enum with that name. 590 func (mb *MessageBuilder) TryRemoveNestedEnum(name string) bool { 591 b := mb.symbols[name] 592 if eb, ok := b.(*EnumBuilder); ok { 593 mb.removeChild(eb) 594 return true 595 } 596 return false 597 } 598 599 // AddNestedEnum adds the given enum as a nested child of this message. If an 600 // error prevents the enum from being added, this method panics. This returns 601 // the message builder, for method chaining. 602 func (mb *MessageBuilder) AddNestedEnum(eb *EnumBuilder) *MessageBuilder { 603 if err := mb.TryAddNestedEnum(eb); err != nil { 604 panic(err) 605 } 606 return mb 607 } 608 609 // TryAddNestedEnum adds the given enum as a nested child of this message, 610 // returning any error that prevents the enum from being added (such as a name 611 // collision with another element already added to the message). 612 func (mb *MessageBuilder) TryAddNestedEnum(eb *EnumBuilder) error { 613 if err := mb.addSymbol(eb); err != nil { 614 return err 615 } 616 Unlink(eb) 617 eb.setParent(mb) 618 mb.nestedEnums = append(mb.nestedEnums, eb) 619 return nil 620 } 621 622 // SetOptions sets the message options for this message and returns the message, 623 // for method chaining. 624 func (mb *MessageBuilder) SetOptions(options *dpb.MessageOptions) *MessageBuilder { 625 mb.Options = options 626 return mb 627 } 628 629 // AddExtensionRange adds the given extension range to this message. The range 630 // is inclusive of both the start and end, just like defining a range in proto 631 // IDL source. This returns the message, for method chaining. 632 func (mb *MessageBuilder) AddExtensionRange(start, end int32) *MessageBuilder { 633 return mb.AddExtensionRangeWithOptions(start, end, nil) 634 } 635 636 // AddExtensionRangeWithOptions adds the given extension range to this message. 637 // The range is inclusive of both the start and end, just like defining a range 638 // in proto IDL source. This returns the message, for method chaining. 639 func (mb *MessageBuilder) AddExtensionRangeWithOptions(start, end int32, options *dpb.ExtensionRangeOptions) *MessageBuilder { 640 er := &dpb.DescriptorProto_ExtensionRange{ 641 Start: proto.Int32(start), 642 End: proto.Int32(end + 1), 643 Options: options, 644 } 645 mb.ExtensionRanges = append(mb.ExtensionRanges, er) 646 return mb 647 } 648 649 // SetExtensionRanges replaces all of this message's extension ranges with the 650 // given slice of ranges. Unlike AddExtensionRange and unlike the way ranges are 651 // defined in proto IDL source, a DescriptorProto_ExtensionRange struct treats 652 // the end of the range as *exclusive*. So the range is inclusive of the start 653 // but exclusive of the end. This returns the message, for method chaining. 654 func (mb *MessageBuilder) SetExtensionRanges(ranges []*dpb.DescriptorProto_ExtensionRange) *MessageBuilder { 655 mb.ExtensionRanges = ranges 656 return mb 657 } 658 659 // AddReservedRange adds the given reserved range to this message. The range is 660 // inclusive of both the start and end, just like defining a range in proto IDL 661 // source. This returns the message, for method chaining. 662 func (mb *MessageBuilder) AddReservedRange(start, end int32) *MessageBuilder { 663 rr := &dpb.DescriptorProto_ReservedRange{ 664 Start: proto.Int32(start), 665 End: proto.Int32(end + 1), 666 } 667 mb.ReservedRanges = append(mb.ReservedRanges, rr) 668 return mb 669 } 670 671 // SetReservedRanges replaces all of this message's reserved ranges with the 672 // given slice of ranges. Unlike AddReservedRange and unlike the way ranges are 673 // defined in proto IDL source, a DescriptorProto_ReservedRange struct treats 674 // the end of the range as *exclusive* (so it would be the value defined in the 675 // IDL plus one). So the range is inclusive of the start but exclusive of the 676 // end. This returns the message, for method chaining. 677 func (mb *MessageBuilder) SetReservedRanges(ranges []*dpb.DescriptorProto_ReservedRange) *MessageBuilder { 678 mb.ReservedRanges = ranges 679 return mb 680 } 681 682 // AddReservedName adds the given name to the list of reserved field names for 683 // this message. This returns the message, for method chaining. 684 func (mb *MessageBuilder) AddReservedName(name string) *MessageBuilder { 685 mb.ReservedNames = append(mb.ReservedNames, name) 686 return mb 687 } 688 689 // SetReservedNames replaces all of this message's reserved field names with the 690 // given slice of names. This returns the message, for method chaining. 691 func (mb *MessageBuilder) SetReservedNames(names []string) *MessageBuilder { 692 mb.ReservedNames = names 693 return mb 694 } 695 696 func (mb *MessageBuilder) buildProto(path []int32, sourceInfo *dpb.SourceCodeInfo) (*dpb.DescriptorProto, error) { 697 addCommentsTo(sourceInfo, path, &mb.comments) 698 699 var needTagsAssigned []*dpb.FieldDescriptorProto 700 nestedMessages := make([]*dpb.DescriptorProto, 0, len(mb.nestedMessages)) 701 oneOfCount := 0 702 for _, b := range mb.fieldsAndOneOfs { 703 if _, ok := b.(*OneOfBuilder); ok { 704 oneOfCount++ 705 } 706 } 707 708 fields := make([]*dpb.FieldDescriptorProto, 0, len(mb.fieldsAndOneOfs)-oneOfCount) 709 oneOfs := make([]*dpb.OneofDescriptorProto, 0, oneOfCount) 710 711 addField := func(flb *FieldBuilder, fld *dpb.FieldDescriptorProto) error { 712 fields = append(fields, fld) 713 if flb.number == 0 { 714 needTagsAssigned = append(needTagsAssigned, fld) 715 } 716 if flb.msgType != nil { 717 nmpath := append(path, internal.Message_nestedMessagesTag, int32(len(nestedMessages))) 718 if entry, err := flb.msgType.buildProto(nmpath, sourceInfo); err != nil { 719 return err 720 } else { 721 nestedMessages = append(nestedMessages, entry) 722 } 723 } 724 return nil 725 } 726 727 for _, b := range mb.fieldsAndOneOfs { 728 if flb, ok := b.(*FieldBuilder); ok { 729 fldpath := append(path, internal.Message_fieldsTag, int32(len(fields))) 730 fld, err := flb.buildProto(fldpath, sourceInfo, mb.Options.GetMessageSetWireFormat()) 731 if err != nil { 732 return nil, err 733 } 734 if err := addField(flb, fld); err != nil { 735 return nil, err 736 } 737 } else { 738 oopath := append(path, internal.Message_oneOfsTag, int32(len(oneOfs))) 739 oob := b.(*OneOfBuilder) 740 oobIndex := len(oneOfs) 741 ood, err := oob.buildProto(oopath, sourceInfo) 742 if err != nil { 743 return nil, err 744 } 745 oneOfs = append(oneOfs, ood) 746 for _, flb := range oob.choices { 747 path := append(path, internal.Message_fieldsTag, int32(len(fields))) 748 fld, err := flb.buildProto(path, sourceInfo, mb.Options.GetMessageSetWireFormat()) 749 if err != nil { 750 return nil, err 751 } 752 fld.OneofIndex = proto.Int32(int32(oobIndex)) 753 if err := addField(flb, fld); err != nil { 754 return nil, err 755 } 756 } 757 } 758 } 759 760 if len(needTagsAssigned) > 0 { 761 tags := make([]int, len(fields)-len(needTagsAssigned)) 762 for i, fld := range fields { 763 tag := fld.GetNumber() 764 if tag != 0 { 765 tags[i] = int(tag) 766 } 767 } 768 sort.Ints(tags) 769 t := 1 770 for len(needTagsAssigned) > 0 { 771 for len(tags) > 0 && t == tags[0] { 772 t++ 773 tags = tags[1:] 774 } 775 needTagsAssigned[0].Number = proto.Int32(int32(t)) 776 needTagsAssigned = needTagsAssigned[1:] 777 t++ 778 } 779 } 780 781 for _, nmb := range mb.nestedMessages { 782 path := append(path, internal.Message_nestedMessagesTag, int32(len(nestedMessages))) 783 if nmd, err := nmb.buildProto(path, sourceInfo); err != nil { 784 return nil, err 785 } else { 786 nestedMessages = append(nestedMessages, nmd) 787 } 788 } 789 790 nestedExtensions := make([]*dpb.FieldDescriptorProto, 0, len(mb.nestedExtensions)) 791 for _, exb := range mb.nestedExtensions { 792 path := append(path, internal.Message_extensionsTag, int32(len(nestedExtensions))) 793 if exd, err := exb.buildProto(path, sourceInfo, isExtendeeMessageSet(exb)); err != nil { 794 return nil, err 795 } else { 796 nestedExtensions = append(nestedExtensions, exd) 797 } 798 } 799 800 nestedEnums := make([]*dpb.EnumDescriptorProto, 0, len(mb.nestedEnums)) 801 for _, eb := range mb.nestedEnums { 802 path := append(path, internal.Message_enumsTag, int32(len(nestedEnums))) 803 if ed, err := eb.buildProto(path, sourceInfo); err != nil { 804 return nil, err 805 } else { 806 nestedEnums = append(nestedEnums, ed) 807 } 808 } 809 810 md := &dpb.DescriptorProto{ 811 Name: proto.String(mb.name), 812 Options: mb.Options, 813 Field: fields, 814 OneofDecl: oneOfs, 815 NestedType: nestedMessages, 816 EnumType: nestedEnums, 817 Extension: nestedExtensions, 818 ExtensionRange: mb.ExtensionRanges, 819 ReservedName: mb.ReservedNames, 820 ReservedRange: mb.ReservedRanges, 821 } 822 823 if mb.GetFile().IsProto3 { 824 internal.ProcessProto3OptionalFields(md) 825 } 826 827 return md, nil 828 } 829 830 // Build constructs a message descriptor based on the contents of this message 831 // builder. If there are any problems constructing the descriptor, including 832 // resolving symbols referenced by the builder or failing to meet certain 833 // validation rules, an error is returned. 834 func (mb *MessageBuilder) Build() (*desc.MessageDescriptor, error) { 835 md, err := mb.BuildDescriptor() 836 if err != nil { 837 return nil, err 838 } 839 return md.(*desc.MessageDescriptor), nil 840 } 841 842 // BuildDescriptor constructs a message descriptor based on the contents of this 843 // message builder. Most usages will prefer Build() instead, whose return type 844 // is a concrete descriptor type. This method is present to satisfy the Builder 845 // interface. 846 func (mb *MessageBuilder) BuildDescriptor() (desc.Descriptor, error) { 847 return doBuild(mb, BuilderOptions{}) 848 }