// Copyright 2017 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.12
// 	protoc        v5.27.1
// source: reflection/grpc_testing/proto2.proto

package grpc_testing

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	unsafe "unsafe"
)

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

type ToBeExtended struct {
	state           protoimpl.MessageState `protogen:"open.v1"`
	Foo             *int32                 `protobuf:"varint,1,req,name=foo" json:"foo,omitempty"`
	extensionFields protoimpl.ExtensionFields
	unknownFields   protoimpl.UnknownFields
	sizeCache       protoimpl.SizeCache
}

func (x *ToBeExtended) Reset() {
	*x = ToBeExtended{}
	mi := &file_reflection_grpc_testing_proto2_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*ToBeExtended) ProtoMessage() {}

func (x *ToBeExtended) ProtoReflect() protoreflect.Message {
	mi := &file_reflection_grpc_testing_proto2_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

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

func (x *ToBeExtended) GetFoo() int32 {
	if x != nil && x.Foo != nil {
		return *x.Foo
	}
	return 0
}

var File_reflection_grpc_testing_proto2_proto protoreflect.FileDescriptor

const file_reflection_grpc_testing_proto2_proto_rawDesc = "" +
	"\n" +
	"$reflection/grpc_testing/proto2.proto\x12\fgrpc.testing\"&\n" +
	"\fToBeExtended\x12\x10\n" +
	"\x03foo\x18\x01 \x02(\x05R\x03foo*\x04\b\n" +
	"\x10\x1fB0Z.google.golang.org/grpc/reflection/grpc_testing"

var (
	file_reflection_grpc_testing_proto2_proto_rawDescOnce sync.Once
	file_reflection_grpc_testing_proto2_proto_rawDescData []byte
)

func file_reflection_grpc_testing_proto2_proto_rawDescGZIP() []byte {
	file_reflection_grpc_testing_proto2_proto_rawDescOnce.Do(func() {
		file_reflection_grpc_testing_proto2_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_reflection_grpc_testing_proto2_proto_rawDesc), len(file_reflection_grpc_testing_proto2_proto_rawDesc)))
	})
	return file_reflection_grpc_testing_proto2_proto_rawDescData
}

var file_reflection_grpc_testing_proto2_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_reflection_grpc_testing_proto2_proto_goTypes = []any{
	(*ToBeExtended)(nil), // 0: grpc.testing.ToBeExtended
}
var file_reflection_grpc_testing_proto2_proto_depIdxs = []int32{
	0, // [0:0] is the sub-list for method output_type
	0, // [0:0] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
}

func init() { file_reflection_grpc_testing_proto2_proto_init() }
func file_reflection_grpc_testing_proto2_proto_init() {
	if File_reflection_grpc_testing_proto2_proto != nil {
		return
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_reflection_grpc_testing_proto2_proto_rawDesc), len(file_reflection_grpc_testing_proto2_proto_rawDesc)),
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_reflection_grpc_testing_proto2_proto_goTypes,
		DependencyIndexes: file_reflection_grpc_testing_proto2_proto_depIdxs,
		MessageInfos:      file_reflection_grpc_testing_proto2_proto_msgTypes,
	}.Build()
	File_reflection_grpc_testing_proto2_proto = out.File
	file_reflection_grpc_testing_proto2_proto_goTypes = nil
	file_reflection_grpc_testing_proto2_proto_depIdxs = nil
}
