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

// DependencyServiceClient is the client API for DependencyService 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 DependencyServiceClient interface {
	// Get the build dependency graph.
	GetBuildDependencyGraph(ctx context.Context, in *GetBuildDependencyGraphRequest, opts ...grpc.CallOption) (*GetBuildDependencyGraphResponse, error)
	// Get the list of source paths that are relevant to the toolchain.
	// Added in R81.
	GetToolchainPaths(ctx context.Context, in *GetToolchainPathsRequest, opts ...grpc.CallOption) (*GetToolchainPathsResponse, error)
	// Get the list of package dependencies.  Added in R87.
	List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
}

type dependencyServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewDependencyServiceClient(cc grpc.ClientConnInterface) DependencyServiceClient {
	return &dependencyServiceClient{cc}
}

func (c *dependencyServiceClient) GetBuildDependencyGraph(ctx context.Context, in *GetBuildDependencyGraphRequest, opts ...grpc.CallOption) (*GetBuildDependencyGraphResponse, error) {
	out := new(GetBuildDependencyGraphResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.DependencyService/GetBuildDependencyGraph", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *dependencyServiceClient) GetToolchainPaths(ctx context.Context, in *GetToolchainPathsRequest, opts ...grpc.CallOption) (*GetToolchainPathsResponse, error) {
	out := new(GetToolchainPathsResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.DependencyService/GetToolchainPaths", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *dependencyServiceClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
	out := new(ListResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.DependencyService/List", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// DependencyServiceServer is the server API for DependencyService service.
// All implementations must embed UnimplementedDependencyServiceServer
// for forward compatibility
type DependencyServiceServer interface {
	// Get the build dependency graph.
	GetBuildDependencyGraph(context.Context, *GetBuildDependencyGraphRequest) (*GetBuildDependencyGraphResponse, error)
	// Get the list of source paths that are relevant to the toolchain.
	// Added in R81.
	GetToolchainPaths(context.Context, *GetToolchainPathsRequest) (*GetToolchainPathsResponse, error)
	// Get the list of package dependencies.  Added in R87.
	List(context.Context, *ListRequest) (*ListResponse, error)
	mustEmbedUnimplementedDependencyServiceServer()
}

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

func (UnimplementedDependencyServiceServer) GetBuildDependencyGraph(context.Context, *GetBuildDependencyGraphRequest) (*GetBuildDependencyGraphResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetBuildDependencyGraph not implemented")
}
func (UnimplementedDependencyServiceServer) GetToolchainPaths(context.Context, *GetToolchainPathsRequest) (*GetToolchainPathsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetToolchainPaths not implemented")
}
func (UnimplementedDependencyServiceServer) List(context.Context, *ListRequest) (*ListResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
}
func (UnimplementedDependencyServiceServer) mustEmbedUnimplementedDependencyServiceServer() {}

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

func RegisterDependencyServiceServer(s grpc.ServiceRegistrar, srv DependencyServiceServer) {
	s.RegisterService(&DependencyService_ServiceDesc, srv)
}

func _DependencyService_GetBuildDependencyGraph_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(GetBuildDependencyGraphRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(DependencyServiceServer).GetBuildDependencyGraph(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.DependencyService/GetBuildDependencyGraph",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(DependencyServiceServer).GetBuildDependencyGraph(ctx, req.(*GetBuildDependencyGraphRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _DependencyService_GetToolchainPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(GetToolchainPathsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(DependencyServiceServer).GetToolchainPaths(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.DependencyService/GetToolchainPaths",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(DependencyServiceServer).GetToolchainPaths(ctx, req.(*GetToolchainPathsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _DependencyService_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(ListRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(DependencyServiceServer).List(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.DependencyService/List",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(DependencyServiceServer).List(ctx, req.(*ListRequest))
	}
	return interceptor(ctx, in, info, handler)
}

// DependencyService_ServiceDesc is the grpc.ServiceDesc for DependencyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var DependencyService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.DependencyService",
	HandlerType: (*DependencyServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "GetBuildDependencyGraph",
			Handler:    _DependencyService_GetBuildDependencyGraph_Handler,
		},
		{
			MethodName: "GetToolchainPaths",
			Handler:    _DependencyService_GetToolchainPaths_Handler,
		},
		{
			MethodName: "List",
			Handler:    _DependencyService_List_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/depgraph.proto",
}
