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 5package filedesc 6 7import ( 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 22type FileImports []protoreflect.FileImport 23 24func (p *FileImports) Len() int { return len(*p) } 25func (p *FileImports) Get(i int) protoreflect.FileImport { return (*p)[i] } 26func (p *FileImports) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 27func (p *FileImports) ProtoInternal(pragma.DoNotImplement) {} 28 29type Names struct { 30 List []protoreflect.Name 31 once sync.Once 32 has map[protoreflect.Name]int // protected by once 33} 34 35func (p *Names) Len() int { return len(p.List) } 36func (p *Names) Get(i int) protoreflect.Name { return p.List[i] } 37func (p *Names) Has(s protoreflect.Name) bool { return p.lazyInit().has[s] > 0 } 38func (p *Names) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 39func (p *Names) ProtoInternal(pragma.DoNotImplement) {} 40func (p *Names) lazyInit() *Names { 41 p.once.Do(func() { 42 if len(p.List) > 0 { 43 p.has = make(map[protoreflect.Name]int, len(p.List)) 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 ..." 54func (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 68type EnumRanges struct { 69 List [][2]protoreflect.EnumNumber // start inclusive; end inclusive 70 once sync.Once 71 sorted [][2]protoreflect.EnumNumber // protected by once 72} 73 74func (p *EnumRanges) Len() int { return len(p.List) } 75func (p *EnumRanges) Get(i int) [2]protoreflect.EnumNumber { return p.List[i] } 76func (p *EnumRanges) Has(n protoreflect.EnumNumber) bool { 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} 90func (p *EnumRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 91func (p *EnumRanges) ProtoInternal(pragma.DoNotImplement) {} 92func (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 ..." 104func (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 119type enumRange [2]protoreflect.EnumNumber 120 121func (r enumRange) Start() protoreflect.EnumNumber { return r[0] } // inclusive 122func (r enumRange) End() protoreflect.EnumNumber { return r[1] } // inclusive 123func (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 130type FieldRanges struct { 131 List [][2]protoreflect.FieldNumber // start inclusive; end exclusive 132 once sync.Once 133 sorted [][2]protoreflect.FieldNumber // protected by once 134} 135 136func (p *FieldRanges) Len() int { return len(p.List) } 137func (p *FieldRanges) Get(i int) [2]protoreflect.FieldNumber { return p.List[i] } 138func (p *FieldRanges) Has(n protoreflect.FieldNumber) bool { 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} 152func (p *FieldRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 153func (p *FieldRanges) ProtoInternal(pragma.DoNotImplement) {} 154func (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 ..." 166func (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. 188func 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. 193func (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 211type fieldRange [2]protoreflect.FieldNumber 212 213func (r fieldRange) Start() protoreflect.FieldNumber { return r[0] } // inclusive 214func (r fieldRange) End() protoreflect.FieldNumber { return r[1] - 1 } // inclusive 215func (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 222type FieldNumbers struct { 223 List []protoreflect.FieldNumber 224 once sync.Once 225 has map[protoreflect.FieldNumber]struct{} // protected by once 226} 227 228func (p *FieldNumbers) Len() int { return len(p.List) } 229func (p *FieldNumbers) Get(i int) protoreflect.FieldNumber { return p.List[i] } 230func (p *FieldNumbers) Has(n protoreflect.FieldNumber) bool { 231 p.once.Do(func() { 232 if len(p.List) > 0 { 233 p.has = make(map[protoreflect.FieldNumber]struct{}, len(p.List)) 234 for _, n := range p.List { 235 p.has[n] = struct{}{} 236 } 237 } 238 }) 239 _, ok := p.has[n] 240 return ok 241} 242func (p *FieldNumbers) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 243func (p *FieldNumbers) ProtoInternal(pragma.DoNotImplement) {} 244 245type OneofFields struct { 246 List []protoreflect.FieldDescriptor 247 once sync.Once 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 252} 253 254func (p *OneofFields) Len() int { return len(p.List) } 255func (p *OneofFields) Get(i int) protoreflect.FieldDescriptor { return p.List[i] } 256func (p *OneofFields) ByName(s protoreflect.Name) protoreflect.FieldDescriptor { 257 return p.lazyInit().byName[s] 258} 259func (p *OneofFields) ByJSONName(s string) protoreflect.FieldDescriptor { 260 return p.lazyInit().byJSON[s] 261} 262func (p *OneofFields) ByTextName(s string) protoreflect.FieldDescriptor { 263 return p.lazyInit().byText[s] 264} 265func (p *OneofFields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor { 266 return p.lazyInit().byNum[n] 267} 268func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } 269func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {} 270 271func (p *OneofFields) lazyInit() *OneofFields { 272 p.once.Do(func() { 273 if len(p.List) > 0 { 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)) 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 290type 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. 294 List []protoreflect.SourceLocation 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. 299 File protoreflect.FileDescriptor 300 301 once sync.Once 302 byPath map[pathKey]int 303} 304 305func (p *SourceLocations) Len() int { return len(p.List) } 306func (p *SourceLocations) Get(i int) protoreflect.SourceLocation { return p.lazyInit().List[i] } 307func (p *SourceLocations) byKey(k pathKey) protoreflect.SourceLocation { 308 if i, ok := p.lazyInit().byPath[k]; ok { 309 return p.List[i] 310 } 311 return protoreflect.SourceLocation{} 312} 313func (p *SourceLocations) ByPath(path protoreflect.SourcePath) protoreflect.SourceLocation { 314 return p.byKey(newPathKey(path)) 315} 316func (p *SourceLocations) ByDescriptor(desc protoreflect.Descriptor) protoreflect.SourceLocation { 317 if p.File != nil && desc != nil && p.File != desc.ParentFile() { 318 return protoreflect.SourceLocation{} // mismatching parent files 319 } 320 var pathArr [16]int32 321 path := pathArr[:0] 322 for { 323 switch desc.(type) { 324 case protoreflect.FileDescriptor: 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)) 330 case protoreflect.MessageDescriptor: 331 path = append(path, int32(desc.Index())) 332 desc = desc.Parent() 333 switch desc.(type) { 334 case protoreflect.FileDescriptor: 335 path = append(path, int32(genid.FileDescriptorProto_MessageType_field_number)) 336 case protoreflect.MessageDescriptor: 337 path = append(path, int32(genid.DescriptorProto_NestedType_field_number)) 338 default: 339 return protoreflect.SourceLocation{} 340 } 341 case protoreflect.FieldDescriptor: 342 isExtension := desc.(protoreflect.FieldDescriptor).IsExtension() 343 path = append(path, int32(desc.Index())) 344 desc = desc.Parent() 345 if isExtension { 346 switch desc.(type) { 347 case protoreflect.FileDescriptor: 348 path = append(path, int32(genid.FileDescriptorProto_Extension_field_number)) 349 case protoreflect.MessageDescriptor: 350 path = append(path, int32(genid.DescriptorProto_Extension_field_number)) 351 default: 352 return protoreflect.SourceLocation{} 353 } 354 } else { 355 switch desc.(type) { 356 case protoreflect.MessageDescriptor: 357 path = append(path, int32(genid.DescriptorProto_Field_field_number)) 358 default: 359 return protoreflect.SourceLocation{} 360 } 361 } 362 case protoreflect.OneofDescriptor: 363 path = append(path, int32(desc.Index())) 364 desc = desc.Parent() 365 switch desc.(type) { 366 case protoreflect.MessageDescriptor: 367 path = append(path, int32(genid.DescriptorProto_OneofDecl_field_number)) 368 default: 369 return protoreflect.SourceLocation{} 370 } 371 case protoreflect.EnumDescriptor: 372 path = append(path, int32(desc.Index())) 373 desc = desc.Parent() 374 switch desc.(type) { 375 case protoreflect.FileDescriptor: 376 path = append(path, int32(genid.FileDescriptorProto_EnumType_field_number)) 377 case protoreflect.MessageDescriptor: 378 path = append(path, int32(genid.DescriptorProto_EnumType_field_number)) 379 default: 380 return protoreflect.SourceLocation{} 381 } 382 case protoreflect.EnumValueDescriptor: 383 path = append(path, int32(desc.Index())) 384 desc = desc.Parent() 385 switch desc.(type) { 386 case protoreflect.EnumDescriptor: 387 path = append(path, int32(genid.EnumDescriptorProto_Value_field_number)) 388 default: 389 return protoreflect.SourceLocation{} 390 } 391 case protoreflect.ServiceDescriptor: 392 path = append(path, int32(desc.Index())) 393 desc = desc.Parent() 394 switch desc.(type) { 395 case protoreflect.FileDescriptor: 396 path = append(path, int32(genid.FileDescriptorProto_Service_field_number)) 397 default: 398 return protoreflect.SourceLocation{} 399 } 400 case protoreflect.MethodDescriptor: 401 path = append(path, int32(desc.Index())) 402 desc = desc.Parent() 403 switch desc.(type) { 404 case protoreflect.ServiceDescriptor: 405 path = append(path, int32(genid.ServiceDescriptorProto_Method_field_number)) 406 default: 407 return protoreflect.SourceLocation{} 408 } 409 default: 410 return protoreflect.SourceLocation{} 411 } 412 } 413} 414func (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} 437func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {} 438 439// pathKey is a comparable representation of protoreflect.SourcePath. 440type 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 445func newPathKey(p protoreflect.SourcePath) (k pathKey) { 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} 458