// Code generated by protoc-gen-go. DO NOT EDIT.
// source: extensions/base/base.proto

package base

import (
	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 BaseMessage struct {
	Field                  *string                   `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"`
	XXX_NoUnkeyedLiteral   struct{}                  `json:"-"`
	XXX_InternalExtensions protoimpl.ExtensionFields `json:"-"`
	XXX_unrecognized       protoimpl.UnknownFields   `json:"-"`
	XXX_sizecache          protoimpl.SizeCache       `json:"-"`
}

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

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

func (*BaseMessage) ProtoMessage() {}

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

func (m *BaseMessage) XXX_Methods() *protoiface.Methods {
	return file_extensions_base_base_proto_msgTypes[0].Methods()
}

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

var extRange_BaseMessage = []protoiface.ExtensionRangeV1{
	{Start: 4, End: 9},
	{Start: 16, End: 536870911},
}

// Deprecated: Use BaseMessage.ProtoReflect.Type.ExtensionRanges instead.
func (*BaseMessage) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
	return extRange_BaseMessage
}

func (x *BaseMessage) GetField() string {
	if x != nil && x.Field != nil {
		return *x.Field
	}
	return ""
}

type MessageSetWireFormatMessage struct {
	XXX_NoUnkeyedLiteral   struct{}                  `json:"-"`
	XXX_InternalExtensions protoimpl.ExtensionFields `protobuf_messageset:"1" json:"-"`
	XXX_unrecognized       protoimpl.UnknownFields   `json:"-"`
	XXX_sizecache          protoimpl.SizeCache       `json:"-"`
}

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

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

func (*MessageSetWireFormatMessage) ProtoMessage() {}

func (x *MessageSetWireFormatMessage) ProtoReflect() protoreflect.Message {
	return file_extensions_base_base_proto_msgTypes[1].MessageOf(x)
}

func (m *MessageSetWireFormatMessage) XXX_Methods() *protoiface.Methods {
	return file_extensions_base_base_proto_msgTypes[1].Methods()
}

// Deprecated: Use MessageSetWireFormatMessage.ProtoReflect.Type instead.
func (*MessageSetWireFormatMessage) Descriptor() ([]byte, []int) {
	return file_extensions_base_base_proto_rawDescGZIP(), []int{1}
}

var extRange_MessageSetWireFormatMessage = []protoiface.ExtensionRangeV1{
	{Start: 100, End: 2147483646},
}

// Deprecated: Use MessageSetWireFormatMessage.ProtoReflect.Type.ExtensionRanges instead.
func (*MessageSetWireFormatMessage) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
	return extRange_MessageSetWireFormatMessage
}

var File_extensions_base_base_proto protoreflect.FileDescriptor

var file_extensions_base_base_proto_rawDesc = []byte{
	0x0a, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x62, 0x61, 0x73,
	0x65, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x67, 0x6f,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x65, 0x78, 0x74,
	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x22, 0x33, 0x0a, 0x0b, 0x42,
	0x61, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69,
	0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64,
	0x2a, 0x04, 0x08, 0x04, 0x10, 0x0a, 0x2a, 0x08, 0x08, 0x10, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
	0x22, 0x2b, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69,
	0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a,
	0x08, 0x08, 0x64, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x3a, 0x02, 0x08, 0x01, 0x42, 0x47, 0x5a,
	0x45, 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, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
	0x73, 0x2f, 0x62, 0x61, 0x73, 0x65,
}

var (
	file_extensions_base_base_proto_rawDescOnce sync.Once
	file_extensions_base_base_proto_rawDescData = file_extensions_base_base_proto_rawDesc
)

func file_extensions_base_base_proto_rawDescGZIP() []byte {
	file_extensions_base_base_proto_rawDescOnce.Do(func() {
		file_extensions_base_base_proto_rawDescData = protoimpl.X.CompressGZIP(file_extensions_base_base_proto_rawDescData)
	})
	return file_extensions_base_base_proto_rawDescData
}

var file_extensions_base_base_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_extensions_base_base_proto_goTypes = []interface{}{
	(*BaseMessage)(nil),                 // 0: goproto.protoc.extension.base.BaseMessage
	(*MessageSetWireFormatMessage)(nil), // 1: goproto.protoc.extension.base.MessageSetWireFormatMessage
}
var file_extensions_base_base_proto_depIdxs = []int32{
	0, // starting offset of method output_type sub-list
	0, // starting offset of method input_type sub-list
	0, // starting offset of extension type_name sub-list
	0, // starting offset of extension extendee sub-list
	0, // starting offset of field type_name sub-list
}

func init() { file_extensions_base_base_proto_init() }
func file_extensions_base_base_proto_init() {
	if File_extensions_base_base_proto != nil {
		return
	}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			RawDescriptor: file_extensions_base_base_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   2,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_extensions_base_base_proto_goTypes,
		DependencyIndexes: file_extensions_base_base_proto_depIdxs,
		MessageInfos:      file_extensions_base_base_proto_msgTypes,
	}.Build()
	File_extensions_base_base_proto = out.File
	file_extensions_base_base_proto_rawDesc = nil
	file_extensions_base_base_proto_goTypes = nil
	file_extensions_base_base_proto_depIdxs = nil
}
