vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
changeset 256 6d9efbef00a9
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
       
     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 protodesc
       
     6 
       
     7 import (
       
     8 	"google.golang.org/protobuf/internal/encoding/defval"
       
     9 	"google.golang.org/protobuf/internal/errors"
       
    10 	"google.golang.org/protobuf/internal/filedesc"
       
    11 	"google.golang.org/protobuf/reflect/protoreflect"
       
    12 	"google.golang.org/protobuf/reflect/protoregistry"
       
    13 
       
    14 	"google.golang.org/protobuf/types/descriptorpb"
       
    15 )
       
    16 
       
    17 // resolver is a wrapper around a local registry of declarations within the file
       
    18 // and the remote resolver. The remote resolver is restricted to only return
       
    19 // descriptors that have been imported.
       
    20 type resolver struct {
       
    21 	local   descsByName
       
    22 	remote  Resolver
       
    23 	imports importSet
       
    24 
       
    25 	allowUnresolvable bool
       
    26 }
       
    27 
       
    28 func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) (err error) {
       
    29 	for i, md := range mds {
       
    30 		m := &ms[i]
       
    31 		for j, fd := range md.GetField() {
       
    32 			f := &m.L2.Fields.List[j]
       
    33 			if f.L1.Cardinality == protoreflect.Required {
       
    34 				m.L2.RequiredNumbers.List = append(m.L2.RequiredNumbers.List, f.L1.Number)
       
    35 			}
       
    36 			if fd.OneofIndex != nil {
       
    37 				k := int(fd.GetOneofIndex())
       
    38 				if !(0 <= k && k < len(md.GetOneofDecl())) {
       
    39 					return errors.New("message field %q has an invalid oneof index: %d", f.FullName(), k)
       
    40 				}
       
    41 				o := &m.L2.Oneofs.List[k]
       
    42 				f.L1.ContainingOneof = o
       
    43 				o.L1.Fields.List = append(o.L1.Fields.List, f)
       
    44 			}
       
    45 
       
    46 			if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
       
    47 				return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
       
    48 			}
       
    49 			if fd.DefaultValue != nil {
       
    50 				v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable)
       
    51 				if err != nil {
       
    52 					return errors.New("message field %q has invalid default: %v", f.FullName(), err)
       
    53 				}
       
    54 				f.L1.Default = filedesc.DefaultValue(v, ev)
       
    55 			}
       
    56 		}
       
    57 
       
    58 		if err := r.resolveMessageDependencies(m.L1.Messages.List, md.GetNestedType()); err != nil {
       
    59 			return err
       
    60 		}
       
    61 		if err := r.resolveExtensionDependencies(m.L1.Extensions.List, md.GetExtension()); err != nil {
       
    62 			return err
       
    63 		}
       
    64 	}
       
    65 	return nil
       
    66 }
       
    67 
       
    68 func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
       
    69 	for i, xd := range xds {
       
    70 		x := &xs[i]
       
    71 		if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil {
       
    72 			return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
       
    73 		}
       
    74 		if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil {
       
    75 			return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
       
    76 		}
       
    77 		if xd.DefaultValue != nil {
       
    78 			v, ev, err := unmarshalDefault(xd.GetDefaultValue(), x, r.allowUnresolvable)
       
    79 			if err != nil {
       
    80 				return errors.New("extension field %q has invalid default: %v", x.FullName(), err)
       
    81 			}
       
    82 			x.L2.Default = filedesc.DefaultValue(v, ev)
       
    83 		}
       
    84 	}
       
    85 	return nil
       
    86 }
       
    87 
       
    88 func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*descriptorpb.ServiceDescriptorProto) (err error) {
       
    89 	for i, sd := range sds {
       
    90 		s := &ss[i]
       
    91 		for j, md := range sd.GetMethod() {
       
    92 			m := &s.L2.Methods.List[j]
       
    93 			m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false)
       
    94 			if err != nil {
       
    95 				return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
       
    96 			}
       
    97 			m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false)
       
    98 			if err != nil {
       
    99 				return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
       
   100 			}
       
   101 		}
       
   102 	}
       
   103 	return nil
       
   104 }
       
   105 
       
   106 // findTarget finds an enum or message descriptor if k is an enum, message,
       
   107 // group, or unknown. If unknown, and the name could be resolved, the kind
       
   108 // returned kind is set based on the type of the resolved descriptor.
       
   109 func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
       
   110 	switch k {
       
   111 	case protoreflect.EnumKind:
       
   112 		ed, err := r.findEnumDescriptor(scope, ref, isWeak)
       
   113 		if err != nil {
       
   114 			return 0, nil, nil, err
       
   115 		}
       
   116 		return k, ed, nil, nil
       
   117 	case protoreflect.MessageKind, protoreflect.GroupKind:
       
   118 		md, err := r.findMessageDescriptor(scope, ref, isWeak)
       
   119 		if err != nil {
       
   120 			return 0, nil, nil, err
       
   121 		}
       
   122 		return k, nil, md, nil
       
   123 	case 0:
       
   124 		// Handle unspecified kinds (possible with parsers that operate
       
   125 		// on a per-file basis without knowledge of dependencies).
       
   126 		d, err := r.findDescriptor(scope, ref)
       
   127 		if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
       
   128 			return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
       
   129 		} else if err == protoregistry.NotFound {
       
   130 			return 0, nil, nil, errors.New("%q not found", ref.FullName())
       
   131 		} else if err != nil {
       
   132 			return 0, nil, nil, err
       
   133 		}
       
   134 		switch d := d.(type) {
       
   135 		case protoreflect.EnumDescriptor:
       
   136 			return protoreflect.EnumKind, d, nil, nil
       
   137 		case protoreflect.MessageDescriptor:
       
   138 			return protoreflect.MessageKind, nil, d, nil
       
   139 		default:
       
   140 			return 0, nil, nil, errors.New("unknown kind")
       
   141 		}
       
   142 	default:
       
   143 		if ref != "" {
       
   144 			return 0, nil, nil, errors.New("target name cannot be specified for %v", k)
       
   145 		}
       
   146 		if !k.IsValid() {
       
   147 			return 0, nil, nil, errors.New("invalid kind: %d", k)
       
   148 		}
       
   149 		return k, nil, nil, nil
       
   150 	}
       
   151 }
       
   152 
       
   153 // findDescriptor finds the descriptor by name,
       
   154 // which may be a relative name within some scope.
       
   155 //
       
   156 // Suppose the scope was "fizz.buzz" and the reference was "Foo.Bar",
       
   157 // then the following full names are searched:
       
   158 //	* fizz.buzz.Foo.Bar
       
   159 //	* fizz.Foo.Bar
       
   160 //	* Foo.Bar
       
   161 func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.Descriptor, error) {
       
   162 	if !ref.IsValid() {
       
   163 		return nil, errors.New("invalid name reference: %q", ref)
       
   164 	}
       
   165 	if ref.IsFull() {
       
   166 		scope, ref = "", ref[1:]
       
   167 	}
       
   168 	var foundButNotImported protoreflect.Descriptor
       
   169 	for {
       
   170 		// Derive the full name to search.
       
   171 		s := protoreflect.FullName(ref)
       
   172 		if scope != "" {
       
   173 			s = scope + "." + s
       
   174 		}
       
   175 
       
   176 		// Check the current file for the descriptor.
       
   177 		if d, ok := r.local[s]; ok {
       
   178 			return d, nil
       
   179 		}
       
   180 
       
   181 		// Check the remote registry for the descriptor.
       
   182 		d, err := r.remote.FindDescriptorByName(s)
       
   183 		if err == nil {
       
   184 			// Only allow descriptors covered by one of the imports.
       
   185 			if r.imports[d.ParentFile().Path()] {
       
   186 				return d, nil
       
   187 			}
       
   188 			foundButNotImported = d
       
   189 		} else if err != protoregistry.NotFound {
       
   190 			return nil, errors.Wrap(err, "%q", s)
       
   191 		}
       
   192 
       
   193 		// Continue on at a higher level of scoping.
       
   194 		if scope == "" {
       
   195 			if d := foundButNotImported; d != nil {
       
   196 				return nil, errors.New("resolved %q, but %q is not imported", d.FullName(), d.ParentFile().Path())
       
   197 			}
       
   198 			return nil, protoregistry.NotFound
       
   199 		}
       
   200 		scope = scope.Parent()
       
   201 	}
       
   202 }
       
   203 
       
   204 func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) {
       
   205 	d, err := r.findDescriptor(scope, ref)
       
   206 	if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
       
   207 		return filedesc.PlaceholderEnum(ref.FullName()), nil
       
   208 	} else if err == protoregistry.NotFound {
       
   209 		return nil, errors.New("%q not found", ref.FullName())
       
   210 	} else if err != nil {
       
   211 		return nil, err
       
   212 	}
       
   213 	ed, ok := d.(protoreflect.EnumDescriptor)
       
   214 	if !ok {
       
   215 		return nil, errors.New("resolved %q, but it is not an enum", d.FullName())
       
   216 	}
       
   217 	return ed, nil
       
   218 }
       
   219 
       
   220 func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) {
       
   221 	d, err := r.findDescriptor(scope, ref)
       
   222 	if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
       
   223 		return filedesc.PlaceholderMessage(ref.FullName()), nil
       
   224 	} else if err == protoregistry.NotFound {
       
   225 		return nil, errors.New("%q not found", ref.FullName())
       
   226 	} else if err != nil {
       
   227 		return nil, err
       
   228 	}
       
   229 	md, ok := d.(protoreflect.MessageDescriptor)
       
   230 	if !ok {
       
   231 		return nil, errors.New("resolved %q, but it is not an message", d.FullName())
       
   232 	}
       
   233 	return md, nil
       
   234 }
       
   235 
       
   236 // partialName is the partial name. A leading dot means that the name is full,
       
   237 // otherwise the name is relative to some current scope.
       
   238 // See google.protobuf.FieldDescriptorProto.type_name.
       
   239 type partialName string
       
   240 
       
   241 func (s partialName) IsFull() bool {
       
   242 	return len(s) > 0 && s[0] == '.'
       
   243 }
       
   244 
       
   245 func (s partialName) IsValid() bool {
       
   246 	if s.IsFull() {
       
   247 		return protoreflect.FullName(s[1:]).IsValid()
       
   248 	}
       
   249 	return protoreflect.FullName(s).IsValid()
       
   250 }
       
   251 
       
   252 const unknownPrefix = "*."
       
   253 
       
   254 // FullName converts the partial name to a full name on a best-effort basis.
       
   255 // If relative, it creates an invalid full name, using a "*." prefix
       
   256 // to indicate that the start of the full name is unknown.
       
   257 func (s partialName) FullName() protoreflect.FullName {
       
   258 	if s.IsFull() {
       
   259 		return protoreflect.FullName(s[1:])
       
   260 	}
       
   261 	return protoreflect.FullName(unknownPrefix + s)
       
   262 }
       
   263 
       
   264 func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvable bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) {
       
   265 	var evs protoreflect.EnumValueDescriptors
       
   266 	if fd.Enum() != nil {
       
   267 		evs = fd.Enum().Values()
       
   268 	}
       
   269 	v, ev, err := defval.Unmarshal(s, fd.Kind(), evs, defval.Descriptor)
       
   270 	if err != nil && allowUnresolvable && evs != nil && protoreflect.Name(s).IsValid() {
       
   271 		v = protoreflect.ValueOfEnum(0)
       
   272 		if evs.Len() > 0 {
       
   273 			v = protoreflect.ValueOfEnum(evs.Get(0).Number())
       
   274 		}
       
   275 		ev = filedesc.PlaceholderEnumValue(fd.Enum().FullName().Parent().Append(protoreflect.Name(s)))
       
   276 	} else if err != nil {
       
   277 		return v, ev, err
       
   278 	}
       
   279 	if fd.Syntax() == protoreflect.Proto3 {
       
   280 		return v, ev, errors.New("cannot be specified under proto3 semantics")
       
   281 	}
       
   282 	if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
       
   283 		return v, ev, errors.New("cannot be specified on composite types")
       
   284 	}
       
   285 	return v, ev, nil
       
   286 }