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

package protos

import (
	context "context"

	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

// ReleaseServiceClient is the client API for ReleaseService 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 ReleaseServiceClient interface {
	// UpdateSigningStatus is a bidirectional connection where server is requesting that the client:
	// - Sign a release artifact.
	// - Provide an update on a previous request to sign a release artifact.
	// - Consider a previous request to sign a release artifact as obsolete.
	// The client initiates a connection with the server and waits for the server to issue a request
	// such as:
	// - An update on the status of a signing request (either running or completed).
	// - An acknowledgement that a request to sign a release artifact has been accepted and initiated.
	UpdateSigningStatus(ctx context.Context, opts ...grpc.CallOption) (ReleaseService_UpdateSigningStatusClient, error)
}

type releaseServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewReleaseServiceClient(cc grpc.ClientConnInterface) ReleaseServiceClient {
	return &releaseServiceClient{cc}
}

func (c *releaseServiceClient) UpdateSigningStatus(ctx context.Context, opts ...grpc.CallOption) (ReleaseService_UpdateSigningStatusClient, error) {
	stream, err := c.cc.NewStream(ctx, &ReleaseService_ServiceDesc.Streams[0], "/protos.ReleaseService/UpdateSigningStatus", opts...)
	if err != nil {
		return nil, err
	}
	x := &releaseServiceUpdateSigningStatusClient{stream}
	return x, nil
}

type ReleaseService_UpdateSigningStatusClient interface {
	Send(*SigningStatus) error
	Recv() (*SigningRequest, error)
	grpc.ClientStream
}

type releaseServiceUpdateSigningStatusClient struct {
	grpc.ClientStream
}

func (x *releaseServiceUpdateSigningStatusClient) Send(m *SigningStatus) error {
	return x.ClientStream.SendMsg(m)
}

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

// ReleaseServiceServer is the server API for ReleaseService service.
// All implementations must embed UnimplementedReleaseServiceServer
// for forward compatibility
type ReleaseServiceServer interface {
	// UpdateSigningStatus is a bidirectional connection where server is requesting that the client:
	// - Sign a release artifact.
	// - Provide an update on a previous request to sign a release artifact.
	// - Consider a previous request to sign a release artifact as obsolete.
	// The client initiates a connection with the server and waits for the server to issue a request
	// such as:
	// - An update on the status of a signing request (either running or completed).
	// - An acknowledgement that a request to sign a release artifact has been accepted and initiated.
	UpdateSigningStatus(ReleaseService_UpdateSigningStatusServer) error
	mustEmbedUnimplementedReleaseServiceServer()
}

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

func (UnimplementedReleaseServiceServer) UpdateSigningStatus(ReleaseService_UpdateSigningStatusServer) error {
	return status.Errorf(codes.Unimplemented, "method UpdateSigningStatus not implemented")
}
func (UnimplementedReleaseServiceServer) mustEmbedUnimplementedReleaseServiceServer() {}

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

func RegisterReleaseServiceServer(s grpc.ServiceRegistrar, srv ReleaseServiceServer) {
	s.RegisterService(&ReleaseService_ServiceDesc, srv)
}

func _ReleaseService_UpdateSigningStatus_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(ReleaseServiceServer).UpdateSigningStatus(&releaseServiceUpdateSigningStatusServer{stream})
}

type ReleaseService_UpdateSigningStatusServer interface {
	Send(*SigningRequest) error
	Recv() (*SigningStatus, error)
	grpc.ServerStream
}

type releaseServiceUpdateSigningStatusServer struct {
	grpc.ServerStream
}

func (x *releaseServiceUpdateSigningStatusServer) Send(m *SigningRequest) error {
	return x.ServerStream.SendMsg(m)
}

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

// ReleaseService_ServiceDesc is the grpc.ServiceDesc for ReleaseService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ReleaseService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "protos.ReleaseService",
	HandlerType: (*ReleaseServiceServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "UpdateSigningStatus",
			Handler:       _ReleaseService_UpdateSigningStatus_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "relui.proto",
}
