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

// TestApiServiceClient is the client API for TestApiService 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 TestApiServiceClient interface {
	// Method that has input and output messages.
	InputOutputMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
	// Method name override.
	RenamedMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
	HiddenMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
}

type testApiServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewTestApiServiceClient(cc grpc.ClientConnInterface) TestApiServiceClient {
	return &testApiServiceClient{cc}
}

func (c *testApiServiceClient) InputOutputMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.TestApiService/InputOutputMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *testApiServiceClient) RenamedMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.TestApiService/RenamedMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *testApiServiceClient) HiddenMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.TestApiService/HiddenMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// TestApiServiceServer is the server API for TestApiService service.
// All implementations must embed UnimplementedTestApiServiceServer
// for forward compatibility
type TestApiServiceServer interface {
	// Method that has input and output messages.
	InputOutputMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	// Method name override.
	RenamedMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	HiddenMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	mustEmbedUnimplementedTestApiServiceServer()
}

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

func (UnimplementedTestApiServiceServer) InputOutputMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method InputOutputMethod not implemented")
}
func (UnimplementedTestApiServiceServer) RenamedMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method RenamedMethod not implemented")
}
func (UnimplementedTestApiServiceServer) HiddenMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method HiddenMethod not implemented")
}
func (UnimplementedTestApiServiceServer) mustEmbedUnimplementedTestApiServiceServer() {}

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

func RegisterTestApiServiceServer(s grpc.ServiceRegistrar, srv TestApiServiceServer) {
	s.RegisterService(&TestApiService_ServiceDesc, srv)
}

func _TestApiService_InputOutputMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(TestApiServiceServer).InputOutputMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.TestApiService/InputOutputMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(TestApiServiceServer).InputOutputMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

func _TestApiService_RenamedMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(TestApiServiceServer).RenamedMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.TestApiService/RenamedMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(TestApiServiceServer).RenamedMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

func _TestApiService_HiddenMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(TestApiServiceServer).HiddenMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.TestApiService/HiddenMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(TestApiServiceServer).HiddenMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

// TestApiService_ServiceDesc is the grpc.ServiceDesc for TestApiService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TestApiService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "chromite.api.TestApiService",
	HandlerType: (*TestApiServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "InputOutputMethod",
			Handler:    _TestApiService_InputOutputMethod_Handler,
		},
		{
			MethodName: "RenamedMethod",
			Handler:    _TestApiService_RenamedMethod_Handler,
		},
		{
			MethodName: "HiddenMethod",
			Handler:    _TestApiService_HiddenMethod_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "chromite/api/build_api_test.proto",
}

// InsideChrootApiServiceClient is the client API for InsideChrootApiService 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 InsideChrootApiServiceClient interface {
	// No override of service level inside assertion.
	InsideServiceInsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
	// Override service level inside assertion with outside assertion.
	InsideServiceOutsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
}

type insideChrootApiServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewInsideChrootApiServiceClient(cc grpc.ClientConnInterface) InsideChrootApiServiceClient {
	return &insideChrootApiServiceClient{cc}
}

func (c *insideChrootApiServiceClient) InsideServiceInsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.InsideChrootApiService/InsideServiceInsideMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *insideChrootApiServiceClient) InsideServiceOutsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.InsideChrootApiService/InsideServiceOutsideMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// InsideChrootApiServiceServer is the server API for InsideChrootApiService service.
// All implementations must embed UnimplementedInsideChrootApiServiceServer
// for forward compatibility
type InsideChrootApiServiceServer interface {
	// No override of service level inside assertion.
	InsideServiceInsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	// Override service level inside assertion with outside assertion.
	InsideServiceOutsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	mustEmbedUnimplementedInsideChrootApiServiceServer()
}

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

func (UnimplementedInsideChrootApiServiceServer) InsideServiceInsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method InsideServiceInsideMethod not implemented")
}
func (UnimplementedInsideChrootApiServiceServer) InsideServiceOutsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method InsideServiceOutsideMethod not implemented")
}
func (UnimplementedInsideChrootApiServiceServer) mustEmbedUnimplementedInsideChrootApiServiceServer() {
}

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

func RegisterInsideChrootApiServiceServer(s grpc.ServiceRegistrar, srv InsideChrootApiServiceServer) {
	s.RegisterService(&InsideChrootApiService_ServiceDesc, srv)
}

func _InsideChrootApiService_InsideServiceInsideMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(InsideChrootApiServiceServer).InsideServiceInsideMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.InsideChrootApiService/InsideServiceInsideMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(InsideChrootApiServiceServer).InsideServiceInsideMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

