// Copyright 2019 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 proto

import (
	
	
	
	
	
	
	

	
	
	
	
)

// filePath is the path to the proto source file.
type filePath = string // e.g., "google/protobuf/descriptor.proto"

// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
type fileDescGZIP = []byte

var fileCache sync.Map // map[filePath]fileDescGZIP

// RegisterFile is called from generated code to register the compressed
// FileDescriptorProto with the file path for a proto source file.
//
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
func ( filePath,  fileDescGZIP) {
	// Decompress the descriptor.
	,  := gzip.NewReader(bytes.NewReader())
	if  != nil {
		panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", ))
	}
	,  := ioutil.ReadAll()
	if  != nil {
		panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", ))
	}

	// Construct a protoreflect.FileDescriptor from the raw descriptor.
	// Note that DescBuilder.Build automatically registers the constructed
	// file descriptor with the v2 registry.
	protoimpl.DescBuilder{RawDescriptor: }.Build()

	// Locally cache the raw descriptor form for the file.
	fileCache.Store(, )
}

// FileDescriptor returns the compressed FileDescriptorProto given the file path
// for a proto source file. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
func ( filePath) fileDescGZIP {
	if ,  := fileCache.Load();  {
		return .(fileDescGZIP)
	}

	// Find the descriptor in the v2 registry.
	var  []byte
	if ,  := protoregistry.GlobalFiles.FindFileByPath();  != nil {
		, _ = Marshal(protodesc.ToFileDescriptorProto())
	}

	// Locally cache the raw descriptor form for the file.
	if len() > 0 {
		,  := fileCache.LoadOrStore(, protoimpl.X.CompressGZIP())
		return .(fileDescGZIP)
	}
	return nil
}

// enumName is the name of an enum. For historical reasons, the enum name is
// neither the full Go name nor the full protobuf name of the enum.
// The name is the dot-separated combination of just the proto package that the
// enum is declared within followed by the Go type name of the generated enum.
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"

// enumsByName maps enum values by name to their numeric counterpart.
type enumsByName = map[string]int32

// enumsByNumber maps enum values by number to their name counterpart.
type enumsByNumber = map[int32]string

var enumCache sync.Map     // map[enumName]enumsByName
var numFilesCache sync.Map // map[protoreflect.FullName]int

// RegisterEnum is called from the generated code to register the mapping of
// enum value names to enum numbers for the enum identified by s.
//
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
func ( enumName,  enumsByNumber,  enumsByName) {
	if ,  := enumCache.Load();  {
		panic("proto: duplicate enum registered: " + )
	}
	enumCache.Store(, )

	// This does not forward registration to the v2 registry since this API
	// lacks sufficient information to construct a complete v2 enum descriptor.
}

// EnumValueMap returns the mapping from enum value names to enum numbers for
// the enum of the given name. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
func ( enumName) enumsByName {
	if ,  := enumCache.Load();  {
		return .(enumsByName)
	}

	// Check whether the cache is stale. If the number of files in the current
	// package differs, then it means that some enums may have been recently
	// registered upstream that we do not know about.
	var  protoreflect.FullName
	if  := strings.LastIndexByte(, '.');  >= 0 {
		 = protoreflect.FullName([:])
	}
	,  := numFilesCache.Load()
	,  := .(int)
	if protoregistry.GlobalFiles.NumFilesByPackage() ==  {
		return nil // cache is up-to-date; was not found earlier
	}

	// Update the enum cache for all enums declared in the given proto package.
	 = 0
	protoregistry.GlobalFiles.RangeFilesByPackage(, func( protoreflect.FileDescriptor) bool {
		walkEnums(, func( protoreflect.EnumDescriptor) {
			 := protoimpl.X.LegacyEnumName()
			if ,  := enumCache.Load(); ! {
				 := make(enumsByName)
				 := .Values()
				for  := .Len() - 1;  >= 0; -- {
					 := .Get()
					[string(.Name())] = int32(.Number())
				}
				enumCache.LoadOrStore(, )
			}
		})
		++
		return true
	})
	numFilesCache.Store(, )

	// Check cache again for enum map.
	if ,  := enumCache.Load();  {
		return .(enumsByName)
	}
	return nil
}

// walkEnums recursively walks all enums declared in d.
func ( interface {
	() protoreflect.EnumDescriptors
	() protoreflect.MessageDescriptors
},  func(protoreflect.EnumDescriptor)) {
	 := .()
	for  := .Len() - 1;  >= 0; -- {
		(.Get())
	}
	 := .()
	for  := .Len() - 1;  >= 0; -- {
		(.Get(), )
	}
}

// messageName is the full name of protobuf message.
type messageName = string

