// Code generated by protoc-gen-go. DO NOT EDIT.
// source: coordinator.proto

package protos

import (
	context "context"
	fmt "fmt"
	math "math"

	proto "github.com/golang/protobuf/proto"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

// ClearResultsRequest specifies the data needed to clear a result.
type ClearResultsRequest struct {
	// builder is the builder to clear results.
	Builder string `protobuf:"bytes,1,opt,name=builder,proto3" json:"builder,omitempty"`
	// hash is the commit hash to clear results.
	Hash                 string   `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *ClearResultsRequest) Reset()         { *m = ClearResultsRequest{} }
func (m *ClearResultsRequest) String() string { return proto.CompactTextString(m) }
func (*ClearResultsRequest) ProtoMessage()    {}
func (*ClearResultsRequest) Descriptor() ([]byte, []int) {
	return fileDescriptor_99e779eb11ceee19, []int{0}
}

func (m *ClearResultsRequest) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_ClearResultsRequest.Unmarshal(m, b)
}
func (m *ClearResultsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_ClearResultsRequest.Marshal(b, m, deterministic)
}
func (m *ClearResultsRequest) XXX_Merge(src proto.Message) {
	xxx_messageInfo_ClearResultsRequest.Merge(m, src)
}
func (m *ClearResultsRequest) XXX_Size() int {
	return xxx_messageInfo_ClearResultsRequest.Size(m)
}
func (m *ClearResultsRequest) XXX_DiscardUnknown() {
	xxx_messageInfo_ClearResultsRequest.DiscardUnknown(m)
}

var xxx_messageInfo_ClearResultsRequest proto.InternalMessageInfo

func (m *ClearResultsRequest) GetBuilder() string {
	if m != nil {
		return m.Builder
	}
	return ""
}

func (m *ClearResultsRequest) GetHash() string {
	if m != nil {
		return m.Hash
	}
	return ""
}

type ClearResultsResponse struct {
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *ClearResultsResponse) Reset()         { *m = ClearResultsResponse{} }
func (m *ClearResultsResponse) String() string { return proto.CompactTextString(m) }
func (*ClearResultsResponse) ProtoMessage()    {}
func (*ClearResultsResponse) Descriptor() ([]byte, []int) {
	return fileDescriptor_99e779eb11ceee19, []int{1}
}

func (m *ClearResultsResponse) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_ClearResultsResponse.Unmarshal(m, b)
}
func (m *ClearResultsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_ClearResultsResponse.Marshal(b, m, deterministic)
}
func (m *ClearResultsResponse) XXX_Merge(src proto.Message) {
	xxx_messageInfo_ClearResultsResponse.Merge(m, src)
}
func (m *ClearResultsResponse) XXX_Size() int {
	return xxx_messageInfo_ClearResultsResponse.Size(m)
}
func (m *ClearResultsResponse) XXX_DiscardUnknown() {
	xxx_messageInfo_ClearResultsResponse.DiscardUnknown(m)
}

var xxx_messageInfo_ClearResultsResponse proto.InternalMessageInfo

func init() {
	proto.RegisterType((*ClearResultsRequest)(nil), "protos.ClearResultsRequest")
	proto.RegisterType((*ClearResultsResponse)(nil), "protos.ClearResultsResponse")
}

func init() { proto.RegisterFile("coordinator.proto", fileDescriptor_99e779eb11ceee19) }

var fileDescriptor_99e779eb11ceee19 = []byte{
	// 151 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0xce, 0xcf, 0x2f,
	0x4a, 0xc9, 0xcc, 0x4b, 0x2c, 0xc9, 0x2f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03,
	0x53, 0xc5, 0x4a, 0xce, 0x5c, 0xc2, 0xce, 0x39, 0xa9, 0x89, 0x45, 0x41, 0xa9, 0xc5, 0xa5, 0x39,
	0x25, 0xc5, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x12, 0x5c, 0xec, 0x49, 0xa5, 0x99,
	0x39, 0x29, 0xa9, 0x45, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x30, 0xae, 0x90, 0x10, 0x17,
	0x4b, 0x46, 0x62, 0x71, 0x86, 0x04, 0x13, 0x58, 0x18, 0xcc, 0x56, 0x12, 0xe3, 0x12, 0x41, 0x35,
	0xa4, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0xd5, 0x28, 0x8a, 0x8b, 0xdb, 0x19, 0x61, 0xb3, 0x90, 0x37,
	0x17, 0x0f, 0xb2, 0x32, 0x21, 0x69, 0x88, 0x5b, 0x8a, 0xf5, 0xb0, 0xb8, 0x40, 0x4a, 0x06, 0xbb,
	0x24, 0xc4, 0x64, 0x25, 0x86, 0x24, 0x88, 0x07, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x10,
	0xa0, 0xb6, 0xbb, 0xdc, 0x00, 0x00, 0x00,
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6

// CoordinatorClient is the client API for Coordinator service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CoordinatorClient interface {
	// ClearResults clears build failures from the coordinator to force them to rebuild.
	ClearResults(ctx context.Context, in *ClearResultsRequest, opts ...grpc.CallOption) (*ClearResultsResponse, error)
}

type coordinatorClient struct {
	cc grpc.ClientConnInterface
}

func NewCoordinatorClient(cc grpc.ClientConnInterface) CoordinatorClient {
	return &coordinatorClient{cc}
}

func (c *coordinatorClient) ClearResults(ctx context.Context, in *ClearResultsRequest, opts ...grpc.CallOption) (*ClearResultsResponse, error) {
	out := new(ClearResultsResponse)
	err := c.cc.Invoke(ctx, "/protos.Coordinator/ClearResults", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// CoordinatorServer is the server API for Coordinator service.
type CoordinatorServer interface {
	// ClearResults clears build failures from the coordinator to force them to rebuild.
	ClearResults(context.Context, *ClearResultsRequest) (*ClearResultsResponse, error)
}

// UnimplementedCoordinatorServer can be embedded to have forward compatible implementations.
type UnimplementedCoordinatorServer struct {
}

func (*UnimplementedCoordinatorServer) ClearResults(ctx context.Context, req *ClearResultsRequest) (*ClearResultsResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method ClearResults not implemented")
}

func RegisterCoordinatorServer(s *grpc.Server, srv CoordinatorServer) {
	s.RegisterService(&_Coordinator_serviceDesc, srv)
}

func _Coordinator_ClearResults_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(ClearResultsRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(CoordinatorServer).ClearResults(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/protos.Coordinator/ClearResults",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(CoordinatorServer).ClearResults(ctx, req.(*ClearResultsRequest))
	}
	return interceptor(ctx, in, info, handler)
}

var _Coordinator_serviceDesc = grpc.ServiceDesc{
	ServiceName: "protos.Coordinator",
	HandlerType: (*CoordinatorServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "ClearResults",
			Handler:    _Coordinator_ClearResults_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "coordinator.proto",
}
