Copyright 2018 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 protoregistry provides data structures to register and lookup protobuf descriptor types. The Files registry contains file descriptors and provides the ability to iterate over the files or lookup a specific descriptor within the files. Files only contains protobuf descriptors and has no understanding of Go type information that may be associated with each descriptor. The Types registry contains descriptor types for which there is a known Go type associated with that descriptor. It provides the ability to iterate over the registered types or lookup a type by name.
package protoregistry

import (
	
	
	
	

	
	
)
ignoreConflict reports whether to ignore a registration conflict given the descriptor being registered and the error. It is a variable so that the behavior is easily overridden in another file.
var ignoreConflict = func( protoreflect.Descriptor,  error) bool {
	log.Printf(""+
		"WARNING: %v\n"+
		"A future release will panic on registration conflicts. See:\n"+
		"https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict\n"+
		"\n", )
	return true
}

var globalMutex sync.RWMutex
GlobalFiles is a global registry of file descriptors.
GlobalTypes is the registry used by default for type lookups unless a local registry is provided by the user.
NotFound is a sentinel error value to indicate that the type was not found. Since registry lookup can happen in the critical performance path, resolvers must return this exact error value, not an error wrapping it.
var NotFound = errors.New("not found")
Files is a registry for looking up or iterating over files and the descriptors contained within them. The Find and Range methods are safe for concurrent use.
The map of descsByName contains: EnumDescriptor EnumValueDescriptor MessageDescriptor ExtensionDescriptor ServiceDescriptor *packageDescriptor Note that files are stored as a slice, since a package may contain multiple files. Only top-level declarations are registered. Note that enum values are in the top-level since that are in the same scope as the parent enum.
RegisterFile registers the provided file descriptor. If any descriptor within the file conflicts with the descriptor of any previously registered file (e.g., two enums with the same full name), then the file is not registered and an error is returned. It is permitted for multiple files to have the same file path.
TODO: Remove this after some soak-in period after moving these types.
		var  string
		const  = "google.golang.org/genproto"
		const  = "cb27e3aa (May 26th, 2020)"
		switch  {
		case "google/protobuf/field_mask.proto":
			 =  + "/protobuf/field_mask"
		case "google/protobuf/api.proto":
			 =  + "/protobuf/api"
		case "google/protobuf/type.proto":
			 =  + "/protobuf/ptype"
		case "google/protobuf/source_context.proto":
			 =  + "/protobuf/source_context"
		}
		if  == GlobalFiles &&  != "" {
			 := strings.TrimSuffix(strings.TrimPrefix(, "google/protobuf/"), ".proto")
			 = strings.Replace(, "_", "", -1) + "pb"
			 := "google.golang.org/protobuf/types/known/" + 
			panic(fmt.Sprintf(""+
				"duplicate registration of %q\n"+
				"\n"+
				"The generated definition for this file has moved:\n"+
				"\tfrom: %q\n"+
				"\tto:   %q\n"+
				"A dependency on the %q module must\n"+
				"be at version %v or higher.\n"+
				"\n"+
				"Upgrade the dependency by running:\n"+
				"\tgo get -u %v\n",
				, , , , , ))
		}

		 := errors.New("file %q is already registered", .Path())
		 = amendErrorWithCaller(, , )
		if  == GlobalFiles && ignoreConflict(, ) {
			 = nil
		}
		return 
	}

	for  := .Package();  != "";  = .Parent() {
		switch  := .descsByName[]; .(type) {
		case nil, *packageDescriptor:
		default:
			 := errors.New("file %q has a package name conflict over %v", .Path(), )
			 = amendErrorWithCaller(, , )
			if  == GlobalFiles && ignoreConflict(, ) {
				 = nil
			}
			return 
		}
	}
	var  error
	var  bool
	rangeTopLevelDescriptors(, func( protoreflect.Descriptor) {
		if  := .descsByName[.FullName()];  != nil {
			 = true
			 = errors.New("file %q has a name conflict over %v", .Path(), .FullName())
			 = amendErrorWithCaller(, , )
			if  == GlobalFiles && ignoreConflict(, ) {
				 = nil
			}
		}
	})
	if  {
		return 
	}

	for  := .Package();  != "";  = .Parent() {
		if .descsByName[] == nil {
			.descsByName[] = &packageDescriptor{}
		}
	}
	 := .descsByName[.Package()].(*packageDescriptor)
	.files = append(.files, )
	rangeTopLevelDescriptors(, func( protoreflect.Descriptor) {
		.descsByName[.FullName()] = 
	})
	.filesByPath[] = 
	return nil
}
FindDescriptorByName looks up a descriptor by the full name. This returns (nil, NotFound) if not found.
func ( *Files) ( protoreflect.FullName) (protoreflect.Descriptor, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	 := 
	 := nameSuffix("")
	for  != "" {
		if ,  := .descsByName[];  {
			switch d := .(type) {
			case protoreflect.EnumDescriptor:
				if .FullName() ==  {
					return , nil
				}
			case protoreflect.EnumValueDescriptor:
				if .FullName() ==  {
					return , nil
				}
			case protoreflect.MessageDescriptor:
				if .FullName() ==  {
					return , nil
				}
				if  := findDescriptorInMessage(, );  != nil && .FullName() ==  {
					return , nil
				}
			case protoreflect.ExtensionDescriptor:
				if .FullName() ==  {
					return , nil
				}
			case protoreflect.ServiceDescriptor:
				if .FullName() ==  {
					return , nil
				}
				if  := .Methods().ByName(.Pop());  != nil && .FullName() ==  {
					return , nil
				}
			}
			return nil, NotFound
		}
		 = .Parent()
		 = nameSuffix([len()+len("."):])
	}
	return nil, NotFound
}

