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

package prototype

import (
	fmt "fmt"
	proto "github.com/golang/protobuf/proto"
	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 PartnerId struct {
	Value                string   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

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

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

var xxx_messageInfo_PartnerId proto.InternalMessageInfo

func (m *PartnerId) GetValue() string {
	if m != nil {
		return m.Value
	}
	return ""
}

type Partner struct {
	Id                   *PartnerId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
	Name                 string     `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
	EmailGroup           string     `protobuf:"bytes,3,opt,name=email_group,json=emailGroup,proto3" json:"email_group,omitempty"`
	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
	XXX_unrecognized     []byte     `json:"-"`
	XXX_sizecache        int32      `json:"-"`
}

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

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

var xxx_messageInfo_Partner proto.InternalMessageInfo

func (m *Partner) GetId() *PartnerId {
	if m != nil {
		return m.Id
	}
	return nil
}

func (m *Partner) GetName() string {
	if m != nil {
		return m.Name
	}
	return ""
}

func (m *Partner) GetEmailGroup() string {
	if m != nil {
		return m.EmailGroup
	}
	return ""
}

type PartnerList struct {
	Value                []*Partner `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"`
	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
	XXX_unrecognized     []byte     `json:"-"`
	XXX_sizecache        int32      `json:"-"`
}

func (m *PartnerList) Reset()         { *m = PartnerList{} }
func (m *PartnerList) String() string { return proto.CompactTextString(m) }
func (*PartnerList) ProtoMessage()    {}
func (*PartnerList) Descriptor() ([]byte, []int) {
	return fileDescriptor_12fb452c5cc762de, []int{2}
}

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

var xxx_messageInfo_PartnerList proto.InternalMessageInfo

func (m *PartnerList) GetValue() []*Partner {
	if m != nil {
		return m.Value
	}
	return nil
}

func init() {
	proto.RegisterType((*PartnerId)(nil), "prototype.PartnerId")
	proto.RegisterType((*Partner)(nil), "prototype.Partner")
	proto.RegisterType((*PartnerList)(nil), "prototype.PartnerList")
}

func init() { proto.RegisterFile("prototype/partner.proto", fileDescriptor_12fb452c5cc762de) }

var fileDescriptor_12fb452c5cc762de = []byte{
	// 209 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x8e, 0xcf, 0x4b, 0xc4, 0x30,
	0x10, 0x85, 0xd9, 0xae, 0x3f, 0xe8, 0xe4, 0x36, 0x2c, 0xd8, 0x9b, 0x5a, 0x3c, 0xf4, 0x94, 0xc0,
	0x2e, 0xe2, 0xdd, 0x8b, 0x08, 0x1e, 0xa4, 0x47, 0x2f, 0x12, 0x4d, 0x8c, 0x81, 0xa6, 0x13, 0xd2,
	0x54, 0xf0, 0xbf, 0x17, 0xa7, 0x35, 0x1e, 0xf6, 0x36, 0xf3, 0xbe, 0xe4, 0x9b, 0x07, 0x17, 0x31,
	0x51, 0xa6, 0xfc, 0x1d, 0xad, 0x8a, 0x3a, 0xe5, 0xd1, 0x26, 0xc9, 0x09, 0xd6, 0x05, 0xb4, 0xd7,
	0x50, 0x3f, 0x2f, 0xec, 0xd1, 0xe0, 0x0e, 0x4e, 0xbf, 0xf4, 0x30, 0xdb, 0x66, 0x73, 0xb5, 0xe9,
	0xea, 0x7e, 0x59, 0x5a, 0x03, 0xe7, 0xeb, 0x13, 0xbc, 0x81, 0xca, 0x1b, 0xa6, 0x62, 0xbf, 0x93,
	0xc5, 0x22, 0x8b, 0xa2, 0xaf, 0xbc, 0x41, 0x84, 0x93, 0x51, 0x07, 0xdb, 0x54, 0x6c, 0xe1, 0x19,
	0x2f, 0x41, 0xd8, 0xa0, 0xfd, 0xf0, 0xea, 0x12, 0xcd, 0xb1, 0xd9, 0x32, 0x02, 0x8e, 0x1e, 0x7e,
	0x93, 0xf6, 0x0e, 0xc4, 0x6a, 0x79, 0xf2, 0x53, 0xc6, 0xee, 0xbf, 0xca, 0xb6, 0x13, 0x7b, 0x3c,
	0x3e, 0xb6, 0xd6, 0xbb, 0xbf, 0x7d, 0x39, 0x38, 0x92, 0xef, 0x9f, 0x89, 0x82, 0x9f, 0x83, 0xa4,
	0xe4, 0xd4, 0xdf, 0x42, 0x93, 0xf2, 0xe3, 0x47, 0xd2, 0x8a, 0x3f, 0x2b, 0x47, 0xaa, 0x58, 0xde,
	0xce, 0x78, 0x3c, 0xfc, 0x04, 0x00, 0x00, 0xff, 0xff, 0x94, 0x0e, 0x3b, 0x60, 0x25, 0x01, 0x00,
	0x00,
}
