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

package imp

import proto "github.com/golang/protobuf/proto"
import "math"
import "os"
import imp1 "imp2.pb"

// Reference proto & math imports to suppress error if they are not otherwise used.
var _ = proto.GetString
var _ = math.Inf

// Types from public import imp2.proto
type PubliclyImportedMessage imp1.PubliclyImportedMessage

func (this *PubliclyImportedMessage) Reset() { (*imp1.PubliclyImportedMessage)(this).Reset() }
func (this *PubliclyImportedMessage) String() string {
	return (*imp1.PubliclyImportedMessage)(this).String()
}

// PubliclyImportedMessage from public import imp.proto

type ImportedMessage_Owner int32

const (
	ImportedMessage_DAVE ImportedMessage_Owner = 1
	ImportedMessage_MIKE ImportedMessage_Owner = 2
)

var ImportedMessage_Owner_name = map[int32]string{
	1: "DAVE",
	2: "MIKE",
}
var ImportedMessage_Owner_value = map[string]int32{
	"DAVE": 1,
	"MIKE": 2,
}

// NewImportedMessage_Owner is deprecated. Use x.Enum() instead.
func NewImportedMessage_Owner(x ImportedMessage_Owner) *ImportedMessage_Owner {
	e := ImportedMessage_Owner(x)
	return &e
}
func (x ImportedMessage_Owner) Enum() *ImportedMessage_Owner {
	p := new(ImportedMessage_Owner)
	*p = x
	return p
}
func (x ImportedMessage_Owner) String() string {
	return proto.EnumName(ImportedMessage_Owner_name, int32(x))
}

type ImportedMessage struct {
	Field            *int64           `protobuf:"varint,1,req,name=field" json:"field,omitempty"`
	XXX_extensions   map[int32][]byte `json:",omitempty"`
	XXX_unrecognized []byte           `json:",omitempty"`
}

func (this *ImportedMessage) Reset()         { *this = ImportedMessage{} }
func (this *ImportedMessage) String() string { return proto.CompactTextString(this) }

var extRange_ImportedMessage = []proto.ExtensionRange{
	proto.ExtensionRange{90, 100},
}

func (*ImportedMessage) ExtensionRangeArray() []proto.ExtensionRange {
	return extRange_ImportedMessage
}
func (this *ImportedMessage) ExtensionMap() map[int32][]byte {
	if this.XXX_extensions == nil {
		this.XXX_extensions = make(map[int32][]byte)
	}
	return this.XXX_extensions
}

type ImportedExtendable struct {
	XXX_extensions   map[int32][]byte `json:",omitempty"`
	XXX_unrecognized []byte           `json:",omitempty"`
}

func (this *ImportedExtendable) Reset()         { *this = ImportedExtendable{} }
func (this *ImportedExtendable) String() string { return proto.CompactTextString(this) }

func (this *ImportedExtendable) Marshal() ([]byte, error) {
	return proto.MarshalMessageSet(this.ExtensionMap())
}
func (this *ImportedExtendable) Unmarshal(buf []byte) error {
	return proto.UnmarshalMessageSet(buf, this.ExtensionMap())
}
// ensure ImportedExtendable satisfies proto.Marshaler and proto.Unmarshaler
var _ proto.Marshaler = (*ImportedExtendable)(nil)
var _ proto.Unmarshaler = (*ImportedExtendable)(nil)

var extRange_ImportedExtendable = []proto.ExtensionRange{
	proto.ExtensionRange{100, 536870911},
}

func (*ImportedExtendable) ExtensionRangeArray() []proto.ExtensionRange {
	return extRange_ImportedExtendable
}
func (this *ImportedExtendable) ExtensionMap() map[int32][]byte {
	if this.XXX_extensions == nil {
		this.XXX_extensions = make(map[int32][]byte)
	}
	return this.XXX_extensions
}

func init() {
	proto.RegisterEnum("imp.ImportedMessage_Owner", ImportedMessage_Owner_name, ImportedMessage_Owner_value)
}
