1package internal
2
3import (
4	"math"
5	"unicode"
6	"unicode/utf8"
7)
8
9const (
10	// MaxNormalTag is the maximum allowed tag number for a field in a normal message.
11	MaxNormalTag = 536870911 // 2^29 - 1
12
13	// MaxMessageSetTag is the maximum allowed tag number of a field in a message that
14	// uses the message set wire format.
15	MaxMessageSetTag = math.MaxInt32 - 1
16
17	// MaxTag is the maximum allowed tag number. (It is the same as MaxMessageSetTag
18	// since that is the absolute highest allowed.)
19	MaxTag = MaxMessageSetTag
20
21	// SpecialReservedStart is the first tag in a range that is reserved and not
22	// allowed for use in message definitions.
23	SpecialReservedStart = 19000
24	// SpecialReservedEnd is the last tag in a range that is reserved and not
25	// allowed for use in message definitions.
26	SpecialReservedEnd = 19999
27
28	// NB: It would be nice to use constants from generated code instead of
29	// hard-coding these here. But code-gen does not emit these as constants
30	// anywhere. The only places they appear in generated code are struct tags
31	// on fields of the generated descriptor protos.
32
33	// File_packageTag is the tag number of the package element in a file
34	// descriptor proto.
35	File_packageTag = 2
36	// File_dependencyTag is the tag number of the dependencies element in a
37	// file descriptor proto.
38	File_dependencyTag = 3
39	// File_messagesTag is the tag number of the messages element in a file
40	// descriptor proto.
41	File_messagesTag = 4
42	// File_enumsTag is the tag number of the enums element in a file descriptor
43	// proto.
44	File_enumsTag = 5
45	// File_servicesTag is the tag number of the services element in a file
46	// descriptor proto.
47	File_servicesTag = 6
48	// File_extensionsTag is the tag number of the extensions element in a file
49	// descriptor proto.
50	File_extensionsTag = 7
51	// File_optionsTag is the tag number of the options element in a file
52	// descriptor proto.
53	File_optionsTag = 8
54	// File_syntaxTag is the tag number of the syntax element in a file
55	// descriptor proto.
56	File_syntaxTag = 12
57	// Message_nameTag is the tag number of the name element in a message
58	// descriptor proto.
59	Message_nameTag = 1
60	// Message_fieldsTag is the tag number of the fields element in a message
61	// descriptor proto.
62	Message_fieldsTag = 2
63	// Message_nestedMessagesTag is the tag number of the nested messages
64	// element in a message descriptor proto.
65	Message_nestedMessagesTag = 3
66	// Message_enumsTag is the tag number of the enums element in a message
67	// descriptor proto.
68	Message_enumsTag = 4
69	// Message_extensionRangeTag is the tag number of the extension ranges
70	// element in a message descriptor proto.
71	Message_extensionRangeTag = 5
72	// Message_extensionsTag is the tag number of the extensions element in a
73	// message descriptor proto.
74	Message_extensionsTag = 6
75	// Message_optionsTag is the tag number of the options element in a message
76	// descriptor proto.
77	Message_optionsTag = 7
78	// Message_oneOfsTag is the tag number of the one-ofs element in a message
79	// descriptor proto.
80	Message_oneOfsTag = 8
81	// Message_reservedRangeTag is the tag number of the reserved ranges element
82	// in a message descriptor proto.
83	Message_reservedRangeTag = 9
84	// Message_reservedNameTag is the tag number of the reserved names element
85	// in a message descriptor proto.
86	Message_reservedNameTag = 10
87	// ExtensionRange_startTag is the tag number of the start index in an
88	// extension range proto.
89	ExtensionRange_startTag = 1
90	// ExtensionRange_endTag is the tag number of the end index in an
91	// extension range proto.
92	ExtensionRange_endTag = 2
93	// ExtensionRange_optionsTag is the tag number of the options element in an
94	// extension range proto.
95	ExtensionRange_optionsTag = 3
96	// ReservedRange_startTag is the tag number of the start index in a reserved
97	// range proto.
98	ReservedRange_startTag = 1
99	// ReservedRange_endTag is the tag number of the end index in a reserved
100	// range proto.
101	ReservedRange_endTag = 2
102	// Field_nameTag is the tag number of the name element in a field descriptor
103	// proto.
104	Field_nameTag = 1
105	// Field_extendeeTag is the tag number of the extendee element in a field
106	// descriptor proto.
107	Field_extendeeTag = 2
108	// Field_numberTag is the tag number of the number element in a field
109	// descriptor proto.
110	Field_numberTag = 3
111	// Field_labelTag is the tag number of the label element in a field
112	// descriptor proto.
113	Field_labelTag = 4
114	// Field_typeTag is the tag number of the type element in a field descriptor
115	// proto.
116	Field_typeTag = 5
117	// Field_typeNameTag is the tag number of the type name element in a field
118	// descriptor proto.
119	Field_typeNameTag = 6
120	// Field_defaultTag is the tag number of the default value element in a
121	// field descriptor proto.
122	Field_defaultTag = 7
123	// Field_optionsTag is the tag number of the options element in a field
124	// descriptor proto.
125	Field_optionsTag = 8
126	// Field_jsonNameTag is the tag number of the JSON name element in a field
127	// descriptor proto.
128	Field_jsonNameTag = 10
129	// Field_proto3OptionalTag is the tag number of the proto3_optional element
130	// in a descriptor proto.
131	Field_proto3OptionalTag = 17
132	// OneOf_nameTag is the tag number of the name element in a one-of
133	// descriptor proto.
134	OneOf_nameTag = 1
135	// OneOf_optionsTag is the tag number of the options element in a one-of
136	// descriptor proto.
137	OneOf_optionsTag = 2
138	// Enum_nameTag is the tag number of the name element in an enum descriptor
139	// proto.
140	Enum_nameTag = 1
141	// Enum_valuesTag is the tag number of the values element in an enum
142	// descriptor proto.
143	Enum_valuesTag = 2
144	// Enum_optionsTag is the tag number of the options element in an enum
145	// descriptor proto.
146	Enum_optionsTag = 3
147	// Enum_reservedRangeTag is the tag number of the reserved ranges element in
148	// an enum descriptor proto.
149	Enum_reservedRangeTag = 4
150	// Enum_reservedNameTag is the tag number of the reserved names element in
151	// an enum descriptor proto.
152	Enum_reservedNameTag = 5
153	// EnumVal_nameTag is the tag number of the name element in an enum value
154	// descriptor proto.
155	EnumVal_nameTag = 1
156	// EnumVal_numberTag is the tag number of the number element in an enum
157	// value descriptor proto.
158	EnumVal_numberTag = 2
159	// EnumVal_optionsTag is the tag number of the options element in an enum
160	// value descriptor proto.
161	EnumVal_optionsTag = 3
162	// Service_nameTag is the tag number of the name element in a service
163	// descriptor proto.
164	Service_nameTag = 1
165	// Service_methodsTag is the tag number of the methods element in a service
166	// descriptor proto.
167	Service_methodsTag = 2
168	// Service_optionsTag is the tag number of the options element in a service
169	// descriptor proto.
170	Service_optionsTag = 3
171	// Method_nameTag is the tag number of the name element in a method
172	// descriptor proto.
173	Method_nameTag = 1
174	// Method_inputTag is the tag number of the input type element in a method
175	// descriptor proto.
176	Method_inputTag = 2
177	// Method_outputTag is the tag number of the output type element in a method
178	// descriptor proto.
179	Method_outputTag = 3
180	// Method_optionsTag is the tag number of the options element in a method
181	// descriptor proto.
182	Method_optionsTag = 4
183	// Method_inputStreamTag is the tag number of the input stream flag in a
184	// method descriptor proto.
185	Method_inputStreamTag = 5
186	// Method_outputStreamTag is the tag number of the output stream flag in a
187	// method descriptor proto.
188	Method_outputStreamTag = 6
189
190	// UninterpretedOptionsTag is the tag number of the uninterpreted options
191	// element. All *Options messages use the same tag for the field that stores
192	// uninterpreted options.
193	UninterpretedOptionsTag = 999
194
195	// Uninterpreted_nameTag is the tag number of the name element in an
196	// uninterpreted options proto.
197	Uninterpreted_nameTag = 2
198	// Uninterpreted_identTag is the tag number of the identifier value in an
199	// uninterpreted options proto.
200	Uninterpreted_identTag = 3
201	// Uninterpreted_posIntTag is the tag number of the positive int value in an
202	// uninterpreted options proto.
203	Uninterpreted_posIntTag = 4
204	// Uninterpreted_negIntTag is the tag number of the negative int value in an
205	// uninterpreted options proto.
206	Uninterpreted_negIntTag = 5
207	// Uninterpreted_doubleTag is the tag number of the double value in an
208	// uninterpreted options proto.
209	Uninterpreted_doubleTag = 6
210	// Uninterpreted_stringTag is the tag number of the string value in an
211	// uninterpreted options proto.
212	Uninterpreted_stringTag = 7
213	// Uninterpreted_aggregateTag is the tag number of the aggregate value in an
214	// uninterpreted options proto.
215	Uninterpreted_aggregateTag = 8
216	// UninterpretedName_nameTag is the tag number of the name element in an
217	// uninterpreted option name proto.
218	UninterpretedName_nameTag = 1
219)
220
221// JsonName returns the default JSON name for a field with the given name.
222func JsonName(name string) string {
223	var js []rune
224	nextUpper := false
225	for i, r := range name {
226		if r == '_' {
227			nextUpper = true
228			continue
229		}
230		if i == 0 {
231			js = append(js, r)
232		} else if nextUpper {
233			nextUpper = false
234			js = append(js, unicode.ToUpper(r))
235		} else {
236			js = append(js, r)
237		}
238	}
239	return string(js)
240}
241
242// InitCap returns the given field name, but with the first letter capitalized.
243func InitCap(name string) string {
244	r, sz := utf8.DecodeRuneInString(name)
245	return string(unicode.ToUpper(r)) + name[sz:]
246}
247
248// CreatePrefixList returns a list of package prefixes to search when resolving
249// a symbol name. If the given package is blank, it returns only the empty
250// string. If the given package contains only one token, e.g. "foo", it returns
251// that token and the empty string, e.g. ["foo", ""]. Otherwise, it returns
252// successively shorter prefixes of the package and then the empty string. For
253// example, for a package named "foo.bar.baz" it will return the following list:
254//   ["foo.bar.baz", "foo.bar", "foo", ""]
255func CreatePrefixList(pkg string) []string {
256	if pkg == "" {
257		return []string{""}
258	}
259
260	numDots := 0
261	// one pass to pre-allocate the returned slice
262	for i := 0; i < len(pkg); i++ {
263		if pkg[i] == '.' {
264			numDots++
265		}
266	}
267	if numDots == 0 {
268		return []string{pkg, ""}
269	}
270
271	prefixes := make([]string, numDots+2)
272	// second pass to fill in returned slice
273	for i := 0; i < len(pkg); i++ {
274		if pkg[i] == '.' {
275			prefixes[numDots] = pkg[:i]
276			numDots--
277		}
278	}
279	prefixes[0] = pkg
280
281	return prefixes
282}
283
284// GetMaxTag returns the max tag number allowed, based on whether a message uses
285// message set wire format or not.
286func GetMaxTag(isMessageSet bool) int32 {
287	if isMessageSet {
288		return MaxMessageSetTag
289	}
290	return MaxNormalTag
291}
292