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

// MeterReportServiceClient is the client API for MeterReportService 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 MeterReportServiceClient interface {
	// Meter data is reported in a certain period. The agent/SDK should report all collected metrics in this period through one stream.
	Collect(ctx context.Context, opts ...grpc.CallOption) (MeterReportService_CollectClient, error)
}

type meterReportServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewMeterReportServiceClient(cc grpc.ClientConnInterface) MeterReportServiceClient {
	return &meterReportServiceClient{cc}
}

func (c *meterReportServiceClient) Collect(ctx context.Context, opts ...grpc.CallOption) (MeterReportService_CollectClient, error) {
	stream, err := c.cc.NewStream(ctx, &MeterReportService_ServiceDesc.Streams[0], "/skywalking.v3.MeterReportService/collect", opts...)
	if err != nil {
		return nil, err
	}
	x := &meterReportServiceCollectClient{stream}
	return x, nil
}

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

type meterReportServiceCollectClient struct {
	grpc.ClientStream
}

func (x *meterReportServiceCollectClient) Send(m *MeterData) error {
	return x.ClientStream.SendMsg(m)
}

func (x *meterReportServiceCollectClient) 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
}

// MeterReportServiceServer is the server API for MeterReportService service.
// All implementations must embed UnimplementedMeterReportServiceServer
// for forward compatibility
type MeterReportServiceServer interface {
	// Meter data is reported in a certain period. The agent/SDK should report all collected metrics in this period through one stream.
	Collect(MeterReportService_CollectServer) error
	mustEmbedUnimplementedMeterReportServiceServer()
}

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

func (UnimplementedMeterReportServiceServer) Collect(MeterReportService_CollectServer) error {
	return status.Errorf(codes.Unimplemented, "method Collect not implemented")
}
func (UnimplementedMeterReportServiceServer) mustEmbedUnimplementedMeterReportServiceServer() {}

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

func RegisterMeterReportServiceServer(s grpc.ServiceRegistrar, srv MeterReportServiceServer) {
	s.RegisterService(&MeterReportService_ServiceDesc, srv)
}

func _MeterReportService_Collect_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(MeterReportServiceServer).Collect(&meterReportServiceCollectServer{stream})
}

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

type meterReportServiceCollectServer struct {
	grpc.ServerStream
}

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

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

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