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

package v3

import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	v3 "skywalking/network/common/v3"
)

// 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

// LogReportServiceClient is the client API for LogReportService 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 LogReportServiceClient interface {
	// Recommend to report log data in a stream mode.
	// The service/instance/endpoint of the log could share the previous value if they are not set.
	// Reporting the logs of same service in the batch mode could reduce the network cost.
	Collect(ctx context.Context, opts ...grpc.CallOption) (LogReportService_CollectClient, error)
}

type logReportServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewLogReportServiceClient(cc grpc.ClientConnInterface) LogReportServiceClient {
	return &logReportServiceClient{cc}
}

func (c *logReportServiceClient) Collect(ctx context.Context, opts ...grpc.CallOption) (LogReportService_CollectClient, error) {
	stream, err := c.cc.NewStream(ctx, &LogReportService_ServiceDesc.Streams[0], "/skywalking.v3.LogReportService/collect", opts...)
	if err != nil {
		return nil, err
	}
	x := &logReportServiceCollectClient{stream}
	return x, nil
}

type LogReportService_CollectClient interface {
	Send(*LogData) error
	CloseAndRecv() (*v3.Commands, error)
	grpc.ClientStream
}

type logReportServiceCollectClient struct {
	grpc.ClientStream
}

func (x *logReportServiceCollectClient) Send(m *LogData) error {
	return x.ClientStream.SendMsg(m)
}

func (x *logReportServiceCollectClient) CloseAndRecv() (*v3.Commands, error) {
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	m := new(v3.Commands)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// LogReportServiceServer is the server API for LogReportService service.
// All implementations must embed UnimplementedLogReportServiceServer
// for forward compatibility
type LogReportServiceServer interface {
	// Recommend to report log data in a stream mode.
	// The service/instance/endpoint of the log could share the previous value if they are not set.
	// Reporting the logs of same service in the batch mode could reduce the network cost.
	Collect(LogReportService_CollectServer) error
	mustEmbedUnimplementedLogReportServiceServer()
}

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

func (UnimplementedLogReportServiceServer) Collect(LogReportService_CollectServer) error {
	return status.Errorf(codes.Unimplemented, "method Collect not implemented")
}
func (UnimplementedLogReportServiceServer) mustEmbedUnimplementedLogReportServiceServer() {}

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

func RegisterLogReportServiceServer(s grpc.ServiceRegistrar, srv LogReportServiceServer) {
	s.RegisterService(&LogReportService_ServiceDesc, srv)
}

func _LogReportService_Collect_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(LogReportServiceServer).Collect(&logReportServiceCollectServer{stream})
}

type LogReportService_CollectServer interface {
	SendAndClose(*v3.Commands) error
	Recv() (*LogData, error)
	grpc.ServerStream
}

type logReportServiceCollectServer struct {
	grpc.ServerStream
}

func (x *logReportServiceCollectServer) SendAndClose(m *v3.Commands) error {
	return x.ServerStream.SendMsg(m)
}

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

// LogReportService_ServiceDesc is the grpc.ServiceDesc for LogReportService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var LogReportService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "skywalking.v3.LogReportService",
	HandlerType: (*LogReportServiceServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "collect",
			Handler:       _LogReportService_Collect_Handler,
			ClientStreams: true,
		},
	},
	Metadata: "logging/Logging.proto",
}
