github.com/jhump/protoreflect@v1.16.0/desc/builder/doc.go (about)

     1  // Package builder contains a means of building and modifying proto descriptors
     2  // programmatically. There are numerous factory methods to aid in constructing
     3  // new descriptors as are there methods for converting existing descriptors into
     4  // builders, for modification.
     5  //
     6  // # Factory Functions
     7  //
     8  // Builders are created using the numerous factory functions. Each type of
     9  // descriptor has two kinds of factory functions for the corresponding type of
    10  // builder.
    11  //
    12  // One accepts a descriptor (From*) and returns a copy of it as a builder. The
    13  // descriptor can be manipulated and built to produce a new variant of the
    14  // original. So this is useful for changing existing constructs.
    15  //
    16  // The other kind of factory function (New*) accepts basic arguments and returns
    17  // a new, empty builder (other than the arguments required by that function).
    18  // This second kind can be used to fabricate descriptors from scratch.
    19  //
    20  // Factory functions panic on bad input. Bad input includes invalid names (all
    21  // identifiers must begin with letter or underscore and include only letters,
    22  // numbers, and underscores), invalid types (for example, map field keys must be
    23  // an integer type, bool, or string), invalid tag numbers (anything greater than
    24  // 2^29-1, anything in the range 19,000->19,999, any non-positive number), and
    25  // nil values for required fields (such as field types, RPC method types, and
    26  // extendee type for extensions).
    27  //
    28  // # Auto-Assigning Tag Numbers and File Names
    29  //
    30  // The factory function for fields does not accept a tag number. This is because
    31  // tags, for fields where none is set or is explicitly set to zero, are
    32  // automatically assigned. The tags are assigned in the order the fields were
    33  // added to a message builder. Fields in one-ofs are assigned after other fields
    34  // that were added to the message before the one-of. Within a single one-of,
    35  // fields are assigned tags in the order they were added to the one-of. Across
    36  // one-ofs, fields are assigned in the order their one-of was added to a message
    37  // builder. It is fine if some fields have tags and some do not. The assigned
    38  // tags will start at one and proceed from there but will not conflict with tags
    39  // that were explicitly assigned to fields.
    40  //
    41  // Similarly, when constructing a file builder, a name is accepted but can be
    42  // blank. A blank name means that the file will be given a generated, unique
    43  // name when the descriptor is built.
    44  //
    45  // Note that extensions *must* be given a tag number. Only non-extension fields
    46  // can have their tags auto-assigned. If an extension is constructed with a zero
    47  // tag (which is not valid), the factory function will panic.
    48  //
    49  // # Descriptor Hierarchy
    50  //
    51  // The hierarchy for builders is mutable. A descriptor builder, such as a field,
    52  // can be moved from one message to another. When this is done, the field is
    53  // unlinked from its previous location (so the message to which it previously
    54  // belonged will no longer have any reference to such a field) and linked with
    55  // its new parent. To instead *duplicate* a descriptor builder, its struct value
    56  // can simply be copied. This allows for copying a descriptor from one parent to
    57  // another, like so:
    58  //
    59  //	msg := builder.FromMessage(someMsgDesc)
    60  //	field1 := msg.GetField("foo")
    61  //	field2 := *field1 // field2 is now a copy
    62  //	otherMsg.AddField(&field2)
    63  //
    64  // All descriptors have a link up the hierarchy to the file in which they were
    65  // declared. However, it is *not* necessary to construct this full hierarchy
    66  // with builders. One can create a message builder, for example, and then
    67  // immediately build it to get the descriptor for that message. If it was never
    68  // added to a file then the GetFile() method on the resulting descriptor returns
    69  // a synthetic file that contains only the one message.
    70  //
    71  // Note, however, that this is not true for enum values, methods, and
    72  // non-extension fields. These kinds of builders *must* be added to an enum, a
    73  // service, or a message (respectively) before they can be "built" into a
    74  // descriptor.
    75  //
    76  // When descriptors are created this way, they are created in the default (e.g.
    77  // unnamed) package. In order to put descriptors into a proper package
    78  // namespace, they must be added to a file that has the right package name.
    79  //
    80  // # Builder Pattern and Method Chaining
    81  //
    82  // Each descriptor has some special fields that can only be updated via a Set*
    83  // method. They also all have some exported fields that can be updated by just
    84  // assigning to the field. But even exported fields have accompanying Set*
    85  // methods in order to support a typical method-chaining flow when building
    86  // objects:
    87  //
    88  //	msg, err := builder.NewMessage("MyMessage").
    89  //	    AddField(NewField("foo", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_STRING)).
    90  //	        SetDefaultValue("bar")).
    91  //	    AddField(NewField("baz", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_INT64)).
    92  //	        SetLabel(descriptor.FieldDescriptorProto_LABEL_REPEATED).
    93  //	        SetOptions(&descriptor.FieldOptions{Packed: proto.Bool(true)})).
    94  //	    Build()
    95  //
    96  // So the various Set* methods all return the builder itself so that multiple
    97  // fields may be set in a single invocation chain.
    98  //
    99  // The Set* operations which perform validations also have a TrySet* form which
   100  // can return an error if validation fails. If the method-chaining Set* form is
   101  // used with inputs that fail validation, the Set* method will panic.
   102  //
   103  // # Type References and Imported Types
   104  //
   105  // When defining fields whose type is a message or enum and when defining
   106  // methods (whose request and response type are a message), the type can be set
   107  // to an actual descriptor (e.g. a *desc.MessageDescriptor) or to a builder for
   108  // the type (e.g. a *builder.MessageBuilder). Since Go does not allow method
   109  // overloading, the naming convention is that types referring to descriptors are
   110  // "imported types" (since their use will result in an import statement in the
   111  // resulting file descriptor, to import the file in which the type was defined.)
   112  //
   113  // When referring to other builders, it is not necessary that the referenced
   114  // types be in the same file. When building the descriptors, multiple file
   115  // descriptors may be created, so that all referenced builders are themselves
   116  // resolved into descriptors.
   117  //
   118  // However, it is illegal to create an import cycle. So if two messages, for
   119  // example, refer to each other (message Foo has a field "bar" of type Bar, and
   120  // message Bar has a field "foo" of type Foo), they must explicitly be assigned
   121  // to the same file builder. If they are not assigned to any files, they will be
   122  // assigned to synthetic files which would result in an import cycle (each file
   123  // imports the other). And the same would be true if one or both files were
   124  // explicitly assigned to a file, but not both to the same file.
   125  //
   126  // # Validations and Caveats
   127  //
   128  // Descriptors that are attained from a builder do not necessarily represent a
   129  // valid construct in the proto source language. There are some validations
   130  // enforced by protoc that are not enforced by builders, for example, ensuring
   131  // that there are no namespace conflicts (e.g. file "foo.proto" declares an
   132  // element named "pkg.bar" and so does a file that it imports). Because of this,
   133  // it is possible for builders to wire up references in a way that the resulting
   134  // descriptors are incorrect. This is mainly possible when file builders are
   135  // used to create files with duplicate symbols and then cross-linked. It can
   136  // also happen when a builder is linked to descriptors from more than one
   137  // version of the same file.
   138  //
   139  // When constructing descriptors using builders, applications should not attempt
   140  // to build invalid constructs. Even though there are many rules in the protobuf
   141  // language that are not enforced, those rules that are enforced can result in
   142  // panics when a violation is detected. Generally, builder methods that do not
   143  // return errors (like those used for method chaining) will panic on bad input
   144  // or when trying to mutate a proto into an invalid state.
   145  //
   146  // Several rules are enforced by the builders. Violating these rules will result
   147  // in errors (or panics for factory functions and methods that do not return
   148  // errors). These are the rules that are currently enforced:
   149  //
   150  //  1. Import cycles are not allowed. (See above for more details.)
   151  //  2. Within a single file, symbols are not allowed to have naming conflicts.
   152  //     This means that is not legal to create a message and an extension with
   153  //     the same name in the same file.
   154  //  3. Messages are not allowed to have multiple fields with the same tag. Note
   155  //     that only non-extension fields are checked when using builders. So
   156  //     builders will allow tag collisions for extensions. (Use caution.)
   157  //  4. Map keys can only be integer types, booleans, and strings.
   158  //  5. Fields cannot have tags in the special reserved range 19000-19999. Also
   159  //     the maximum allowed tag value is 536870911 (2^29 - 1). Finally, fields
   160  //     cannot have negative values.
   161  //  6. Element names should include only underscore, letters, and numbers, and
   162  //     must begin with an underscore or letter.
   163  //  7. Files with a syntax of proto3 are not allowed to have required fields.
   164  //  8. Files with a syntax of proto3 are not allowed to have messages that
   165  //     define extension ranges.
   166  //  9. Files with a syntax of proto3 are not allowed to use groups.
   167  //  10. Files with a syntax of proto3 are not allowed to declare default values
   168  //     for fields.
   169  //  11. Extension fields must use tag numbers that are in an extension range
   170  //     defined on the extended message.
   171  //  12. Non-extension fields are not allowed to use tags that lie in a message's
   172  //     extension ranges or reserved ranges.
   173  //  13. Non-extension fields are not allowed to use names that the message has
   174  //     marked as reserved.
   175  //  14. Extension ranges and reserved ranges must not overlap.
   176  //
   177  // Validation rules that are *not* enforced by builders, and thus would be
   178  // allowed and result in illegal constructs, include the following:
   179  //
   180  //  1. Names are supposed to be globally unique, even across multiple files
   181  //     if multiple files are defined in the same package.
   182  //  2. Multiple extensions for the same message cannot re-use tag numbers, even
   183  //     across multiple files.
   184  package builder