var messageTypeCache sync.Map // map[messageName]reflect.Type

// RegisterType is called from generated code to register the message Go type
// for a message of the given name.
//
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
func ( Message,  messageName) {
	 := protoimpl.X.LegacyMessageTypeOf(, protoreflect.FullName())
	if  := protoregistry.GlobalTypes.RegisterMessage();  != nil {
		panic()
	}
	messageTypeCache.Store(, reflect.TypeOf())
}

// RegisterMapType is called from generated code to register the Go map type
// for a protobuf message representing a map entry.
//
// Deprecated: Do not use.
func ( interface{},  messageName) {
	 := reflect.TypeOf()
	if .Kind() != reflect.Map {
		panic(fmt.Sprintf("invalid map kind: %v", ))
	}
	if ,  := messageTypeCache.Load();  {
		panic(fmt.Errorf("proto: duplicate proto message registered: %s", ))
	}
	messageTypeCache.Store(, )
}

// MessageType returns the message type for a named message.
// It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
func ( messageName) reflect.Type {
	if ,  := messageTypeCache.Load();  {
		return .(reflect.Type)
	}

	// Derive the message type from the v2 registry.
	var  reflect.Type
	if ,  := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName());  != nil {
		 = messageGoType()
	}

	// If we could not get a concrete type, it is possible that it is a
	// pseudo-message for a map entry.
	if  == nil {
		,  := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName())
		if ,  := .(protoreflect.MessageDescriptor);  != nil && .IsMapEntry() {
			 := goTypeForField(.Fields().ByNumber(1))
			 := goTypeForField(.Fields().ByNumber(2))
			 = reflect.MapOf(, )
		}
	}

	// Locally cache the message type for the given name.
	if  != nil {
		,  := messageTypeCache.LoadOrStore(, )
		return .(reflect.Type)
	}
	return nil
}

func ( protoreflect.FieldDescriptor) reflect.Type {
	switch  := .Kind();  {
	case protoreflect.EnumKind:
		if ,  := protoregistry.GlobalTypes.FindEnumByName(.Enum().FullName());  != nil {
			return enumGoType()
		}
		return reflect.TypeOf(protoreflect.EnumNumber(0))
	case protoreflect.MessageKind, protoreflect.GroupKind:
		if ,  := protoregistry.GlobalTypes.FindMessageByName(.Message().FullName());  != nil {
			return messageGoType()
		}
		return reflect.TypeOf((*protoreflect.Message)(nil)).Elem()
	default:
		return reflect.TypeOf(.Default().Interface())
	}
}

func ( protoreflect.EnumType) reflect.Type {
	return reflect.TypeOf(.New(0))
}

func ( protoreflect.MessageType) reflect.Type {
	return reflect.TypeOf(MessageV1(.Zero().Interface()))
}

// MessageName returns the full protobuf name for the given message type.
//
// Deprecated: Use protoreflect.MessageDescriptor.FullName instead.
func ( Message) messageName {
	if  == nil {
		return ""
	}
	if ,  := .(interface{ () messageName });  {
		return .()
	}
	return messageName(protoimpl.X.MessageDescriptorOf().FullName())
}

// RegisterExtension is called from the generated code to register
// the extension descriptor.
//
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
func ( *ExtensionDesc) {
	if  := protoregistry.GlobalTypes.RegisterExtension();  != nil {
		panic()
	}
}

type extensionsByNumber = map[int32]*ExtensionDesc

var extensionCache sync.Map // map[messageName]extensionsByNumber

// RegisteredExtensions returns a map of the registered extensions for the
// provided protobuf message, indexed by the extension field number.
//
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
func ( Message) extensionsByNumber {
	// Check whether the cache is stale. If the number of extensions for
	// the given message differs, then it means that some extensions were
	// recently registered upstream that we do not know about.
	 := MessageName()
	,  := extensionCache.Load()
	,  := .(extensionsByNumber)
	if protoregistry.GlobalTypes.NumExtensionsByMessage(protoreflect.FullName()) == len() {
		return  // cache is up-to-date
	}

	// Cache is stale, re-compute the extensions map.
	 = make(extensionsByNumber)
	protoregistry.GlobalTypes.RangeExtensionsByMessage(protoreflect.FullName(), func( protoreflect.ExtensionType) bool {
		if ,  := .(*ExtensionDesc);  {
			[int32(.TypeDescriptor().Number())] = 
		} else {
			// TODO: This implies that the protoreflect.ExtensionType is a
			// custom type not generated by protoc-gen-go. We could try and
			// convert the type to an ExtensionDesc.
		}
		return true
	})
	extensionCache.Store(, )
	return 
}