256
|
1 |
// Copyright 2019 The Go Authors. All rights reserved. |
|
2 |
// Use of this source code is governed by a BSD-style |
|
3 |
// license that can be found in the LICENSE file. |
|
4 |
|
|
5 |
package filedesc |
|
6 |
|
|
7 |
import ( |
|
8 |
"fmt" |
|
9 |
"math" |
|
10 |
"sort" |
|
11 |
"sync" |
|
12 |
|
|
13 |
"google.golang.org/protobuf/internal/genid" |
|
14 |
|
|
15 |
"google.golang.org/protobuf/encoding/protowire" |
|
16 |
"google.golang.org/protobuf/internal/descfmt" |
|
17 |
"google.golang.org/protobuf/internal/errors" |
|
18 |
"google.golang.org/protobuf/internal/pragma" |
|
19 |
"google.golang.org/protobuf/reflect/protoreflect" |
|
20 |
) |
|
21 |
|
260
|
22 |
type FileImports []protoreflect.FileImport |
256
|
23 |
|
|
24 |
func (p *FileImports) Len() int { return len(*p) } |
260
|
25 |
func (p *FileImports) Get(i int) protoreflect.FileImport { return (*p)[i] } |
256
|
26 |
func (p *FileImports) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
27 |
func (p *FileImports) ProtoInternal(pragma.DoNotImplement) {} |
|
28 |
|
|
29 |
type Names struct { |
260
|
30 |
List []protoreflect.Name |
256
|
31 |
once sync.Once |
260
|
32 |
has map[protoreflect.Name]int // protected by once |
256
|
33 |
} |
|
34 |
|
|
35 |
func (p *Names) Len() int { return len(p.List) } |
260
|
36 |
func (p *Names) Get(i int) protoreflect.Name { return p.List[i] } |
|
37 |
func (p *Names) Has(s protoreflect.Name) bool { return p.lazyInit().has[s] > 0 } |
256
|
38 |
func (p *Names) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
39 |
func (p *Names) ProtoInternal(pragma.DoNotImplement) {} |
|
40 |
func (p *Names) lazyInit() *Names { |
|
41 |
p.once.Do(func() { |
|
42 |
if len(p.List) > 0 { |
260
|
43 |
p.has = make(map[protoreflect.Name]int, len(p.List)) |
256
|
44 |
for _, s := range p.List { |
|
45 |
p.has[s] = p.has[s] + 1 |
|
46 |
} |
|
47 |
} |
|
48 |
}) |
|
49 |
return p |
|
50 |
} |
|
51 |
|
|
52 |
// CheckValid reports any errors with the set of names with an error message |
|
53 |
// that completes the sentence: "ranges is invalid because it has ..." |
|
54 |
func (p *Names) CheckValid() error { |
|
55 |
for s, n := range p.lazyInit().has { |
|
56 |
switch { |
|
57 |
case n > 1: |
|
58 |
return errors.New("duplicate name: %q", s) |
|
59 |
case false && !s.IsValid(): |
|
60 |
// NOTE: The C++ implementation does not validate the identifier. |
|
61 |
// See https://github.com/protocolbuffers/protobuf/issues/6335. |
|
62 |
return errors.New("invalid name: %q", s) |
|
63 |
} |
|
64 |
} |
|
65 |
return nil |
|
66 |
} |
|
67 |
|
|
68 |
type EnumRanges struct { |
260
|
69 |
List [][2]protoreflect.EnumNumber // start inclusive; end inclusive |
256
|
70 |
once sync.Once |
260
|
71 |
sorted [][2]protoreflect.EnumNumber // protected by once |
256
|
72 |
} |
|
73 |
|
260
|
74 |
func (p *EnumRanges) Len() int { return len(p.List) } |
|
75 |
func (p *EnumRanges) Get(i int) [2]protoreflect.EnumNumber { return p.List[i] } |
|
76 |
func (p *EnumRanges) Has(n protoreflect.EnumNumber) bool { |
256
|
77 |
for ls := p.lazyInit().sorted; len(ls) > 0; { |
|
78 |
i := len(ls) / 2 |
|
79 |
switch r := enumRange(ls[i]); { |
|
80 |
case n < r.Start(): |
|
81 |
ls = ls[:i] // search lower |
|
82 |
case n > r.End(): |
|
83 |
ls = ls[i+1:] // search upper |
|
84 |
default: |
|
85 |
return true |
|
86 |
} |
|
87 |
} |
|
88 |
return false |
|
89 |
} |
|
90 |
func (p *EnumRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
91 |
func (p *EnumRanges) ProtoInternal(pragma.DoNotImplement) {} |
|
92 |
func (p *EnumRanges) lazyInit() *EnumRanges { |
|
93 |
p.once.Do(func() { |
|
94 |
p.sorted = append(p.sorted, p.List...) |
|
95 |
sort.Slice(p.sorted, func(i, j int) bool { |
|
96 |
return p.sorted[i][0] < p.sorted[j][0] |
|
97 |
}) |
|
98 |
}) |
|
99 |
return p |
|
100 |
} |
|
101 |
|
|
102 |
// CheckValid reports any errors with the set of names with an error message |
|
103 |
// that completes the sentence: "ranges is invalid because it has ..." |
|
104 |
func (p *EnumRanges) CheckValid() error { |
|
105 |
var rp enumRange |
|
106 |
for i, r := range p.lazyInit().sorted { |
|
107 |
r := enumRange(r) |
|
108 |
switch { |
|
109 |
case !(r.Start() <= r.End()): |
|
110 |
return errors.New("invalid range: %v", r) |
|
111 |
case !(rp.End() < r.Start()) && i > 0: |
|
112 |
return errors.New("overlapping ranges: %v with %v", rp, r) |
|
113 |
} |
|
114 |
rp = r |
|
115 |
} |
|
116 |
return nil |
|
117 |
} |
|
118 |
|
|
119 |
type enumRange [2]protoreflect.EnumNumber |
|
120 |
|
|
121 |
func (r enumRange) Start() protoreflect.EnumNumber { return r[0] } // inclusive |
|
122 |
func (r enumRange) End() protoreflect.EnumNumber { return r[1] } // inclusive |
|
123 |
func (r enumRange) String() string { |
|
124 |
if r.Start() == r.End() { |
|
125 |
return fmt.Sprintf("%d", r.Start()) |
|
126 |
} |
|
127 |
return fmt.Sprintf("%d to %d", r.Start(), r.End()) |
|
128 |
} |
|
129 |
|
|
130 |
type FieldRanges struct { |
260
|
131 |
List [][2]protoreflect.FieldNumber // start inclusive; end exclusive |
256
|
132 |
once sync.Once |
260
|
133 |
sorted [][2]protoreflect.FieldNumber // protected by once |
256
|
134 |
} |
|
135 |
|
260
|
136 |
func (p *FieldRanges) Len() int { return len(p.List) } |
|
137 |
func (p *FieldRanges) Get(i int) [2]protoreflect.FieldNumber { return p.List[i] } |
|
138 |
func (p *FieldRanges) Has(n protoreflect.FieldNumber) bool { |
256
|
139 |
for ls := p.lazyInit().sorted; len(ls) > 0; { |
|
140 |
i := len(ls) / 2 |
|
141 |
switch r := fieldRange(ls[i]); { |
|
142 |
case n < r.Start(): |
|
143 |
ls = ls[:i] // search lower |
|
144 |
case n > r.End(): |
|
145 |
ls = ls[i+1:] // search upper |
|
146 |
default: |
|
147 |
return true |
|
148 |
} |
|
149 |
} |
|
150 |
return false |
|
151 |
} |
|
152 |
func (p *FieldRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
153 |
func (p *FieldRanges) ProtoInternal(pragma.DoNotImplement) {} |
|
154 |
func (p *FieldRanges) lazyInit() *FieldRanges { |
|
155 |
p.once.Do(func() { |
|
156 |
p.sorted = append(p.sorted, p.List...) |
|
157 |
sort.Slice(p.sorted, func(i, j int) bool { |
|
158 |
return p.sorted[i][0] < p.sorted[j][0] |
|
159 |
}) |
|
160 |
}) |
|
161 |
return p |
|
162 |
} |
|
163 |
|
|
164 |
// CheckValid reports any errors with the set of ranges with an error message |
|
165 |
// that completes the sentence: "ranges is invalid because it has ..." |
|
166 |
func (p *FieldRanges) CheckValid(isMessageSet bool) error { |
|
167 |
var rp fieldRange |
|
168 |
for i, r := range p.lazyInit().sorted { |
|
169 |
r := fieldRange(r) |
|
170 |
switch { |
|
171 |
case !isValidFieldNumber(r.Start(), isMessageSet): |
|
172 |
return errors.New("invalid field number: %d", r.Start()) |
|
173 |
case !isValidFieldNumber(r.End(), isMessageSet): |
|
174 |
return errors.New("invalid field number: %d", r.End()) |
|
175 |
case !(r.Start() <= r.End()): |
|
176 |
return errors.New("invalid range: %v", r) |
|
177 |
case !(rp.End() < r.Start()) && i > 0: |
|
178 |
return errors.New("overlapping ranges: %v with %v", rp, r) |
|
179 |
} |
|
180 |
rp = r |
|
181 |
} |
|
182 |
return nil |
|
183 |
} |
|
184 |
|
|
185 |
// isValidFieldNumber reports whether the field number is valid. |
|
186 |
// Unlike the FieldNumber.IsValid method, it allows ranges that cover the |
|
187 |
// reserved number range. |
|
188 |
func isValidFieldNumber(n protoreflect.FieldNumber, isMessageSet bool) bool { |
|
189 |
return protowire.MinValidNumber <= n && (n <= protowire.MaxValidNumber || isMessageSet) |
|
190 |
} |
|
191 |
|
|
192 |
// CheckOverlap reports an error if p and q overlap. |
|
193 |
func (p *FieldRanges) CheckOverlap(q *FieldRanges) error { |
|
194 |
rps := p.lazyInit().sorted |
|
195 |
rqs := q.lazyInit().sorted |
|
196 |
for pi, qi := 0, 0; pi < len(rps) && qi < len(rqs); { |
|
197 |
rp := fieldRange(rps[pi]) |
|
198 |
rq := fieldRange(rqs[qi]) |
|
199 |
if !(rp.End() < rq.Start() || rq.End() < rp.Start()) { |
|
200 |
return errors.New("overlapping ranges: %v with %v", rp, rq) |
|
201 |
} |
|
202 |
if rp.Start() < rq.Start() { |
|
203 |
pi++ |
|
204 |
} else { |
|
205 |
qi++ |
|
206 |
} |
|
207 |
} |
|
208 |
return nil |
|
209 |
} |
|
210 |
|
|
211 |
type fieldRange [2]protoreflect.FieldNumber |
|
212 |
|
|
213 |
func (r fieldRange) Start() protoreflect.FieldNumber { return r[0] } // inclusive |
|
214 |
func (r fieldRange) End() protoreflect.FieldNumber { return r[1] - 1 } // inclusive |
|
215 |
func (r fieldRange) String() string { |
|
216 |
if r.Start() == r.End() { |
|
217 |
return fmt.Sprintf("%d", r.Start()) |
|
218 |
} |
|
219 |
return fmt.Sprintf("%d to %d", r.Start(), r.End()) |
|
220 |
} |
|
221 |
|
|
222 |
type FieldNumbers struct { |
260
|
223 |
List []protoreflect.FieldNumber |
256
|
224 |
once sync.Once |
260
|
225 |
has map[protoreflect.FieldNumber]struct{} // protected by once |
256
|
226 |
} |
|
227 |
|
260
|
228 |
func (p *FieldNumbers) Len() int { return len(p.List) } |
|
229 |
func (p *FieldNumbers) Get(i int) protoreflect.FieldNumber { return p.List[i] } |
|
230 |
func (p *FieldNumbers) Has(n protoreflect.FieldNumber) bool { |
256
|
231 |
p.once.Do(func() { |
|
232 |
if len(p.List) > 0 { |
260
|
233 |
p.has = make(map[protoreflect.FieldNumber]struct{}, len(p.List)) |
256
|
234 |
for _, n := range p.List { |
|
235 |
p.has[n] = struct{}{} |
|
236 |
} |
|
237 |
} |
|
238 |
}) |
|
239 |
_, ok := p.has[n] |
|
240 |
return ok |
|
241 |
} |
|
242 |
func (p *FieldNumbers) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
243 |
func (p *FieldNumbers) ProtoInternal(pragma.DoNotImplement) {} |
|
244 |
|
|
245 |
type OneofFields struct { |
260
|
246 |
List []protoreflect.FieldDescriptor |
256
|
247 |
once sync.Once |
260
|
248 |
byName map[protoreflect.Name]protoreflect.FieldDescriptor // protected by once |
|
249 |
byJSON map[string]protoreflect.FieldDescriptor // protected by once |
|
250 |
byText map[string]protoreflect.FieldDescriptor // protected by once |
|
251 |
byNum map[protoreflect.FieldNumber]protoreflect.FieldDescriptor // protected by once |
256
|
252 |
} |
|
253 |
|
260
|
254 |
func (p *OneofFields) Len() int { return len(p.List) } |
|
255 |
func (p *OneofFields) Get(i int) protoreflect.FieldDescriptor { return p.List[i] } |
|
256 |
func (p *OneofFields) ByName(s protoreflect.Name) protoreflect.FieldDescriptor { |
|
257 |
return p.lazyInit().byName[s] |
|
258 |
} |
|
259 |
func (p *OneofFields) ByJSONName(s string) protoreflect.FieldDescriptor { |
|
260 |
return p.lazyInit().byJSON[s] |
|
261 |
} |
|
262 |
func (p *OneofFields) ByTextName(s string) protoreflect.FieldDescriptor { |
|
263 |
return p.lazyInit().byText[s] |
|
264 |
} |
|
265 |
func (p *OneofFields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor { |
|
266 |
return p.lazyInit().byNum[n] |
|
267 |
} |
|
268 |
func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } |
|
269 |
func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {} |
256
|
270 |
|
|
271 |
func (p *OneofFields) lazyInit() *OneofFields { |
|
272 |
p.once.Do(func() { |
|
273 |
if len(p.List) > 0 { |
260
|
274 |
p.byName = make(map[protoreflect.Name]protoreflect.FieldDescriptor, len(p.List)) |
|
275 |
p.byJSON = make(map[string]protoreflect.FieldDescriptor, len(p.List)) |
|
276 |
p.byText = make(map[string]protoreflect.FieldDescriptor, len(p.List)) |
|
277 |
p.byNum = make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor, len(p.List)) |
256
|
278 |
for _, f := range p.List { |
|
279 |
// Field names and numbers are guaranteed to be unique. |
|
280 |
p.byName[f.Name()] = f |
|
281 |
p.byJSON[f.JSONName()] = f |
|
282 |
p.byText[f.TextName()] = f |
|
283 |
p.byNum[f.Number()] = f |
|
284 |
} |
|
285 |
} |
|
286 |
}) |
|
287 |
return p |
|
288 |
} |
|
289 |
|
|
290 |
type SourceLocations struct { |
|
291 |
// List is a list of SourceLocations. |
|
292 |
// The SourceLocation.Next field does not need to be populated |
|
293 |
// as it will be lazily populated upon first need. |
260
|
294 |
List []protoreflect.SourceLocation |
256
|
295 |
|
|
296 |
// File is the parent file descriptor that these locations are relative to. |
|
297 |
// If non-nil, ByDescriptor verifies that the provided descriptor |
|
298 |
// is a child of this file descriptor. |
260
|
299 |
File protoreflect.FileDescriptor |
256
|
300 |
|
|
301 |
once sync.Once |
|
302 |
byPath map[pathKey]int |
|
303 |
} |
|
304 |
|
260
|
305 |
func (p *SourceLocations) Len() int { return len(p.List) } |
|
306 |
func (p *SourceLocations) Get(i int) protoreflect.SourceLocation { return p.lazyInit().List[i] } |
|
307 |
func (p *SourceLocations) byKey(k pathKey) protoreflect.SourceLocation { |
256
|
308 |
if i, ok := p.lazyInit().byPath[k]; ok { |
|
309 |
return p.List[i] |
|
310 |
} |
260
|
311 |
return protoreflect.SourceLocation{} |
256
|
312 |
} |
260
|
313 |
func (p *SourceLocations) ByPath(path protoreflect.SourcePath) protoreflect.SourceLocation { |
256
|
314 |
return p.byKey(newPathKey(path)) |
|
315 |
} |
260
|
316 |
func (p *SourceLocations) ByDescriptor(desc protoreflect.Descriptor) protoreflect.SourceLocation { |
256
|
317 |
if p.File != nil && desc != nil && p.File != desc.ParentFile() { |
260
|
318 |
return protoreflect.SourceLocation{} // mismatching parent files |
256
|
319 |
} |
|
320 |
var pathArr [16]int32 |
|
321 |
path := pathArr[:0] |
|
322 |
for { |
|
323 |
switch desc.(type) { |
260
|
324 |
case protoreflect.FileDescriptor: |
256
|
325 |
// Reverse the path since it was constructed in reverse. |
|
326 |
for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 { |
|
327 |
path[i], path[j] = path[j], path[i] |
|
328 |
} |
|
329 |
return p.byKey(newPathKey(path)) |
260
|
330 |
case protoreflect.MessageDescriptor: |
256
|
331 |
path = append(path, int32(desc.Index())) |
|
332 |
desc = desc.Parent() |
|
333 |
switch desc.(type) { |
260
|
334 |
case protoreflect.FileDescriptor: |
256
|
335 |
path = append(path, int32(genid.FileDescriptorProto_MessageType_field_number)) |
260
|
336 |
case protoreflect.MessageDescriptor: |
256
|
337 |
path = append(path, int32(genid.DescriptorProto_NestedType_field_number)) |
|
338 |
default: |
260
|
339 |
return protoreflect.SourceLocation{} |
256
|
340 |
} |
260
|
341 |
case protoreflect.FieldDescriptor: |
|
342 |
isExtension := desc.(protoreflect.FieldDescriptor).IsExtension() |
256
|
343 |
path = append(path, int32(desc.Index())) |
|
344 |
desc = desc.Parent() |
|
345 |
if isExtension { |
|
346 |
switch desc.(type) { |
260
|
347 |
case protoreflect.FileDescriptor: |
256
|
348 |
path = append(path, int32(genid.FileDescriptorProto_Extension_field_number)) |
260
|
349 |
case protoreflect.MessageDescriptor: |
256
|
350 |
path = append(path, int32(genid.DescriptorProto_Extension_field_number)) |
|
351 |
default: |
260
|
352 |
return protoreflect.SourceLocation{} |
256
|
353 |
} |
|
354 |
} else { |
|
355 |
switch desc.(type) { |
260
|
356 |
case protoreflect.MessageDescriptor: |
256
|
357 |
path = append(path, int32(genid.DescriptorProto_Field_field_number)) |
|
358 |
default: |
260
|
359 |
return protoreflect.SourceLocation{} |
256
|
360 |
} |
|
361 |
} |
260
|
362 |
case protoreflect.OneofDescriptor: |
256
|
363 |
path = append(path, int32(desc.Index())) |
|
364 |
desc = desc.Parent() |
|
365 |
switch desc.(type) { |
260
|
366 |
case protoreflect.MessageDescriptor: |
256
|
367 |
path = append(path, int32(genid.DescriptorProto_OneofDecl_field_number)) |
|
368 |
default: |
260
|
369 |
return protoreflect.SourceLocation{} |
256
|
370 |
} |
260
|
371 |
case protoreflect.EnumDescriptor: |
256
|
372 |
path = append(path, int32(desc.Index())) |
|
373 |
desc = desc.Parent() |
|
374 |
switch desc.(type) { |
260
|
375 |
case protoreflect.FileDescriptor: |
256
|
376 |
path = append(path, int32(genid.FileDescriptorProto_EnumType_field_number)) |
260
|
377 |
case protoreflect.MessageDescriptor: |
256
|
378 |
path = append(path, int32(genid.DescriptorProto_EnumType_field_number)) |
|
379 |
default: |
260
|
380 |
return protoreflect.SourceLocation{} |
256
|
381 |
} |
260
|
382 |
case protoreflect.EnumValueDescriptor: |
256
|
383 |
path = append(path, int32(desc.Index())) |
|
384 |
desc = desc.Parent() |
|
385 |
switch desc.(type) { |
260
|
386 |
case protoreflect.EnumDescriptor: |
256
|
387 |
path = append(path, int32(genid.EnumDescriptorProto_Value_field_number)) |
|
388 |
default: |
260
|
389 |
return protoreflect.SourceLocation{} |
256
|
390 |
} |
260
|
391 |
case protoreflect.ServiceDescriptor: |
256
|
392 |
path = append(path, int32(desc.Index())) |
|
393 |
desc = desc.Parent() |
|
394 |
switch desc.(type) { |
260
|
395 |
case protoreflect.FileDescriptor: |
256
|
396 |
path = append(path, int32(genid.FileDescriptorProto_Service_field_number)) |
|
397 |
default: |
260
|
398 |
return protoreflect.SourceLocation{} |
256
|
399 |
} |
260
|
400 |
case protoreflect.MethodDescriptor: |
256
|
401 |
path = append(path, int32(desc.Index())) |
|
402 |
desc = desc.Parent() |
|
403 |
switch desc.(type) { |
260
|
404 |
case protoreflect.ServiceDescriptor: |
256
|
405 |
path = append(path, int32(genid.ServiceDescriptorProto_Method_field_number)) |
|
406 |
default: |
260
|
407 |
return protoreflect.SourceLocation{} |
256
|
408 |
} |
|
409 |
default: |
260
|
410 |
return protoreflect.SourceLocation{} |
256
|
411 |
} |
|
412 |
} |
|
413 |
} |
|
414 |
func (p *SourceLocations) lazyInit() *SourceLocations { |
|
415 |
p.once.Do(func() { |
|
416 |
if len(p.List) > 0 { |
|
417 |
// Collect all the indexes for a given path. |
|
418 |
pathIdxs := make(map[pathKey][]int, len(p.List)) |
|
419 |
for i, l := range p.List { |
|
420 |
k := newPathKey(l.Path) |
|
421 |
pathIdxs[k] = append(pathIdxs[k], i) |
|
422 |
} |
|
423 |
|
|
424 |
// Update the next index for all locations. |
|
425 |
p.byPath = make(map[pathKey]int, len(p.List)) |
|
426 |
for k, idxs := range pathIdxs { |
|
427 |
for i := 0; i < len(idxs)-1; i++ { |
|
428 |
p.List[idxs[i]].Next = idxs[i+1] |
|
429 |
} |
|
430 |
p.List[idxs[len(idxs)-1]].Next = 0 |
|
431 |
p.byPath[k] = idxs[0] // record the first location for this path |
|
432 |
} |
|
433 |
} |
|
434 |
}) |
|
435 |
return p |
|
436 |
} |
|
437 |
func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {} |
|
438 |
|
|
439 |
// pathKey is a comparable representation of protoreflect.SourcePath. |
|
440 |
type pathKey struct { |
|
441 |
arr [16]uint8 // first n-1 path segments; last element is the length |
|
442 |
str string // used if the path does not fit in arr |
|
443 |
} |
|
444 |
|
260
|
445 |
func newPathKey(p protoreflect.SourcePath) (k pathKey) { |
256
|
446 |
if len(p) < len(k.arr) { |
|
447 |
for i, ps := range p { |
|
448 |
if ps < 0 || math.MaxUint8 <= ps { |
|
449 |
return pathKey{str: p.String()} |
|
450 |
} |
|
451 |
k.arr[i] = uint8(ps) |
|
452 |
} |
|
453 |
k.arr[len(k.arr)-1] = uint8(len(p)) |
|
454 |
return k |
|
455 |
} |
|
456 |
return pathKey{str: p.String()} |
|
457 |
} |