// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.10
// 	protoc        v7.34.0
// source: api_proto/api.proto

package api_proto

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 Output_Record_Field_ERROR int32

const (
	Output_Record_Field_UNKNOWN           Output_Record_Field_ERROR = 0
	Output_Record_Field_MISSING           Output_Record_Field_ERROR = 1
	Output_Record_Field_MISSING_LIST_ITEM Output_Record_Field_ERROR = 2
)

// Enum value maps for Output_Record_Field_ERROR.
var (
	Output_Record_Field_ERROR_name = map[int32]string{
		0: "UNKNOWN",
		1: "MISSING",
		2: "MISSING_LIST_ITEM",
	}
	Output_Record_Field_ERROR_value = map[string]int32{
		"UNKNOWN":           0,
		"MISSING":           1,
		"MISSING_LIST_ITEM": 2,
	}
)

func (x Output_Record_Field_ERROR) Enum() *Output_Record_Field_ERROR {
	p := new(Output_Record_Field_ERROR)
	*p = x
	return p
}

func (x Output_Record_Field_ERROR) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (Output_Record_Field_ERROR) Descriptor() protoreflect.EnumDescriptor {
	return file_api_proto_api_proto_enumTypes[0].Descriptor()
}

func (Output_Record_Field_ERROR) Type() protoreflect.EnumType {
	return &file_api_proto_api_proto_enumTypes[0]
}

func (x Output_Record_Field_ERROR) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use Output_Record_Field_ERROR.Descriptor instead.
func (Output_Record_Field_ERROR) EnumDescriptor() ([]byte, []int) {
	return file_api_proto_api_proto_rawDescGZIP(), []int{0, 0, 0, 0}
}

type Output struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Records       []*Output_Record       `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

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

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

func (*Output) ProtoMessage() {}

func (x *Output) ProtoReflect() protoreflect.Message {
	mi := &file_api_proto_api_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 Output.ProtoReflect.Descriptor instead.
func (*Output) Descriptor() ([]byte, []int) {
	return file_api_proto_api_proto_rawDescGZIP(), []int{0}
}

func (x *Output) GetRecords() []*Output_Record {
	if x != nil {
		return x.Records
	}
	return nil
}

type RepeatedString struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Strings       []string               `protobuf:"bytes,1,rep,name=strings,proto3" json:"strings,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *RepeatedString) Reset() {
	*x = RepeatedString{}
	mi := &file_api_proto_api_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*RepeatedString) ProtoMessage() {}

