func (m *MethodDescriptor) GetName() string {
	return m.MethodDescriptor.GetName()
}
GetName returns the name of the method.
package reflection
import (
	"fmt"
	"github.com/fullstorydev/grpcurl"
	"github.com/golang/protobuf/proto"
	"github.com/jhump/protoreflect/desc"
	"github.com/jhump/protoreflect/dynamic"
	"github.com/pkg/errors"
	perrors "github.com/gdong42/grpc-mate/errors"
)
type MethodInvocation struct {
	*MethodDescriptor
	Message
}
type Reflector interface {
	CreateInvocation(serviceName, methodName string, input []byte) (*MethodInvocation, error)
	ListServices() ([]string, error)
	DescribeService(serviceName string) ([]*MethodDescriptor, error)
}
func NewReflector(rc grpcreflectClient) Reflector {
	return &reflectorImpl{
		rc: newReflectionClient(rc),
	}
}
type reflectorImpl struct {
	rc *reflectionClient
}
func (r *reflectorImpl) CreateInvocation(serviceName,
	methodName string,
	input []byte,
) (*MethodInvocation, error) {
	serviceDesc, err := r.rc.resolveService(serviceName)
	if err != nil {
		return nil, errors.Wrap(err, "service was not found upstream even though it should have been there")
	}
	methodDesc, err := serviceDesc.FindMethodByName(methodName)
	if err != nil {
		return nil, errors.Wrap(err, "method not found upstream")
	}
	inputMessage := methodDesc.GetInputType().NewMessage()
	err = inputMessage.UnmarshalJSON(input)
	if err != nil {
		return nil, err
	}
	return &MethodInvocation{
		MethodDescriptor: methodDesc,
		Message:          inputMessage,
	}, nil
}
func (r *reflectorImpl) ListServices() ([]string, error) {
	return r.rc.listServices()
}
func (r *reflectorImpl) DescribeService(serviceName string) ([]*MethodDescriptor, error) {
	serviceDesc, err := r.rc.resolveService(serviceName)
	if err != nil {
		return nil, errors.Wrap(err, "service was not found upstream even though it should have been there")
	}
	methodDescs, err := serviceDesc.GetMethods()
	if err != nil {
		return nil, errors.Wrap(err, "cannot get methods from service "+serviceName)
	}
	return methodDescs, nil
}
type reflectionClient struct {
	grpcreflectClient
}
type grpcreflectClient interface {
	ResolveService(serviceName string) (*desc.ServiceDescriptor, error)
	ListServices() ([]string, error)
}
func newReflectionClient(rc grpcreflectClient) *reflectionClient {
	return &reflectionClient{
		grpcreflectClient: rc,
	}
}
func (c *reflectionClient) resolveService(serviceName string) (*ServiceDescriptor, error) {
	d, err := c.grpcreflectClient.ResolveService(serviceName)
	if err != nil {
		return nil, &perrors.ProxyError{
			Code:    perrors.ServiceNotFound,
			Message: fmt.Sprintf("service %s was not found upstream", serviceName),
		}
	}
	return &ServiceDescriptor{
		ServiceDescriptor: d,
	}, nil
}
func (c *reflectionClient) listServices() ([]string, error) {
	d, err := c.grpcreflectClient.ListServices()
	if err != nil {
		return nil, &perrors.ProxyError{
			Code:    perrors.ServiceNotFound,
			Message: fmt.Sprintf("listing service failed: %v", err),
		}
	}
	return d, nil
}
type ServiceDescriptor struct {
	*desc.ServiceDescriptor
}
func ServiceDescriptorFromFileDescriptor(fd *desc.FileDescriptor, service string) *ServiceDescriptor {
	d := fd.FindService(service)
	if d == nil {
		return nil
	}
	return &ServiceDescriptor{
		ServiceDescriptor: d,
	}
}
func (s *ServiceDescriptor) GetMethods() ([]*MethodDescriptor, error) {
	methods := s.ServiceDescriptor.GetMethods()
	ret := make([]*MethodDescriptor, len(methods))
	for i, m := range methods {
		ret[i] = &MethodDescriptor{
			MethodDescriptor: m,
		}
	}
	return ret, nil
}
func (s *ServiceDescriptor) FindMethodByName(name string) (*MethodDescriptor, error) {
	d := s.ServiceDescriptor.FindMethodByName(name)
	if d == nil {
		return nil, &perrors.ProxyError{
			Code:    perrors.MethodNotFound,
			Message: fmt.Sprintf("the method %s was not found", name),
		}
	}
	return &MethodDescriptor{
		MethodDescriptor: d,
	}, nil
}
type MethodDescriptor struct {
	*desc.MethodDescriptor
}
func (m *MethodDescriptor) GetInputType() *MessageDescriptor {
	return &MessageDescriptor{
		desc: m.MethodDescriptor.GetInputType(),
	}
}
func (m *MethodDescriptor) GetOutputType() *MessageDescriptor {
	return &MessageDescriptor{
		desc: m.MethodDescriptor.GetOutputType(),
	}
}
func (m *MethodDescriptor) AsProtoreflectDescriptor() *desc.MethodDescriptor {
	return m.MethodDescriptor
}