func _InsideChrootApiService_InsideServiceOutsideMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(InsideChrootApiServiceServer).InsideServiceOutsideMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.InsideChrootApiService/InsideServiceOutsideMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(InsideChrootApiServiceServer).InsideServiceOutsideMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

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

// OutsideChrootApiServiceClient is the client API for OutsideChrootApiService 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 OutsideChrootApiServiceClient interface {
	// No override of service level outside assertion.
	OutsideServiceOutsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
	// Override service level outside assertion with inside assertion.
	OutsideServiceInsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
}

type outsideChrootApiServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewOutsideChrootApiServiceClient(cc grpc.ClientConnInterface) OutsideChrootApiServiceClient {
	return &outsideChrootApiServiceClient{cc}
}

func (c *outsideChrootApiServiceClient) OutsideServiceOutsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.OutsideChrootApiService/OutsideServiceOutsideMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *outsideChrootApiServiceClient) OutsideServiceInsideMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.OutsideChrootApiService/OutsideServiceInsideMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// OutsideChrootApiServiceServer is the server API for OutsideChrootApiService service.
// All implementations must embed UnimplementedOutsideChrootApiServiceServer
// for forward compatibility
type OutsideChrootApiServiceServer interface {
	// No override of service level outside assertion.
	OutsideServiceOutsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	// Override service level outside assertion with inside assertion.
	OutsideServiceInsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	mustEmbedUnimplementedOutsideChrootApiServiceServer()
}

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

func (UnimplementedOutsideChrootApiServiceServer) OutsideServiceOutsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method OutsideServiceOutsideMethod not implemented")
}
func (UnimplementedOutsideChrootApiServiceServer) OutsideServiceInsideMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method OutsideServiceInsideMethod not implemented")
}
func (UnimplementedOutsideChrootApiServiceServer) mustEmbedUnimplementedOutsideChrootApiServiceServer() {
}

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

func RegisterOutsideChrootApiServiceServer(s grpc.ServiceRegistrar, srv OutsideChrootApiServiceServer) {
	s.RegisterService(&OutsideChrootApiService_ServiceDesc, srv)
}

func _OutsideChrootApiService_OutsideServiceOutsideMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(OutsideChrootApiServiceServer).OutsideServiceOutsideMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.OutsideChrootApiService/OutsideServiceOutsideMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(OutsideChrootApiServiceServer).OutsideServiceOutsideMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

func _OutsideChrootApiService_OutsideServiceInsideMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(OutsideChrootApiServiceServer).OutsideServiceInsideMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.OutsideChrootApiService/OutsideServiceInsideMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(OutsideChrootApiServiceServer).OutsideServiceInsideMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

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

// HiddenServiceClient is the client API for HiddenService 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 HiddenServiceClient interface {
	HiddenMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error)
}

type hiddenServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewHiddenServiceClient(cc grpc.ClientConnInterface) HiddenServiceClient {
	return &hiddenServiceClient{cc}
}

func (c *hiddenServiceClient) HiddenMethod(ctx context.Context, in *TestRequestMessage, opts ...grpc.CallOption) (*TestResultMessage, error) {
	out := new(TestResultMessage)
	err := c.cc.Invoke(ctx, "/chromite.api.HiddenService/HiddenMethod", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// HiddenServiceServer is the server API for HiddenService service.
// All implementations must embed UnimplementedHiddenServiceServer
// for forward compatibility
type HiddenServiceServer interface {
	HiddenMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error)
	mustEmbedUnimplementedHiddenServiceServer()
}

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

func (UnimplementedHiddenServiceServer) HiddenMethod(context.Context, *TestRequestMessage) (*TestResultMessage, error) {
	return nil, status.Errorf(codes.Unimplemented, "method HiddenMethod not implemented")
}
func (UnimplementedHiddenServiceServer) mustEmbedUnimplementedHiddenServiceServer() {}

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

func RegisterHiddenServiceServer(s grpc.ServiceRegistrar, srv HiddenServiceServer) {
	s.RegisterService(&HiddenService_ServiceDesc, srv)
}

func _HiddenService_HiddenMethod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestRequestMessage)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(HiddenServiceServer).HiddenMethod(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/chromite.api.HiddenService/HiddenMethod",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(HiddenServiceServer).HiddenMethod(ctx, req.(*TestRequestMessage))
	}
	return interceptor(ctx, in, info, handler)
}

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