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

package import_public

import (
	sub2 "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/import_public/sub2"
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoiface "google.golang.org/protobuf/runtime/protoiface"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	sync "sync"
)

const (
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 0)
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(0 - protoimpl.MinVersion)
)

type UsingPublicImport struct {
	// Local is declared in b.proto, which is a public import of a.proto.
	Local *Local `protobuf:"bytes,1,opt,name=local" json:"local,omitempty"`
	// Sub2Message is declared in sub2/a.proto, which is a public import of
	// sub/a.proto, which is a public import of a.proto.
	Sub2          *sub2.Sub2Message `protobuf:"bytes,2,opt,name=sub2" json:"sub2,omitempty"`
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
}

func (x *UsingPublicImport) Reset() {
	*x = UsingPublicImport{}
}

func (x *UsingPublicImport) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*UsingPublicImport) ProtoMessage() {}

func (x *UsingPublicImport) ProtoReflect() protoreflect.Message {
	return file_import_public_c_proto_msgTypes[0].MessageOf(x)
}

func (m *UsingPublicImport) XXX_Methods() *protoiface.Methods {
	return file_import_public_c_proto_msgTypes[0].Methods()
}

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

func (x *UsingPublicImport) GetLocal() *Local {
	if x != nil {
		return x.Local
	}
	return nil
}

func (x *UsingPublicImport) GetSub2() *sub2.Sub2Message {
	if x != nil {
		return x.Sub2
	}
	return nil
}

var File_import_public_c_proto protoreflect.FileDescriptor

var file_import_public_c_proto_rawDesc = []byte{
	0x0a, 0x15, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f,
	0x63, 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, 0x15, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75,
	0x62, 0x6c, 0x69, 0x63, 0x2f, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, 0x0a,
	0x11, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6d, 0x70, 0x6f,
	0x72, 0x74, 0x12, 0x39, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 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, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x42, 0x0a,
	0x04, 0x73, 0x75, 0x62, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x32, 0x2e,
	0x53, 0x75, 0x62, 0x32, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x73, 0x75, 0x62,
	0x32, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61,
	0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 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,
}

var (
	file_import_public_c_proto_rawDescOnce sync.Once
	file_import_public_c_proto_rawDescData = file_import_public_c_proto_rawDesc
)

func file_import_public_c_proto_rawDescGZIP() []byte {
	file_import_public_c_proto_rawDescOnce.Do(func() {
		file_import_public_c_proto_rawDescData = protoimpl.X.CompressGZIP(file_import_public_c_proto_rawDescData)
	})
	return file_import_public_c_proto_rawDescData
}

var file_import_public_c_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_import_public_c_proto_goTypes = []interface{}{
	(*UsingPublicImport)(nil), // 0: goproto.protoc.import_public.UsingPublicImport
	(*Local)(nil),             // 1: goproto.protoc.import_public.Local
	(*sub2.Sub2Message)(nil),  // 2: goproto.protoc.import_public.sub2.Sub2Message
}
var file_import_public_c_proto_depIdxs = []int32{
	1, // goproto.protoc.import_public.UsingPublicImport.local:type_name -> goproto.protoc.import_public.Local
	2, // goproto.protoc.import_public.UsingPublicImport.sub2:type_name -> goproto.protoc.import_public.sub2.Sub2Message
	2, // starting offset of method output_type sub-list
	2, // starting offset of method input_type sub-list
	2, // starting offset of extension type_name sub-list
	2, // starting offset of extension extendee sub-list
	0, // starting offset of field type_name sub-list
}

func init() { file_import_public_c_proto_init() }
func file_import_public_c_proto_init() {
	if File_import_public_c_proto != nil {
		return
	}
	file_import_public_a_proto_init()
	if !protoimpl.UnsafeEnabled {
		file_import_public_c_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*UsingPublicImport); i {
			case 2:
				return &v.sizeCache
			case 3:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			RawDescriptor: file_import_public_c_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_import_public_c_proto_goTypes,
		DependencyIndexes: file_import_public_c_proto_depIdxs,
		MessageInfos:      file_import_public_c_proto_msgTypes,
	}.Build()
	File_import_public_c_proto = out.File
	file_import_public_c_proto_rawDesc = nil
	file_import_public_c_proto_goTypes = nil
	file_import_public_c_proto_depIdxs = nil
}