func ( protoreflect.MessageDescriptor,  nameSuffix) protoreflect.Descriptor {
	 := .Pop()
	if  == "" {
		if  := .Enums().ByName();  != nil {
			return 
		}
		for  := .Enums().Len() - 1;  >= 0; -- {
			if  := .Enums().Get().Values().ByName();  != nil {
				return 
			}
		}
		if  := .Extensions().ByName();  != nil {
			return 
		}
		if  := .Fields().ByName();  != nil {
			return 
		}
		if  := .Oneofs().ByName();  != nil {
			return 
		}
	}
	if  := .Messages().ByName();  != nil {
		if  == "" {
			return 
		}
		return (, )
	}
	return nil
}

type nameSuffix string

func ( *nameSuffix) () ( protoreflect.Name) {
	if  := strings.IndexByte(string(*), '.');  >= 0 {
		, * = protoreflect.Name((*)[:]), (*)[+1:]
	} else {
		, * = protoreflect.Name((*)), ""
	}
	return 
}
FindFileByPath looks up a file by the path. This returns (nil, NotFound) if not found.
func ( *Files) ( string) (protoreflect.FileDescriptor, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	if ,  := .filesByPath[];  {
		return , nil
	}
	return nil, NotFound
}
NumFiles reports the number of registered files.
func ( *Files) () int {
	if  == nil {
		return 0
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	return len(.filesByPath)
}
RangeFiles iterates over all registered files while f returns true. The iteration order is undefined.
func ( *Files) ( func(protoreflect.FileDescriptor) bool) {
	if  == nil {
		return
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	for ,  := range .filesByPath {
		if !() {
			return
		}
	}
}
NumFilesByPackage reports the number of registered files in a proto package.
func ( *Files) ( protoreflect.FullName) int {
	if  == nil {
		return 0
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	,  := .descsByName[].(*packageDescriptor)
	if ! {
		return 0
	}
	return len(.files)
}
RangeFilesByPackage iterates over all registered files in a given proto package while f returns true. The iteration order is undefined.
func ( *Files) ( protoreflect.FullName,  func(protoreflect.FileDescriptor) bool) {
	if  == nil {
		return
	}
	if  == GlobalFiles {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	,  := .descsByName[].(*packageDescriptor)
	if ! {
		return
	}
	for ,  := range .files {
		if !() {
			return
		}
	}
}
rangeTopLevelDescriptors iterates over all top-level descriptors in a file which will be directly entered into the registry.
func ( protoreflect.FileDescriptor,  func(protoreflect.Descriptor)) {
	 := .Enums()
	for  := .Len() - 1;  >= 0; -- {
		(.Get())
		 := .Get().Values()
		for  := .Len() - 1;  >= 0; -- {
			(.Get())
		}
	}
	 := .Messages()
	for  := .Len() - 1;  >= 0; -- {
		(.Get())
	}
	 := .Extensions()
	for  := .Len() - 1;  >= 0; -- {
		(.Get())
	}
	 := .Services()
	for  := .Len() - 1;  >= 0; -- {
		(.Get())
	}
}
MessageTypeResolver is an interface for looking up messages. A compliant implementation must deterministically return the same type if no error is encountered. The Types type implements this interface.
FindMessageByName looks up a message by its full name. E.g., "google.protobuf.Any" This return (nil, NotFound) if not found.
	FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error)
FindMessageByURL looks up a message by a URL identifier. See documentation on google.protobuf.Any.type_url for the URL format. This returns (nil, NotFound) if not found.
	FindMessageByURL(url string) (protoreflect.MessageType, error)
}
ExtensionTypeResolver is an interface for looking up extensions. A compliant implementation must deterministically return the same type if no error is encountered. The Types type implements this interface.
FindExtensionByName looks up a extension field by the field's full name. Note that this is the full name of the field as determined by where the extension is declared and is unrelated to the full name of the message being extended. This returns (nil, NotFound) if not found.
	FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
FindExtensionByNumber looks up a extension field by the field number within some parent message, identified by full name. This returns (nil, NotFound) if not found.
Types is a registry for looking up or iterating over descriptor types. The Find and Range methods are safe for concurrent use.
RegisterMessage registers the provided message type. If a naming conflict occurs, the type is not registered and an error is returned.
Under rare circumstances getting the descriptor might recursively examine the registry, so fetch it before locking.
	 := .Descriptor()

	if  == GlobalTypes {
		globalMutex.Lock()
		defer globalMutex.Unlock()
	}

	if  := .register("message", , );  != nil {
		return 
	}
	.numMessages++
	return nil
}
RegisterEnum registers the provided enum type. If a naming conflict occurs, the type is not registered and an error is returned.
Under rare circumstances getting the descriptor might recursively examine the registry, so fetch it before locking.
	 := .Descriptor()

	if  == GlobalTypes {
		globalMutex.Lock()
		defer globalMutex.Unlock()
	}

	if  := .register("enum", , );  != nil {
		return 
	}
	.numEnums++
	return nil
}
RegisterExtension registers the provided extension type. If a naming conflict occurs, the type is not registered and an error is returned.
Under rare circumstances getting the descriptor might recursively examine the registry, so fetch it before locking. A known case where this can happen: Fetching the TypeDescriptor for a legacy ExtensionDesc can consult the global registry.
	 := .TypeDescriptor()

	if  == GlobalTypes {
		globalMutex.Lock()
		defer globalMutex.Unlock()
	}

	 := .Number()
	 := .ContainingMessage().FullName()
	if  := .extensionsByMessage[][];  != nil {
		 := errors.New("extension number %d is already registered on message %v", , )
		 = amendErrorWithCaller(, , )
		if !( == GlobalTypes && ignoreConflict(, )) {
			return 
		}
	}

	if  := .register("extension", , );  != nil {
		return 
	}
	if .extensionsByMessage == nil {
		.extensionsByMessage = make(extensionsByMessage)
	}
	if .extensionsByMessage[] == nil {
		.extensionsByMessage[] = make(extensionsByNumber)
	}
	.extensionsByMessage[][] = 
	.numExtensions++
	return nil
}

