// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpc/grpc.proto

package grpc

import (
	proto "github.com/golang/protobuf/proto"
	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
	prototype "github.com/golang/protobuf/v2/reflect/prototype"
	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

type Request struct {
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

type xxx_Request struct{ m *Request }

func (m *Request) ProtoReflect() protoreflect.Message {
	return xxx_Request{m}
}
func (m xxx_Request) Type() protoreflect.MessageType {
	return xxx_Grpc_ProtoFile_MessageTypes[0].Type
}
func (m xxx_Request) KnownFields() protoreflect.KnownFields {
	return xxx_Grpc_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
}
func (m xxx_Request) UnknownFields() protoreflect.UnknownFields {
	return xxx_Grpc_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
}
func (m xxx_Request) Interface() protoreflect.ProtoMessage {
	return m.m
}

func (m *Request) Reset()         { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage()    {}
func (*Request) Descriptor() ([]byte, []int) {
	return fileDescriptor_81ea47a3f88c2082, []int{0}
}

func (m *Request) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Request.Unmarshal(m, b)
}
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Request.Marshal(b, m, deterministic)
}
func (m *Request) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Request.Merge(m, src)
}
func (m *Request) XXX_Size() int {
	return xxx_messageInfo_Request.Size(m)
}
func (m *Request) XXX_DiscardUnknown() {
	xxx_messageInfo_Request.DiscardUnknown(m)
}

var xxx_messageInfo_Request proto.InternalMessageInfo

type Response struct {
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

type xxx_Response struct{ m *Response }

func (m *Response) ProtoReflect() protoreflect.Message {
	return xxx_Response{m}
}
func (m xxx_Response) Type() protoreflect.MessageType {
	return xxx_Grpc_ProtoFile_MessageTypes[1].Type
}
func (m xxx_Response) KnownFields() protoreflect.KnownFields {
	return xxx_Grpc_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
}
func (m xxx_Response) UnknownFields() protoreflect.UnknownFields {
	return xxx_Grpc_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
}
func (m xxx_Response) Interface() protoreflect.ProtoMessage {
	return m.m
}

func (m *Response) Reset()         { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage()    {}
func (*Response) Descriptor() ([]byte, []int) {
	return fileDescriptor_81ea47a3f88c2082, []int{1}
}

func (m *Response) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
	xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
	return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
	xxx_messageInfo_Response.DiscardUnknown(m)
}

var xxx_messageInfo_Response proto.InternalMessageInfo

func init() {
	proto.RegisterFile("grpc/grpc.proto", fileDescriptor_81ea47a3f88c2082)
	proto.RegisterType((*Request)(nil), "goproto.protoc.grpc.Request")
	proto.RegisterType((*Response)(nil), "goproto.protoc.grpc.Response")
}

var fileDescriptor_81ea47a3f88c2082 = []byte{
	// 218 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0xd1, 0x3d, 0x4b, 0x04, 0x31,
	0x10, 0x06, 0x60, 0xd6, 0x42, 0xbd, 0x41, 0x39, 0x88, 0x9d, 0x68, 0x73, 0x95, 0xcd, 0x25, 0xc7,
	0x59, 0x8b, 0x60, 0x27, 0x88, 0xc8, 0x96, 0x36, 0x4b, 0x3e, 0xc6, 0x18, 0xd8, 0xcd, 0xc4, 0x7c,
	0xac, 0xf8, 0x13, 0xfd, 0x57, 0xb2, 0x59, 0x4b, 0xad, 0x6e, 0x9b, 0x90, 0x97, 0x77, 0x78, 0x8a,
	0x19, 0x58, 0xdb, 0x18, 0xb4, 0x98, 0x1e, 0x1e, 0x22, 0x65, 0x62, 0x17, 0x96, 0xea, 0x67, 0x8e,
	0x9a, 0x4f, 0xd5, 0x66, 0x05, 0x27, 0x2d, 0x7e, 0x14, 0x4c, 0x79, 0x03, 0x70, 0xda, 0x62, 0x0a,
	0xe4, 0x13, 0xee, 0xbf, 0x8f, 0xe0, 0x2c, 0x63, 0xca, 0x5d, 0xc2, 0x38, 0x3a, 0x8d, 0xec, 0x11,
	0xa0, 0x78, 0x19, 0xbf, 0x3a, 0x2d, 0xfb, 0x9e, 0x5d, 0xf1, 0x3f, 0x2c, 0xfe, 0x0b, 0x5d, 0x5e,
	0xff, 0xd3, 0xce, 0x36, 0x7b, 0x81, 0xb5, 0xa1, 0x4f, 0x9f, 0x72, 0x44, 0x39, 0x1c, 0xee, 0xed,
	0x1a, 0xf6, 0x0c, 0xe7, 0x25, 0x2c, 0xe5, 0xdd, 0x34, 0xec, 0x09, 0x56, 0xca, 0x19, 0xb7, 0x84,
	0xb5, 0x6b, 0x1e, 0xee, 0x5f, 0xef, 0xac, 0xcb, 0xef, 0x45, 0x71, 0x4d, 0x83, 0xb0, 0xd4, 0x4b,
	0x6f, 0x45, 0x9d, 0x56, 0xe5, 0x4d, 0x8c, 0x7b, 0xa1, 0x07, 0x33, 0x67, 0xbd, 0xb5, 0xe8, 0xb7,
	0x96, 0xc4, 0xb4, 0x7a, 0x23, 0xb3, 0xac, 0xe7, 0x53, 0xc7, 0xb5, 0xbc, 0xfd, 0x09, 0x00, 0x00,
	0xff, 0xff, 0x74, 0x8e, 0x77, 0x1d, 0xd2, 0x01, 0x00, 0x00,
}

func init() {
	xxx_Grpc_ProtoFile_FileDesc.Messages = xxx_Grpc_ProtoFile_MessageDescs[0:2]
	var err error
	Grpc_ProtoFile, err = prototype.NewFile(&xxx_Grpc_ProtoFile_FileDesc)
	if err != nil {
		panic(err)
	}
}

const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)

var Grpc_ProtoFile protoreflect.FileDescriptor

var xxx_Grpc_ProtoFile_FileDesc = prototype.File{
	Syntax:  protoreflect.Proto3,
	Path:    "grpc/grpc.proto",
	Package: "goproto.protoc.grpc",
}
var xxx_Grpc_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
	{Type: prototype.GoMessage(
		xxx_Grpc_ProtoFile_MessageDescs[0].Reference(),
		func(protoreflect.MessageType) protoreflect.Message {
			return xxx_Request{new(Request)}
		},
	)},
	{Type: prototype.GoMessage(
		xxx_Grpc_ProtoFile_MessageDescs[1].Reference(),
		func(protoreflect.MessageType) protoreflect.Message {
			return xxx_Response{new(Response)}
		},
	)},
}
var xxx_Grpc_ProtoFile_MessageDescs = [2]prototype.Message{
	{
		Name: "Request",
	},
	{
		Name: "Response",
	},
}
