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

package extra

import (
	proto "github.com/golang/protobuf/proto"
	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
	prototype "github.com/golang/protobuf/v2/reflect/prototype"
	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

type ExtraMessage struct {
	Data                 []byte   `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

type xxx_ExtraMessage struct{ m *ExtraMessage }

func (m *ExtraMessage) ProtoReflect() protoreflect.Message {
	return xxx_ExtraMessage{m}
}
func (m xxx_ExtraMessage) Type() protoreflect.MessageType {
	return xxx_Extra_ProtoFile_MessageTypes[0].Type
}
func (m xxx_ExtraMessage) KnownFields() protoreflect.KnownFields {
	return xxx_Extra_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
}
func (m xxx_ExtraMessage) UnknownFields() protoreflect.UnknownFields {
	return xxx_Extra_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
}
func (m xxx_ExtraMessage) Interface() protoreflect.ProtoMessage {
	return m.m
}

func (m *ExtraMessage) Reset()         { *m = ExtraMessage{} }
func (m *ExtraMessage) String() string { return proto.CompactTextString(m) }
func (*ExtraMessage) ProtoMessage()    {}
func (*ExtraMessage) Descriptor() ([]byte, []int) {
	return fileDescriptor_496c2a5e9c1e8739, []int{0}
}

func (m *ExtraMessage) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_ExtraMessage.Unmarshal(m, b)
}
func (m *ExtraMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_ExtraMessage.Marshal(b, m, deterministic)
}
func (m *ExtraMessage) XXX_Merge(src proto.Message) {
	xxx_messageInfo_ExtraMessage.Merge(m, src)
}
func (m *ExtraMessage) XXX_Size() int {
	return xxx_messageInfo_ExtraMessage.Size(m)
}
func (m *ExtraMessage) XXX_DiscardUnknown() {
	xxx_messageInfo_ExtraMessage.DiscardUnknown(m)
}

var xxx_messageInfo_ExtraMessage proto.InternalMessageInfo

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

func init() {
	proto.RegisterFile("extensions/extra/extra.proto", fileDescriptor_496c2a5e9c1e8739)
	proto.RegisterType((*ExtraMessage)(nil), "goproto.protoc.extension.extra.ExtraMessage")
}

var fileDescriptor_496c2a5e9c1e8739 = []byte{
	// 149 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xad, 0x28, 0x49,
	0xcd, 0x2b, 0xce, 0xcc, 0xcf, 0x2b, 0xd6, 0x4f, 0xad, 0x28, 0x29, 0x4a, 0x84, 0x90, 0x7a, 0x05,
	0x45, 0xf9, 0x25, 0xf9, 0x42, 0x72, 0xe9, 0xf9, 0x60, 0x06, 0x84, 0x9b, 0xac, 0x07, 0x57, 0xac,
	0x07, 0x56, 0xa5, 0xa4, 0xc4, 0xc5, 0xe3, 0x0a, 0x62, 0xf8, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7,
	0x0a, 0x09, 0x71, 0xb1, 0xa4, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81,
	0xd9, 0x4e, 0xde, 0x51, 0x9e, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa,
	0xe9, 0xf9, 0x39, 0x89, 0x79, 0xe9, 0xfa, 0x60, 0xf3, 0x92, 0x4a, 0xd3, 0xf4, 0xcb, 0x8c, 0xf4,
	0x93, 0x73, 0x53, 0x20, 0xfc, 0x64, 0xdd, 0xf4, 0xd4, 0x3c, 0xdd, 0xf4, 0x7c, 0xfd, 0x92, 0xd4,
	0xe2, 0x12, 0x90, 0x5e, 0x7d, 0x74, 0xc7, 0x01, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xfb, 0x31,
	0xfc, 0xaf, 0x00, 0x00, 0x00,
}

func init() {
	xxx_Extra_ProtoFile_FileDesc.Messages = xxx_Extra_ProtoFile_MessageDescs[0:1]
	var err error
	Extra_ProtoFile, err = prototype.NewFile(&xxx_Extra_ProtoFile_FileDesc)
	if err != nil {
		panic(err)
	}
}

const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)

var Extra_ProtoFile protoreflect.FileDescriptor

var xxx_Extra_ProtoFile_FileDesc = prototype.File{
	Syntax:  protoreflect.Proto2,
	Path:    "extensions/extra/extra.proto",
	Package: "goproto.protoc.extension.extra",
}
var xxx_Extra_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
	{Type: prototype.GoMessage(
		xxx_Extra_ProtoFile_MessageDescs[0].Reference(),
		func(protoreflect.MessageType) protoreflect.Message {
			return xxx_ExtraMessage{new(ExtraMessage)}
		},
	)},
}
var xxx_Extra_ProtoFile_MessageDescs = [1]prototype.Message{
	{
		Name: "ExtraMessage",
		Fields: []prototype.Field{
			{
				Name:        "data",
				Number:      1,
				Cardinality: protoreflect.Optional,
				Kind:        protoreflect.BytesKind,
				JSONName:    "data",
				IsPacked:    prototype.False,
			},
		},
	},
}
