// Code generated by protoc-gen-go. DO NOT EDIT.
// source: imports/fmt/m.proto

package fmt

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoregistry "google.golang.org/protobuf/reflect/protoregistry"
	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 M struct {
	XXX_NoUnkeyedLiteral struct{}                `json:"-"`
	XXX_unrecognized     protoimpl.UnknownFields `json:"-"`
	XXX_sizecache        protoimpl.SizeCache     `json:"-"`
}

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

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

func (*M) ProtoMessage() {}

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

func (m *M) XXX_Methods() *protoiface.Methods {
	return file_imports_fmt_m_proto_msgTypes[0].Methods()
}

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

var File_imports_fmt_m_proto protoreflect.FileDescriptor

var file_imports_fmt_m_proto_rawDesc = []byte{
	0x0a, 0x13, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2f, 0x66, 0x6d, 0x74, 0x2f, 0x6d, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x66, 0x6d, 0x74, 0x22, 0x03, 0x0a, 0x01, 0x4d, 0x42,
	0x43, 0x5a, 0x41, 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, 0x73,
	0x2f, 0x66, 0x6d, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_imports_fmt_m_proto_rawDescOnce sync.Once
	file_imports_fmt_m_proto_rawDescData = file_imports_fmt_m_proto_rawDesc
)

func file_imports_fmt_m_proto_rawDescGZIP() []byte {
	file_imports_fmt_m_proto_rawDescOnce.Do(func() {
		file_imports_fmt_m_proto_rawDescData = protoimpl.X.CompressGZIP(file_imports_fmt_m_proto_rawDescData)
	})
	return file_imports_fmt_m_proto_rawDescData
}

var file_imports_fmt_m_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_imports_fmt_m_proto_goTypes = []interface{}{
	(*M)(nil), // 0: fmt.M
}
var file_imports_fmt_m_proto_depIdxs = []int32{}

func init() { file_imports_fmt_m_proto_init() }
func file_imports_fmt_m_proto_init() {
	if File_imports_fmt_m_proto != nil {
		return
	}
	File_imports_fmt_m_proto = protoimpl.FileBuilder{
		RawDescriptor:      file_imports_fmt_m_proto_rawDesc,
		GoTypes:            file_imports_fmt_m_proto_goTypes,
		DependencyIndexes:  file_imports_fmt_m_proto_depIdxs,
		MessageOutputTypes: file_imports_fmt_m_proto_msgTypes,
		FilesRegistry:      protoregistry.GlobalFiles,
		TypesRegistry:      protoregistry.GlobalTypes,
	}.Init()
	file_imports_fmt_m_proto_rawDesc = nil
	file_imports_fmt_m_proto_goTypes = nil
	file_imports_fmt_m_proto_depIdxs = nil
}
