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