vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
changeset 256 6d9efbef00a9
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
       
     1 // Copyright 2018 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 protoregistry provides data structures to register and lookup
       
     6 // protobuf descriptor types.
       
     7 //
       
     8 // The Files registry contains file descriptors and provides the ability
       
     9 // to iterate over the files or lookup a specific descriptor within the files.
       
    10 // Files only contains protobuf descriptors and has no understanding of Go
       
    11 // type information that may be associated with each descriptor.
       
    12 //
       
    13 // The Types registry contains descriptor types for which there is a known
       
    14 // Go type associated with that descriptor. It provides the ability to iterate
       
    15 // over the registered types or lookup a type by name.
       
    16 package protoregistry
       
    17 
       
    18 import (
       
    19 	"fmt"
       
    20 	"os"
       
    21 	"strings"
       
    22 	"sync"
       
    23 
       
    24 	"google.golang.org/protobuf/internal/encoding/messageset"
       
    25 	"google.golang.org/protobuf/internal/errors"
       
    26 	"google.golang.org/protobuf/internal/flags"
       
    27 	"google.golang.org/protobuf/reflect/protoreflect"
       
    28 )
       
    29 
       
    30 // conflictPolicy configures the policy for handling registration conflicts.
       
    31 //
       
    32 // It can be over-written at compile time with a linker-initialized variable:
       
    33 //	go build -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"
       
    34 //
       
    35 // It can be over-written at program execution with an environment variable:
       
    36 //	GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn ./main
       
    37 //
       
    38 // Neither of the above are covered by the compatibility promise and
       
    39 // may be removed in a future release of this module.
       
    40 var conflictPolicy = "panic" // "panic" | "warn" | "ignore"
       
    41 
       
    42 // ignoreConflict reports whether to ignore a registration conflict
       
    43 // given the descriptor being registered and the error.
       
    44 // It is a variable so that the behavior is easily overridden in another file.
       
    45 var ignoreConflict = func(d protoreflect.Descriptor, err error) bool {
       
    46 	const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT"
       
    47 	const faq = "https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict"
       
    48 	policy := conflictPolicy
       
    49 	if v := os.Getenv(env); v != "" {
       
    50 		policy = v
       
    51 	}
       
    52 	switch policy {
       
    53 	case "panic":
       
    54 		panic(fmt.Sprintf("%v\nSee %v\n", err, faq))
       
    55 	case "warn":
       
    56 		fmt.Fprintf(os.Stderr, "WARNING: %v\nSee %v\n\n", err, faq)
       
    57 		return true
       
    58 	case "ignore":
       
    59 		return true
       
    60 	default:
       
    61 		panic("invalid " + env + " value: " + os.Getenv(env))
       
    62 	}
       
    63 }
       
    64 
       
    65 var globalMutex sync.RWMutex
       
    66 
       
    67 // GlobalFiles is a global registry of file descriptors.
       
    68 var GlobalFiles *Files = new(Files)
       
    69 
       
    70 // GlobalTypes is the registry used by default for type lookups
       
    71 // unless a local registry is provided by the user.
       
    72 var GlobalTypes *Types = new(Types)
       
    73 
       
    74 // NotFound is a sentinel error value to indicate that the type was not found.
       
    75 //
       
    76 // Since registry lookup can happen in the critical performance path, resolvers
       
    77 // must return this exact error value, not an error wrapping it.
       
    78 var NotFound = errors.New("not found")
       
    79 
       
    80 // Files is a registry for looking up or iterating over files and the
       
    81 // descriptors contained within them.
       
    82 // The Find and Range methods are safe for concurrent use.
       
    83 type Files struct {
       
    84 	// The map of descsByName contains:
       
    85 	//	EnumDescriptor
       
    86 	//	EnumValueDescriptor
       
    87 	//	MessageDescriptor
       
    88 	//	ExtensionDescriptor
       
    89 	//	ServiceDescriptor
       
    90 	//	*packageDescriptor
       
    91 	//
       
    92 	// Note that files are stored as a slice, since a package may contain
       
    93 	// multiple files. Only top-level declarations are registered.
       
    94 	// Note that enum values are in the top-level since that are in the same
       
    95 	// scope as the parent enum.
       
    96 	descsByName map[protoreflect.FullName]interface{}
       
    97 	filesByPath map[string][]protoreflect.FileDescriptor
       
    98 	numFiles    int
       
    99 }
       
   100 
       
   101 type packageDescriptor struct {
       
   102 	files []protoreflect.FileDescriptor
       
   103 }
       
   104 
       
   105 // RegisterFile registers the provided file descriptor.
       
   106 //
       
   107 // If any descriptor within the file conflicts with the descriptor of any
       
   108 // previously registered file (e.g., two enums with the same full name),
       
   109 // then the file is not registered and an error is returned.
       
   110 //
       
   111 // It is permitted for multiple files to have the same file path.
       
   112 func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
       
   113 	if r == GlobalFiles {
       
   114 		globalMutex.Lock()
       
   115 		defer globalMutex.Unlock()
       
   116 	}
       
   117 	if r.descsByName == nil {
       
   118 		r.descsByName = map[protoreflect.FullName]interface{}{
       
   119 			"": &packageDescriptor{},
       
   120 		}
       
   121 		r.filesByPath = make(map[string][]protoreflect.FileDescriptor)
       
   122 	}
       
   123 	path := file.Path()
       
   124 	if prev := r.filesByPath[path]; len(prev) > 0 {
       
   125 		r.checkGenProtoConflict(path)
       
   126 		err := errors.New("file %q is already registered", file.Path())
       
   127 		err = amendErrorWithCaller(err, prev[0], file)
       
   128 		if !(r == GlobalFiles && ignoreConflict(file, err)) {
       
   129 			return err
       
   130 		}
       
   131 	}
       
   132 
       
   133 	for name := file.Package(); name != ""; name = name.Parent() {
       
   134 		switch prev := r.descsByName[name]; prev.(type) {
       
   135 		case nil, *packageDescriptor:
       
   136 		default:
       
   137 			err := errors.New("file %q has a package name conflict over %v", file.Path(), name)
       
   138 			err = amendErrorWithCaller(err, prev, file)
       
   139 			if r == GlobalFiles && ignoreConflict(file, err) {
       
   140 				err = nil
       
   141 			}
       
   142 			return err
       
   143 		}
       
   144 	}
       
   145 	var err error
       
   146 	var hasConflict bool
       
   147 	rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) {
       
   148 		if prev := r.descsByName[d.FullName()]; prev != nil {
       
   149 			hasConflict = true
       
   150 			err = errors.New("file %q has a name conflict over %v", file.Path(), d.FullName())
       
   151 			err = amendErrorWithCaller(err, prev, file)
       
   152 			if r == GlobalFiles && ignoreConflict(d, err) {
       
   153 				err = nil
       
   154 			}
       
   155 		}
       
   156 	})
       
   157 	if hasConflict {
       
   158 		return err
       
   159 	}
       
   160 
       
   161 	for name := file.Package(); name != ""; name = name.Parent() {
       
   162 		if r.descsByName[name] == nil {
       
   163 			r.descsByName[name] = &packageDescriptor{}
       
   164 		}
       
   165 	}
       
   166 	p := r.descsByName[file.Package()].(*packageDescriptor)
       
   167 	p.files = append(p.files, file)
       
   168 	rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) {
       
   169 		r.descsByName[d.FullName()] = d
       
   170 	})
       
   171 	r.filesByPath[path] = append(r.filesByPath[path], file)
       
   172 	r.numFiles++
       
   173 	return nil
       
   174 }
       
   175 
       
   176 // Several well-known types were hosted in the google.golang.org/genproto module
       
   177 // but were later moved to this module. To avoid a weak dependency on the
       
   178 // genproto module (and its relatively large set of transitive dependencies),
       
   179 // we rely on a registration conflict to determine whether the genproto version
       
   180 // is too old (i.e., does not contain aliases to the new type declarations).
       
   181 func (r *Files) checkGenProtoConflict(path string) {
       
   182 	if r != GlobalFiles {
       
   183 		return
       
   184 	}
       
   185 	var prevPath string
       
   186 	const prevModule = "google.golang.org/genproto"
       
   187 	const prevVersion = "cb27e3aa (May 26th, 2020)"
       
   188 	switch path {
       
   189 	case "google/protobuf/field_mask.proto":
       
   190 		prevPath = prevModule + "/protobuf/field_mask"
       
   191 	case "google/protobuf/api.proto":
       
   192 		prevPath = prevModule + "/protobuf/api"
       
   193 	case "google/protobuf/type.proto":
       
   194 		prevPath = prevModule + "/protobuf/ptype"
       
   195 	case "google/protobuf/source_context.proto":
       
   196 		prevPath = prevModule + "/protobuf/source_context"
       
   197 	default:
       
   198 		return
       
   199 	}
       
   200 	pkgName := strings.TrimSuffix(strings.TrimPrefix(path, "google/protobuf/"), ".proto")
       
   201 	pkgName = strings.Replace(pkgName, "_", "", -1) + "pb" // e.g., "field_mask" => "fieldmaskpb"
       
   202 	currPath := "google.golang.org/protobuf/types/known/" + pkgName
       
   203 	panic(fmt.Sprintf(""+
       
   204 		"duplicate registration of %q\n"+
       
   205 		"\n"+
       
   206 		"The generated definition for this file has moved:\n"+
       
   207 		"\tfrom: %q\n"+
       
   208 		"\tto:   %q\n"+
       
   209 		"A dependency on the %q module must\n"+
       
   210 		"be at version %v or higher.\n"+
       
   211 		"\n"+
       
   212 		"Upgrade the dependency by running:\n"+
       
   213 		"\tgo get -u %v\n",
       
   214 		path, prevPath, currPath, prevModule, prevVersion, prevPath))
       
   215 }
       
   216 
       
   217 // FindDescriptorByName looks up a descriptor by the full name.
       
   218 //
       
   219 // This returns (nil, NotFound) if not found.
       
   220 func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
       
   221 	if r == nil {
       
   222 		return nil, NotFound
       
   223 	}
       
   224 	if r == GlobalFiles {
       
   225 		globalMutex.RLock()
       
   226 		defer globalMutex.RUnlock()
       
   227 	}
       
   228 	prefix := name
       
   229 	suffix := nameSuffix("")
       
   230 	for prefix != "" {
       
   231 		if d, ok := r.descsByName[prefix]; ok {
       
   232 			switch d := d.(type) {
       
   233 			case protoreflect.EnumDescriptor:
       
   234 				if d.FullName() == name {
       
   235 					return d, nil
       
   236 				}
       
   237 			case protoreflect.EnumValueDescriptor:
       
   238 				if d.FullName() == name {
       
   239 					return d, nil
       
   240 				}
       
   241 			case protoreflect.MessageDescriptor:
       
   242 				if d.FullName() == name {
       
   243 					return d, nil
       
   244 				}
       
   245 				if d := findDescriptorInMessage(d, suffix); d != nil && d.FullName() == name {
       
   246 					return d, nil
       
   247 				}
       
   248 			case protoreflect.ExtensionDescriptor:
       
   249 				if d.FullName() == name {
       
   250 					return d, nil
       
   251 				}
       
   252 			case protoreflect.ServiceDescriptor:
       
   253 				if d.FullName() == name {
       
   254 					return d, nil
       
   255 				}
       
   256 				if d := d.Methods().ByName(suffix.Pop()); d != nil && d.FullName() == name {
       
   257 					return d, nil
       
   258 				}
       
   259 			}
       
   260 			return nil, NotFound
       
   261 		}
       
   262 		prefix = prefix.Parent()
       
   263 		suffix = nameSuffix(name[len(prefix)+len("."):])
       
   264 	}
       
   265 	return nil, NotFound
       
   266 }
       
   267 
       
   268 func findDescriptorInMessage(md protoreflect.MessageDescriptor, suffix nameSuffix) protoreflect.Descriptor {
       
   269 	name := suffix.Pop()
       
   270 	if suffix == "" {
       
   271 		if ed := md.Enums().ByName(name); ed != nil {
       
   272 			return ed
       
   273 		}
       
   274 		for i := md.Enums().Len() - 1; i >= 0; i-- {
       
   275 			if vd := md.Enums().Get(i).Values().ByName(name); vd != nil {
       
   276 				return vd
       
   277 			}
       
   278 		}
       
   279 		if xd := md.Extensions().ByName(name); xd != nil {
       
   280 			return xd
       
   281 		}
       
   282 		if fd := md.Fields().ByName(name); fd != nil {
       
   283 			return fd
       
   284 		}
       
   285 		if od := md.Oneofs().ByName(name); od != nil {
       
   286 			return od
       
   287 		}
       
   288 	}
       
   289 	if md := md.Messages().ByName(name); md != nil {
       
   290 		if suffix == "" {
       
   291 			return md
       
   292 		}
       
   293 		return findDescriptorInMessage(md, suffix)
       
   294 	}
       
   295 	return nil
       
   296 }
       
   297 
       
   298 type nameSuffix string
       
   299 
       
   300 func (s *nameSuffix) Pop() (name protoreflect.Name) {
       
   301 	if i := strings.IndexByte(string(*s), '.'); i >= 0 {
       
   302 		name, *s = protoreflect.Name((*s)[:i]), (*s)[i+1:]
       
   303 	} else {
       
   304 		name, *s = protoreflect.Name((*s)), ""
       
   305 	}
       
   306 	return name
       
   307 }
       
   308 
       
   309 // FindFileByPath looks up a file by the path.
       
   310 //
       
   311 // This returns (nil, NotFound) if not found.
       
   312 // This returns an error if multiple files have the same path.
       
   313 func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
       
   314 	if r == nil {
       
   315 		return nil, NotFound
       
   316 	}
       
   317 	if r == GlobalFiles {
       
   318 		globalMutex.RLock()
       
   319 		defer globalMutex.RUnlock()
       
   320 	}
       
   321 	fds := r.filesByPath[path]
       
   322 	switch len(fds) {
       
   323 	case 0:
       
   324 		return nil, NotFound
       
   325 	case 1:
       
   326 		return fds[0], nil
       
   327 	default:
       
   328 		return nil, errors.New("multiple files named %q", path)
       
   329 	}
       
   330 }
       
   331 
       
   332 // NumFiles reports the number of registered files,
       
   333 // including duplicate files with the same name.
       
   334 func (r *Files) NumFiles() int {
       
   335 	if r == nil {
       
   336 		return 0
       
   337 	}
       
   338 	if r == GlobalFiles {
       
   339 		globalMutex.RLock()
       
   340 		defer globalMutex.RUnlock()
       
   341 	}
       
   342 	return r.numFiles
       
   343 }
       
   344 
       
   345 // RangeFiles iterates over all registered files while f returns true.
       
   346 // If multiple files have the same name, RangeFiles iterates over all of them.
       
   347 // The iteration order is undefined.
       
   348 func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
       
   349 	if r == nil {
       
   350 		return
       
   351 	}
       
   352 	if r == GlobalFiles {
       
   353 		globalMutex.RLock()
       
   354 		defer globalMutex.RUnlock()
       
   355 	}
       
   356 	for _, files := range r.filesByPath {
       
   357 		for _, file := range files {
       
   358 			if !f(file) {
       
   359 				return
       
   360 			}
       
   361 		}
       
   362 	}
       
   363 }
       
   364 
       
   365 // NumFilesByPackage reports the number of registered files in a proto package.
       
   366 func (r *Files) NumFilesByPackage(name protoreflect.FullName) int {
       
   367 	if r == nil {
       
   368 		return 0
       
   369 	}
       
   370 	if r == GlobalFiles {
       
   371 		globalMutex.RLock()
       
   372 		defer globalMutex.RUnlock()
       
   373 	}
       
   374 	p, ok := r.descsByName[name].(*packageDescriptor)
       
   375 	if !ok {
       
   376 		return 0
       
   377 	}
       
   378 	return len(p.files)
       
   379 }
       
   380 
       
   381 // RangeFilesByPackage iterates over all registered files in a given proto package
       
   382 // while f returns true. The iteration order is undefined.
       
   383 func (r *Files) RangeFilesByPackage(name protoreflect.FullName, f func(protoreflect.FileDescriptor) bool) {
       
   384 	if r == nil {
       
   385 		return
       
   386 	}
       
   387 	if r == GlobalFiles {
       
   388 		globalMutex.RLock()
       
   389 		defer globalMutex.RUnlock()
       
   390 	}
       
   391 	p, ok := r.descsByName[name].(*packageDescriptor)
       
   392 	if !ok {
       
   393 		return
       
   394 	}
       
   395 	for _, file := range p.files {
       
   396 		if !f(file) {
       
   397 			return
       
   398 		}
       
   399 	}
       
   400 }
       
   401 
       
   402 // rangeTopLevelDescriptors iterates over all top-level descriptors in a file
       
   403 // which will be directly entered into the registry.
       
   404 func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflect.Descriptor)) {
       
   405 	eds := fd.Enums()
       
   406 	for i := eds.Len() - 1; i >= 0; i-- {
       
   407 		f(eds.Get(i))
       
   408 		vds := eds.Get(i).Values()
       
   409 		for i := vds.Len() - 1; i >= 0; i-- {
       
   410 			f(vds.Get(i))
       
   411 		}
       
   412 	}
       
   413 	mds := fd.Messages()
       
   414 	for i := mds.Len() - 1; i >= 0; i-- {
       
   415 		f(mds.Get(i))
       
   416 	}
       
   417 	xds := fd.Extensions()
       
   418 	for i := xds.Len() - 1; i >= 0; i-- {
       
   419 		f(xds.Get(i))
       
   420 	}
       
   421 	sds := fd.Services()
       
   422 	for i := sds.Len() - 1; i >= 0; i-- {
       
   423 		f(sds.Get(i))
       
   424 	}
       
   425 }
       
   426 
       
   427 // MessageTypeResolver is an interface for looking up messages.
       
   428 //
       
   429 // A compliant implementation must deterministically return the same type
       
   430 // if no error is encountered.
       
   431 //
       
   432 // The Types type implements this interface.
       
   433 type MessageTypeResolver interface {
       
   434 	// FindMessageByName looks up a message by its full name.
       
   435 	// E.g., "google.protobuf.Any"
       
   436 	//
       
   437 	// This return (nil, NotFound) if not found.
       
   438 	FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error)
       
   439 
       
   440 	// FindMessageByURL looks up a message by a URL identifier.
       
   441 	// See documentation on google.protobuf.Any.type_url for the URL format.
       
   442 	//
       
   443 	// This returns (nil, NotFound) if not found.
       
   444 	FindMessageByURL(url string) (protoreflect.MessageType, error)
       
   445 }
       
   446 
       
   447 // ExtensionTypeResolver is an interface for looking up extensions.
       
   448 //
       
   449 // A compliant implementation must deterministically return the same type
       
   450 // if no error is encountered.
       
   451 //
       
   452 // The Types type implements this interface.
       
   453 type ExtensionTypeResolver interface {
       
   454 	// FindExtensionByName looks up a extension field by the field's full name.
       
   455 	// Note that this is the full name of the field as determined by
       
   456 	// where the extension is declared and is unrelated to the full name of the
       
   457 	// message being extended.
       
   458 	//
       
   459 	// This returns (nil, NotFound) if not found.
       
   460 	FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
       
   461 
       
   462 	// FindExtensionByNumber looks up a extension field by the field number
       
   463 	// within some parent message, identified by full name.
       
   464 	//
       
   465 	// This returns (nil, NotFound) if not found.
       
   466 	FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
       
   467 }
       
   468 
       
   469 var (
       
   470 	_ MessageTypeResolver   = (*Types)(nil)
       
   471 	_ ExtensionTypeResolver = (*Types)(nil)
       
   472 )
       
   473 
       
   474 // Types is a registry for looking up or iterating over descriptor types.
       
   475 // The Find and Range methods are safe for concurrent use.
       
   476 type Types struct {
       
   477 	typesByName         typesByName
       
   478 	extensionsByMessage extensionsByMessage
       
   479 
       
   480 	numEnums      int
       
   481 	numMessages   int
       
   482 	numExtensions int
       
   483 }
       
   484 
       
   485 type (
       
   486 	typesByName         map[protoreflect.FullName]interface{}
       
   487 	extensionsByMessage map[protoreflect.FullName]extensionsByNumber
       
   488 	extensionsByNumber  map[protoreflect.FieldNumber]protoreflect.ExtensionType
       
   489 )
       
   490 
       
   491 // RegisterMessage registers the provided message type.
       
   492 //
       
   493 // If a naming conflict occurs, the type is not registered and an error is returned.
       
   494 func (r *Types) RegisterMessage(mt protoreflect.MessageType) error {
       
   495 	// Under rare circumstances getting the descriptor might recursively
       
   496 	// examine the registry, so fetch it before locking.
       
   497 	md := mt.Descriptor()
       
   498 
       
   499 	if r == GlobalTypes {
       
   500 		globalMutex.Lock()
       
   501 		defer globalMutex.Unlock()
       
   502 	}
       
   503 
       
   504 	if err := r.register("message", md, mt); err != nil {
       
   505 		return err
       
   506 	}
       
   507 	r.numMessages++
       
   508 	return nil
       
   509 }
       
   510 
       
   511 // RegisterEnum registers the provided enum type.
       
   512 //
       
   513 // If a naming conflict occurs, the type is not registered and an error is returned.
       
   514 func (r *Types) RegisterEnum(et protoreflect.EnumType) error {
       
   515 	// Under rare circumstances getting the descriptor might recursively
       
   516 	// examine the registry, so fetch it before locking.
       
   517 	ed := et.Descriptor()
       
   518 
       
   519 	if r == GlobalTypes {
       
   520 		globalMutex.Lock()
       
   521 		defer globalMutex.Unlock()
       
   522 	}
       
   523 
       
   524 	if err := r.register("enum", ed, et); err != nil {
       
   525 		return err
       
   526 	}
       
   527 	r.numEnums++
       
   528 	return nil
       
   529 }
       
   530 
       
   531 // RegisterExtension registers the provided extension type.
       
   532 //
       
   533 // If a naming conflict occurs, the type is not registered and an error is returned.
       
   534 func (r *Types) RegisterExtension(xt protoreflect.ExtensionType) error {
       
   535 	// Under rare circumstances getting the descriptor might recursively
       
   536 	// examine the registry, so fetch it before locking.
       
   537 	//
       
   538 	// A known case where this can happen: Fetching the TypeDescriptor for a
       
   539 	// legacy ExtensionDesc can consult the global registry.
       
   540 	xd := xt.TypeDescriptor()
       
   541 
       
   542 	if r == GlobalTypes {
       
   543 		globalMutex.Lock()
       
   544 		defer globalMutex.Unlock()
       
   545 	}
       
   546 
       
   547 	field := xd.Number()
       
   548 	message := xd.ContainingMessage().FullName()
       
   549 	if prev := r.extensionsByMessage[message][field]; prev != nil {
       
   550 		err := errors.New("extension number %d is already registered on message %v", field, message)
       
   551 		err = amendErrorWithCaller(err, prev, xt)
       
   552 		if !(r == GlobalTypes && ignoreConflict(xd, err)) {
       
   553 			return err
       
   554 		}
       
   555 	}
       
   556 
       
   557 	if err := r.register("extension", xd, xt); err != nil {
       
   558 		return err
       
   559 	}
       
   560 	if r.extensionsByMessage == nil {
       
   561 		r.extensionsByMessage = make(extensionsByMessage)
       
   562 	}
       
   563 	if r.extensionsByMessage[message] == nil {
       
   564 		r.extensionsByMessage[message] = make(extensionsByNumber)
       
   565 	}
       
   566 	r.extensionsByMessage[message][field] = xt
       
   567 	r.numExtensions++
       
   568 	return nil
       
   569 }
       
   570 
       
   571 func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interface{}) error {
       
   572 	name := desc.FullName()
       
   573 	prev := r.typesByName[name]
       
   574 	if prev != nil {
       
   575 		err := errors.New("%v %v is already registered", kind, name)
       
   576 		err = amendErrorWithCaller(err, prev, typ)
       
   577 		if !(r == GlobalTypes && ignoreConflict(desc, err)) {
       
   578 			return err
       
   579 		}
       
   580 	}
       
   581 	if r.typesByName == nil {
       
   582 		r.typesByName = make(typesByName)
       
   583 	}
       
   584 	r.typesByName[name] = typ
       
   585 	return nil
       
   586 }
       
   587 
       
   588 // FindEnumByName looks up an enum by its full name.
       
   589 // E.g., "google.protobuf.Field.Kind".
       
   590 //
       
   591 // This returns (nil, NotFound) if not found.
       
   592 func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
       
   593 	if r == nil {
       
   594 		return nil, NotFound
       
   595 	}
       
   596 	if r == GlobalTypes {
       
   597 		globalMutex.RLock()
       
   598 		defer globalMutex.RUnlock()
       
   599 	}
       
   600 	if v := r.typesByName[enum]; v != nil {
       
   601 		if et, _ := v.(protoreflect.EnumType); et != nil {
       
   602 			return et, nil
       
   603 		}
       
   604 		return nil, errors.New("found wrong type: got %v, want enum", typeName(v))
       
   605 	}
       
   606 	return nil, NotFound
       
   607 }
       
   608 
       
   609 // FindMessageByName looks up a message by its full name,
       
   610 // e.g. "google.protobuf.Any".
       
   611 //
       
   612 // This returns (nil, NotFound) if not found.
       
   613 func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
       
   614 	if r == nil {
       
   615 		return nil, NotFound
       
   616 	}
       
   617 	if r == GlobalTypes {
       
   618 		globalMutex.RLock()
       
   619 		defer globalMutex.RUnlock()
       
   620 	}
       
   621 	if v := r.typesByName[message]; v != nil {
       
   622 		if mt, _ := v.(protoreflect.MessageType); mt != nil {
       
   623 			return mt, nil
       
   624 		}
       
   625 		return nil, errors.New("found wrong type: got %v, want message", typeName(v))
       
   626 	}
       
   627 	return nil, NotFound
       
   628 }
       
   629 
       
   630 // FindMessageByURL looks up a message by a URL identifier.
       
   631 // See documentation on google.protobuf.Any.type_url for the URL format.
       
   632 //
       
   633 // This returns (nil, NotFound) if not found.
       
   634 func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
       
   635 	// This function is similar to FindMessageByName but
       
   636 	// truncates anything before and including '/' in the URL.
       
   637 	if r == nil {
       
   638 		return nil, NotFound
       
   639 	}
       
   640 	if r == GlobalTypes {
       
   641 		globalMutex.RLock()
       
   642 		defer globalMutex.RUnlock()
       
   643 	}
       
   644 	message := protoreflect.FullName(url)
       
   645 	if i := strings.LastIndexByte(url, '/'); i >= 0 {
       
   646 		message = message[i+len("/"):]
       
   647 	}
       
   648 
       
   649 	if v := r.typesByName[message]; v != nil {
       
   650 		if mt, _ := v.(protoreflect.MessageType); mt != nil {
       
   651 			return mt, nil
       
   652 		}
       
   653 		return nil, errors.New("found wrong type: got %v, want message", typeName(v))
       
   654 	}
       
   655 	return nil, NotFound
       
   656 }
       
   657 
       
   658 // FindExtensionByName looks up a extension field by the field's full name.
       
   659 // Note that this is the full name of the field as determined by
       
   660 // where the extension is declared and is unrelated to the full name of the
       
   661 // message being extended.
       
   662 //
       
   663 // This returns (nil, NotFound) if not found.
       
   664 func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
       
   665 	if r == nil {
       
   666 		return nil, NotFound
       
   667 	}
       
   668 	if r == GlobalTypes {
       
   669 		globalMutex.RLock()
       
   670 		defer globalMutex.RUnlock()
       
   671 	}
       
   672 	if v := r.typesByName[field]; v != nil {
       
   673 		if xt, _ := v.(protoreflect.ExtensionType); xt != nil {
       
   674 			return xt, nil
       
   675 		}
       
   676 
       
   677 		// MessageSet extensions are special in that the name of the extension
       
   678 		// is the name of the message type used to extend the MessageSet.
       
   679 		// This naming scheme is used by text and JSON serialization.
       
   680 		//
       
   681 		// This feature is protected by the ProtoLegacy flag since MessageSets
       
   682 		// are a proto1 feature that is long deprecated.
       
   683 		if flags.ProtoLegacy {
       
   684 			if _, ok := v.(protoreflect.MessageType); ok {
       
   685 				field := field.Append(messageset.ExtensionName)
       
   686 				if v := r.typesByName[field]; v != nil {
       
   687 					if xt, _ := v.(protoreflect.ExtensionType); xt != nil {
       
   688 						if messageset.IsMessageSetExtension(xt.TypeDescriptor()) {
       
   689 							return xt, nil
       
   690 						}
       
   691 					}
       
   692 				}
       
   693 			}
       
   694 		}
       
   695 
       
   696 		return nil, errors.New("found wrong type: got %v, want extension", typeName(v))
       
   697 	}
       
   698 	return nil, NotFound
       
   699 }
       
   700 
       
   701 // FindExtensionByNumber looks up a extension field by the field number
       
   702 // within some parent message, identified by full name.
       
   703 //
       
   704 // This returns (nil, NotFound) if not found.
       
   705 func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
       
   706 	if r == nil {
       
   707 		return nil, NotFound
       
   708 	}
       
   709 	if r == GlobalTypes {
       
   710 		globalMutex.RLock()
       
   711 		defer globalMutex.RUnlock()
       
   712 	}
       
   713 	if xt, ok := r.extensionsByMessage[message][field]; ok {
       
   714 		return xt, nil
       
   715 	}
       
   716 	return nil, NotFound
       
   717 }
       
   718 
       
   719 // NumEnums reports the number of registered enums.
       
   720 func (r *Types) NumEnums() int {
       
   721 	if r == nil {
       
   722 		return 0
       
   723 	}
       
   724 	if r == GlobalTypes {
       
   725 		globalMutex.RLock()
       
   726 		defer globalMutex.RUnlock()
       
   727 	}
       
   728 	return r.numEnums
       
   729 }
       
   730 
       
   731 // RangeEnums iterates over all registered enums while f returns true.
       
   732 // Iteration order is undefined.
       
   733 func (r *Types) RangeEnums(f func(protoreflect.EnumType) bool) {
       
   734 	if r == nil {
       
   735 		return
       
   736 	}
       
   737 	if r == GlobalTypes {
       
   738 		globalMutex.RLock()
       
   739 		defer globalMutex.RUnlock()
       
   740 	}
       
   741 	for _, typ := range r.typesByName {
       
   742 		if et, ok := typ.(protoreflect.EnumType); ok {
       
   743 			if !f(et) {
       
   744 				return
       
   745 			}
       
   746 		}
       
   747 	}
       
   748 }
       
   749 
       
   750 // NumMessages reports the number of registered messages.
       
   751 func (r *Types) NumMessages() int {
       
   752 	if r == nil {
       
   753 		return 0
       
   754 	}
       
   755 	if r == GlobalTypes {
       
   756 		globalMutex.RLock()
       
   757 		defer globalMutex.RUnlock()
       
   758 	}
       
   759 	return r.numMessages
       
   760 }
       
   761 
       
   762 // RangeMessages iterates over all registered messages while f returns true.
       
   763 // Iteration order is undefined.
       
   764 func (r *Types) RangeMessages(f func(protoreflect.MessageType) bool) {
       
   765 	if r == nil {
       
   766 		return
       
   767 	}
       
   768 	if r == GlobalTypes {
       
   769 		globalMutex.RLock()
       
   770 		defer globalMutex.RUnlock()
       
   771 	}
       
   772 	for _, typ := range r.typesByName {
       
   773 		if mt, ok := typ.(protoreflect.MessageType); ok {
       
   774 			if !f(mt) {
       
   775 				return
       
   776 			}
       
   777 		}
       
   778 	}
       
   779 }
       
   780 
       
   781 // NumExtensions reports the number of registered extensions.
       
   782 func (r *Types) NumExtensions() int {
       
   783 	if r == nil {
       
   784 		return 0
       
   785 	}
       
   786 	if r == GlobalTypes {
       
   787 		globalMutex.RLock()
       
   788 		defer globalMutex.RUnlock()
       
   789 	}
       
   790 	return r.numExtensions
       
   791 }
       
   792 
       
   793 // RangeExtensions iterates over all registered extensions while f returns true.
       
   794 // Iteration order is undefined.
       
   795 func (r *Types) RangeExtensions(f func(protoreflect.ExtensionType) bool) {
       
   796 	if r == nil {
       
   797 		return
       
   798 	}
       
   799 	if r == GlobalTypes {
       
   800 		globalMutex.RLock()
       
   801 		defer globalMutex.RUnlock()
       
   802 	}
       
   803 	for _, typ := range r.typesByName {
       
   804 		if xt, ok := typ.(protoreflect.ExtensionType); ok {
       
   805 			if !f(xt) {
       
   806 				return
       
   807 			}
       
   808 		}
       
   809 	}
       
   810 }
       
   811 
       
   812 // NumExtensionsByMessage reports the number of registered extensions for
       
   813 // a given message type.
       
   814 func (r *Types) NumExtensionsByMessage(message protoreflect.FullName) int {
       
   815 	if r == nil {
       
   816 		return 0
       
   817 	}
       
   818 	if r == GlobalTypes {
       
   819 		globalMutex.RLock()
       
   820 		defer globalMutex.RUnlock()
       
   821 	}
       
   822 	return len(r.extensionsByMessage[message])
       
   823 }
       
   824 
       
   825 // RangeExtensionsByMessage iterates over all registered extensions filtered
       
   826 // by a given message type while f returns true. Iteration order is undefined.
       
   827 func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) {
       
   828 	if r == nil {
       
   829 		return
       
   830 	}
       
   831 	if r == GlobalTypes {
       
   832 		globalMutex.RLock()
       
   833 		defer globalMutex.RUnlock()
       
   834 	}
       
   835 	for _, xt := range r.extensionsByMessage[message] {
       
   836 		if !f(xt) {
       
   837 			return
       
   838 		}
       
   839 	}
       
   840 }
       
   841 
       
   842 func typeName(t interface{}) string {
       
   843 	switch t.(type) {
       
   844 	case protoreflect.EnumType:
       
   845 		return "enum"
       
   846 	case protoreflect.MessageType:
       
   847 		return "message"
       
   848 	case protoreflect.ExtensionType:
       
   849 		return "extension"
       
   850 	default:
       
   851 		return fmt.Sprintf("%T", t)
       
   852 	}
       
   853 }
       
   854 
       
   855 func amendErrorWithCaller(err error, prev, curr interface{}) error {
       
   856 	prevPkg := goPackage(prev)
       
   857 	currPkg := goPackage(curr)
       
   858 	if prevPkg == "" || currPkg == "" || prevPkg == currPkg {
       
   859 		return err
       
   860 	}
       
   861 	return errors.New("%s\n\tpreviously from: %q\n\tcurrently from:  %q", err, prevPkg, currPkg)
       
   862 }
       
   863 
       
   864 func goPackage(v interface{}) string {
       
   865 	switch d := v.(type) {
       
   866 	case protoreflect.EnumType:
       
   867 		v = d.Descriptor()
       
   868 	case protoreflect.MessageType:
       
   869 		v = d.Descriptor()
       
   870 	case protoreflect.ExtensionType:
       
   871 		v = d.TypeDescriptor()
       
   872 	}
       
   873 	if d, ok := v.(protoreflect.Descriptor); ok {
       
   874 		v = d.ParentFile()
       
   875 	}
       
   876 	if d, ok := v.(interface{ GoPackagePath() string }); ok {
       
   877 		return d.GoPackagePath()
       
   878 	}
       
   879 	return ""
       
   880 }