// Code generated by protoc-gen-go. DO NOT EDIT.
// source: api/bbsim/bbsim_dmi.proto

package bbsim

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

type DmiEvent struct {
	EventName            string   `protobuf:"bytes,1,opt,name=event_name,json=eventName,proto3" json:"event_name,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

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

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

var xxx_messageInfo_DmiEvent proto.InternalMessageInfo

func (m *DmiEvent) GetEventName() string {
	if m != nil {
		return m.EventName
	}
	return ""
}

type DmiCreateEventResponse struct {
	StatusCode           int32    `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
	Message              string   `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

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

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

var xxx_messageInfo_DmiCreateEventResponse proto.InternalMessageInfo

func (m *DmiCreateEventResponse) GetStatusCode() int32 {
	if m != nil {
		return m.StatusCode
	}
	return 0
}

func (m *DmiCreateEventResponse) GetMessage() string {
	if m != nil {
		return m.Message
	}
	return ""
}

func init() {
	proto.RegisterType((*DmiEvent)(nil), "bbsim.DmiEvent")
	proto.RegisterType((*DmiCreateEventResponse)(nil), "bbsim.DmiCreateEventResponse")
}

func init() { proto.RegisterFile("api/bbsim/bbsim_dmi.proto", fileDescriptor_49e784b4938902cc) }

var fileDescriptor_49e784b4938902cc = []byte{
	// 190 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0x2c, 0xc8, 0xd4,
	0x4f, 0x4a, 0x2a, 0xce, 0xcc, 0x85, 0x90, 0xf1, 0x29, 0xb9, 0x99, 0x7a, 0x05, 0x45, 0xf9, 0x25,
	0xf9, 0x42, 0xac, 0x60, 0x01, 0x25, 0x4d, 0x2e, 0x0e, 0x97, 0xdc, 0x4c, 0xd7, 0xb2, 0xd4, 0xbc,
	0x12, 0x21, 0x59, 0x2e, 0xae, 0x54, 0x10, 0x23, 0x3e, 0x2f, 0x31, 0x37, 0x55, 0x82, 0x51, 0x81,
	0x51, 0x83, 0x33, 0x88, 0x13, 0x2c, 0xe2, 0x97, 0x98, 0x9b, 0xaa, 0x14, 0xcc, 0x25, 0xe6, 0x92,
	0x9b, 0xe9, 0x5c, 0x94, 0x9a, 0x58, 0x92, 0x0a, 0xd6, 0x10, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57,
	0x9c, 0x2a, 0x24, 0xcf, 0xc5, 0x5d, 0x5c, 0x92, 0x58, 0x52, 0x5a, 0x1c, 0x9f, 0x9c, 0x9f, 0x02,
	0xd1, 0xc9, 0x1a, 0xc4, 0x05, 0x11, 0x72, 0xce, 0x4f, 0x49, 0x15, 0x92, 0xe0, 0x62, 0xcf, 0x4d,
	0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x95, 0x60, 0x02, 0x1b, 0x0b, 0xe3, 0x1a, 0xf9, 0x70, 0x71, 0x3a,
	0x39, 0x41, 0x5d, 0x26, 0x64, 0xcf, 0xc5, 0x8d, 0x64, 0xbc, 0x10, 0xbf, 0x1e, 0xd8, 0x8d, 0x7a,
	0x30, 0x07, 0x4a, 0xc9, 0x22, 0x04, 0xb0, 0x38, 0x43, 0x89, 0x21, 0x89, 0x0d, 0xec, 0x37, 0x63,
	0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x8b, 0xf2, 0xfd, 0xf8, 0x00, 0x00, 0x00,
}

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

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

// BBsimDmiClient is the client API for BBsimDmi service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BBsimDmiClient interface {
	// Ask the DMI Server to create an event
	CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error)
}

type bBsimDmiClient struct {
	cc *grpc.ClientConn
}

func NewBBsimDmiClient(cc *grpc.ClientConn) BBsimDmiClient {
	return &bBsimDmiClient{cc}
}

func (c *bBsimDmiClient) CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error) {
	out := new(DmiCreateEventResponse)
	err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/CreateEvent", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// BBsimDmiServer is the server API for BBsimDmi service.
type BBsimDmiServer interface {
	// Ask the DMI Server to create an event
	CreateEvent(context.Context, *DmiEvent) (*DmiCreateEventResponse, error)
}

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

func (*UnimplementedBBsimDmiServer) CreateEvent(ctx context.Context, req *DmiEvent) (*DmiCreateEventResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method CreateEvent not implemented")
}

func RegisterBBsimDmiServer(s *grpc.Server, srv BBsimDmiServer) {
	s.RegisterService(&_BBsimDmi_serviceDesc, srv)
}

func _BBsimDmi_CreateEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(DmiEvent)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(BBsimDmiServer).CreateEvent(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/bbsim.BBsim_dmi/CreateEvent",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(BBsimDmiServer).CreateEvent(ctx, req.(*DmiEvent))
	}
	return interceptor(ctx, in, info, handler)
}

var _BBsimDmi_serviceDesc = grpc.ServiceDesc{
	ServiceName: "bbsim.BBsim_dmi",
	HandlerType: (*BBsimDmiServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "CreateEvent",
			Handler:    _BBsimDmi_CreateEvent_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "api/bbsim/bbsim_dmi.proto",
}
