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

// ToolchainServiceClient is the client API for ToolchainService 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 ToolchainServiceClient interface {
	// DEPRECATED for recipes: used only by legacy toolchain builders.
	// See also crbug/1019868.  R87 is the last release branch that supports the
	// legacy toolchain builders.
	// Update Chrome ebuild with most recent unvetted orderfile.  Added in R78.
	UpdateEbuildWithAFDOArtifacts(ctx context.Context, in *VerifyAFDOArtifactsRequest, opts ...grpc.CallOption) (*VerifyAFDOArtifactsResponse, error)
	// DEPRECATED for recipes: used only by legacy toolchain builders.
	// See also crbug/1019868.  R87 is the last release branch that supports the
	// legacy toolchain builders.
	// Copy the orderfile from unvetted GS bucket to vetted bucket.  Added in R78.
	UploadVettedAFDOArtifacts(ctx context.Context, in *VerifyAFDOArtifactsRequest, opts ...grpc.CallOption) (*VerifyAFDOArtifactsResponse, error)
	// TODO(crbug/1034529): Migrate this to ArtifactsService/BuildSetup.
	// Prepare to build toolchain artifacts.  This will be called twice:
	// Once with chroot and sysroot = None, before the chroot is created, and
	// again at the start of the 'install packages' step, if the build gets that
	// far.  Added in R80.
	PrepareForBuild(ctx context.Context, in *PrepareForToolchainBuildRequest, opts ...grpc.CallOption) (*PrepareForToolchainBuildResponse, error)
	// TODO(crbug/1034529): Migrate this to ArtifactsService/Get.
	// Bundle toolchain artifacts.  Added in R80.
	BundleArtifacts(ctx context.Context, in *BundleToolchainRequest, opts ...grpc.CallOption) (*BundleToolchainResponse, error)
	// Added in R90.
	GetUpdatedFiles(ctx context.Context, in *GetUpdatedFilesRequest, opts ...grpc.CallOption) (*GetUpdatedFilesResponse, error)
}

type toolchainServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewToolchainServiceClient(cc grpc.ClientConnInterface) ToolchainServiceClient {
	return &toolchainServiceClient{cc}
}

