2019-06-06 13:01:53 -07:00
|
|
|
// 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 (
|
|
|
|
"reflect"
|
2019-07-06 18:08:55 -07:00
|
|
|
"sync"
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
"google.golang.org/protobuf/internal/descopts"
|
|
|
|
"google.golang.org/protobuf/internal/encoding/wire"
|
|
|
|
"google.golang.org/protobuf/internal/fieldnum"
|
2019-07-07 01:49:59 -07:00
|
|
|
"google.golang.org/protobuf/internal/strs"
|
2019-06-06 13:01:53 -07:00
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
pref "google.golang.org/protobuf/reflect/protoreflect"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (fd *File) lazyRawInit() {
|
|
|
|
fd.unmarshalFull(fd.builder.RawDescriptor)
|
|
|
|
fd.resolveMessages()
|
|
|
|
fd.resolveExtensions()
|
|
|
|
fd.resolveServices()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (file *File) resolveMessages() {
|
|
|
|
var depIdx int32
|
|
|
|
for i := range file.allMessages {
|
|
|
|
md := &file.allMessages[i]
|
|
|
|
|
|
|
|
// Resolve message field dependencies.
|
|
|
|
for j := range md.L2.Fields.List {
|
|
|
|
fd := &md.L2.Fields.List[j]
|
|
|
|
|
2019-08-05 13:41:37 -07:00
|
|
|
// Weak fields are resolved upon actual use.
|
2019-06-06 13:01:53 -07:00
|
|
|
if fd.L1.IsWeak {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve message field dependency.
|
|
|
|
switch fd.L1.Kind {
|
|
|
|
case pref.EnumKind:
|
|
|
|
fd.L1.Enum = file.resolveEnumDependency(fd.L1.Enum, listFieldDeps, depIdx)
|
|
|
|
depIdx++
|
|
|
|
case pref.MessageKind, pref.GroupKind:
|
|
|
|
fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx)
|
|
|
|
depIdx++
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default is resolved here since it depends on Enum being resolved.
|
|
|
|
if v := fd.L1.Default.val; v.IsValid() {
|
|
|
|
fd.L1.Default = unmarshalDefault(v.Bytes(), fd.L1.Kind, file, fd.L1.Enum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (file *File) resolveExtensions() {
|
|
|
|
var depIdx int32
|
|
|
|
for i := range file.allExtensions {
|
|
|
|
xd := &file.allExtensions[i]
|
|
|
|
|
|
|
|
// Resolve extension field dependency.
|
|
|
|
switch xd.L1.Kind {
|
|
|
|
case pref.EnumKind:
|
|
|
|
xd.L2.Enum = file.resolveEnumDependency(xd.L2.Enum, listExtDeps, depIdx)
|
|
|
|
depIdx++
|
|
|
|
case pref.MessageKind, pref.GroupKind:
|
|
|
|
xd.L2.Message = file.resolveMessageDependency(xd.L2.Message, listExtDeps, depIdx)
|
|
|
|
depIdx++
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default is resolved here since it depends on Enum being resolved.
|
|
|
|
if v := xd.L2.Default.val; v.IsValid() {
|
|
|
|
xd.L2.Default = unmarshalDefault(v.Bytes(), xd.L1.Kind, file, xd.L2.Enum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (file *File) resolveServices() {
|
|
|
|
var depIdx int32
|
|
|
|
for i := range file.allServices {
|
|
|
|
sd := &file.allServices[i]
|
|
|
|
|
|
|
|
// Resolve method dependencies.
|
|
|
|
for j := range sd.L2.Methods.List {
|
|
|
|
md := &sd.L2.Methods.List[j]
|
|
|
|
md.L1.Input = file.resolveMessageDependency(md.L1.Input, listMethInDeps, depIdx)
|
|
|
|
md.L1.Output = file.resolveMessageDependency(md.L1.Output, listMethOutDeps, depIdx)
|
|
|
|
depIdx++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (file *File) resolveEnumDependency(ed pref.EnumDescriptor, i, j int32) pref.EnumDescriptor {
|
|
|
|
r := file.builder.FileRegistry
|
|
|
|
if r, ok := r.(resolverByIndex); ok {
|
|
|
|
if ed2 := r.FindEnumByIndex(i, j, file.allEnums, file.allMessages); ed2 != nil {
|
|
|
|
return ed2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := range file.allEnums {
|
|
|
|
if ed2 := &file.allEnums[i]; ed2.L0.FullName == ed.FullName() {
|
|
|
|
return ed2
|
|
|
|
}
|
|
|
|
}
|
2019-06-24 16:19:06 -07:00
|
|
|
if d, _ := r.FindDescriptorByName(ed.FullName()); d != nil {
|
|
|
|
return d.(pref.EnumDescriptor)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
return ed
|
|
|
|
}
|
|
|
|
|
|
|
|
func (file *File) resolveMessageDependency(md pref.MessageDescriptor, i, j int32) pref.MessageDescriptor {
|
|
|
|
r := file.builder.FileRegistry
|
|
|
|
if r, ok := r.(resolverByIndex); ok {
|
|
|
|
if md2 := r.FindMessageByIndex(i, j, file.allEnums, file.allMessages); md2 != nil {
|
|
|
|
return md2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := range file.allMessages {
|
|
|
|
if md2 := &file.allMessages[i]; md2.L0.FullName == md.FullName() {
|
|
|
|
return md2
|
|
|
|
}
|
|
|
|
}
|
2019-06-24 16:19:06 -07:00
|
|
|
if d, _ := r.FindDescriptorByName(md.FullName()); d != nil {
|
|
|
|
return d.(pref.MessageDescriptor)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
return md
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fd *File) unmarshalFull(b []byte) {
|
2019-07-07 01:49:59 -07:00
|
|
|
sb := getBuilder()
|
|
|
|
defer putBuilder(sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
|
|
|
|
var enumIdx, messageIdx, extensionIdx, serviceIdx int
|
|
|
|
var rawOptions []byte
|
|
|
|
fd.L2 = new(FileL2)
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FileDescriptorProto_PublicDependency:
|
|
|
|
fd.L2.Imports[v].IsPublic = true
|
|
|
|
case fieldnum.FileDescriptorProto_WeakDependency:
|
|
|
|
fd.L2.Imports[v].IsWeak = true
|
|
|
|
}
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FileDescriptorProto_Dependency:
|
2019-07-07 01:49:59 -07:00
|
|
|
path := sb.MakeString(v)
|
2019-06-06 13:01:53 -07:00
|
|
|
imp, _ := fd.builder.FileRegistry.FindFileByPath(path)
|
|
|
|
if imp == nil {
|
|
|
|
imp = PlaceholderFile(path)
|
|
|
|
}
|
|
|
|
fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp})
|
|
|
|
case fieldnum.FileDescriptorProto_EnumType:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
enumIdx++
|
|
|
|
case fieldnum.FileDescriptorProto_MessageType:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
messageIdx++
|
|
|
|
case fieldnum.FileDescriptorProto_Extension:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
extensionIdx++
|
|
|
|
case fieldnum.FileDescriptorProto_Service:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
serviceIdx++
|
|
|
|
case fieldnum.FileDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) {
|
2019-06-06 13:01:53 -07:00
|
|
|
var rawValues [][]byte
|
|
|
|
var rawOptions []byte
|
reflect/protoreflect: register all desciptors in Files
This change makes it such that Files now functionally registers all
descriptors in a file (not just enums, messages, extensions, and services),
but also including enum values, messages fields/oneofs, and service methods.
The ability to look up any descriptor by full name is needed to:
1) properly detect namespace conflicts on enum values
2) properly implement the relative name lookup logic in reflect/protodesc
The approach taken:
1) Assumes that a FileDescriptor has no internal name conflicts.
This will (in a future CL) be guaranteed by reflect/protodesc and
is guaranteed today by protoc for generated descriptors.
2) Observes that the only declarations that can possibly conflict
with another file are top-level declarations (i.e., enums, enum values,
messages, extensions, and services). Enum values are annoying
since they live in the same scope as the parent enum, rather than
being under the enum.
For the internal data structure of Files, we only register the top-level
declarations. This is the bare minimum needed to detect whether the file
being registered has any namespace conflicts with previously registered files.
We shift the effort to lookups, where we now need to peel off the end fragments
of a full name until we find a match in the internal registry. If a match
is found, we may need to descend into that declaration to find a nested
declaration by name.
For initialization, we modify internal/filedesc to initialize the
enum values for all top-level enums. This performance cost is offsetted
by the fact that Files.Register now avoids internally registering
nested enums, messages, and extensions.
For lookup, the cost has shifted from O(1) to O(N),
where N is the number of segments in the full name.
Top-level descriptors still have O(1) lookup times.
Nested descriptors have O(M) lookup times,
where M is the level of nesting within a single file.
Change-Id: I950163423431f04a503b6201ddcc20a62ccba017
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183697
Reviewed-by: Damien Neil <dneil@google.com>
2019-06-21 14:25:16 -07:00
|
|
|
if !ed.L1.eagerValues {
|
|
|
|
ed.L2 = new(EnumL2)
|
|
|
|
}
|
2019-06-06 13:01:53 -07:00
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.EnumDescriptorProto_Value:
|
|
|
|
rawValues = append(rawValues, v)
|
|
|
|
case fieldnum.EnumDescriptorProto_ReservedName:
|
2019-07-07 01:49:59 -07:00
|
|
|
ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.EnumDescriptorProto_ReservedRange:
|
|
|
|
ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v))
|
|
|
|
case fieldnum.EnumDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
reflect/protoreflect: register all desciptors in Files
This change makes it such that Files now functionally registers all
descriptors in a file (not just enums, messages, extensions, and services),
but also including enum values, messages fields/oneofs, and service methods.
The ability to look up any descriptor by full name is needed to:
1) properly detect namespace conflicts on enum values
2) properly implement the relative name lookup logic in reflect/protodesc
The approach taken:
1) Assumes that a FileDescriptor has no internal name conflicts.
This will (in a future CL) be guaranteed by reflect/protodesc and
is guaranteed today by protoc for generated descriptors.
2) Observes that the only declarations that can possibly conflict
with another file are top-level declarations (i.e., enums, enum values,
messages, extensions, and services). Enum values are annoying
since they live in the same scope as the parent enum, rather than
being under the enum.
For the internal data structure of Files, we only register the top-level
declarations. This is the bare minimum needed to detect whether the file
being registered has any namespace conflicts with previously registered files.
We shift the effort to lookups, where we now need to peel off the end fragments
of a full name until we find a match in the internal registry. If a match
is found, we may need to descend into that declaration to find a nested
declaration by name.
For initialization, we modify internal/filedesc to initialize the
enum values for all top-level enums. This performance cost is offsetted
by the fact that Files.Register now avoids internally registering
nested enums, messages, and extensions.
For lookup, the cost has shifted from O(1) to O(N),
where N is the number of segments in the full name.
Top-level descriptors still have O(1) lookup times.
Nested descriptors have O(M) lookup times,
where M is the level of nesting within a single file.
Change-Id: I950163423431f04a503b6201ddcc20a62ccba017
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/183697
Reviewed-by: Damien Neil <dneil@google.com>
2019-06-21 14:25:16 -07:00
|
|
|
if !ed.L1.eagerValues && len(rawValues) > 0 {
|
2019-06-06 13:01:53 -07:00
|
|
|
ed.L2.Values.List = make([]EnumValue, len(rawValues))
|
|
|
|
for i, b := range rawValues {
|
2019-07-07 01:49:59 -07:00
|
|
|
ed.L2.Values.List[i].unmarshalFull(b, sb, ed.L0.ParentFile, ed, i)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
ed.L2.Options = ed.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Enum, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) {
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.EnumDescriptorProto_EnumReservedRange_Start:
|
|
|
|
r[0] = pref.EnumNumber(v)
|
|
|
|
case fieldnum.EnumDescriptorProto_EnumReservedRange_End:
|
|
|
|
r[1] = pref.EnumNumber(v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (vd *EnumValue) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
|
2019-06-06 13:01:53 -07:00
|
|
|
vd.L0.ParentFile = pf
|
|
|
|
vd.L0.Parent = pd
|
|
|
|
vd.L0.Index = i
|
|
|
|
|
|
|
|
var rawOptions []byte
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.EnumValueDescriptorProto_Number:
|
|
|
|
vd.L1.Number = pref.EnumNumber(v)
|
|
|
|
}
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.EnumValueDescriptorProto_Name:
|
|
|
|
// NOTE: Enum values are in the same scope as the enum parent.
|
2019-07-07 01:49:59 -07:00
|
|
|
vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v)
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.EnumValueDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
vd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.EnumValue, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) {
|
2019-06-06 13:01:53 -07:00
|
|
|
var rawFields, rawOneofs [][]byte
|
|
|
|
var enumIdx, messageIdx, extensionIdx int
|
|
|
|
var rawOptions []byte
|
|
|
|
md.L2 = new(MessageL2)
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.DescriptorProto_Field:
|
|
|
|
rawFields = append(rawFields, v)
|
|
|
|
case fieldnum.DescriptorProto_OneofDecl:
|
|
|
|
rawOneofs = append(rawOneofs, v)
|
|
|
|
case fieldnum.DescriptorProto_ReservedName:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v)))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.DescriptorProto_ReservedRange:
|
|
|
|
md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v))
|
|
|
|
case fieldnum.DescriptorProto_ExtensionRange:
|
|
|
|
r, rawOptions := unmarshalMessageExtensionRange(v)
|
2019-08-02 13:16:57 -07:00
|
|
|
opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r)
|
|
|
|
md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts)
|
|
|
|
case fieldnum.DescriptorProto_EnumType:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L1.Enums.List[enumIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
enumIdx++
|
|
|
|
case fieldnum.DescriptorProto_NestedType:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L1.Messages.List[messageIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
messageIdx++
|
|
|
|
case fieldnum.DescriptorProto_Extension:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb)
|
2019-06-06 13:01:53 -07:00
|
|
|
extensionIdx++
|
|
|
|
case fieldnum.DescriptorProto_Options:
|
|
|
|
md.unmarshalOptions(v)
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(rawFields) > 0 || len(rawOneofs) > 0 {
|
|
|
|
md.L2.Fields.List = make([]Field, len(rawFields))
|
|
|
|
md.L2.Oneofs.List = make([]Oneof, len(rawOneofs))
|
|
|
|
for i, b := range rawFields {
|
|
|
|
fd := &md.L2.Fields.List[i]
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.unmarshalFull(b, sb, md.L0.ParentFile, md, i)
|
2019-06-06 13:01:53 -07:00
|
|
|
if fd.L1.Cardinality == pref.Required {
|
|
|
|
md.L2.RequiredNumbers.List = append(md.L2.RequiredNumbers.List, fd.L1.Number)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i, b := range rawOneofs {
|
|
|
|
od := &md.L2.Oneofs.List[i]
|
2019-07-07 01:49:59 -07:00
|
|
|
od.unmarshalFull(b, sb, md.L0.ParentFile, md, i)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (md *Message) unmarshalOptions(b []byte) {
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.MessageOptions_MapEntry:
|
|
|
|
md.L2.IsMapEntry = wire.DecodeBool(v)
|
|
|
|
case fieldnum.MessageOptions_MessageSetWireFormat:
|
|
|
|
md.L2.IsMessageSet = wire.DecodeBool(v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) {
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.DescriptorProto_ReservedRange_Start:
|
|
|
|
r[0] = pref.FieldNumber(v)
|
|
|
|
case fieldnum.DescriptorProto_ReservedRange_End:
|
|
|
|
r[1] = pref.FieldNumber(v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, rawOptions []byte) {
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.DescriptorProto_ExtensionRange_Start:
|
|
|
|
r[0] = pref.FieldNumber(v)
|
|
|
|
case fieldnum.DescriptorProto_ExtensionRange_End:
|
|
|
|
r[1] = pref.FieldNumber(v)
|
|
|
|
}
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.DescriptorProto_ExtensionRange_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r, rawOptions
|
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
|
2019-06-06 13:01:53 -07:00
|
|
|
fd.L0.ParentFile = pf
|
|
|
|
fd.L0.Parent = pd
|
|
|
|
fd.L0.Index = i
|
|
|
|
|
|
|
|
var rawTypeName []byte
|
|
|
|
var rawOptions []byte
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FieldDescriptorProto_Number:
|
|
|
|
fd.L1.Number = pref.FieldNumber(v)
|
|
|
|
case fieldnum.FieldDescriptorProto_Label:
|
|
|
|
fd.L1.Cardinality = pref.Cardinality(v)
|
|
|
|
case fieldnum.FieldDescriptorProto_Type:
|
|
|
|
fd.L1.Kind = pref.Kind(v)
|
|
|
|
case fieldnum.FieldDescriptorProto_OneofIndex:
|
|
|
|
// In Message.unmarshalFull, we allocate slices for both
|
|
|
|
// the field and oneof descriptors before unmarshaling either
|
|
|
|
// of them. This ensures pointers to slice elements are stable.
|
|
|
|
od := &pd.(*Message).L2.Oneofs.List[v]
|
|
|
|
od.L1.Fields.List = append(od.L1.Fields.List, fd)
|
|
|
|
if fd.L1.ContainingOneof != nil {
|
|
|
|
panic("oneof type already set")
|
|
|
|
}
|
|
|
|
fd.L1.ContainingOneof = od
|
|
|
|
}
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FieldDescriptorProto_Name:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L0.FullName = appendFullName(sb, pd.FullName(), v)
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.FieldDescriptorProto_JsonName:
|
2019-07-07 01:49:59 -07:00
|
|
|
fd.L1.JSONName = JSONName(sb.MakeString(v))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.FieldDescriptorProto_DefaultValue:
|
2019-09-17 13:38:48 -07:00
|
|
|
fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.FieldDescriptorProto_TypeName:
|
|
|
|
rawTypeName = v
|
|
|
|
case fieldnum.FieldDescriptorProto_Options:
|
|
|
|
fd.unmarshalOptions(v)
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if rawTypeName != nil {
|
2019-07-07 01:49:59 -07:00
|
|
|
name := makeFullName(sb, rawTypeName)
|
2019-06-06 13:01:53 -07:00
|
|
|
switch fd.L1.Kind {
|
|
|
|
case pref.EnumKind:
|
|
|
|
fd.L1.Enum = PlaceholderEnum(name)
|
|
|
|
case pref.MessageKind, pref.GroupKind:
|
|
|
|
fd.L1.Message = PlaceholderMessage(name)
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
fd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Field, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (fd *Field) unmarshalOptions(b []byte) {
|
2019-07-13 00:44:41 -07:00
|
|
|
const FieldOptions_EnforceUTF8 = 13
|
|
|
|
|
2019-06-06 13:01:53 -07:00
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FieldOptions_Packed:
|
|
|
|
fd.L1.HasPacked = true
|
|
|
|
fd.L1.IsPacked = wire.DecodeBool(v)
|
|
|
|
case fieldnum.FieldOptions_Weak:
|
|
|
|
fd.L1.IsWeak = wire.DecodeBool(v)
|
2019-07-13 00:44:41 -07:00
|
|
|
case FieldOptions_EnforceUTF8:
|
|
|
|
fd.L1.HasEnforceUTF8 = true
|
2019-07-31 11:29:40 -07:00
|
|
|
fd.L1.EnforceUTF8 = wire.DecodeBool(v)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
|
2019-06-06 13:01:53 -07:00
|
|
|
od.L0.ParentFile = pf
|
|
|
|
od.L0.Parent = pd
|
|
|
|
od.L0.Index = i
|
|
|
|
|
|
|
|
var rawOptions []byte
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.OneofDescriptorProto_Name:
|
2019-07-07 01:49:59 -07:00
|
|
|
od.L0.FullName = appendFullName(sb, pd.FullName(), v)
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.OneofDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
od.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Oneof, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) {
|
2019-06-06 13:01:53 -07:00
|
|
|
var rawTypeName []byte
|
|
|
|
var rawOptions []byte
|
|
|
|
xd.L2 = new(ExtensionL2)
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FieldDescriptorProto_JsonName:
|
2019-07-07 01:49:59 -07:00
|
|
|
xd.L2.JSONName = JSONName(sb.MakeString(v))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.FieldDescriptorProto_DefaultValue:
|
2019-09-17 13:38:48 -07:00
|
|
|
xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.FieldDescriptorProto_TypeName:
|
|
|
|
rawTypeName = v
|
|
|
|
case fieldnum.FieldDescriptorProto_Options:
|
|
|
|
xd.unmarshalOptions(v)
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if rawTypeName != nil {
|
2019-07-07 01:49:59 -07:00
|
|
|
name := makeFullName(sb, rawTypeName)
|
2019-06-06 13:01:53 -07:00
|
|
|
switch xd.L1.Kind {
|
|
|
|
case pref.EnumKind:
|
|
|
|
xd.L2.Enum = PlaceholderEnum(name)
|
|
|
|
case pref.MessageKind, pref.GroupKind:
|
|
|
|
xd.L2.Message = PlaceholderMessage(name)
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (xd *Extension) unmarshalOptions(b []byte) {
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.FieldOptions_Packed:
|
|
|
|
xd.L2.IsPacked = wire.DecodeBool(v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) {
|
2019-06-06 13:01:53 -07:00
|
|
|
var rawMethods [][]byte
|
|
|
|
var rawOptions []byte
|
|
|
|
sd.L2 = new(ServiceL2)
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.ServiceDescriptorProto_Method:
|
|
|
|
rawMethods = append(rawMethods, v)
|
|
|
|
case fieldnum.ServiceDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(rawMethods) > 0 {
|
|
|
|
sd.L2.Methods.List = make([]Method, len(rawMethods))
|
|
|
|
for i, b := range rawMethods {
|
2019-07-07 01:49:59 -07:00
|
|
|
sd.L2.Methods.List[i].unmarshalFull(b, sb, sd.L0.ParentFile, sd, i)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
sd.L2.Options = sd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Service, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
2019-07-07 01:49:59 -07:00
|
|
|
func (md *Method) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
|
2019-06-06 13:01:53 -07:00
|
|
|
md.L0.ParentFile = pf
|
|
|
|
md.L0.Parent = pd
|
|
|
|
md.L0.Index = i
|
|
|
|
|
|
|
|
var rawOptions []byte
|
|
|
|
for len(b) > 0 {
|
|
|
|
num, typ, n := wire.ConsumeTag(b)
|
|
|
|
b = b[n:]
|
|
|
|
switch typ {
|
|
|
|
case wire.VarintType:
|
|
|
|
v, m := wire.ConsumeVarint(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.MethodDescriptorProto_ClientStreaming:
|
|
|
|
md.L1.IsStreamingClient = wire.DecodeBool(v)
|
|
|
|
case fieldnum.MethodDescriptorProto_ServerStreaming:
|
|
|
|
md.L1.IsStreamingServer = wire.DecodeBool(v)
|
|
|
|
}
|
|
|
|
case wire.BytesType:
|
|
|
|
v, m := wire.ConsumeBytes(b)
|
|
|
|
b = b[m:]
|
|
|
|
switch num {
|
|
|
|
case fieldnum.MethodDescriptorProto_Name:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L0.FullName = appendFullName(sb, pd.FullName(), v)
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.MethodDescriptorProto_InputType:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L1.Input = PlaceholderMessage(makeFullName(sb, v))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.MethodDescriptorProto_OutputType:
|
2019-07-07 01:49:59 -07:00
|
|
|
md.L1.Output = PlaceholderMessage(makeFullName(sb, v))
|
2019-06-06 13:01:53 -07:00
|
|
|
case fieldnum.MethodDescriptorProto_Options:
|
|
|
|
rawOptions = appendOptions(rawOptions, v)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
m := wire.ConsumeFieldValue(num, typ, b)
|
|
|
|
b = b[m:]
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 13:16:57 -07:00
|
|
|
md.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Method, rawOptions)
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// appendOptions appends src to dst, where the returned slice is never nil.
|
|
|
|
// This is necessary to distinguish between empty and unpopulated options.
|
|
|
|
func appendOptions(dst, src []byte) []byte {
|
|
|
|
if dst == nil {
|
|
|
|
dst = []byte{}
|
|
|
|
}
|
|
|
|
return append(dst, src...)
|
|
|
|
}
|
|
|
|
|
2019-08-02 13:16:57 -07:00
|
|
|
// optionsUnmarshaler constructs a lazy unmarshal function for an options message.
|
|
|
|
//
|
|
|
|
// The type of message to unmarshal to is passed as a pointer since the
|
|
|
|
// vars in descopts may not yet be populated at the time this function is called.
|
2019-08-05 15:49:29 -07:00
|
|
|
func (db *Builder) optionsUnmarshaler(p *pref.ProtoMessage, b []byte) func() pref.ProtoMessage {
|
2019-06-06 13:01:53 -07:00
|
|
|
if b == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2019-07-06 18:08:55 -07:00
|
|
|
var opts pref.ProtoMessage
|
|
|
|
var once sync.Once
|
2019-06-06 13:01:53 -07:00
|
|
|
return func() pref.ProtoMessage {
|
2019-07-06 18:08:55 -07:00
|
|
|
once.Do(func() {
|
2019-08-02 13:16:57 -07:00
|
|
|
if *p == nil {
|
|
|
|
panic("Descriptor.Options called without importing the descriptor package")
|
|
|
|
}
|
|
|
|
opts = reflect.New(reflect.TypeOf(*p).Elem()).Interface().(pref.ProtoMessage)
|
2019-07-06 18:08:55 -07:00
|
|
|
if err := (proto.UnmarshalOptions{
|
|
|
|
AllowPartial: true,
|
|
|
|
Resolver: db.TypeResolver,
|
|
|
|
}).Unmarshal(b, opts); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return opts
|
2019-06-06 13:01:53 -07:00
|
|
|
}
|
|
|
|
}
|