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

package v1

import (
	context "context"

	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

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

// TraceClient is the client API for Trace 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 TraceClient interface {
	Query(ctx context.Context, in *EntityCriteria, opts ...grpc.CallOption) (*QueryResponse, error)
	Write(ctx context.Context, opts ...grpc.CallOption) (Trace_WriteClient, error)
}

type traceClient struct {
	cc grpc.ClientConnInterface
}

func NewTraceClient(cc grpc.ClientConnInterface) TraceClient {
	return &traceClient{cc}
}

func (c *traceClient) Query(ctx context.Context, in *EntityCriteria, opts ...grpc.CallOption) (*QueryResponse, error) {
	out := new(QueryResponse)
	err := c.cc.Invoke(ctx, "/banyandb.v1.Trace/Query", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *traceClient) Write(ctx context.Context, opts ...grpc.CallOption) (Trace_WriteClient, error) {
	stream, err := c.cc.NewStream(ctx, &Trace_ServiceDesc.Streams[0], "/banyandb.v1.Trace/Write", opts...)
	if err != nil {
		return nil, err
	}
	x := &traceWriteClient{stream}
	return x, nil
}

type Trace_WriteClient interface {
	Send(*WriteEntity) error
	Recv() (*emptypb.Empty, error)
	grpc.ClientStream
}

type traceWriteClient struct {
	grpc.ClientStream
}

func (x *traceWriteClient) Send(m *WriteEntity) error {
	return x.ClientStream.SendMsg(m)
}

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

// TraceServer is the server API for Trace service.
// All implementations must embed UnimplementedTraceServer
// for forward compatibility
type TraceServer interface {
	Query(context.Context, *EntityCriteria) (*QueryResponse, error)
	Write(Trace_WriteServer) error
	mustEmbedUnimplementedTraceServer()
}

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

func (UnimplementedTraceServer) Query(context.Context, *EntityCriteria) (*QueryResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Query not implemented")
}
func (UnimplementedTraceServer) Write(Trace_WriteServer) error {
	return status.Errorf(codes.Unimplemented, "method Write not implemented")
}
func (UnimplementedTraceServer) mustEmbedUnimplementedTraceServer() {}

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

func RegisterTraceServer(s grpc.ServiceRegistrar, srv TraceServer) {
	s.RegisterService(&Trace_ServiceDesc, srv)
}

func _Trace_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(EntityCriteria)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(TraceServer).Query(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/banyandb.v1.Trace/Query",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(TraceServer).Query(ctx, req.(*EntityCriteria))
	}
	return interceptor(ctx, in, info, handler)
}

func _Trace_Write_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(TraceServer).Write(&traceWriteServer{stream})
}

type Trace_WriteServer interface {
	Send(*emptypb.Empty) error
	Recv() (*WriteEntity, error)
	grpc.ServerStream
}

type traceWriteServer struct {
	grpc.ServerStream
}

func (x *traceWriteServer) Send(m *emptypb.Empty) error {
	return x.ServerStream.SendMsg(m)
}

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

// Trace_ServiceDesc is the grpc.ServiceDesc for Trace service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Trace_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "banyandb.v1.Trace",
	HandlerType: (*TraceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Query",
			Handler:    _Trace_Query_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "Write",
			Handler:       _Trace_Write_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "banyandb/v1/rpc.proto",
}
