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

// ApiServiceClient is the client API for ApiService 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 ApiServiceClient interface {
	// Added in R90.
	CompileProto(ctx context.Context, in *CompileProtoRequest, opts ...grpc.CallOption) (*CompileProtoResponse, error)
}

type apiServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewApiServiceClient(cc grpc.ClientConnInterface) ApiServiceClient {
	return &apiServiceClient{cc}
}

func (c *apiServiceClient) CompileProto(ctx context.Context, in *CompileProtoRequest, opts ...grpc.CallOption) (*CompileProtoResponse, error) {
	out := new(CompileProtoResponse)
	err := c.cc.Invoke(ctx, "/chromite.api.ApiService/CompileProto", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// ApiServiceServer is the server API for ApiService service.
// All implementations must embed UnimplementedApiServiceServer
// for forward compatibility
type ApiServiceServer interface {
	// Added in R90.
	CompileProto(context.Context, *CompileProtoRequest) (*CompileProtoResponse, error)
	mustEmbedUnimplementedApiServiceServer()
}

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

func (UnimplementedApiServiceServer) CompileProto(context.Context, *CompileProtoRequest) (*CompileProtoResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method CompileProto not implemented")
}
func (UnimplementedApiServiceServer) mustEmbedUnimplementedApiServiceServer() {}

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

func RegisterApiServiceServer(s grpc.ServiceRegistrar, srv ApiServiceServer) {
	s.RegisterService(&ApiService_ServiceDesc, srv)
}

func _ApiService_CompileProto_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(CompileProtoRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(ApiServiceServer).CompileProto(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.ApiService/CompileProto",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(ApiServiceServer).CompileProto(ctx, req.(*CompileProtoRequest))
	}
	return interceptor(ctx, in, info, handler)
}

// ApiService_ServiceDesc is the grpc.ServiceDesc for ApiService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ApiService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.ApiService",
	HandlerType: (*ApiServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "CompileProto",
			Handler:    _ApiService_CompileProto_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/api.proto",
}

// MethodServiceClient is the client API for MethodService 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 MethodServiceClient interface {
	// Added in R77.
	Get(ctx context.Context, in *MethodGetRequest, opts ...grpc.CallOption) (*MethodGetResponse, error)
}

type methodServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewMethodServiceClient(cc grpc.ClientConnInterface) MethodServiceClient {
	return &methodServiceClient{cc}
}

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

// MethodServiceServer is the server API for MethodService service.
// All implementations must embed UnimplementedMethodServiceServer
// for forward compatibility
type MethodServiceServer interface {
	// Added in R77.
	Get(context.Context, *MethodGetRequest) (*MethodGetResponse, error)
	mustEmbedUnimplementedMethodServiceServer()
}

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

func (UnimplementedMethodServiceServer) Get(context.Context, *MethodGetRequest) (*MethodGetResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (UnimplementedMethodServiceServer) mustEmbedUnimplementedMethodServiceServer() {}

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

func RegisterMethodServiceServer(s grpc.ServiceRegistrar, srv MethodServiceServer) {
	s.RegisterService(&MethodService_ServiceDesc, srv)
}

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

// MethodService_ServiceDesc is the grpc.ServiceDesc for MethodService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var MethodService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.MethodService",
	HandlerType: (*MethodServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Get",
			Handler:    _MethodService_Get_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/api.proto",
}

// VersionServiceClient is the client API for VersionService 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 VersionServiceClient interface {
	// Added in R77.
	Get(ctx context.Context, in *VersionGetRequest, opts ...grpc.CallOption) (*VersionGetResponse, error)
}

type versionServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewVersionServiceClient(cc grpc.ClientConnInterface) VersionServiceClient {
	return &versionServiceClient{cc}
}

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

// VersionServiceServer is the server API for VersionService service.
// All implementations must embed UnimplementedVersionServiceServer
// for forward compatibility
type VersionServiceServer interface {
	// Added in R77.
	Get(context.Context, *VersionGetRequest) (*VersionGetResponse, error)
	mustEmbedUnimplementedVersionServiceServer()
}

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

func (UnimplementedVersionServiceServer) Get(context.Context, *VersionGetRequest) (*VersionGetResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (UnimplementedVersionServiceServer) mustEmbedUnimplementedVersionServiceServer() {}

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

func RegisterVersionServiceServer(s grpc.ServiceRegistrar, srv VersionServiceServer) {
	s.RegisterService(&VersionService_ServiceDesc, srv)
}

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

// VersionService_ServiceDesc is the grpc.ServiceDesc for VersionService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var VersionService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.VersionService",
	HandlerType: (*VersionServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Get",
			Handler:    _VersionService_Get_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/api.proto",
}
