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

package import_public

import (
	proto "github.com/golang/protobuf/proto"
	sub "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/import_public/sub"
	sub2 "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/import_public/sub2"
	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
	reflect "reflect"
)

// Symbols defined in public import of import_public/sub/a.proto

type E = sub.E

const E_ZERO = sub.E_ZERO

var E_name = sub.E_name
var E_value = sub.E_value

type M_Subenum = sub.M_Subenum

const M_M_ZERO = sub.M_M_ZERO

var M_Subenum_name = sub.M_Subenum_name
var M_Subenum_value = sub.M_Subenum_value

type M_Submessage_Submessage_Subenum = sub.M_Submessage_Submessage_Subenum

const M_Submessage_M_SUBMESSAGE_ZERO = sub.M_Submessage_M_SUBMESSAGE_ZERO

var M_Submessage_Submessage_Subenum_name = sub.M_Submessage_Submessage_Subenum_name
var M_Submessage_Submessage_Subenum_value = sub.M_Submessage_Submessage_Subenum_value

type M = sub.M

const Default_M_S = sub.Default_M_S

var Default_M_B = sub.Default_M_B
var Default_M_F = sub.Default_M_F

type M_OneofInt32 = sub.M_OneofInt32
type M_OneofInt64 = sub.M_OneofInt64
type M_Submessage = sub.M_Submessage
type M_Submessage_SubmessageOneofInt32 = sub.M_Submessage_SubmessageOneofInt32
type M_Submessage_SubmessageOneofInt64 = sub.M_Submessage_SubmessageOneofInt64

var E_ExtensionField = sub.E_ExtensionField

// Symbols defined in public import of import_public/sub2/a.proto

type Sub2Message = sub2.Sub2Message

type Public struct {
	M                    *sub.M   `protobuf:"bytes,1,opt,name=m" json:"m,omitempty"`
	E                    *sub.E   `protobuf:"varint,2,opt,name=e,enum=goproto.protoc.import_public.sub.E" json:"e,omitempty"`
	Local                *Local   `protobuf:"bytes,3,opt,name=local" json:"local,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *Public) ProtoReflect() protoreflect.Message {
	return xxx_File_import_public_a_proto_messageTypes[0].MessageOf(m)
}
func (m *Public) Reset()         { *m = Public{} }
func (m *Public) String() string { return proto.CompactTextString(m) }
func (*Public) ProtoMessage()    {}

// Deprecated: Use Public.ProtoReflect.Type instead.
func (*Public) Descriptor() ([]byte, []int) {
	return xxx_File_import_public_a_proto_rawdesc_gzipped, []int{0}
}

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

var xxx_messageInfo_Public proto.InternalMessageInfo

func (m *Public) GetM() *sub.M {
	if m != nil {
		return m.M
	}
	return nil
}

func (m *Public) GetE() sub.E {
	if m != nil && m.E != nil {
		return *m.E
	}
	return sub.E_ZERO
}

func (m *Public) GetLocal() *Local {
	if m != nil {
		return m.Local
	}
	return nil
}

var xxx_File_import_public_a_proto_rawdesc = []byte{
	// 383 bytes of the wire-encoded FileDescriptorProto
	0x0a, 0x15, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f,
	0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70,
	0x75, 0x62, 0x6c, 0x69, 0x63, 0x1a, 0x19, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75,
	0x62, 0x6c, 0x69, 0x63, 0x2f, 0x73, 0x75, 0x62, 0x2f, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
	0x1a, 0x1a, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f,
	0x73, 0x75, 0x62, 0x32, 0x2f, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x69, 0x6d,
	0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x62, 0x2e, 0x70, 0x72,
	0x6f, 0x74, 0x6f, 0x22, 0xa9, 0x01, 0x0a, 0x06, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x31,
	0x0a, 0x01, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x70, 0x72,
	0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72,
	0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2e, 0x73, 0x75, 0x62, 0x2e, 0x4d, 0x52, 0x01,
	0x6d, 0x12, 0x31, 0x0a, 0x01, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67,
	0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x69, 0x6d,
	0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2e, 0x73, 0x75, 0x62, 0x2e,
	0x45, 0x52, 0x01, 0x65, 0x12, 0x39, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x03, 0x20,
	0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72,
	0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c,
	0x69, 0x63, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42,
	0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f,
	0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x32,
	0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d,
	0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x69, 0x6d, 0x70, 0x6f,
	0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x50, 0x00, 0x50, 0x01, 0x50, 0x02,
}

var xxx_File_import_public_a_proto_rawdesc_gzipped = protoimpl.X.CompressGZIP(xxx_File_import_public_a_proto_rawdesc)

const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)

var File_import_public_a_proto protoreflect.FileDescriptor

var xxx_File_import_public_a_proto_messageTypes = make([]protoimpl.MessageType, 1)
var xxx_File_import_public_a_proto_goTypes = []interface{}{
	(*Public)(nil), // 0: goproto.protoc.import_public.Public
	(*sub.M)(nil),  // 1: goproto.protoc.import_public.sub.M
	(sub.E)(0),     // 2: goproto.protoc.import_public.sub.E
	(*Local)(nil),  // 3: goproto.protoc.import_public.Local
}
var xxx_File_import_public_a_proto_depIdxs = []int32{
	1, // goproto.protoc.import_public.Public.m:type_name -> goproto.protoc.import_public.sub.M
	2, // goproto.protoc.import_public.Public.e:type_name -> goproto.protoc.import_public.sub.E
	3, // goproto.protoc.import_public.Public.local:type_name -> goproto.protoc.import_public.Local
}

func init() { xxx_File_import_public_a_proto_init() }
func xxx_File_import_public_a_proto_init() {
	if File_import_public_a_proto != nil {
		return
	}
	xxx_File_import_public_b_proto_init()
	messageTypes := make([]protoreflect.MessageType, 1)
	File_import_public_a_proto = protoimpl.FileBuilder{
		RawDescriptor:      xxx_File_import_public_a_proto_rawdesc,
		GoTypes:            xxx_File_import_public_a_proto_goTypes,
		DependencyIndexes:  xxx_File_import_public_a_proto_depIdxs,
		MessageOutputTypes: messageTypes,
	}.Init()
	messageGoTypes := xxx_File_import_public_a_proto_goTypes[0:][:1]
	for i, mt := range messageTypes {
		xxx_File_import_public_a_proto_messageTypes[i].GoType = reflect.TypeOf(messageGoTypes[i])
		xxx_File_import_public_a_proto_messageTypes[i].PBType = mt
	}
	proto.RegisterFile("import_public/a.proto", xxx_File_import_public_a_proto_rawdesc_gzipped)
	proto.RegisterType((*Public)(nil), "goproto.protoc.import_public.Public")
	xxx_File_import_public_a_proto_goTypes = nil
	xxx_File_import_public_a_proto_depIdxs = nil
}
