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