// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// 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"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

type UsingPublicImport struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// 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"` // declared in sub2/a.proto
}

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 {
	mi := &file_import_public_c_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use UsingPublicImport.ProtoReflect.Descriptor 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, // 0: goproto.protoc.import_public.UsingPublicImport.local:type_name -> goproto.protoc.import_public.Local
	2, // 1: goproto.protoc.import_public.UsingPublicImport.sub2:type_name -> goproto.protoc.import_public.sub2.Sub2Message
	2, // [2:2] is the sub-list for method output_type
	2, // [2:2] is the sub-list for method input_type
	2, // [2:2] is the sub-list for extension type_name
	2, // [2:2] is the sub-list for extension extendee
	0, // [0:2] is the sub-list for field type_name
}

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 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			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
}
