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