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