func (r *MessageRegistry) FindEnumTypeByUrl(url string) (*desc.EnumDescriptor, error) {
	ed, err := r.getRegisteredEnumTypeByUrl(url)
	if err != nil {
		return nil, err
	} else if ed != nil {
		return ed, err
	}
	if r.resolver.fetcher == nil {
		return nil, nil
	}
	if ed, err := r.resolver.resolveUrlToEnumDescriptor(url); err != nil {
		return nil, err
	} else {
		return ed, nil
	}
}
FindEnumTypeByUrl finds an enum descriptor for the type at the given URL. It may return nil
if the registry is empty and cannot resolve unknown URLs. If an error occurs while resolving
the URL, it is returned. If the resolved type is a message, ErrUnexpectedType is returned.
package msgregistry
import (
	"fmt"
	"reflect"
	"strings"
	"sync"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/any"
	"github.com/golang/protobuf/ptypes/wrappers"
	"google.golang.org/genproto/protobuf/api"
	"google.golang.org/genproto/protobuf/ptype"
	"google.golang.org/genproto/protobuf/source_context"
	"github.com/jhump/protoreflect/desc"
	"github.com/jhump/protoreflect/dynamic"
)
const googleApisDomain = "type.googleapis.com"
type ErrUnexpectedType struct {
	URL          string
	ShouldBeEnum bool
}
func (e *ErrUnexpectedType) Error() string {
	msg := "wanted message, got enum"
	if e.ShouldBeEnum {
		msg = "wanted enum, got message"
	}
	return fmt.Sprintf("type for URL %q is the wrong type: %s", e.URL, msg)
}
type MessageRegistry struct {
	resolver       typeResolver
	mf             *dynamic.MessageFactory
	er             *dynamic.ExtensionRegistry
	mu             sync.RWMutex
	types          map[string]desc.Descriptor
	baseUrls       map[string]string
	defaultBaseUrl string
}
func NewMessageRegistryWithDefaults() *MessageRegistry {
	mf := dynamic.NewMessageFactoryWithDefaults()
	return &MessageRegistry{
		mf: mf,
		er: mf.GetExtensionRegistry(),
	}
}
func (r *MessageRegistry) WithFetcher(fetcher TypeFetcher) *MessageRegistry {
	r.resolver = typeResolver{fetcher: fetcher, mr: r}
	return r
}
func (r *MessageRegistry) WithMessageFactory(mf *dynamic.MessageFactory) *MessageRegistry {
	r.mf = mf
	if mf == nil {
		r.er = nil
	} else {
		r.er = mf.GetExtensionRegistry()
	}
	return r
}
func (r *MessageRegistry) WithDefaultBaseUrl(baseUrl string) *MessageRegistry {
	baseUrl = stripTrailingSlash(baseUrl)
	r.defaultBaseUrl = baseUrl
	return r
}
func stripTrailingSlash(url string) string {
	if url[len(url)-1] == '/' {
		return url[:len(url)-1]
	}
	return url
}
func (r *MessageRegistry) AddMessage(url string, md *desc.MessageDescriptor) error {
	url = ensureScheme(url)
	baseUrl := strings.TrimSuffix(url, "/"+md.GetFullyQualifiedName())
	if url == baseUrl {
		return fmt.Errorf("URL %s is invalid: it should end with path element %s", url, md.GetFullyQualifiedName())
	}
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.types == nil {
		r.types = map[string]desc.Descriptor{}
	}
	r.types[url] = md
	if r.baseUrls == nil {
		r.baseUrls = map[string]string{}
	}
	r.baseUrls[md.GetFullyQualifiedName()] = baseUrl
	return nil
}
func (r *MessageRegistry) AddEnum(url string, ed *desc.EnumDescriptor) error {
	url = ensureScheme(url)
	baseUrl := strings.TrimSuffix(url, "/"+ed.GetFullyQualifiedName())
	if url == baseUrl {
		return fmt.Errorf("URL %s is invalid: it should end with path element %s", url, ed.GetFullyQualifiedName())
	}
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.types == nil {
		r.types = map[string]desc.Descriptor{}
	}
	r.types[url] = ed
	if r.baseUrls == nil {
		r.baseUrls = map[string]string{}
	}
	r.baseUrls[ed.GetFullyQualifiedName()] = baseUrl
	return nil
}
func (r *MessageRegistry) AddFile(baseUrl string, fd *desc.FileDescriptor) {
	baseUrl = stripTrailingSlash(ensureScheme(baseUrl))
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.types == nil {
		r.types = map[string]desc.Descriptor{}
	}
	if r.baseUrls == nil {
		r.baseUrls = map[string]string{}
	}
	r.addEnumTypesLocked(baseUrl, fd.GetEnumTypes())
	r.addMessageTypesLocked(baseUrl, fd.GetMessageTypes())
}
func (r *MessageRegistry) addEnumTypesLocked(baseUrl string, enums []*desc.EnumDescriptor) {
	for _, ed := range enums {
		url := fmt.Sprintf("%s/%s", baseUrl, ed.GetFullyQualifiedName())
		r.types[url] = ed
		r.baseUrls[ed.GetFullyQualifiedName()] = baseUrl
	}
}
func (r *MessageRegistry) addMessageTypesLocked(baseUrl string, msgs []*desc.MessageDescriptor) {
	for _, md := range msgs {
		url := fmt.Sprintf("%s/%s", baseUrl, md.GetFullyQualifiedName())
		r.types[url] = md
		r.baseUrls[md.GetFullyQualifiedName()] = baseUrl
		r.addEnumTypesLocked(baseUrl, md.GetNestedEnumTypes())
		r.addMessageTypesLocked(baseUrl, md.GetNestedMessageTypes())
	}
}
func (r *MessageRegistry) FindMessageTypeByUrl(url string) (*desc.MessageDescriptor, error) {
	md, err := r.getRegisteredMessageTypeByUrl(url)
	if err != nil {
		return nil, err
	} else if md != nil {
		return md, err
	}
	if r.resolver.fetcher == nil {
		return nil, nil
	}
	return r.resolver.resolveUrlToMessageDescriptor(url)
}
func (r *MessageRegistry) getRegisteredMessageTypeByUrl(url string) (*desc.MessageDescriptor, error) {
	if r != nil {
		r.mu.RLock()
		m := r.types[ensureScheme(url)]
		r.mu.RUnlock()
		if m != nil {
			if md, ok := m.(*desc.MessageDescriptor); ok {
				return md, nil
			}
			return nil, &ErrUnexpectedType{
				URL: url,
			}
		}
	}
	var ktr *dynamic.KnownTypeRegistry
	if r != nil {
		ktr = r.mf.GetKnownTypeRegistry()
	}
	msgType := ktr.GetKnownType(typeName(url))
	if msgType == nil {
		return nil, nil
	}
	return desc.LoadMessageDescriptorForType(msgType)
}