func (c *toolchainServiceClient) UpdateEbuildWithAFDOArtifacts(ctx context.Context, in *VerifyAFDOArtifactsRequest, opts ...grpc.CallOption) (*VerifyAFDOArtifactsResponse, error) {
	out := new(VerifyAFDOArtifactsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ToolchainService/UpdateEbuildWithAFDOArtifacts", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *toolchainServiceClient) UploadVettedAFDOArtifacts(ctx context.Context, in *VerifyAFDOArtifactsRequest, opts ...grpc.CallOption) (*VerifyAFDOArtifactsResponse, error) {
	out := new(VerifyAFDOArtifactsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ToolchainService/UploadVettedAFDOArtifacts", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *toolchainServiceClient) PrepareForBuild(ctx context.Context, in *PrepareForToolchainBuildRequest, opts ...grpc.CallOption) (*PrepareForToolchainBuildResponse, error) {
	out := new(PrepareForToolchainBuildResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ToolchainService/PrepareForBuild", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *toolchainServiceClient) BundleArtifacts(ctx context.Context, in *BundleToolchainRequest, opts ...grpc.CallOption) (*BundleToolchainResponse, error) {
	out := new(BundleToolchainResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ToolchainService/BundleArtifacts", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *toolchainServiceClient) GetUpdatedFiles(ctx context.Context, in *GetUpdatedFilesRequest, opts ...grpc.CallOption) (*GetUpdatedFilesResponse, error) {
	out := new(GetUpdatedFilesResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ToolchainService/GetUpdatedFiles", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// ToolchainServiceServer is the server API for ToolchainService service.
// All implementations must embed UnimplementedToolchainServiceServer
// for forward compatibility
type ToolchainServiceServer interface {
	// DEPRECATED for recipes: used only by legacy toolchain builders.
	// See also crbug/1019868.  R87 is the last release branch that supports the
	// legacy toolchain builders.
	// Update Chrome ebuild with most recent unvetted orderfile.  Added in R78.
	UpdateEbuildWithAFDOArtifacts(context.Context, *VerifyAFDOArtifactsRequest) (*VerifyAFDOArtifactsResponse, error)
	// DEPRECATED for recipes: used only by legacy toolchain builders.
	// See also crbug/1019868.  R87 is the last release branch that supports the
	// legacy toolchain builders.
	// Copy the orderfile from unvetted GS bucket to vetted bucket.  Added in R78.
	UploadVettedAFDOArtifacts(context.Context, *VerifyAFDOArtifactsRequest) (*VerifyAFDOArtifactsResponse, error)
	// TODO(crbug/1034529): Migrate this to ArtifactsService/BuildSetup.
	// Prepare to build toolchain artifacts.  This will be called twice:
	// Once with chroot and sysroot = None, before the chroot is created, and
	// again at the start of the 'install packages' step, if the build gets that
	// far.  Added in R80.
	PrepareForBuild(context.Context, *PrepareForToolchainBuildRequest) (*PrepareForToolchainBuildResponse, error)
	// TODO(crbug/1034529): Migrate this to ArtifactsService/Get.
	// Bundle toolchain artifacts.  Added in R80.
	BundleArtifacts(context.Context, *BundleToolchainRequest) (*BundleToolchainResponse, error)
	// Added in R90.
	GetUpdatedFiles(context.Context, *GetUpdatedFilesRequest) (*GetUpdatedFilesResponse, error)
	mustEmbedUnimplementedToolchainServiceServer()
}

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

func (UnimplementedToolchainServiceServer) UpdateEbuildWithAFDOArtifacts(context.Context, *VerifyAFDOArtifactsRequest) (*VerifyAFDOArtifactsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method UpdateEbuildWithAFDOArtifacts not implemented")
}
func (UnimplementedToolchainServiceServer) UploadVettedAFDOArtifacts(context.Context, *VerifyAFDOArtifactsRequest) (*VerifyAFDOArtifactsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method UploadVettedAFDOArtifacts not implemented")
}
func (UnimplementedToolchainServiceServer) PrepareForBuild(context.Context, *PrepareForToolchainBuildRequest) (*PrepareForToolchainBuildResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method PrepareForBuild not implemented")
}
func (UnimplementedToolchainServiceServer) BundleArtifacts(context.Context, *BundleToolchainRequest) (*BundleToolchainResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method BundleArtifacts not implemented")
}
func (UnimplementedToolchainServiceServer) GetUpdatedFiles(context.Context, *GetUpdatedFilesRequest) (*GetUpdatedFilesResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetUpdatedFiles not implemented")
}
func (UnimplementedToolchainServiceServer) mustEmbedUnimplementedToolchainServiceServer() {}

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

func RegisterToolchainServiceServer(s grpc.ServiceRegistrar, srv ToolchainServiceServer) {
	s.RegisterService(&ToolchainService_ServiceDesc, srv)
}

func _ToolchainService_UpdateEbuildWithAFDOArtifacts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(VerifyAFDOArtifactsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ToolchainServiceServer).UpdateEbuildWithAFDOArtifacts(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ToolchainService/UpdateEbuildWithAFDOArtifacts",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ToolchainServiceServer).UpdateEbuildWithAFDOArtifacts(ctx, req.(*VerifyAFDOArtifactsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _ToolchainService_UploadVettedAFDOArtifacts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(VerifyAFDOArtifactsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ToolchainServiceServer).UploadVettedAFDOArtifacts(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ToolchainService/UploadVettedAFDOArtifacts",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ToolchainServiceServer).UploadVettedAFDOArtifacts(ctx, req.(*VerifyAFDOArtifactsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _ToolchainService_PrepareForBuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(PrepareForToolchainBuildRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ToolchainServiceServer).PrepareForBuild(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ToolchainService/PrepareForBuild",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ToolchainServiceServer).PrepareForBuild(ctx, req.(*PrepareForToolchainBuildRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _ToolchainService_BundleArtifacts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(BundleToolchainRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ToolchainServiceServer).BundleArtifacts(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ToolchainService/BundleArtifacts",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ToolchainServiceServer).BundleArtifacts(ctx, req.(*BundleToolchainRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _ToolchainService_GetUpdatedFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(GetUpdatedFilesRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ToolchainServiceServer).GetUpdatedFiles(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ToolchainService/GetUpdatedFiles",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ToolchainServiceServer).GetUpdatedFiles(ctx, req.(*GetUpdatedFilesRequest))
	}
	return interceptor(ctx, in, info, handler)
}

// ToolchainService_ServiceDesc is the grpc.ServiceDesc for ToolchainService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ToolchainService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.ToolchainService",
	HandlerType: (*ToolchainServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "UpdateEbuildWithAFDOArtifacts",
			Handler:    _ToolchainService_UpdateEbuildWithAFDOArtifacts_Handler,
		},
		{
			MethodName: "UploadVettedAFDOArtifacts",
			Handler:    _ToolchainService_UploadVettedAFDOArtifacts_Handler,
		},
		{
			MethodName: "PrepareForBuild",
			Handler:    _ToolchainService_PrepareForBuild_Handler,
		},
		{
			MethodName: "BundleArtifacts",
			Handler:    _ToolchainService_BundleArtifacts_Handler,
		},
		{
			MethodName: "GetUpdatedFiles",
			Handler:    _ToolchainService_GetUpdatedFiles_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/toolchain.proto",
}
