package protodesc
import (
)
type resolver struct {
local descsByName
remote Resolver
imports importSet
allowUnresolvable bool
}
func ( *resolver) ( []filedesc.Message, []*descriptorpb.DescriptorProto) ( error) {
for , := range {
:= &[]
for , := range .GetField() {
:= &.L2.Fields.List[]
if .L1.Cardinality == protoreflect.Required {
.L2.RequiredNumbers.List = append(.L2.RequiredNumbers.List, .L1.Number)
}
if .OneofIndex != nil {
:= int(.GetOneofIndex())
if !(0 <= && < len(.GetOneofDecl())) {
return errors.New("message field %q has an invalid oneof index: %d", .FullName(), )
}
:= &.L2.Oneofs.List[]
.L1.ContainingOneof =
.L1.Fields.List = append(.L1.Fields.List, )
}
if .L1.Kind, .L1.Enum, .L1.Message, = .findTarget(.Kind(), .Parent().FullName(), partialName(.GetTypeName()), .IsWeak()); != nil {
return errors.New("message field %q cannot resolve type: %v", .FullName(), )
}
if .DefaultValue != nil {
, , := unmarshalDefault(.GetDefaultValue(), , .allowUnresolvable)
if != nil {
return errors.New("message field %q has invalid default: %v", .FullName(), )
}
.L1.Default = filedesc.DefaultValue(, )
}
}
if := .(.L1.Messages.List, .GetNestedType()); != nil {
return
}
if := .resolveExtensionDependencies(.L1.Extensions.List, .GetExtension()); != nil {
return
}
}
return nil
}
func ( *resolver) ( []filedesc.Extension, []*descriptorpb.FieldDescriptorProto) ( error) {
for , := range {
:= &[]
if .L1.Extendee, = .findMessageDescriptor(.Parent().FullName(), partialName(.GetExtendee()), false); != nil {
return errors.New("extension field %q cannot resolve extendee: %v", .FullName(), )
}
if .L1.Kind, .L2.Enum, .L2.Message, = .findTarget(.Kind(), .Parent().FullName(), partialName(.GetTypeName()), false); != nil {
return errors.New("extension field %q cannot resolve type: %v", .FullName(), )
}
if .DefaultValue != nil {
, , := unmarshalDefault(.GetDefaultValue(), , .allowUnresolvable)
if != nil {
return errors.New("extension field %q has invalid default: %v", .FullName(), )
}
.L2.Default = filedesc.DefaultValue(, )
}
}
return nil
}
func ( *resolver) ( []filedesc.Service, []*descriptorpb.ServiceDescriptorProto) ( error) {
for , := range {
:= &[]
for , := range .GetMethod() {
:= &.L2.Methods.List[]
.L1.Input, = .findMessageDescriptor(.Parent().FullName(), partialName(.GetInputType()), false)
if != nil {
return errors.New("service method %q cannot resolve input: %v", .FullName(), )
}
.L1.Output, = .findMessageDescriptor(.FullName(), partialName(.GetOutputType()), false)
if != nil {
return errors.New("service method %q cannot resolve output: %v", .FullName(), )
}
}
}
return nil
}
func ( *resolver) ( protoreflect.Kind, protoreflect.FullName, partialName, bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
switch {
case protoreflect.EnumKind:
, := .findEnumDescriptor(, , )
if != nil {
return 0, nil, nil,
}
return , , nil, nil
case protoreflect.MessageKind, protoreflect.GroupKind:
, := .findMessageDescriptor(, , )
if != nil {
return 0, nil, nil,
}
return , nil, , nil
case 0:
, := .findDescriptor(, )
if == protoregistry.NotFound && (.allowUnresolvable || ) {
return , filedesc.PlaceholderEnum(.FullName()), filedesc.PlaceholderMessage(.FullName()), nil
} else if == protoregistry.NotFound {
return 0, nil, nil, errors.New("%q not found", .FullName())
} else if != nil {
return 0, nil, nil,
}
switch d := .(type) {
case protoreflect.EnumDescriptor:
return protoreflect.EnumKind, , nil, nil
case protoreflect.MessageDescriptor:
return protoreflect.MessageKind, nil, , nil
default:
return 0, nil, nil, errors.New("unknown kind")
}
default:
if != "" {
return 0, nil, nil, errors.New("target name cannot be specified for %v", )
}
if !.IsValid() {
return 0, nil, nil, errors.New("invalid kind: %d", )
}
return , nil, nil, nil
}
}
func ( *resolver) ( protoreflect.FullName, partialName) (protoreflect.Descriptor, error) {
if !.IsValid() {
return nil, errors.New("invalid name reference: %q", )
}
if .IsFull() {
, = "", [1:]
}
var protoreflect.Descriptor
for {
:= protoreflect.FullName()
if != "" {
= + "." +
}
if , := .local[]; {
return , nil
}
, := .remote.FindDescriptorByName()
if == nil {
if .imports[.ParentFile().Path()] {
return , nil
}
=
} else if != protoregistry.NotFound {
return nil, errors.Wrap(, "%q", )
}
if == "" {
if := ; != nil {
return nil, errors.New("resolved %q, but %q is not imported", .FullName(), .ParentFile().Path())
}
return nil, protoregistry.NotFound
}
= .Parent()
}
}
func ( *resolver) ( protoreflect.FullName, partialName, bool) (protoreflect.EnumDescriptor, error) {
, := .findDescriptor(, )
if == protoregistry.NotFound && (.allowUnresolvable || ) {
return filedesc.PlaceholderEnum(.FullName()), nil
} else if == protoregistry.NotFound {
return nil, errors.New("%q not found", .FullName())
} else if != nil {
return nil,
}
, := .(protoreflect.EnumDescriptor)
if ! {
return nil, errors.New("resolved %q, but it is not an enum", .FullName())
}
return , nil
}
func ( *resolver) ( protoreflect.FullName, partialName, bool) (protoreflect.MessageDescriptor, error) {
, := .findDescriptor(, )
if == protoregistry.NotFound && (.allowUnresolvable || ) {
return filedesc.PlaceholderMessage(.FullName()), nil
} else if == protoregistry.NotFound {
return nil, errors.New("%q not found", .FullName())
} else if != nil {
return nil,
}
, := .(protoreflect.MessageDescriptor)
if ! {
return nil, errors.New("resolved %q, but it is not an message", .FullName())
}
return , nil
}
type partialName string
func ( partialName) () bool {
return len() > 0 && [0] == '.'
}
func ( partialName) () bool {
if .IsFull() {
return protoreflect.FullName([1:]).IsValid()
}
return protoreflect.FullName().IsValid()
}
const unknownPrefix = "*."
func ( partialName) () protoreflect.FullName {
if .IsFull() {
return protoreflect.FullName([1:])
}
return protoreflect.FullName(unknownPrefix + )
}
func ( string, protoreflect.FieldDescriptor, bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) {
var protoreflect.EnumValueDescriptors
if .Enum() != nil {
= .Enum().Values()
}
, , := defval.Unmarshal(, .Kind(), , defval.Descriptor)
if != nil && && != nil && protoreflect.Name().IsValid() {
= protoreflect.ValueOfEnum(0)
if .Len() > 0 {
= protoreflect.ValueOfEnum(.Get(0).Number())
}
= filedesc.PlaceholderEnumValue(.Enum().FullName().Parent().Append(protoreflect.Name()))
} else if != nil {
return , ,
}
if .Syntax() == protoreflect.Proto3 {
return , , errors.New("cannot be specified under proto3 semantics")
}
if .Kind() == protoreflect.MessageKind || .Kind() == protoreflect.GroupKind || .Cardinality() == protoreflect.Repeated {
return , , errors.New("cannot be specified on composite types")
}
return , , nil
}