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

package v1alpha1

import (
	context "context"
)

import (
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7

// ServiceNameMappingServiceClient is the client API for ServiceNameMappingService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ServiceNameMappingServiceClient interface {
	// MappingRegister from dp to cp, data plane register snp information to
	// control plane.
	MappingRegister(ctx context.Context, in *MappingRegisterRequest, opts ...grpc.CallOption) (*MappingRegisterResponse, error)
	// MappingSync from cp to dp, control plane sync snp information to data
	// plane. Only in Kubernetes environment without zk/nacos, this rpc works. In
	// other case (exists zk/nacos), data plane search in zk/nacos.
	//
	// data plane and control plane keep a streaming link:
	// when Mapping Resource updated, control plane sync Mapping Resource to
	// data plane.
	MappingSync(ctx context.Context, opts ...grpc.CallOption) (ServiceNameMappingService_MappingSyncClient, error)
}

type serviceNameMappingServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewServiceNameMappingServiceClient(cc grpc.ClientConnInterface) ServiceNameMappingServiceClient {
	return &serviceNameMappingServiceClient{cc}
}

func (c *serviceNameMappingServiceClient) MappingRegister(ctx context.Context, in *MappingRegisterRequest, opts ...grpc.CallOption) (*MappingRegisterResponse, error) {
	out := new(MappingRegisterResponse)
	err := c.cc.Invoke(ctx, "/dubbo.mesh.v1alpha1.ServiceNameMappingService/MappingRegister", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *serviceNameMappingServiceClient) MappingSync(ctx context.Context, opts ...grpc.CallOption) (ServiceNameMappingService_MappingSyncClient, error) {
	stream, err := c.cc.NewStream(ctx, &ServiceNameMappingService_ServiceDesc.Streams[0], "/dubbo.mesh.v1alpha1.ServiceNameMappingService/MappingSync", opts...)
	if err != nil {
		return nil, err
	}
	x := &serviceNameMappingServiceMappingSyncClient{stream}
	return x, nil
}

type ServiceNameMappingService_MappingSyncClient interface {
	Send(*MappingSyncRequest) error
	Recv() (*MappingSyncResponse, error)
	grpc.ClientStream
}

type serviceNameMappingServiceMappingSyncClient struct {
	grpc.ClientStream
}

func (x *serviceNameMappingServiceMappingSyncClient) Send(m *MappingSyncRequest) error {
	return x.ClientStream.SendMsg(m)
}

func (x *serviceNameMappingServiceMappingSyncClient) Recv() (*MappingSyncResponse, error) {
	m := new(MappingSyncResponse)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// ServiceNameMappingServiceServer is the server API for ServiceNameMappingService service.
// All implementations must embed UnimplementedServiceNameMappingServiceServer
// for forward compatibility
type ServiceNameMappingServiceServer interface {
	// MappingRegister from dp to cp, data plane register snp information to
	// control plane.
	MappingRegister(context.Context, *MappingRegisterRequest) (*MappingRegisterResponse, error)
	// MappingSync from cp to dp, control plane sync snp information to data
	// plane. Only in Kubernetes environment without zk/nacos, this rpc works. In
	// other case (exists zk/nacos), data plane search in zk/nacos.
	//
	// data plane and control plane keep a streaming link:
	// when Mapping Resource updated, control plane sync Mapping Resource to
	// data plane.
	MappingSync(ServiceNameMappingService_MappingSyncServer) error
	mustEmbedUnimplementedServiceNameMappingServiceServer()
}

// UnimplementedServiceNameMappingServiceServer must be embedded to have forward compatible implementations.
type UnimplementedServiceNameMappingServiceServer struct {
}

func (UnimplementedServiceNameMappingServiceServer) MappingRegister(context.Context, *MappingRegisterRequest) (*MappingRegisterResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method MappingRegister not implemented")
}
func (UnimplementedServiceNameMappingServiceServer) MappingSync(ServiceNameMappingService_MappingSyncServer) error {
	return status.Errorf(codes.Unimplemented, "method MappingSync not implemented")
}
func (UnimplementedServiceNameMappingServiceServer) mustEmbedUnimplementedServiceNameMappingServiceServer() {
}

// UnsafeServiceNameMappingServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ServiceNameMappingServiceServer will
// result in compilation errors.
type UnsafeServiceNameMappingServiceServer interface {
	mustEmbedUnimplementedServiceNameMappingServiceServer()
}

func RegisterServiceNameMappingServiceServer(s grpc.ServiceRegistrar, srv ServiceNameMappingServiceServer) {
	s.RegisterService(&ServiceNameMappingService_ServiceDesc, srv)
}

func _ServiceNameMappingService_MappingRegister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(MappingRegisterRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ServiceNameMappingServiceServer).MappingRegister(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/dubbo.mesh.v1alpha1.ServiceNameMappingService/MappingRegister",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ServiceNameMappingServiceServer).MappingRegister(ctx, req.(*MappingRegisterRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _ServiceNameMappingService_MappingSync_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(ServiceNameMappingServiceServer).MappingSync(&serviceNameMappingServiceMappingSyncServer{stream})
}

type ServiceNameMappingService_MappingSyncServer interface {
	Send(*MappingSyncResponse) error
	Recv() (*MappingSyncRequest, error)
	grpc.ServerStream
}

type serviceNameMappingServiceMappingSyncServer struct {
	grpc.ServerStream
}

func (x *serviceNameMappingServiceMappingSyncServer) Send(m *MappingSyncResponse) error {
	return x.ServerStream.SendMsg(m)
}

func (x *serviceNameMappingServiceMappingSyncServer) Recv() (*MappingSyncRequest, error) {
	m := new(MappingSyncRequest)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// ServiceNameMappingService_ServiceDesc is the grpc.ServiceDesc for ServiceNameMappingService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ServiceNameMappingService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "dubbo.mesh.v1alpha1.ServiceNameMappingService",
	HandlerType: (*ServiceNameMappingServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "MappingRegister",
			Handler:    _ServiceNameMappingService_MappingRegister_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "MappingSync",
			Handler:       _ServiceNameMappingService_MappingSync_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "api/mesh/v1alpha1/mapping.proto",
}
