// 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.apache.org/repo/goapi/collect/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

// BrowserPerfServiceClient is the client API for BrowserPerfService 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 BrowserPerfServiceClient interface {
	// report once per page
	CollectPerfData(ctx context.Context, in *BrowserPerfData, opts ...grpc.CallOption) (*v3.Commands, error)
	// report one or more error logs for pages, could report multiple times.
	CollectErrorLogs(ctx context.Context, opts ...grpc.CallOption) (BrowserPerfService_CollectErrorLogsClient, error)
}

type browserPerfServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewBrowserPerfServiceClient(cc grpc.ClientConnInterface) BrowserPerfServiceClient {
	return &browserPerfServiceClient{cc}
}

func (c *browserPerfServiceClient) CollectPerfData(ctx context.Context, in *BrowserPerfData, opts ...grpc.CallOption) (*v3.Commands, error) {
	out := new(v3.Commands)
	err := c.cc.Invoke(ctx, "/skywalking.v3.BrowserPerfService/collectPerfData", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *browserPerfServiceClient) CollectErrorLogs(ctx context.Context, opts ...grpc.CallOption) (BrowserPerfService_CollectErrorLogsClient, error) {
	stream, err := c.cc.NewStream(ctx, &BrowserPerfService_ServiceDesc.Streams[0], "/skywalking.v3.BrowserPerfService/collectErrorLogs", opts...)
	if err != nil {
		return nil, err
	}
	x := &browserPerfServiceCollectErrorLogsClient{stream}
	return x, nil
}

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

type browserPerfServiceCollectErrorLogsClient struct {
	grpc.ClientStream
}

func (x *browserPerfServiceCollectErrorLogsClient) Send(m *BrowserErrorLog) error {
	return x.ClientStream.SendMsg(m)
}

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

// BrowserPerfServiceServer is the server API for BrowserPerfService service.
// All implementations must embed UnimplementedBrowserPerfServiceServer
// for forward compatibility
type BrowserPerfServiceServer interface {
	// report once per page
	CollectPerfData(context.Context, *BrowserPerfData) (*v3.Commands, error)
	// report one or more error logs for pages, could report multiple times.
	CollectErrorLogs(BrowserPerfService_CollectErrorLogsServer) error
	mustEmbedUnimplementedBrowserPerfServiceServer()
}

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

func (UnimplementedBrowserPerfServiceServer) CollectPerfData(context.Context, *BrowserPerfData) (*v3.Commands, error) {
	return nil, status.Errorf(codes.Unimplemented, "method CollectPerfData not implemented")
}
func (UnimplementedBrowserPerfServiceServer) CollectErrorLogs(BrowserPerfService_CollectErrorLogsServer) error {
	return status.Errorf(codes.Unimplemented, "method CollectErrorLogs not implemented")
}
func (UnimplementedBrowserPerfServiceServer) mustEmbedUnimplementedBrowserPerfServiceServer() {}

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

func RegisterBrowserPerfServiceServer(s grpc.ServiceRegistrar, srv BrowserPerfServiceServer) {
	s.RegisterService(&BrowserPerfService_ServiceDesc, srv)
}

func _BrowserPerfService_CollectPerfData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(BrowserPerfData)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BrowserPerfServiceServer).CollectPerfData(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/skywalking.v3.BrowserPerfService/collectPerfData",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BrowserPerfServiceServer).CollectPerfData(ctx, req.(*BrowserPerfData))
	}
	return interceptor(ctx, in, info, handler)
}

func _BrowserPerfService_CollectErrorLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(BrowserPerfServiceServer).CollectErrorLogs(&browserPerfServiceCollectErrorLogsServer{stream})
}

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

type browserPerfServiceCollectErrorLogsServer struct {
	grpc.ServerStream
}

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

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

// BrowserPerfService_ServiceDesc is the grpc.ServiceDesc for BrowserPerfService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var BrowserPerfService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "skywalking.v3.BrowserPerfService",
	HandlerType: (*BrowserPerfServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "collectPerfData",
			Handler:    _BrowserPerfService_CollectPerfData_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "collectErrorLogs",
			Handler:       _BrowserPerfService_CollectErrorLogs_Handler,
			ClientStreams: true,
		},
	},
	Metadata: "browser/BrowserPerf.proto",
}