func ( *Types) ( string,  protoreflect.Descriptor,  interface{}) error {
	 := .FullName()
	 := .typesByName[]
	if  != nil {
		 := errors.New("%v %v is already registered", , )
		 = amendErrorWithCaller(, , )
		if !( == GlobalTypes && ignoreConflict(, )) {
			return 
		}
	}
	if .typesByName == nil {
		.typesByName = make(typesByName)
	}
	.typesByName[] = 
	return nil
}
FindEnumByName looks up an enum by its full name. E.g., "google.protobuf.Field.Kind". This returns (nil, NotFound) if not found.
func ( *Types) ( protoreflect.FullName) (protoreflect.EnumType, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	if  := .typesByName[];  != nil {
		if ,  := .(protoreflect.EnumType);  != nil {
			return , nil
		}
		return nil, errors.New("found wrong type: got %v, want enum", typeName())
	}
	return nil, NotFound
}
FindMessageByName looks up a message by its full name. E.g., "google.protobuf.Any" This return (nil, NotFound) if not found.
The full name by itself is a valid URL.
	return .FindMessageByURL(string())
}
FindMessageByURL looks up a message by a URL identifier. See documentation on google.protobuf.Any.type_url for the URL format. This returns (nil, NotFound) if not found.
func ( *Types) ( string) (protoreflect.MessageType, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	 := protoreflect.FullName()
	if  := strings.LastIndexByte(, '/');  >= 0 {
		 = [+len("/"):]
	}

	if  := .typesByName[];  != nil {
		if ,  := .(protoreflect.MessageType);  != nil {
			return , nil
		}
		return nil, errors.New("found wrong type: got %v, want message", typeName())
	}
	return nil, NotFound
}
FindExtensionByName looks up a extension field by the field's full name. Note that this is the full name of the field as determined by where the extension is declared and is unrelated to the full name of the message being extended. This returns (nil, NotFound) if not found.
func ( *Types) ( protoreflect.FullName) (protoreflect.ExtensionType, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	if  := .typesByName[];  != nil {
		if ,  := .(protoreflect.ExtensionType);  != nil {
			return , nil
		}
		return nil, errors.New("found wrong type: got %v, want extension", typeName())
	}
	return nil, NotFound
}
FindExtensionByNumber looks up a extension field by the field number within some parent message, identified by full name. This returns (nil, NotFound) if not found.
func ( *Types) ( protoreflect.FullName,  protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
	if  == nil {
		return nil, NotFound
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	if ,  := .extensionsByMessage[][];  {
		return , nil
	}
	return nil, NotFound
}
NumEnums reports the number of registered enums.
func ( *Types) () int {
	if  == nil {
		return 0
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	return .numEnums
}
RangeEnums iterates over all registered enums while f returns true. Iteration order is undefined.
func ( *Types) ( func(protoreflect.EnumType) bool) {
	if  == nil {
		return
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	for ,  := range .typesByName {
		if ,  := .(protoreflect.EnumType);  {
			if !() {
				return
			}
		}
	}
}
NumMessages reports the number of registered messages.
func ( *Types) () int {
	if  == nil {
		return 0
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	return .numMessages
}
RangeMessages iterates over all registered messages while f returns true. Iteration order is undefined.
func ( *Types) ( func(protoreflect.MessageType) bool) {
	if  == nil {
		return
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	for ,  := range .typesByName {
		if ,  := .(protoreflect.MessageType);  {
			if !() {
				return
			}
		}
	}
}
NumExtensions reports the number of registered extensions.
func ( *Types) () int {
	if  == nil {
		return 0
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	return .numExtensions
}
RangeExtensions iterates over all registered extensions while f returns true. Iteration order is undefined.
func ( *Types) ( func(protoreflect.ExtensionType) bool) {
	if  == nil {
		return
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	for ,  := range .typesByName {
		if ,  := .(protoreflect.ExtensionType);  {
			if !() {
				return
			}
		}
	}
}
NumExtensionsByMessage reports the number of registered extensions for a given message type.
func ( *Types) ( protoreflect.FullName) int {
	if  == nil {
		return 0
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	return len(.extensionsByMessage[])
}
RangeExtensionsByMessage iterates over all registered extensions filtered by a given message type while f returns true. Iteration order is undefined.
func ( *Types) ( protoreflect.FullName,  func(protoreflect.ExtensionType) bool) {
	if  == nil {
		return
	}
	if  == GlobalTypes {
		globalMutex.RLock()
		defer globalMutex.RUnlock()
	}
	for ,  := range .extensionsByMessage[] {
		if !() {
			return
		}
	}
}

func ( interface{}) string {
	switch .(type) {
	case protoreflect.EnumType:
		return "enum"
	case protoreflect.MessageType:
		return "message"
	case protoreflect.ExtensionType:
		return "extension"
	default:
		return fmt.Sprintf("%T", )
	}
}

func ( error, ,  interface{}) error {
	 := goPackage()
	 := goPackage()
	if  == "" ||  == "" ||  ==  {
		return 
	}
	return errors.New("%s\n\tpreviously from: %q\n\tcurrently from:  %q", , , )
}

func ( interface{}) string {
	switch d := .(type) {
	case protoreflect.EnumType:
		 = .Descriptor()
	case protoreflect.MessageType:
		 = .Descriptor()
	case protoreflect.ExtensionType:
		 = .TypeDescriptor()
	}
	if ,  := .(protoreflect.Descriptor);  {
		 = .ParentFile()
	}
	if ,  := .(interface{ () string });  {
		return .()
	}
	return ""