func (x *RepeatedString) ProtoReflect() protoreflect.Message {
	mi := &file_api_proto_api_proto_msgTypes[1]
	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 RepeatedString.ProtoReflect.Descriptor instead.
func (*RepeatedString) Descriptor() ([]byte, []int) {
	return file_api_proto_api_proto_rawDescGZIP(), []int{1}
}

func (x *RepeatedString) GetStrings() []string {
	if x != nil {
		return x.Strings
	}
	return nil
}

type Output_Record struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Fields        []*Output_Record_Field `protobuf:"bytes,1,rep,name=fields,proto3" json:"fields,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Output_Record) Reset() {
	*x = Output_Record{}
	mi := &file_api_proto_api_proto_msgTypes[2]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*Output_Record) ProtoMessage() {}

func (x *Output_Record) ProtoReflect() protoreflect.Message {
	mi := &file_api_proto_api_proto_msgTypes[2]
	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 Output_Record.ProtoReflect.Descriptor instead.
func (*Output_Record) Descriptor() ([]byte, []int) {
	return file_api_proto_api_proto_rawDescGZIP(), []int{0, 0}
}

func (x *Output_Record) GetFields() []*Output_Record_Field {
	if x != nil {
		return x.Fields
	}
	return nil
}

type Output_Record_Field struct {
	state protoimpl.MessageState `protogen:"open.v1"`
	// Types that are valid to be assigned to Value:
	//
	//	*Output_Record_Field_Text
	//	*Output_Record_Field_Number
	//	*Output_Record_Field_Error
	//	*Output_Record_Field_List
	Value             isOutput_Record_Field_Value `protobuf_oneof:"value"`
	QuoteWhenPrinting bool                        `protobuf:"varint,7,opt,name=quote_when_printing,json=quoteWhenPrinting,proto3" json:"quote_when_printing,omitempty"`
	unknownFields     protoimpl.UnknownFields
	sizeCache         protoimpl.SizeCache
}

func (x *Output_Record_Field) Reset() {
	*x = Output_Record_Field{}
	mi := &file_api_proto_api_proto_msgTypes[3]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

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

func (*Output_Record_Field) ProtoMessage() {}

func (x *Output_Record_Field) ProtoReflect() protoreflect.Message {
	mi := &file_api_proto_api_proto_msgTypes[3]
	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 Output_Record_Field.ProtoReflect.Descriptor instead.
func (*Output_Record_Field) Descriptor() ([]byte, []int) {
	return file_api_proto_api_proto_rawDescGZIP(), []int{0, 0, 0}
}

func (x *Output_Record_Field) GetValue() isOutput_Record_Field_Value {
	if x != nil {
		return x.Value
	}
	return nil
}

func (x *Output_Record_Field) GetText() string {
	if x != nil {
		if x, ok := x.Value.(*Output_Record_Field_Text); ok {
			return x.Text
		}
	}
	return ""
}

func (x *Output_Record_Field) GetNumber() int32 {
	if x != nil {
		if x, ok := x.Value.(*Output_Record_Field_Number); ok {
			return x.Number
		}
	}
	return 0
}

func (x *Output_Record_Field) GetError() Output_Record_Field_ERROR {
	if x != nil {
		if x, ok := x.Value.(*Output_Record_Field_Error); ok {
			return x.Error
		}
	}
	return Output_Record_Field_UNKNOWN
}

func (x *Output_Record_Field) GetList() *RepeatedString {
	if x != nil {
		if x, ok := x.Value.(*Output_Record_Field_List); ok {
			return x.List
		}
	}
	return nil
}

func (x *Output_Record_Field) GetQuoteWhenPrinting() bool {
	if x != nil {
		return x.QuoteWhenPrinting
	}
	return false
}

type isOutput_Record_Field_Value interface {
	isOutput_Record_Field_Value()
}

type Output_Record_Field_Text struct {
	Text string `protobuf:"bytes,1,opt,name=text,proto3,oneof"`
}

type Output_Record_Field_Number struct {
	Number int32 `protobuf:"varint,2,opt,name=number,proto3,oneof"`
}

type Output_Record_Field_Error struct {
	Error Output_Record_Field_ERROR `protobuf:"varint,3,opt,name=error,proto3,enum=devtools.buildozer.Output_Record_Field_ERROR,oneof"`
}

type Output_Record_Field_List struct {
	List *RepeatedString `protobuf:"bytes,5,opt,name=list,proto3,oneof"`
}

func (*Output_Record_Field_Text) isOutput_Record_Field_Value() {}

func (*Output_Record_Field_Number) isOutput_Record_Field_Value() {}

func (*Output_Record_Field_Error) isOutput_Record_Field_Value() {}

func (*Output_Record_Field_List) isOutput_Record_Field_Value() {}

var File_api_proto_api_proto protoreflect.FileDescriptor

const file_api_proto_api_proto_rawDesc = "" +
	"\n" +
	"\x13api_proto/api.proto\x12\x12devtools.buildozer\"\xbf\x03\n" +
	"\x06Output\x12;\n" +
	"\arecords\x18\x01 \x03(\v2!.devtools.buildozer.Output.RecordR\arecords\x1a\xf7\x02\n" +
	"\x06Record\x12?\n" +
	"\x06fields\x18\x01 \x03(\v2'.devtools.buildozer.Output.Record.FieldR\x06fields\x1a\xab\x02\n" +
	"\x05Field\x12\x14\n" +
	"\x04text\x18\x01 \x01(\tH\x00R\x04text\x12\x18\n" +
	"\x06number\x18\x02 \x01(\x05H\x00R\x06number\x12E\n" +
	"\x05error\x18\x03 \x01(\x0e2-.devtools.buildozer.Output.Record.Field.ERRORH\x00R\x05error\x128\n" +
	"\x04list\x18\x05 \x01(\v2\".devtools.buildozer.RepeatedStringH\x00R\x04list\x12.\n" +
	"\x13quote_when_printing\x18\a \x01(\bR\x11quoteWhenPrinting\"8\n" +
	"\x05ERROR\x12\v\n" +
	"\aUNKNOWN\x10\x00\x12\v\n" +
	"\aMISSING\x10\x01\x12\x15\n" +
	"\x11MISSING_LIST_ITEM\x10\x02B\a\n" +
	"\x05value\"*\n" +
	"\x0eRepeatedString\x12\x18\n" +
	"\astrings\x18\x01 \x03(\tR\astringsB\vZ\tapi_protob\x06proto3"

var (
	file_api_proto_api_proto_rawDescOnce sync.Once
	file_api_proto_api_proto_rawDescData []byte
)

func file_api_proto_api_proto_rawDescGZIP() []byte {
	file_api_proto_api_proto_rawDescOnce.Do(func() {
		file_api_proto_api_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_api_proto_rawDesc), len(file_api_proto_api_proto_rawDesc)))
	})
	return file_api_proto_api_proto_rawDescData
}

var file_api_proto_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_api_proto_api_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_api_proto_api_proto_goTypes = []any{
	(Output_Record_Field_ERROR)(0), // 0: devtools.buildozer.Output.Record.Field.ERROR
	(*Output)(nil),                 // 1: devtools.buildozer.Output
	(*RepeatedString)(nil),         // 2: devtools.buildozer.RepeatedString
	(*Output_Record)(nil),          // 3: devtools.buildozer.Output.Record
	(*Output_Record_Field)(nil),    // 4: devtools.buildozer.Output.Record.Field
}
var file_api_proto_api_proto_depIdxs = []int32{
	3, // 0: devtools.buildozer.Output.records:type_name -> devtools.buildozer.Output.Record
	4, // 1: devtools.buildozer.Output.Record.fields:type_name -> devtools.buildozer.Output.Record.Field
	0, // 2: devtools.buildozer.Output.Record.Field.error:type_name -> devtools.buildozer.Output.Record.Field.ERROR
	2, // 3: devtools.buildozer.Output.Record.Field.list:type_name -> devtools.buildozer.RepeatedString
	4, // [4:4] is the sub-list for method output_type
	4, // [4:4] is the sub-list for method input_type
	4, // [4:4] is the sub-list for extension type_name
	4, // [4:4] is the sub-list for extension extendee
	0, // [0:4] is the sub-list for field type_name
}

func init() { file_api_proto_api_proto_init() }
func file_api_proto_api_proto_init() {
	if File_api_proto_api_proto != nil {
		return
	}
	file_api_proto_api_proto_msgTypes[3].OneofWrappers = []any{
		(*Output_Record_Field_Text)(nil),
		(*Output_Record_Field_Number)(nil),
		(*Output_Record_Field_Error)(nil),
		(*Output_Record_Field_List)(nil),
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_api_proto_rawDesc), len(file_api_proto_api_proto_rawDesc)),
			NumEnums:      1,
			NumMessages:   4,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_api_proto_api_proto_goTypes,
		DependencyIndexes: file_api_proto_api_proto_depIdxs,
		EnumInfos:         file_api_proto_api_proto_enumTypes,
		MessageInfos:      file_api_proto_api_proto_msgTypes,
	}.Build()
	File_api_proto_api_proto = out.File
	file_api_proto_api_proto_goTypes = nil
	file_api_proto_api_proto_depIdxs = nil
}
