mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-07 12:56:47 +00:00
d888139e7b
The internal/fileinit package is split apart into two packages: * internal/filedesc constructs descriptors from the raw proto. It is very similar to the previous internal/fileinit package. * internal/filetype wraps descriptors with Go type information Overview: * The internal/fileinit package will be deleted in a future CL. It is kept around since the v1 repo currently depends on it. * The internal/prototype package is deleted. All former usages of it are now using internal/filedesc instead. Most significantly, the reflect/protodesc package was almost entirely re-written. * The internal/impl package drops support for messages that do not have a Descriptor method (pre-2016). This removes a significant amount of technical debt. filedesc.Builder to parse raw descriptors. * The internal/encoding/defval package now handles enum values by name. Change-Id: I3957bcc8588a70470fd6c7de1122216b80615ab7 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/182360 Reviewed-by: Damien Neil <dneil@google.com>
190 lines
5.7 KiB
Go
190 lines
5.7 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package filedesc
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"sync"
|
|
|
|
"google.golang.org/protobuf/internal/descfmt"
|
|
"google.golang.org/protobuf/internal/pragma"
|
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
type FileImports []pref.FileImport
|
|
|
|
func (p *FileImports) Len() int { return len(*p) }
|
|
func (p *FileImports) Get(i int) pref.FileImport { return (*p)[i] }
|
|
func (p *FileImports) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *FileImports) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
type Names struct {
|
|
List []pref.Name
|
|
once sync.Once
|
|
has map[pref.Name]struct{} // protected by once
|
|
}
|
|
|
|
func (p *Names) Len() int { return len(p.List) }
|
|
func (p *Names) Get(i int) pref.Name { return p.List[i] }
|
|
func (p *Names) Has(s pref.Name) bool {
|
|
p.once.Do(func() {
|
|
if len(p.List) > 0 {
|
|
p.has = make(map[pref.Name]struct{}, len(p.List))
|
|
for _, s := range p.List {
|
|
p.has[s] = struct{}{}
|
|
}
|
|
}
|
|
})
|
|
_, ok := p.has[s]
|
|
return ok
|
|
}
|
|
func (p *Names) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *Names) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
type EnumRanges struct {
|
|
List [][2]pref.EnumNumber // start inclusive; end inclusive
|
|
once sync.Once
|
|
sorted [][2]pref.EnumNumber // protected by once
|
|
has map[pref.EnumNumber]struct{} // protected by once
|
|
}
|
|
|
|
func (p *EnumRanges) Len() int { return len(p.List) }
|
|
func (p *EnumRanges) Get(i int) [2]pref.EnumNumber { return p.List[i] }
|
|
func (p *EnumRanges) Has(n pref.EnumNumber) bool {
|
|
p.once.Do(func() {
|
|
for _, r := range p.List {
|
|
if r[0] == r[1]-0 {
|
|
if p.has == nil {
|
|
p.has = make(map[pref.EnumNumber]struct{}, len(p.List))
|
|
}
|
|
p.has[r[0]] = struct{}{}
|
|
} else {
|
|
p.sorted = append(p.sorted, r)
|
|
}
|
|
}
|
|
sort.Slice(p.sorted, func(i, j int) bool {
|
|
return p.sorted[i][0] < p.sorted[j][0]
|
|
})
|
|
})
|
|
if _, ok := p.has[n]; ok {
|
|
return true
|
|
}
|
|
for ls := p.sorted; len(ls) > 0; {
|
|
i := len(ls) / 2
|
|
switch r := ls[i]; {
|
|
case n < r[0]:
|
|
ls = ls[:i] // search lower
|
|
case n > r[1]:
|
|
ls = ls[i+1:] // search upper
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
func (p *EnumRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *EnumRanges) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
type FieldRanges struct {
|
|
List [][2]pref.FieldNumber // start inclusive; end exclusive
|
|
once sync.Once
|
|
sorted [][2]pref.FieldNumber // protected by once
|
|
has map[pref.FieldNumber]struct{} // protected by once
|
|
}
|
|
|
|
func (p *FieldRanges) Len() int { return len(p.List) }
|
|
func (p *FieldRanges) Get(i int) [2]pref.FieldNumber { return p.List[i] }
|
|
func (p *FieldRanges) Has(n pref.FieldNumber) bool {
|
|
p.once.Do(func() {
|
|
for _, r := range p.List {
|
|
if r[0] == r[1]-1 {
|
|
if p.has == nil {
|
|
p.has = make(map[pref.FieldNumber]struct{}, len(p.List))
|
|
}
|
|
p.has[r[0]] = struct{}{}
|
|
} else {
|
|
p.sorted = append(p.sorted, r)
|
|
}
|
|
}
|
|
sort.Slice(p.sorted, func(i, j int) bool {
|
|
return p.sorted[i][0] < p.sorted[j][0]
|
|
})
|
|
})
|
|
if _, ok := p.has[n]; ok {
|
|
return true
|
|
}
|
|
for ls := p.sorted; len(ls) > 0; {
|
|
i := len(ls) / 2
|
|
switch r := ls[i]; {
|
|
case n < r[0]:
|
|
ls = ls[:i] // search lower
|
|
case n >= r[1]:
|
|
ls = ls[i+1:] // search higher
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
func (p *FieldRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *FieldRanges) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
type FieldNumbers struct {
|
|
List []pref.FieldNumber
|
|
once sync.Once
|
|
has map[pref.FieldNumber]struct{} // protected by once
|
|
}
|
|
|
|
func (p *FieldNumbers) Len() int { return len(p.List) }
|
|
func (p *FieldNumbers) Get(i int) pref.FieldNumber { return p.List[i] }
|
|
func (p *FieldNumbers) Has(n pref.FieldNumber) bool {
|
|
p.once.Do(func() {
|
|
if len(p.List) > 0 {
|
|
p.has = make(map[pref.FieldNumber]struct{}, len(p.List))
|
|
for _, n := range p.List {
|
|
p.has[n] = struct{}{}
|
|
}
|
|
}
|
|
})
|
|
_, ok := p.has[n]
|
|
return ok
|
|
}
|
|
func (p *FieldNumbers) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *FieldNumbers) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
type OneofFields struct {
|
|
List []pref.FieldDescriptor
|
|
once sync.Once
|
|
byName map[pref.Name]pref.FieldDescriptor // protected by once
|
|
byJSON map[string]pref.FieldDescriptor // protected by once
|
|
byNum map[pref.FieldNumber]pref.FieldDescriptor // protected by once
|
|
}
|
|
|
|
func (p *OneofFields) Len() int { return len(p.List) }
|
|
func (p *OneofFields) Get(i int) pref.FieldDescriptor { return p.List[i] }
|
|
func (p *OneofFields) ByName(s pref.Name) pref.FieldDescriptor { return p.lazyInit().byName[s] }
|
|
func (p *OneofFields) ByJSONName(s string) pref.FieldDescriptor { return p.lazyInit().byJSON[s] }
|
|
func (p *OneofFields) ByNumber(n pref.FieldNumber) pref.FieldDescriptor { return p.lazyInit().byNum[n] }
|
|
func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) }
|
|
func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {}
|
|
|
|
func (p *OneofFields) lazyInit() *OneofFields {
|
|
p.once.Do(func() {
|
|
if len(p.List) > 0 {
|
|
p.byName = make(map[pref.Name]pref.FieldDescriptor, len(p.List))
|
|
p.byJSON = make(map[string]pref.FieldDescriptor, len(p.List))
|
|
p.byNum = make(map[pref.FieldNumber]pref.FieldDescriptor, len(p.List))
|
|
for _, f := range p.List {
|
|
// Field names and numbers are guaranteed to be unique.
|
|
p.byName[f.Name()] = f
|
|
p.byJSON[f.JSONName()] = f
|
|
p.byNum[f.Number()] = f
|
|
}
|
|
}
|
|
})
|
|
return p
|
|
}
|