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

package extra

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 ExtraMessage struct {
	Data          []byte `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
}

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

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

func (*ExtraMessage) ProtoMessage() {}

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

func (m *ExtraMessage) XXX_Methods() *protoiface.Methods {
	return file_extensions_extra_extra_proto_msgTypes[0].Methods()
}

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

func (x *ExtraMessage) GetData() []byte {
	if x != nil {
		return x.Data
	}
	return nil
}

var File_extensions_extra_extra_proto protoreflect.FileDescriptor

var file_extensions_extra_extra_proto_rawDesc = []byte{
	0x0a, 0x1c, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x65, 0x78, 0x74,
	0x72, 0x61, 0x2f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e,
	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, 0x65, 0x78, 0x74, 0x72, 0x61, 0x22, 0x22,
	0x0a, 0x0c, 0x45, 0x78, 0x74, 0x72, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12,
	0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61,
	0x74, 0x61, 0x42, 0x48, 0x5a, 0x46, 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, 0x65, 0x78, 0x74, 0x72, 0x61,
}

var (
	file_extensions_extra_extra_proto_rawDescOnce sync.Once
	file_extensions_extra_extra_proto_rawDescData = file_extensions_extra_extra_proto_rawDesc
)

func file_extensions_extra_extra_proto_rawDescGZIP() []byte {
	file_extensions_extra_extra_proto_rawDescOnce.Do(func() {
		file_extensions_extra_extra_proto_rawDescData = protoimpl.X.CompressGZIP(file_extensions_extra_extra_proto_rawDescData)
	})
	return file_extensions_extra_extra_proto_rawDescData
}

var file_extensions_extra_extra_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_extensions_extra_extra_proto_goTypes = []interface{}{
	(*ExtraMessage)(nil), // 0: goproto.protoc.extension.extra.ExtraMessage
}
var file_extensions_extra_extra_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_extra_extra_proto_init() }
func file_extensions_extra_extra_proto_init() {
	if File_extensions_extra_extra_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_extensions_extra_extra_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*ExtraMessage); i {
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			RawDescriptor: file_extensions_extra_extra_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_extensions_extra_extra_proto_goTypes,
		DependencyIndexes: file_extensions_extra_extra_proto_depIdxs,
		MessageInfos:      file_extensions_extra_extra_proto_msgTypes,
	}.Build()
	File_extensions_extra_extra_proto = out.File
	file_extensions_extra_extra_proto_rawDesc = nil
	file_extensions_extra_extra_proto_goTypes = nil
	file_extensions_extra_extra_proto_depIdxs = nil
}
