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

package protos

import (
	context "context"
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	math "math"
)

// 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",
}
