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

package api

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

// BinhostServiceClient is the client API for BinhostService 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 BinhostServiceClient interface {
	// Get the binhosts for a build target.  Added in R77.
	Get(ctx context.Context, in *BinhostGetRequest, opts ...grpc.CallOption) (*BinhostGetResponse, error)
	// Get the arguments from the private overlay's ACL file.  Added in R77.
	GetPrivatePrebuiltAclArgs(ctx context.Context, in *AclArgsRequest, opts ...grpc.CallOption) (*AclArgsResponse, error)
	// Return a list of files to upload to the binhost. Importantly, this method
	// assumes that all files, once uploaded, will share the same relative path
	// on the remote disk as they do on the remote disk. E.g., package foo/bar,
	// stored locally at /mnt/bin/foo/bar, must be uploaded to <uri>/foo/bar.
	PrepareBinhostUploads(ctx context.Context, in *PrepareBinhostUploadsRequest, opts ...grpc.CallOption) (*PrepareBinhostUploadsResponse, error)
	// Return a list of dev-install files to upload to the binhost. Like
	// PrepareBinhostUploads, this method assumes that all files, once uploaded,
	// will share the same relative path on the remote disk as they do on the
	// remote disk.  Added in R78.
	PrepareDevInstallBinhostUploads(ctx context.Context, in *PrepareDevInstallBinhostUploadsRequest, opts ...grpc.CallOption) (*PrepareDevInstallBinhostUploadsResponse, error)
	// Update the binhost key for a build targets.
	SetBinhost(ctx context.Context, in *SetBinhostRequest, opts ...grpc.CallOption) (*SetBinhostResponse, error)
	// Regenerate the builder cache.  Added in R78.
	RegenBuildCache(ctx context.Context, in *RegenBuildCacheRequest, opts ...grpc.CallOption) (*RegenBuildCacheResponse, error)
}

type binhostServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewBinhostServiceClient(cc grpc.ClientConnInterface) BinhostServiceClient {
	return &binhostServiceClient{cc}
}

func (c *binhostServiceClient) Get(ctx context.Context, in *BinhostGetRequest, opts ...grpc.CallOption) (*BinhostGetResponse, error) {
	out := new(BinhostGetResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/Get", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *binhostServiceClient) GetPrivatePrebuiltAclArgs(ctx context.Context, in *AclArgsRequest, opts ...grpc.CallOption) (*AclArgsResponse, error) {
	out := new(AclArgsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/GetPrivatePrebuiltAclArgs", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *binhostServiceClient) PrepareBinhostUploads(ctx context.Context, in *PrepareBinhostUploadsRequest, opts ...grpc.CallOption) (*PrepareBinhostUploadsResponse, error) {
	out := new(PrepareBinhostUploadsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/PrepareBinhostUploads", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *binhostServiceClient) PrepareDevInstallBinhostUploads(ctx context.Context, in *PrepareDevInstallBinhostUploadsRequest, opts ...grpc.CallOption) (*PrepareDevInstallBinhostUploadsResponse, error) {
	out := new(PrepareDevInstallBinhostUploadsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/PrepareDevInstallBinhostUploads", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *binhostServiceClient) SetBinhost(ctx context.Context, in *SetBinhostRequest, opts ...grpc.CallOption) (*SetBinhostResponse, error) {
	out := new(SetBinhostResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/SetBinhost", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *binhostServiceClient) RegenBuildCache(ctx context.Context, in *RegenBuildCacheRequest, opts ...grpc.CallOption) (*RegenBuildCacheResponse, error) {
	out := new(RegenBuildCacheResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.BinhostService/RegenBuildCache", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// BinhostServiceServer is the server API for BinhostService service.
// All implementations must embed UnimplementedBinhostServiceServer
// for forward compatibility
type BinhostServiceServer interface {
	// Get the binhosts for a build target.  Added in R77.
	Get(context.Context, *BinhostGetRequest) (*BinhostGetResponse, error)
	// Get the arguments from the private overlay's ACL file.  Added in R77.
	GetPrivatePrebuiltAclArgs(context.Context, *AclArgsRequest) (*AclArgsResponse, error)
	// Return a list of files to upload to the binhost. Importantly, this method
	// assumes that all files, once uploaded, will share the same relative path
	// on the remote disk as they do on the remote disk. E.g., package foo/bar,
	// stored locally at /mnt/bin/foo/bar, must be uploaded to <uri>/foo/bar.
	PrepareBinhostUploads(context.Context, *PrepareBinhostUploadsRequest) (*PrepareBinhostUploadsResponse, error)
	// Return a list of dev-install files to upload to the binhost. Like
	// PrepareBinhostUploads, this method assumes that all files, once uploaded,
	// will share the same relative path on the remote disk as they do on the
	// remote disk.  Added in R78.
	PrepareDevInstallBinhostUploads(context.Context, *PrepareDevInstallBinhostUploadsRequest) (*PrepareDevInstallBinhostUploadsResponse, error)
	// Update the binhost key for a build targets.
	SetBinhost(context.Context, *SetBinhostRequest) (*SetBinhostResponse, error)
	// Regenerate the builder cache.  Added in R78.
	RegenBuildCache(context.Context, *RegenBuildCacheRequest) (*RegenBuildCacheResponse, error)
	mustEmbedUnimplementedBinhostServiceServer()
}

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

func (UnimplementedBinhostServiceServer) Get(context.Context, *BinhostGetRequest) (*BinhostGetResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (UnimplementedBinhostServiceServer) GetPrivatePrebuiltAclArgs(context.Context, *AclArgsRequest) (*AclArgsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetPrivatePrebuiltAclArgs not implemented")
}
func (UnimplementedBinhostServiceServer) PrepareBinhostUploads(context.Context, *PrepareBinhostUploadsRequest) (*PrepareBinhostUploadsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method PrepareBinhostUploads not implemented")
}
func (UnimplementedBinhostServiceServer) PrepareDevInstallBinhostUploads(context.Context, *PrepareDevInstallBinhostUploadsRequest) (*PrepareDevInstallBinhostUploadsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method PrepareDevInstallBinhostUploads not implemented")
}
func (UnimplementedBinhostServiceServer) SetBinhost(context.Context, *SetBinhostRequest) (*SetBinhostResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method SetBinhost not implemented")
}
func (UnimplementedBinhostServiceServer) RegenBuildCache(context.Context, *RegenBuildCacheRequest) (*RegenBuildCacheResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method RegenBuildCache not implemented")
}
func (UnimplementedBinhostServiceServer) mustEmbedUnimplementedBinhostServiceServer() {}

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

func RegisterBinhostServiceServer(s grpc.ServiceRegistrar, srv BinhostServiceServer) {
	s.RegisterService(&BinhostService_ServiceDesc, srv)
}

func _BinhostService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(BinhostGetRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).Get(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/Get",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).Get(ctx, req.(*BinhostGetRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _BinhostService_GetPrivatePrebuiltAclArgs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(AclArgsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).GetPrivatePrebuiltAclArgs(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/GetPrivatePrebuiltAclArgs",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).GetPrivatePrebuiltAclArgs(ctx, req.(*AclArgsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _BinhostService_PrepareBinhostUploads_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(PrepareBinhostUploadsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).PrepareBinhostUploads(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/PrepareBinhostUploads",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).PrepareBinhostUploads(ctx, req.(*PrepareBinhostUploadsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _BinhostService_PrepareDevInstallBinhostUploads_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(PrepareDevInstallBinhostUploadsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).PrepareDevInstallBinhostUploads(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/PrepareDevInstallBinhostUploads",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).PrepareDevInstallBinhostUploads(ctx, req.(*PrepareDevInstallBinhostUploadsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _BinhostService_SetBinhost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(SetBinhostRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).SetBinhost(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/SetBinhost",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).SetBinhost(ctx, req.(*SetBinhostRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _BinhostService_RegenBuildCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(RegenBuildCacheRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BinhostServiceServer).RegenBuildCache(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.BinhostService/RegenBuildCache",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BinhostServiceServer).RegenBuildCache(ctx, req.(*RegenBuildCacheRequest))
	}
	return interceptor(ctx, in, info, handler)
}

// BinhostService_ServiceDesc is the grpc.ServiceDesc for BinhostService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var BinhostService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.BinhostService",
	HandlerType: (*BinhostServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Get",
			Handler:    _BinhostService_Get_Handler,
		},
		{
			MethodName: "GetPrivatePrebuiltAclArgs",
			Handler:    _BinhostService_GetPrivatePrebuiltAclArgs_Handler,
		},
		{
			MethodName: "PrepareBinhostUploads",
			Handler:    _BinhostService_PrepareBinhostUploads_Handler,
		},
		{
			MethodName: "PrepareDevInstallBinhostUploads",
			Handler:    _BinhostService_PrepareDevInstallBinhostUploads_Handler,
		},
		{
			MethodName: "SetBinhost",
			Handler:    _BinhostService_SetBinhost_Handler,
		},
		{
			MethodName: "RegenBuildCache",
			Handler:    _BinhostService_RegenBuildCache_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/binhost.proto",
}
